diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-18 19:55:43 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-18 19:55:43 -0500 |
| commit | bc1d81d835237343a4ced82a9025f2dc34f45865 (patch) | |
| tree | 173150aadac7932eb55759bf294fb18ca2b453a7 /todo.org | |
| parent | 6523ed5b789689a2b77925fb3825570b2d8e5686 (diff) | |
| download | rulesets-bc1d81d835237343a4ced82a9025f2dc34f45865.tar.gz rulesets-bc1d81d835237343a4ced82a9025f2dc34f45865.zip | |
chore(todo): file four backlog tasks from the inbox pass
Filed as [#B] work items with their origin proposals preserved under docs/design/: the todo-cleanup dated-seal archiving model, the dated-log planning-line strip plus its lint backstop, a hook to enforce the task-boundary inbox check, and home's colloquialisms / "the list" before-close-queue convention. The first two both touch todo-cleanup.el and are cross-linked to build as one batch. The last two carry the design worked out this session so they start warm.
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 149 |
1 files changed, 149 insertions, 0 deletions
@@ -1310,6 +1310,155 @@ having a skill to generate or check OV-1-shaped artifacts. Don't build speculatively — defense-specific notations are narrow enough that each skill should be driven by a concrete contract need, not aspiration. +** TODO [#B] todo-cleanup.el dated-seal archiving :feature:solo: +Redefine =--archive-done= aging from a 7-day roll-into-one-file model to a +one-month retention with dated seals. Craig ratified the design in the work +project 2026-07-17; origin handoff preserved at +[[file:docs/design/2026-07-17-todo-cleanup-dated-seal-proposal.md]]. + +Changes to =.ai/scripts/todo-cleanup.el= (canonical in +=claude-templates/.ai/scripts/=): +- =tc-archive-retain-days= default 7 → 31. +- Aging predicate: archive a level-2 DONE/CANCELLED subtree when CLOSED is + older than the retain window OR CLOSED is unparseable. The unparseable case + already archives per the docstring; make it explicit in the contract. +- New seal step (flag, e.g. =--seal=): rename the working =tc-archive-file= + (=task-archive.org=) → =resolved-YYYY-MM-DD.org= beside it; next aging + recreates a fresh working file. Auto-seal-at-quarter vs manual flag is an + open call — default manual (the per-project rotation task covers cadence). +- Update the file-aging tests (=test-todo-cleanup.el= lines 362, 378, 491, + 513, 518) for the new retain default and the seal/rename behavior. The + gitignore-inheritance logic (=tc--ensure-archive-gitignored=) applies to both + names unchanged. + +TDD, canonical-then-mirror per the sync-check invariant. Home's planning-line +strip proposal (filed alongside) also touches todo-cleanup.el =--convert-subtasks= +— the two can be built as one batch. + +** TODO [#B] Strip stale planning lines on dated completion + lint backstop :feature:solo: +Two linked fixes so a closed sub-task can't keep polluting the org agenda. Origin: +home handoff 2026-07-17; design preserved at +[[file:docs/design/2026-07-17-dated-log-planning-line-strip-proposal.md]]. A dated-log +heading (no TODO keyword) that still carries an active =SCHEDULED:= renders as +weeks-overdue on the agenda forever — invisible to a keyword scan and surviving +=--archive-done=. Root cause: the completion rewrite strips keyword/priority/tags +but nothing strips the planning line, and an interactive org close only stamps +=CLOSED:=. + +1. =claude-rules/todo-format.md= (canonical rule) — in the "=***= and deeper — + rewrite to a dated event-log entry" section, add a step: remove any + =SCHEDULED:=/=DEADLINE:= line when rewriting to the dated form. Apply the same + to the VERIFY dated-completion path. +2. =.ai/scripts/lint-org.el= (canonical in =claude-templates/.ai/scripts/=) — new + checker =dated-log-heading-active-timestamp=: flag any dated-log heading (the + =YYYY-MM-DD ... @ ...= form, no TODO keyword) carrying an active =<...>= + SCHEDULED or DEADLINE. The mechanical backstop for #1, mirroring + =subtask-done-not-dated=. +3. =todo-cleanup.el= =--convert-subtasks= — drop the planning line alongside its + existing CLOSED-timestamp pull. + +Build notes: the checker's regex must key on "no TODO keyword" so it never flags a +live TODO that legitimately carries a SCHEDULED. TDD, canonical-then-mirror. Batches +with the dated-seal task above (both touch todo-cleanup.el). + +** TODO [#B] Enforce the task-boundary inbox check via a hook :feature: +Today the "check =inbox/= at every task boundary" rule (protocols.org, "Inbox +Monitoring Cadence") is prose-only — present in all 27 projects' synced +protocols.org, but nothing mechanically enforces it, so it holds only as well as +the agent's adherence. Convert it to a hook so a pending handoff can't slip past a +turn unseen. Design worked out with Craig 2026-07-18. + +*** The one decision to settle at kickoff +Hard-block vs soft-nudge (this is why the task isn't =:solo:= — it's a preference +call). My recommendation: *soft-nudge*. Answer this first, then the rest is +mechanical. +- *Hard-block*: the Stop hook blocks EVERY yield while items are pending, forcing + the agent to process before it can return control. Strongest guarantee, but it + also fires when the agent pauses mid-task to ask Craig a clarifying question + (that pause is also a Stop), pushing inbox processing ahead of the question. +- *Soft-nudge*: use the =stop_hook_active= flag to inject the reason once per turn, + then let the turn end if the agent chooses not to act. Stronger than today's + prose rule, no clarifying-question hijack. + +*** Why the Stop event +The harness has no "task boundary" event. But the rule's own definition — "after +finishing a unit of work, before reporting back or asking what's next" — maps onto +the Stop event (agent finishing its turn, about to yield). Every "reporting back" +is a Stop. PostToolUse is wrong granularity (fires per tool call); UserPromptSubmit +is the START of the next task, useful only as a complement (below). + +*** Mechanism +A Stop hook returns =\{"decision":"block","reason":"N pending handoffs — process +per inbox.org before yielding."\}= when =inbox-status -q= exits 1. The harness then +keeps the agent going with that reason injected instead of returning to Craig. The +loop self-terminates: once items are dispositioned (deleted or renamed +=PROCESSED-=, which =inbox-status= excludes), the next Stop exits 0 and the turn +ends. The harness passes =stop_hook_active: true= on the re-entry — check it to +nudge once rather than wedge on an item the agent genuinely can't process. + +*** The complement (optional, pair with the Stop hook) +A =UserPromptSubmit= hook that runs =inbox-status= and injects a one-line "N +pending handoffs" note into context at the start of Craig's next instruction. +Non-blocking; guarantees the agent sees pending items the moment a new task starts. +Catches the "arrived while away" case from the other direction. Can ship alone +(pure visibility) or alongside the Stop hook. Recommended: ship both. + +*** Placement + files +- Global, in =~/.claude/settings.json= (the =Stop= array already holds + =ai-wrap-teardown.sh= — add a second entry, or a combined script). +- Ship the script from =claude-templates/.claude/hooks/= (e.g. + =inbox-boundary-check.sh=); =make install-hooks= links it; wire it in the tracked + =settings.json= so it travels. Mirror the reference pattern in + =hooks/ai-wrap-teardown.sh= — reads =cwd= from stdin JSON via =jq=, basenames to + the project. +- Self-skips where inapplicable: =inbox-status= exits 2 with no =inbox/= dir, so + the hook no-ops in any project without an inbox. One hook, every project, no + config. + +*** Verify +- bats around the hook script (=hooks/tests/=): exit-1 inbox → block JSON emitted; + exit-0 → no output; =stop_hook_active: true= input → single-nudge path; no + =inbox/= → clean no-op. Follow the existing hook-test pattern. +- Live: drop a test handoff, confirm the agent is pushed to process it at turn end. + +*** Honest limitation to carry forward +No hook can perfectly tell "a unit of work finished" from "the agent paused for any +other reason" — the harness exposes only "the turn is ending," not "a task is +ending." The design leans on those two being usually the same in Craig's workflow. +That's the tradeoff hard-block vs soft-nudge is really about. + +** TODO [#B] "Colloquialisms and Expansions" + "the list" before-close-queue convention :feature: +Home proposes two linked cross-project norms; Craig recommends rolling them out. +Origin: home handoff 2026-07-18, design preserved at +[[file:docs/design/2026-07-18-colloquialisms-and-the-list-proposal.md]]. Needs Craig's +adoption decision + a small design pass before implementation — that's why it's +filed, not applied. + +The two parts: +1. *"the list" = a before-close FIFO queue.* "Put X on the list" / "add X to the + list" appends X to a session-scoped Before-Close Queue, worked oldest-first at + wrap-up before teardown, unfinished items surfaced rather than dropped. Resets + when the session anchor archives. Anything that must outlive the session is a + =todo.org= task instead. +2. *"Colloquialisms and Expansions" shorthand dictionary.* A per-project (or + shared) map of Craig shorthand → expansion the agent applies without asking. + Seed entries: "the list" → the queue above; "tell <project> <msg>" → drop the + message in that project's inbox via =inbox-send= (already the sanctioned + handoff, so this entry is near-documentation). + +Durable wiring (why rulesets, not home-local): (a) a colloquialisms reference in +the template — a =protocols.org= section or a shipped reference file; (b) a +=wrap-it-up.org= step that processes the Before-Close Queue before teardown. +=wrap-it-up.org= is a synced rulesets-owned workflow, so home can't wire (b) +durably from downstream — it stubbed the norm via its local =notes.org= for now. + +Design pass to settle first: where the colloquialisms reference lives (protocols.org +section vs a new shipped reference file); where the queue itself lives (home used a +=* Before-Close Queue= heading in =session-context.org=); and the exact wrap-it-up +insertion point (before the teardown/valediction, alongside the roam-inbox +sub-step). Then it's a synced-file change (canonical-then-mirror) + a test that the +wrap step drains the queue. + * Rulesets Resolved ** CANCELLED [#C] ntfy phone channel as general two-way agent-comms :feature:spec: CLOSED: [2026-07-13 Mon] |
