diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-13 01:26:17 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-13 01:26:17 -0500 |
| commit | 7b65b2dd04d97c2dc34e5afa715a07ce14b851ae (patch) | |
| tree | 276ad68e57459f976cc7ff530ccea7f750c75e14 | |
| parent | 049aafb512e735dc04b77274c2167a67eec4f99f (diff) | |
| download | rulesets-7b65b2dd04d97c2dc34e5afa715a07ce14b851ae.tar.gz rulesets-7b65b2dd04d97c2dc34e5afa715a07ce14b851ae.zip | |
docs(design): draft wrap-up routing spec
A spec for the optional wrap-up step that routes inbox items (and, vNext, transcripts) to the project they belong to. Three decisions settled from grounding (reuse todo-cleanup's Open Work matcher as the destination anchor, move atomically through one helper, keep cross-project writes visible with a provenance note); three left open for Craig (separate router step vs merged into the inbox sanity check, transcript scope and trigger, reconciling with the defer-and-stage router). Five implementation phases, acceptance criteria, readiness dimensions.
Status stays draft while decisions are open. The todo task moves to DOING and links the spec.
From the archsetup handoff 2026-06-13.
| -rw-r--r-- | docs/design/wrapup-routing-spec.org | 177 | ||||
| -rw-r--r-- | todo.org | 14 |
2 files changed, 180 insertions, 11 deletions
diff --git a/docs/design/wrapup-routing-spec.org b/docs/design/wrapup-routing-spec.org new file mode 100644 index 0000000..396fb45 --- /dev/null +++ b/docs/design/wrapup-routing-spec.org @@ -0,0 +1,177 @@ +#+TITLE: Wrap-Up Inbox/Transcript Routing — Spec +#+AUTHOR: Craig Jennings +#+DATE: 2026-06-13 +#+TODO: TODO | DONE SUPERSEDED CANCELLED + +* Metadata +| Status | draft | +|----------+-----------------------------------------------------| +| Owner | Craig Jennings | +|----------+-----------------------------------------------------| +| Reviewer | Codex (spec-review) | +|----------+-----------------------------------------------------| +| Related | [[file:../../todo.org][todo.org: wrap-up routing task]] · [[file:2026-06-13-wrapup-inbox-transcript-routing-proposal.org][archsetup proposal]] | +|----------+-----------------------------------------------------| + +* Summary + +At wrap-up, an inbox handoff that belongs to another project has nowhere to go but the current project's =todo.org= or a deferral. This adds an optional routing step to =wrap-it-up.org=: surface the items that belong elsewhere, recommend a destination project for each, and move the whole batch there on one confirmation. A parallel step files meeting-transcript recordings into the right project's =assets/=. + +* Problem / Context + +=process-inbox.org= dispositions each handoff as act / fold / file / reject, and "file as TODO" lands the task in the *current* project's =todo.org=. When the real home is a different project, the choices today are: file it locally and let it rot in the wrong tracker, hand-edit two projects' =todo.org= files, or defer it and carry the debt to next session. + +The wrap-up's existing Step 3 "Inbox sanity check" only counts unprocessed items and blocks the wrap until they clear. It answers "is the inbox clean?" — it doesn't route anything. + +Meeting transcripts have the same homelessness: a recording dropped during a session belongs in some project's =assets/=, but nothing moves it there at wrap. + +The friction is small per-item but recurring, and the manual cross-project edit is error-prone (two files, two repos, easy to leave one half-done). + +* Goals and Non-Goals + +** Goals +- At wrap-up, surface inbox items (and transcripts) whose home is a different project, with a recommended destination each. +- Move the whole batch on one confirmation ("go with recommendations") or leave it entirely ("skip"). No per-item triage. +- Move a task/event item as a proper org task into the destination's "Open Work" section per =todo-format.md=; move a transcript as a flat-filed artifact per =working-files.md=. +- Keep the move atomic and visible (it shows in the destination's next git diff, with a provenance note). +- Discover any project with a =todo.org= as a candidate destination, not only =.ai/= projects. + +** Non-Goals +- Not a wrap gate. A skip is a clean, complete wrap. +- Not per-item triage. The interaction is batch-level: go or skip. +- Not a replacement for =process-inbox.org='s value gate. Routing assumes the item is already an accepted keeper. +- Not a confidence-free auto-mover. A low-confidence destination recommendation says so, and the batch "go" stays trustworthy because the surfaced list is reviewable before the keystroke. + +** Scope tiers +- v1: task/event routing to a destination project's =todo.org=. The interaction, the recommendation engine, the atomic move helper, the widened project discovery. +- Out of scope: per-item destination editing, an interactive correction loop, moving items that aren't accepted keepers. +- vNext: meeting-transcript filing (gated on the unresolved source-location decision and the file-vs-file+extract question — see Decisions). + +* Design + +** 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: + +1. Go with the recommendations — apply every recommended move. +2. Skip — leave the whole batch in place. A skip is a clean wrap. + +That is the entire interaction. No per-item walk. The surfaced list is the review surface; the single keystroke is trustworthy because the list was reviewable and low-confidence recommendations flagged themselves. + +A move of a task/event relocates it into the destination project's "Open Work" section as a proper org task (terse heading, body for detail, tags on the heading line, per =todo-format.md=), and removes it from the source. A skipped or unroutable item stays where it is; the existing sanity check still governs whether the wrap is clean. + +** Implementer (the mechanics) + +*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. + +*The move helper.* A small tool inserts a task subtree under a named project's "Open Work" heading and removes the source atomically — extend =todo-cleanup.el= (it already owns the section matcher and the subtree-move logic for =--archive-done=) or add a sibling =.ai/scripts= tool. Hand-editing across two repos is the error-prone path this replaces. + +*Recommendation engine.* Infer the destination from the item's content — project names, file paths, topic words — matched against the discovered project list. Conservative by design: a weak match is labeled low-confidence so "go" stays a safe single keystroke. The engine is the interesting, uncertain part; it earns the spec. + +*Cross-project write discipline.* Moving an item into project X's =todo.org= writes into X's scope (=cross-project.md=). The batch "go" authorizes it, but the move stays visible (X's next git diff) and leaves a one-line provenance note on the moved task naming the source project. + +* Alternatives Considered + +** Per-item triage instead of batch go/skip +- Good, because it gives precise control over each destination. +- Bad, because it taxes the common case (a batch that's all-correct, or all-stay) with a walk. Craig explicitly asked for two options, not a triage loop. +- Neutral, because per-item correction could return as a vNext refinement if batch-only proves too blunt. + +** 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.) + +** 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 [/] + +** 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. +- Decision: We will reuse =todo-cleanup.el='s =tc--find-section "open work"= matcher, which already handles the unique / missing / ambiguous cases, and skip+surface any destination without a clean Open Work heading. +- Consequences: easier — no new parser, consistent with =--archive-done=. Harder — destinations must carry the "Open Work" heading convention, so a project with a differently-named section is silently unroutable until it conforms. + +** DONE Move atomically through a helper, never hand-edit two repos +- Context: a move touches two files in two repos; a half-done move loses or duplicates a task. +- Decision: We will route every move through one helper (extend =todo-cleanup.el= or a sibling =.ai/scripts= tool) that inserts under the destination's Open Work heading and removes the source as one operation. +- Consequences: easier — no partial-move corruption, one place to test. Harder — a new helper to build and cover with tests before the router can ship. + +** DONE Cross-project writes stay visible and carry provenance +- Context: writing into another project's =todo.org= crosses the =cross-project.md= scope boundary. +- 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. + +** TODO Transcript routing — scope and trigger +- Owner / by-when: Craig / before any transcript work starts. +- 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. + +** 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. + +* Implementation phases + +** Phase 1 — Widened project discovery +A discovery function returning every project with a =todo.org= that has a clean Open Work heading, reusing =tc--find-section=. Unit-tested against fixtures: =.ai/= project, plain-code-repo-with-todo, todo-without-Open-Work (excluded), ambiguous-Open-Work (excluded). Leaves the tree working — nothing calls it yet. + +** 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 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. + +** Phase 5 — Transcript routing (vNext, gated on the transcript decision) +Only after the transcript-scope decision resolves. File a recording into the destination =assets/= per =working-files.md=, batch go/skip mirroring the task router. + +* Acceptance criteria +- [ ] At wrap, an inbox item naming another project is surfaced with that project as the recommended destination. +- [ ] "Go" moves every recommended item into its destination's Open Work section as a valid org task with a provenance line, and removes it from the source. +- [ ] "Skip" leaves every item in place and the wrap completes cleanly. +- [ ] A destination =todo.org= without a clean Open Work heading is surfaced and skipped, never corrupted. +- [ ] A low-confidence recommendation is visibly labeled in the surfaced list. +- [ ] A plain code repo with a =todo.org= (no =.ai/=) is a valid destination. +- [ ] A failed move leaves both source and destination unchanged (no partial move). + +* Readiness dimensions +- Data model & ownership: items are org subtrees; the destination owns the moved task after the move (provenance note records origin). N/A for remote/cached state — all local files. +- Errors, empty states & failure: missing/ambiguous Open Work heading → skip+surface; failed move → atomic no-op; empty routable set → router stays silent (no prompt). +- Security & privacy: N/A — local org files, no credentials or external services. +- Observability: the move shows in the destination's git diff plus the provenance line; the surfaced batch list is the pre-move view. +- Performance & scale: bounded by inbox size (single digits) and project count (tens); no hot path. +- Reuse & lost opportunities: reuses =tc--find-section= and todo-cleanup's subtree-move; widens existing discovery rather than adding a parallel one. +- Architecture fit & weak points: the recommendation engine is the weak point (a wrong-confident destination is the worst failure) — mitigated by the confidence label and reviewable batch list. +- Config surface: possibly a discovery-root list (defaults to =~/projects/=, =~/code/=, matching =inbox-send.py=). Name it if it needs to be user-visible. +- Documentation plan: =wrap-it-up.org= step prose; a note in =cross-project.md= that the router is a sanctioned cross-project write path. +- Dev tooling: ERT for the elisp helper + discovery; the existing =make test= picks up new test files by glob. +- Rollout, compatibility & rollback: additive workflow step; rollback is removing the sub-step. No persisted-data migration. +- External APIs & deps: none. + +* Risks, Rabbit Holes, and Drawbacks +- *Recommendation accuracy is the rabbit hole.* A confidently-wrong destination silently files a task in the wrong project. Dodge: keep the engine conservative, label low confidence, and keep the batch list reviewable before the keystroke. Don't chase a clever inference model in v1. +- *Two inbox-touching steps* (sanity check + router) risk reading as redundant. Dodge: the D1 decision states the gate-vs-optional split in the workflow prose. +- *Scope creep into transcripts* before the source-location question is answered would stall v1. Dodge: transcripts are explicitly vNext behind decision D4. + +* Review and iteration history + +** 2026-06-13 Sat @ 01:23:13 -0500 — Claude Code (rulesets) — author +- 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. @@ -34,22 +34,14 @@ Tags are assigned and refreshed by =task-audit=; =task-review= keeps them honest * Rulesets Open Work -** TODO [#B] Wrap-up inbox/transcript routing to destination projects :feature:spec: +** DOING [#B] Wrap-up inbox/transcript routing to destination projects :feature:spec: :PROPERTIES: :CREATED: [2026-06-13 Sat] :LAST_REVIEWED: 2026-06-13 :END: -Add a routing step to =wrap-it-up.org=: when outstanding inbox items remain, surface them, recommend a destination project for each, and offer a batch-level "go with recommendations / skip" (not per-item, not a wrap gate). Task/event items move into the destination's =todo.org= "Open Work" section per =todo-format.md=; a parallel step files meeting transcripts into =assets/= per =working-files.md=. +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. -Spec-bound, not implement-now — clears the spec-create Phase 0 bar (>6h, real design uncertainty, cross-cutting, hard to reverse). Run =spec-create= first. Design questions the spec must settle: -- Reconcile with this session's defer-and-stage router in =process-inbox.org= (the Skeptical Review's VERIFY path) — two "move inbox items to todo.org" mechanisms shouldn't compete. -- Merge into the existing wrap-up "Inbox sanity check" step or stay a separate optional router (archsetup leans separate: one gates, one is optional). -- Transcript half has an unresolved dependency (where recordings accumulate) and an open question (extract action items into todo.org, or file the artifact only and let the task-router handle items). Consider splitting transcript work to vNext. -- Recommendation engine: infer destination from item content against discovered projects; low-confidence recs must flag themselves so the single keystroke stays trustworthy. -- Widen project discovery from "=.ai/protocols.org= present" to "has =todo.org= with an Open Work heading" (reuse =todo-cleanup.el='s =--archive-done= matcher); a plain code repo with a =todo.org= is a valid destination. -- Cross-project write discipline (=cross-project.md=): the batch "go" authorizes the write into another project's scope, but the move stays visible and leaves a provenance note. Likely needs an atomic cross-project move helper (extend =todo-cleanup.el= or a new =.ai/scripts= tool). - -Source: archsetup handoff 2026-06-13 (=inbox/2026-06-13-0021-from-archsetup-wrapup-inbox-routing-request.org=, moved to =docs/design/= on filing). No archsetup-side work; entirely a rulesets workflow change. +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. ** TODO [#B] Helper-instance support — concurrent same-project Claude :feature:spec: :PROPERTIES: |
