diff options
| -rw-r--r-- | .ai/notes.org | 2 | ||||
| -rw-r--r-- | todo.org | 232 |
2 files changed, 233 insertions, 1 deletions
diff --git a/.ai/notes.org b/.ai/notes.org index b6c85f8..be6708c 100644 --- a/.ai/notes.org +++ b/.ai/notes.org @@ -85,6 +85,6 @@ Format: Markers maintained by workflows to record when they last ran. Read by other workflows that gate their behavior on freshness. :LAST_AUDIT: 2026-07-20 (open set current — this session's shipped work (working/temp, triage-source-activation, silent-until-signal, suspend detach) closed as it went; sentry cluster consolidated (merged the /schedule tasks, added cross-host-coordination); nothing shipped-but-open per git reconcile. Live finding: the Polyglot + Subprojects scouting tasks are SCHEDULED 2026-07-20 and due.) -:LAST_INBOX_PROCESS: 2026-07-31 (four work handoffs: standup-scripts proposal accepted with four changes and shipped as a212eeb; voice pattern #48 filed [#B], then its interaction.md mirror folded in on Craig's approval; a correction FYI acknowledged — my project-workflows fork claim was wrong, Phase 11 composes rather than shadows) +:LAST_INBOX_PROCESS: 2026-08-04 (ten handoffs, batch-approved: four implemented — signature paths, lint-org anchor scope, gmail pagination floor, telega 404 callback; two folded — work's link sweep as independent confirmation, KB orphans 42 → 113; four filed — [#B] teardown live-sibling gate, [#B] agent-scoped anchor default, [#C] install-lang track-mode ignores, [#C] hook message names a step not a command; all four senders replied to) Format: one =:MARKER: YYYY-MM-DD= line per workflow. Workflows overwrite their own marker on completion. @@ -179,6 +179,201 @@ The gate already exists and is nearly right. =scripts/lint.sh='s =check_md_links Found by the adversarial reviewer on the =references/= fix, 2026-07-28, as the sibling class the original report missed. +*** 2026-08-04 Tue @ 09:51:13 -0500 Independently confirmed by work's link sweep +Work swept all 533 tracked org files in their project (sentry cycle, 2026-08-03) +and landed on the same defect from the opposite direction — a consuming project +finding the dead targets rather than rulesets predicting them. Their table +matches this task site for site: task-review ×3 plus one to =docs/design/=, +task-audit ×1, open-tasks ×1, suspend ×1. + +Two things the confirmation adds. They checked =inbox.org=:97's +=[[file:working/<slug>/proposed.diff]]= and correctly excluded it — that one is +a template placeholder inside an example block, so the fix must not sweep it up. +And they independently proposed the same fix direction I'd filed, plus an +absolute =~/code/rulesets/...= target as an alternative to prose. I'd still +prefer prose: an absolute path resolves in both trees but bakes a machine layout +into a file that ships everywhere. + +Nothing to change in the plan; this raises confidence that the seven sites are +the whole set. + +** TODO [#B] Teardown has no live-sibling gate :bug: +:PROPERTIES: +:LAST_REVIEWED: 2026-08-04 +:END: +Wrap-up's teardown mode kills the =aiv-<project>= tmux session without checking +whether another agent is living in it. Archsetup hit this on 2026-08-04: two +primaries in one project, two windows in one tmux session, and teardown would +have taken both. They caught it by reading the pane layout before dropping the +sentinel and aborted the wrap by hand. + +Shutdown mode already has exactly this guard — it gates on +=cj/ai-term-live-count= and =wrap-it-up.org= calls that gate "the load-bearing +safety of the whole feature." Teardown, twenty lines away, has nothing. Verified +in the canonical: Step 6's teardown branch drops =/tmp/ai-wrap-teardown-<project>= +unconditionally. + +Grading: Critical severity (kills another agent's live session and its +in-progress work — the anchor survives, but anything unwritten does not) × +rare edge case (needs two primaries in one project) = P2 = =[#B]=. + +Fix direction, and archsetup's own suggestion is the better one: gate on the +pane count of *this* project's session (=tmux list-panes -t aiv-<project>=) +rather than reusing the machine-wide =cj/ai-term-live-count=. Live-count is +global, so reusing it would abort a legitimate teardown whenever any unrelated +project had a session up. The narrow check also keeps the fix inside rulesets — +no =.emacs.d= handoff needed, unlike anything routed through =ai-term.el=. + +Add the check in both places, because the window between them is real: at +sentinel-drop (where the decision is made and can be reported in the +valediction) and again in the hook before it consumes the sentinel (a sibling +can arrive in between). The hook already re-verifies the clean-tree certificate, +so it has the shape for a second gate. + +Not =:solo:= — the verification that matters is a live two-session drill in +Craig's terminal, and a fix that passes bats while still killing a real sibling +is exactly the failure mode here. + +Source: inbox/2026-08-04-0023-from-archsetup-addendum-to-today-s-agent-anchor.org + +** TODO [#B] Agent-scoped session anchor as the default :spec: +:PROPERTIES: +:LAST_REVIEWED: 2026-08-04 +:END: +Archsetup proposes that =.ai/session-context.d/<id>.org= become the path +always, rather than the =AI_AGENT_ID=-set special case. Their argument is that +the unset case is also the common case: every agent wants an anchor that is +its own, and the single-agent situation is just the one with no contention yet. +Defaulting to the directory removes the race by construction. + +The collision that prompted it was real. Two archsetup sessions both resolved +to =.ai/session-context.org= and interleaved their logs; nothing was lost, but +only because the second one noticed and appended rather than writing. At wrap +they had to hand-split the file to avoid archiving the sibling's in-progress +record along with their own. + +The obstacle is protocols.org's invariant: =session-context-path= is called +many times per session and must return the same path every time, so it must +never mint an id itself. Archsetup lists three ways out — derive from something +already stable, let the resolver mint once and persist, or make every launcher +set =AI_AGENT_ID= — and leans on the third. I don't think the third can work: +a bare =claude= is always available, protocols.org already concedes it runs +full primary startup regardless, and their own collision was two bare +invocations. + +There's a fourth option they didn't list, and I think it beats all three: +=$TMUX_PANE= is exported into the agent's Bash environment and is stable across +calls (measured =%19= on two separate invocations, 2026-08-04). A resolver that +falls back to the pane id when =AI_AGENT_ID= is unset stays a *pure function of +the environment* — no minting, no state file, no clearing rule — which is +exactly the invariant the three listed options each have to bargain with. + +What to check before committing to it: pane ids are unique per tmux server but +reset when the server restarts, so the collision moves rather than vanishing +(narrower, since an old anchor is archived at wrap). And an agent outside tmux +has no =$TMUX_PANE= at all, so the fallback needs its own fallback — possibly +the controlling terminal, possibly the current unscoped path. + +Also decide in the same pass: the absence of =.ai/session-context.org= is +currently the signal that the last session wrapped cleanly, and both startup and +wrap-up key on it. Moving to a directory turns that into "is the directory +empty," and both call sites have to change together or a crashed session stops +being detectable. + +Their second proposal — a startup roster check so a bare invocation learns a +sibling is live — is already scoped in the helper-agent task ("Startup +detection-first: the roster check runs before Phase A.0's pulls"), so it belongs +there rather than here. Worth sequencing: the roster check surfaces the +collision, this removes it. + +Source: inbox/2026-08-03-1443-from-archsetup-proposal-from-a-concrete-collision-in.org + +** TODO [#C] install-lang ignores tooling a track-mode project tracks :bug:solo: +:PROPERTIES: +:LAST_REVIEWED: 2026-08-04 +:END: +Every language bundle's =gitignore-add.txt= opens with the same unconditional +block — =.claude/=, =CLAUDE.md=, =githooks/= — which =install-lang.sh= appends +to the target's =.gitignore=. In a track-mode project those three lines assert +the opposite of the project's actual policy. Work hit it installing the python +bundle into a project that tracks both =CLAUDE.md= and =githooks/pre-commit=. + +Verified across the whole set: bash, elisp, go, python and typescript all carry +the identical header block, so this is not python-specific. The build-artifact +entries below it (=*.pyc=, =htmlcov/=, =node_modules/=, =*.elc= …) are correct +unconditionally — only the tooling header is mode-dependent. + +Nothing breaks today, which is why it went unnoticed: git keeps honoring a path +that is already tracked. The failure is latent and quiet — a *new* file added +under =githooks/= goes untracked with no warning, so a hook that should travel +to the other daily driver silently doesn't. And the =.gitignore= now +misrepresents the project's own policy to whoever reads it next. + +Grading: Major severity (a new hook or rules file silently untracked, and +nothing signals it — the change just fails to reach the other machine) × some +users sometimes (a track-mode project installing a language bundle) = P3 = +=[#C]=. + +Fix, specified so it needs no design call: split =gitignore-add.txt= into the +tooling header and the build-artifact body, and append the header only in +gitignore mode. The mode detection already exists — =scripts/sweep-gitignore-tooling.sh= +recognizes both the anchored (=/.ai/=) and unanchored (=.ai/=) ignore styles for +exactly this purpose; reuse its predicate rather than writing a second one that +can disagree with it. Track mode gets the build-artifact body alone, plus a +comment saying why the tooling entries were omitted, so a later install isn't +read as having forgotten them. + +Done when: all five bundles split, the predicate shared with the sweep script +rather than duplicated, bats covering both modes against both ignore styles, and +=make test= green. + +Smaller thing from the same report, worth doing in the same pass: =install-lang= +seeds =coverage-makefile.txt= at the project root unconditionally, so a project +with no suite for those targets gets a stray fragment. Either gate the seed or +say in the file what it's for. + +Source: inbox/2026-08-02-2210-from-work-install-lang-mis-ignores-a-track-mode.org + +** TODO [#C] Stop hook blocks on a step its workflow may not carry :bug:quick:solo: +:PROPERTIES: +:LAST_REVIEWED: 2026-08-04 +:END: +The wrap teardown hook blocked a wrap in website because that project's synced +=wrap-it-up.org= predated the =git-worktree-gate certify= step the hook enforces. +The block message told them to rerun the final wrap verification, which doesn't +point at the fix, so diagnosing it meant reading the hook's source. + +The underlying asymmetry is real: the hook reaches a project as a =~/.claude= +symlink from =make install=, which startup runs unconditionally in Phase A.0, +while the workflow that drives it arrives by the *guarded* rsync in Phase A. The +two halves of one feature can move independently, and nothing signals the skew +until the hook fires. + +Partly overtaken by events, and the report says so honestly without knowing it: +the per-path sync narrowing (=f69dc22=) landed four minutes before that handoff +was written. The specific cause named — one dirty =sentry.org= withholding all +three rsyncs — can't happen now. What survives is the general case: a workflow +withheld for its *own* dirt, or a project branch behind upstream (that guard is +still all-or-nothing), still runs old against a new hook. + +Grading: Minor severity (a blocked wrap with a misdirecting message; the +sentinel survives, running the gate by hand clears it, nothing is lost) × some +users sometimes = P3 = =[#C]=. + +Fix, and take only the first half: make the hook's block message name the +command (=git-worktree-gate certify=) rather than describing a workflow step. +That is correct whatever version of the workflow the project holds, which is +precisely the property the skew breaks — a message that names the *step* is +another thing that can drift, while a message that names the *command* can't. + +The report's second suggestion — startup warns when a rulesets-owned hook is +newer than the project's synced copy of the workflow that drives it — is a +version-skew detector, and a real idea, but it needs a hook-to-workflow mapping +that nothing maintains today. Leaving it here as a note rather than filing it: +if the message fix doesn't stop the class, that's the escalation. + +Source: inbox/2026-07-31-2247-from-website-drift-report-from-website-s-wrap-up.org + ** TODO [#C] start-work Phase 7 still summarizes the old publish flow :chore:solo: :PROPERTIES: :LAST_REVIEWED: 2026-07-28 @@ -484,6 +679,27 @@ Both found 2026-07-23 reading =claude-templates/bin/agent-text= and =scripts/sig Grading: Minor severity for both (one is a latent hang in a tool with a documented fallback, the other a warning on an account nothing currently depends on) x most users, frequently (the stale warning is a standing condition on this host; the hang needs a stall) = P3 = [#C]. ** TODO Manual testing and validation +*** Telegram scan — no spurious 404 after the loadChats callback fix +What we're verifying: passing =#'ignore= to =telega--loadChats= stops the two +=Telega error 404: Not Found= lines each Telegram scan printed into the echo area +and =*Messages*=, without changing what the scan reads. The fix is code-verified +against telega 20260706.2147 but has never been run — it needs a live telega, so +it can't be checked from an agent session. +- Clear the decks so the count is unambiguous. +#+begin_src emacs-lisp +(with-current-buffer "*Messages*" (let ((inhibit-read-only t)) (erase-buffer))) +#+end_src +- Run a Telegram triage scan (the =triage-intake= telegram source). +- Check what the chat table holds and whether the noise reappeared. +#+begin_src emacs-lisp +(list :chats (hash-table-count telega--chats) + :errors (with-current-buffer "*Messages*" + (how-many "Telega error 404" (point-min) (point-max)))) +#+end_src +Expected: =:chats= is populated as before (non-zero, matching what a scan used to +report) and =:errors= is 0. Before the fix this reliably printed two per scan, so +a non-zero count means the callback isn't being consumed and the fix is wrong. + *** Sentry — entry gates fire with Craig present What we're verifying: the interactive entry gates stop for the right states and start the loop only on a clean, green baseline. - On rulesets (ratio), with a clean tree and green suite, say "start sentry hourly". @@ -599,6 +815,22 @@ From the roam inbox (2026-07-11): work in progress in one project shouldn't stop :END: The 2026-07-01 kb-hygiene report listed 42 agent KB nodes with no inbound id: links (of 53 agent nodes; 0 conflicts, no duplicate titles). Orphan-ness alone isn't a defect — agent nodes are found by rg, not only by links — but a periodic pass is worth doing: prune nodes that aged out, merge near-duplicates, add id: links where clusters exist. Regenerate the list with the kb-hygiene script rather than trusting the snapshot. Propose deletions/merges to Craig before applying (auto-cleanup allowed only for :agent:-tagged nodes after approval, per knowledge-base.md). +*** 2026-08-04 Tue @ 09:51:13 -0500 Fresh hygiene report — orphans 42 → 113 +The 2026-08-01 report: 124 agent nodes, 625 total KB org files, 0 conflicts, no +duplicate titles, and 113 orphans. So orphans grew 2.7× in a month while agent +nodes roughly doubled — nearly every node written since 2026-07-01 landed +unlinked. + +That reframes the task. At 42 this was a cleanup backlog; at 113, with the ratio +holding at about nine in ten, the backlog is a symptom and the write path is the +cause. Nodes are being written without =[[id:]]= links to their neighbours, so +pruning the list would leave the same list regrowing. Worth folding into the +pass: does =knowledge-base.md='s write block ask for the links firmly enough, +and would a node-write prompt to name one related node close it at the source? + +Grading unchanged at =[#C]= — orphan-ness still isn't a defect on its own, and +=rg= still finds these nodes. The number is a signal, not a failure. + ** TODO [#B] Helper-agent instance support — concurrent same-project Claude :feature:spec: :PROPERTIES: :CREATED: [2026-06-11 Thu] |
