diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-13 01:38:42 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-13 01:38:42 -0500 |
| commit | 62cd707c2b78508e35177f553b72258ac6114198 (patch) | |
| tree | 667ba86fca8cbb5f1638c2296c01775282db0aef | |
| parent | 7b65b2dd04d97c2dc34e5afa715a07ce14b851ae (diff) | |
| download | rulesets-62cd707c2b78508e35177f553b72258ac6114198.tar.gz rulesets-62cd707c2b78508e35177f553b72258ac6114198.zip | |
docs(design): resolve wrap-up routing spec decisions (Reading B)
All six decisions resolved. The router's input is filed keepers that belong to another project, not raw inbox files (Reading B). That keeps it a separate sub-step from the inbox gate (D1) and distinct from the defer-and-stage router (D5). Transcript routing is deferred to vNext (D4).
I reworked the design to match: the input definition, a candidate-set note bounding the router to session-filed keepers rather than the standing backlog, and Phase 3. The cookie reads [6/6] and the Status moved to ready for review.
The A-vs-B input ambiguity was the root under D1 and D5. Reading B keeps the inbox gate, the router, and defer-and-stage each simple instead of entangling all three.
| -rw-r--r-- | docs/design/wrapup-routing-spec.org | 44 | ||||
| -rw-r--r-- | todo.org | 4 |
2 files changed, 26 insertions, 22 deletions
diff --git a/docs/design/wrapup-routing-spec.org b/docs/design/wrapup-routing-spec.org index 396fb45..0091806 100644 --- a/docs/design/wrapup-routing-spec.org +++ b/docs/design/wrapup-routing-spec.org @@ -4,7 +4,7 @@ #+TODO: TODO | DONE SUPERSEDED CANCELLED * Metadata -| Status | draft | +| Status | ready for review | |----------+-----------------------------------------------------| | Owner | Craig Jennings | |----------+-----------------------------------------------------| @@ -51,7 +51,7 @@ The friction is small per-item but recurring, and the manual cross-project edit ** User-facing (the wrap interaction) -The router is a new sub-step of =wrap-it-up.org='s Step 3, running after the existing inbox sanity check. When it finds inbox items whose recommended home is a different project, it surfaces them as a list, one line each: the item, the recommended destination project, and a confidence marker when the inference is weak. Then two options, batch-level: +The router is a new sub-step of =wrap-it-up.org='s Step 3, running after the existing inbox sanity check. Its input is filed keepers, not raw inbox files (decision: Reading B): tasks =process-inbox= accepted and filed into the local =todo.org= this session whose inferred home is a different project. When the router finds such a keeper, it surfaces it in a list, one line each: the task, the recommended destination project, and a confidence marker when the inference is weak. Then two options, batch-level: 1. Go with the recommendations — apply every recommended move. 2. Skip — leave the whole batch in place. A skip is a clean wrap. @@ -62,6 +62,8 @@ A move of a task/event relocates it into the destination project's "Open Work" s ** Implementer (the mechanics) +*Candidate set (what the router considers).* Reading B means the router does not scan the whole local backlog — it would otherwise suggest moving legitimate local tasks every wrap. The candidate set is keepers =process-inbox= filed this session whose inferred home differs from the current project. How those are marked is an implementation detail for Phase 3/4: either =process-inbox= tags a cross-project-candidate keeper at file time, or the router infers from a =CREATED= stamp dated this session plus content. The reviewer should pin which; the design constraint is "session-filed inbox keepers only, never the standing backlog." + *Destination discovery.* Widen the project-discovery filter from "directory with a =.ai/protocols.org= marker" (what =inbox-send.py= and the =ai= launcher use) to "directory with a =todo.org= containing a level-1 'Open Work' heading." A plain code repo Craig keeps a =todo.org= in is a valid destination; an =.ai/= directory is not required. *Destination anchor.* Reuse =todo-cleanup.el='s existing matcher: =tc--find-section= locates the unique level-1 heading containing "Open Work" (case-insensitive) and returns =nil= / ='multiple= when absent or ambiguous. A destination whose =todo.org= lacks a clean Open Work heading is surfaced and skipped, never guessed at. @@ -82,14 +84,14 @@ A move of a task/event relocates it into the destination project's "Open Work" s ** Fold the router into the existing Inbox sanity check step - Good, because one inbox step is simpler than two. - Bad, because the sanity check *gates* the wrap (blocks until clean) and the router is *optional* (skip is clean). Merging a blocking check with an optional action muddies both. -- Neutral, because the two could share discovery code while staying separate steps. (This is open decision D1.) +- Neutral, because the two share discovery code while staying separate steps. (Resolved: D1 keeps them separate, with the router acting on filed keepers rather than inbox files.) ** Reuse process-inbox's "file as TODO" with a destination argument - Good, because it avoids a second mechanism. - Bad, because =process-inbox= runs per-item mid-session against the local project; the router runs at wrap, batch-level, cross-project. Different cadence, different scope. - Neutral, because both ultimately call the same atomic move helper — the helper is the shared primitive, the two callers stay distinct. -* Decisions [/] +* Decisions [6/6] ** DONE Reuse the Open Work matcher for destination anchoring - Context: the move needs a reliable insertion point in the destination =todo.org=; guessing risks corrupting another project's file. @@ -106,23 +108,20 @@ A move of a task/event relocates it into the destination project's "Open Work" s - Decision: We will treat the batch "go" as the authorization, leave the move visible in the destination's git diff, and stamp a one-line provenance note (source project + date) on each moved task. - Consequences: easier — the boundary rule is honored without a per-move prompt. Harder — the destination's next session sees an externally-authored task it didn't file, so the provenance note is load-bearing, not decorative. -** TODO Separate router step or merge into the inbox sanity check -- Owner / by-when: Craig / before implementation. -- Context: the sanity check gates the wrap; the router is optional. archsetup leans separate; so do I (a blocking check and an optional action read more clearly apart). But it's Craig's wrap-cadence call. -- Decision: We will (proposed) keep the router a *separate* optional sub-step running after the sanity check, sharing only the discovery code. -- Consequences: easier — each step has one job, the optional one can't accidentally block. Harder — two inbox-touching steps in one wrap, slightly more workflow prose. +** DONE Separate router step, operating on filed keepers (Reading B) +- Context: the sanity check gates the wrap on inbox/ contents; the router is optional. The deeper question was the router's input — raw inbox files (Reading A, which overlaps the sanity check) or already-filed keepers that belong elsewhere (Reading B, a todo-routing concern). +- Decision: We will keep the router a separate optional sub-step after the sanity check, and its input is Reading B: accepted keepers process-inbox filed into the local =todo.org= whose inferred home is another project. The sanity check stays a pure inbox gate; the router is a todo-routing action that shares only the destination-discovery code. +- Consequences: easier — each step has one job, the gate can't be muddied by an optional action, and the router never competes with the inbox gate over the same files. Harder — the candidate set (which local tasks the router considers) needs a marking mechanism (see the Implementer "candidate set" note); Reading A's "dispose raw inbox files at wrap" convenience is given up. -** TODO Transcript routing — scope and trigger -- Owner / by-when: Craig / before any transcript work starts. +** DONE Transcript routing deferred to vNext - Context: transcripts file as artifacts, not tasks, and a meeting usually produces both a recording to keep and action items to track. Two unknowns block it: where recordings accumulate (a recordings inbox, a downloads dir, wherever the meeting tooling drops them), and whether filing should also extract action items into the destination's =todo.org=. -- Decision: We will (proposed) defer transcript routing to vNext, file the recording as an artifact only, and let action items route through the v1 task-router as a separate batch — keeping documents and tasks orthogonal. -- Consequences: easier — v1 ships without the unresolved source-location dependency. Harder — a meeting's recording and its action items get handled by two mechanisms, which Craig may prefer combined into one "process this transcript" move. +- Decision: We will defer transcript routing to vNext. Both the source-location dependency and the file-only-vs-extract-action-items question are deferred with it, to be settled when the vNext work is specced. v1 ships task routing only. +- Consequences: easier — v1 isn't blocked on the unresolved source location. Harder — until vNext, a meeting recording still has no automatic home; only its action items (if filed as tasks) route through v1. -** TODO Reconcile with the process-inbox defer-and-stage router -- Owner / by-when: Craig + author / before implementation. -- Context: the 2026-06-12 Skeptical Review added a defer-and-stage path in =process-inbox.org= that files a =[#B]= VERIFY for shared-asset proposals parked for review. That also moves an inbox item toward a =todo.org= task — overlapping surface with this router. -- Decision: We will (proposed) keep them distinct: defer-and-stage parks a *proposal under review* locally as a VERIFY; this router moves an *accepted keeper* to its home project. Shared primitive is the atomic move helper, not the policy. -- Consequences: easier — two clear, non-competing policies. Harder — the workflows must state the boundary so a future reader doesn't collapse them into one and reintroduce the ambiguity. +** DONE Keep defer-and-stage and the router as distinct policies +- Context: the 2026-06-12 Skeptical Review added a defer-and-stage path in =process-inbox.org= that files a =[#B]= VERIFY for shared-asset proposals parked for review. That also turns an inbox item into a =todo.org= task — overlapping surface with this router. +- Decision: We will keep them distinct. Defer-and-stage parks a proposal-under-review locally as a VERIFY; the router moves an accepted keeper to its home project as a TODO. They differ on review status (proposal vs accepted) and destination (local vs cross-project), and share only the atomic move helper, not the policy. Reading B makes the split clean: the router acts on accepted keepers, never on proposals under review. +- Consequences: easier — two clear, non-competing policies on one shared primitive. Harder — the workflow prose must name the boundary so a future reader doesn't collapse them and reintroduce the ambiguity. * Implementation phases @@ -132,8 +131,8 @@ A discovery function returning every project with a =todo.org= that has a clean ** Phase 2 — Atomic cross-project move helper Extend =todo-cleanup.el= (or sibling tool) with a "move this subtree into project X's Open Work" operation that inserts at the destination and removes the source as one step, stamping the provenance line. ERT coverage: successful move, missing-destination-heading refusal, source-removal-on-success, no-partial-move-on-failure. -** Phase 3 — Recommendation engine -Infer destination from item content against the discovered list, with a confidence label. Unit-tested: strong match (project named in item), weak match (topic-only → low-confidence), no match (stays put). Pure function over (item, project-list) → (destination, confidence). +** Phase 3 — Recommendation engine + candidate-set marking +Infer destination from item content against the discovered list, with a confidence label. Pure function over (item, project-list) → (destination, confidence). Unit-tested: strong match (project named in item), weak match (topic-only → low-confidence), no match (stays put). Also settle the candidate-set marking (tag at file time vs CREATED-this-session inference) so the router considers only session-filed inbox keepers, never the standing backlog. ** Phase 4 — Wrap-up step wiring Add the router sub-step to =wrap-it-up.org= Step 3: surface the batch, the two options, apply-on-go via the Phase 2 helper. Per the D1/D5 decisions once settled. Sync the =.ai/= mirror. @@ -175,3 +174,8 @@ Only after the transcript-scope decision resolves. File a recording into the des - What: initial draft. Problem, goals/scope tiers, two-altitude design, alternatives, six decisions (three DONE from grounding, three TODO for Craig), five implementation phases, acceptance criteria, readiness dimensions, risks. - Why: the archsetup 2026-06-13 handoff cleared the spec bar in inbox triage and was filed spec-bound rather than applied. This draft turns the proposal into a reviewable design with the open questions isolated as decision tasks. - Artifacts: proposal source at =docs/design/2026-06-13-wrapup-inbox-transcript-routing-proposal.org=; grounded against =wrap-it-up.org= Step 3, =todo-cleanup.el= =tc--find-section=, and =inbox-send.py= discovery. + +** 2026-06-13 Sat @ 01:36:28 -0500 — Craig Jennings + Claude Code (rulesets) — author +- What: resolved all three open decisions. The router's input is Reading B (filed keepers that belong elsewhere, not raw inbox files), so D1 keeps it a separate sub-step from the inbox gate and D5 keeps it distinct from the defer-and-stage router; D4 defers transcript routing to vNext. Reworked the design (input definition, a candidate-set note bounding the router to session-filed keepers) and Phase 3 to match. Cookie now [6/6]; Status moved to ready-for-review. +- Why: Craig chose Reading B after the A-vs-B input ambiguity surfaced as the root under D1 and D5. Reading B keeps the inbox gate, the router, and defer-and-stage each simple instead of entangling three mechanisms. +- Artifacts: this spec; the candidate-set marking mechanism is the one detail flagged for spec-review to pin. @@ -39,9 +39,9 @@ Tags are assigned and refreshed by =task-audit=; =task-review= keeps them honest :CREATED: [2026-06-13 Sat] :LAST_REVIEWED: 2026-06-13 :END: -Optional wrap-up step that surfaces inbox items belonging to another project, recommends a destination, and batch-moves them into that project's =todo.org= Open Work section (transcript filing deferred to vNext). Spec drafted, decisions D1/D4/D5 awaiting Craig before implementation-ready. +Optional wrap-up step that surfaces filed keepers belonging to another project, recommends a destination, and batch-moves them into that project's =todo.org= Open Work section (transcript filing deferred to vNext). All six decisions resolved (Reading B: the router acts on session-filed keepers, separate from the inbox gate and from defer-and-stage). Spec ready for review. -Spec: [[file:docs/design/wrapup-routing-spec.org]]. Source proposal: [[file:docs/design/2026-06-13-wrapup-inbox-transcript-routing-proposal.org]] (archsetup handoff 2026-06-13). Next: =spec-review= once the open decisions resolve. +Spec: [[file:docs/design/wrapup-routing-spec.org]]. Source proposal: [[file:docs/design/2026-06-13-wrapup-inbox-transcript-routing-proposal.org]] (archsetup handoff 2026-06-13). Next: =spec-review=. ** TODO [#B] Helper-instance support — concurrent same-project Claude :feature:spec: :PROPERTIES: |
