#+TITLE: Rulesets — Work #+AUTHOR: Craig Jennings #+DATE: 2026-04-19 Tracking TODOs for the rulesets repo that span more than one commit. Project-scoped (not the global =~/org/roam/inbox.org= list). * Rulesets Priority Scheme ** Priority - =[#A]= *Urgent risk or current workflow blocker.* Credential exposure, data loss, destructive behavior, startup breakage, failing tests that block work, or a feature/refactor that unblocks a core daily workflow. =[#A]= requires a =SCHEDULED:= or =DEADLINE:= date — if it can't be dated, it isn't really =[#A]=. - =[#B]= *Important planned work.* Concrete bugs, high-leverage architecture cleanup, brittle load-order or test gaps, dependency failures, or feature work with clear design and expected near-term use. - =[#C]= *Useful but optional.* Low-risk cleanup, ergonomics, smoke tests, investigations with limited current impact, or feature work that would improve the setup but isn't yet a committed workflow. - =[#D]= *Someday or watchlist.* Speculative features, tiny polish, upstream tracking, optimizations without current pain, deferred ideas that shouldn't compete with active maintenance. The scheme is importance-driven with optional urgency lift. Priority signals "does this matter and when," not "how big" — effort lives in the tags. ** Tags Every task carries one *type tag* from this set: - =:feature:= — adds new capability. - =:chore:= — meta or housekeeping (tooling, sync, version bump, mechanical cleanup). - =:spec:= — design document, brainstorm output, or research-backed proposal that precedes implementation. - =:bug:= — fix to incorrect behavior. Optional *effort and autonomy tags* — orthogonal to type, both can apply on the same task: - =:quick:= — likely to take ≤30 minutes from start through verification. - =:solo:= — Claude can complete the work end to end, including verification, without input from Craig. Optional *dependency tags* — cross-project, both plain tags with the which-project detail in the task body (per =todo-format.md=): - =:blocked:= — the task can't advance until another project delivers the work named in its body. =open-tasks.org= pulls =:blocked:= tasks out of the cascade and surfaces them on their own. Distinct from =VERIFY= (which waits on Craig). - =:blocker:= — this task owes work that's blocking another project (named in its body). =open-tasks.org= surfaces =:blocker:= tasks first, since clearing one unblocks the other project. Tags are assigned and refreshed by =task-audit=; =task-review= keeps them honest in passing. * Rulesets Open Work ** TODO [#C] ai launcher hardening — bug hunt + refactor pass :refactor:solo: :PROPERTIES: :CREATED: [2026-07-13 Mon] :LAST_REVIEWED: 2026-07-13 :END: From the roam inbox (2026-07-13): find bugs in =bin/ai= until no more are visible, then refactor until no worthwhile opportunities remain. The launcher gained =--runtime= + =--print-launch= + 6 bats tests today (04c3b29); this pass extends coverage over the legacy paths (multi_mode, sort_windows, git prep, window sorting) and cleans as it goes. The runtime-selection asks from the same capture are tracked on the generic-agent-runtime parent (claude/codex shipped; ollama/qwen pending the model-floor eval); an interactive runtime picker is fair game here if it stays lightweight. ** TODO [#B] Extend ui-prototyping rule with build-to-prototype :feature: :PROPERTIES: :CREATED: [2026-07-11 Sat] :LAST_REVIEWED: 2026-07-13 :END: .emacs.d proposal (2026-07-11, Craig-approved promotion), extending the ui-prototyping rule shipped tonight (=claude-rules/ui-prototyping.md=, 53f6ce6). The base rule covers research → prototypes → iterate → decisions-backed-by-a-prototype, but not the "build to the prototype" half. Add: after prototyping, fold what settled back into the spec and make the *build target* the prototype rather than the original spec text — the built feature should match the prototype, and any deviation is documented in a "Prototype & deviations" addendum section the build keeps current. Wire into four touch points: =brainstorm= Phase 3 (a UI design isn't "accepted" until it's been through the prototype loop; Next Steps say "build to the prototype"), =spec-create= (emit the deviations-addendum section for UI specs), =spec-response= (a UI spec decomposes into a prototype loop first, then build-to-prototype tasks), =start-work= (its verify phase drives the UI end-to-end; the bar becomes "matches the prototype," deviations logged). Worked example: the takuzu Emacs game — colored tiles read as all-black in the real terminal frame (dark faces + GUI-only box cursor), caught by a prototype loop on the first screenshot where build-to-spec would have shipped an unusable board. Multi-asset synced-rule change, so review-gated and needs a focused session; decide brainstorm-vs-lifecycle placement with Craig. Source: =inbox/PROCESSED-2026-07-11-0222-from-.emacs.d-ui-prototype-rule-proposal.org=. ** TODO [#C] Roam-only startup for .ai projects — investigate :spec: :PROPERTIES: :CREATED: [2026-07-11 Sat] :LAST_REVIEWED: 2026-07-13 :END: Open question from the roam inbox (2026-07-11): could the startup sequence for .ai projects use org-roam as the single store instead of local files? Potential gain is near-guaranteed shared information across projects — lessons and proven techniques on a common thread, scannable across similar projects. It would need a way to isolate a project from the rest. Weigh the pros/cons, the risk, and whether it's worth it before any build. Exploratory, no commitment yet. ** TODO [#C] Keep WIP from blocking the template sync gate :feature: :PROPERTIES: :CREATED: [2026-07-11 Sat] :LAST_REVIEWED: 2026-07-13 :END: From the roam inbox (2026-07-11): work in progress in one project shouldn't stop the sync gate. Idea: keep all diffs/changes in a =working/= directory and exclude it (and its subdirectories) from the sync gate. Many projects run at once, so their WIP files need to be grouped. Also add a per-project count of when the gate tripped, tracked as a metric to investigate. Distinct from the 2026-07-02 policy (untracked/gitignored changes already pass — this is about *tracked* WIP under =working/=). Verify how the gate detects dirtiness today before designing. ** TODO [#C] Put install-ai on PATH, launchable as =install-ai= :chore:quick:solo: :PROPERTIES: :CREATED: [2026-07-11 Sat] :LAST_REVIEWED: 2026-07-13 :END: From the roam inbox (2026-07-11): make install-ai launchable as =install-ai= (no =.sh=) from PATH. dotfiles needs a copy that stays in sync with the rulesets canonical — decide whether the startup script-sync already covers it or a dedicated mechanism is needed. ** TODO [#B] Org-table helpers corrupt example blocks :bug:solo: :PROPERTIES: :CREATED: [2026-07-11 Sat] :LAST_REVIEWED: 2026-07-13 :END: =wrap-org-table.el= and =lint-org.el= both scan for =/^\s*|/= lines and rewrite them as org tables without skipping =#+begin_example=/=src=/=quote= regions, so ASCII art using pipe characters gets mangled into bordered tables. Reproduced 2026-07-09 in the work project against an architecture doc with a pipe/=v= flow diagram; a plain indented block became a table with =|---|= rules between every line. Two separable defects: (1) table detection is line-based — both helpers should use =org-element-at-point= / =org-in-block-p= to skip example/src/quote/verse blocks; (2) =lint-org.el= mutates its input on disk with no confirmation — passing five files reformatted all five (one by 1949 lines). A linter must report, not write; put the reformat behind an explicit =--fix= flag. Grading (severity × frequency, per todo-format.md): Critical severity (silent org data loss; recoverable here only because the content was git-staged) × rare-edge-case frequency (fires only when a mixed table+example file is passed to the helper) = P2 = [#B]. Regression test: run =wrap-org-table.el= against a file containing a =#+begin_example= block whose lines start with =|= and assert the block is byte-identical afterward. Source: work handoff 2026-07-09 (=inbox/2026-07-09-1341-from-work-bug-data-loss-wrap-org-table-el-and.org=). ** TODO [#B] Document (and own) the Signal pager :feature:spec: :PROPERTIES: :CREATED: [2026-07-11 Sat] :LAST_REVIEWED: 2026-07-13 :END: home retired the ntfy phone-notification channel (phone-notify/phone-recv, self-hosted ntfy on ratio) on 2026-07-04 in favor of paging over Signal, and tore ntfy down. The Signal pager it replaced ntfy with is undocumented: no pager script in =~/.local/bin=, and =notify= doesn't reference Signal. What exists on ratio: signal-cli 0.14.5, account 404211. Deliverable: a documented Signal pager (send + read-replies), the signal-cli setup/account notes, and the sync path — the Signal equivalent of the retired ntfy runbook. Cross-machine tooling, so canonical home + docs belong in rulesets. RECONCILE FIRST: =protocols.org= "Paging Craig" already documents an agent-paging path via the *signal-mcp* tool (=send_message_to_user=, pager account +15045173983, Craig's UUID =b1b5601e-…=, verified 2026-06-30). home's handoff is about a *different* mechanism (signal-cli / account 404211, home's own paging). Decide whether these are one channel or two, and whether the signal-cli side needs its own runbook or should route through signal-mcp. Source: home handoff 2026-07-04 (=inbox/2026-07-04-1302-from-home-task-for-rulesets-document-and-decide.org=). Successor to the 2026-06-17 two-way-comms proposal. *** 2026-07-13 Mon @ 05:16:37 -0500 Folded home's ownership ack + current-state report into the reconcile scope home confirmed (2026-07-11 reply) rulesets owns this task and the two-paths reconciliation is the right first step. New facts for the reconcile: from a home session on 2026-07-09, signal-mcp was NOT connected, and the local signal-cli is registered as Craig's own number — =send --note-to-self= returns a message id but produces no phone push. So home currently has no working ad-hoc page channel at all; whatever the runbook lands on must give home a live path. *** 2026-07-13 Mon @ 14:40:00 -0500 Added runtime-portability as a second motivation (Craig approved) The MCP portability inventory ([[file:docs/design/2026-07-13-runtime-portability-inventories.org]]) found signal-mcp exists only claude.ai-side — no local config anywhere — so a non-Claude agent (Codex-style or local LLM) has no paging path at all. The signal-cli runbook this task produces is therefore also the runtime-neutral page channel, not just home's replacement for ntfy. *** 2026-07-13 Mon @ 18:30:19 -0500 agent-page shipped — every project now knows both channels Craig's call: make paging universal and rename it the agent pager. NEW =claude-templates/bin/agent-page= (runs signal-cli directly on velox, ssh-relays from anywhere else, desktop-fallback hint on failure; 4 bats tests; live-verified from ratio through the real script). protocols.org "Paging Craig" rewritten around the two channels (notify desktop + agent-page phone; signal-mcp demoted to a velox-local nicety); page-me.org gained the phone section + fire-both guidance; work-the-backlog's end-of-set page names both surfaces; INDEX updated. Every project inherits via the startup sync + make install. Remaining here: the runbook proper, the receive timer, ssh-only vs linked-device. *** 2026-07-13 Mon @ 18:13:07 -0500 RECONCILED — one channel, on velox; live page verified end to end The two-paths question is answered: there is ONE pager identity, +15045173983, registered in velox's signal-cli (account file 465310) — and signal-mcp is a locally-configured MCP server in velox's global ~/.claude.json (not claude.ai-side as the 14:40 entry inferred; it's just invisible from ratio, which is why home and this session couldn't find it). ratio's signal-cli holds only Craig's personal number (note-to-self, no push). Verified live today: =ssh velox 'signal-cli -a +15045173983 send -m … b1b5601e-6126-47f8-afaa-0a59f5188fde'= buzzed Craig's phone — his remembered CLI page was this same account on velox. Reliability findings for the runbook: both accounts throw receive-staleness warnings (velox 40 days, ratio 26; the signal protocol wants regular receives — a systemd receive timer on velox is the roam-sync-shaped fix), and the channel requires velox to be up. Remaining deliverables sharpened: the runbook (send + read-replies + receive timer + account notes); decide ssh-over-tailnet-only vs registering ratio as a linked device of the pager account; update protocols.org "Paging Craig" (it names signal-mcp as the only supported path — true only on velox; the ssh recipe is the cross-machine path) — shared-asset edit, own review pass. Interim recipe sent to home so it's unblocked today. ** TODO [#C] KB orphan-node review pass :chore: :PROPERTIES: :CREATED: [2026-07-01 Wed] :LAST_REVIEWED: 2026-07-13 :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). ** TODO [#B] Helper-agent instance support — concurrent same-project Claude :feature:spec: :PROPERTIES: :CREATED: [2026-06-11 Thu] :LAST_REVIEWED: 2026-07-13 :END: SPEC REVIEWED 2026-06-12: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org][Codex review]] now rates Phase 1.5 =Ready with caveats=. Before any build, keep the Emacs integration as a cross-project handoff to =~/.emacs.d=, preserve the three-ring gate (bats → sandbox drills → pilot project), and do not let startup/helper changes reach synced template paths until the live drills pass. Implement Phase 1.5 of the generic-agent-runtime spec ([[file:docs/design/2026-05-28-generic-agent-runtime-spec.org][spec]], amended 2026-06-11 with the "Concurrent same-project agents" section). Craig's case: spawn a second Claude in the same project to look things up or update tasks safely while the primary works. The session-context split (AI_AGENT_ID + session-context.d/) already shipped; this builds the rest: - =agent-roster= detection script (the load-bearing piece, replaces operator action entirely): pgrep + /proc cwd match within project root + self-ancestry exclusion; verified live 2026-06-11 with 4 concurrent agents. Bats coverage. - Startup detection-first: the roster check runs before Phase A.0's pulls; not-alone routes to the new =helper-mode.org= role contract and runs nothing else; alone keeps crashed-vs-fresh anchor logic (the roster also disambiguates crashed primary from live primary). - =helper-mode.org= template workflow: identity self-assignment (helper-, recorded in its own .d/ context file), the read/write tiers, light start, helper wrap-up. Auto-routed, no trigger phrase. - =ai --helper= as the deterministic spawn path (Craig's shell-script point: a script can't skip the check): roster → id export → launch with the helper-mode opener; warn-and-run-primary on empty roster. The startup roster check stays as the safety net for raw launches. - Wrap-up ordering: helper wrap-up re-runs the roster — orphaned helper (primary already gone) assumes full closing duties incl. commit+push (the git ban is concurrency-scoped and lifts when alone; otherwise its edits strand as a dirty tree); primary wrap-up with live helpers pauses at the commit and asks (commit helper WIP / wait / leave closing to the helper). - Shared-file read/write contract into protocols.org pointing at helper-mode.org (helper: scoped single-heading org edits only; file-wide passes, inbox processing, and all git mutation stay primary-only); helper branches in startup.org (light path, no pulls/rsync) and wrap-it-up.org (archive own file, skip hygiene + commit). - Bats: launcher id assignment/sanitization, helper-vs-primary resolution, two simultaneous context files. - Data-integrity items (spec second pass, 2026-06-11): live-helper gate before any file-wide hygiene pass (todo-cleanup/lint-org/wrap-org-table check session-context.d/, pause + ask on live files, surface stale ones); todo-cleanup.el brought up to the backup-to-/tmp invariant (lint-org and wrap-org-table already conform — verified); log-before-write journaling for helper shared-file edits; memory writes primary-only (MEMORY.md has no heading anchors — helpers log candidates instead); agent id in helper-originated inbox-send slugs (minute-resolution filenames can collide). - Manual validation with Craig: live helper against a live primary — lookup, one scoped todo.org edit, wrap-up, primary commits the helper's edit cleanly. Then the corruption drill: primary attempts wrap-up while the helper is mid-task and the hygiene gate visibly pauses. Independent of the spec's phases 2-6 (runtime-neutral refactor), which stay gated on their own go/no-go. *** 2026-06-15 progress — detection + contract landed (inert); wiring is what's left RESUME NOTE. Before picking this back up as the big item, re-read what it is, does, and why first — don't dive straight into the next slice. The orientation, in one breath: this lets Craig open a second Claude in the *same project* while a primary session is running (a second terminal, to look something up or make a small task edit) without the two sessions clobbering each other's files. The whole risk it manages is two Edit-tool writers on one shared file (todo.org, notes.org) losing each other's writes, last-write-wins, silently. The design's answer: a singleton primary keeps the unisolated session-context.org; helpers get their own session-context.d/.org, make only scoped single-heading edits to shared files, and never touch git. Full why-and-how in the spec ([[file:docs/design/2026-05-28-generic-agent-runtime-spec.org]], "Concurrent same-project agents" amendment) and the contract ([[file:.ai/workflows/helper-mode.org]]). A helper is NOT a subagent — subagents are for bounded dispatched lookups; this is for interactive parallel work Craig drives himself. Done so far (shipped, pushed, inert until wiring routes to them): - agent-roster (commit f8bdf30): the detection primitive. pgrep -x claude → /proc cwd → keep in-project → drop own ancestry. Exit 0 alone / 1 others / 2 unavailable. Injectable boundary (ROSTER_PGREP/PROC/SELF_PID), 11 bats, live-verified against 4 real sessions. [[file:.ai/scripts/agent-roster]]. - helper-mode.org (commit 0b681dc): the canonical contract — read/write tiers, four data-integrity rules, light startup, helper wrap-up. Triggerless INDEX entry, protocols.org pointer. - Already shipped earlier: the AI_AGENT_ID + session-context.d/ split, and (2026-06-14) the epoch-on-the-tail id convention. What's next — the WIRING, all behind the spec's three-ring gate (bats → sandbox drills → live pilot), none of it sync'd to live template paths until the two-session drill passes: - Startup roster-detection branch: roster runs first; not-alone routes to helper-mode.org, alone keeps crashed-vs-fresh anchor logic. (Edits startup.org — synced, gated.) - wrap-it-up.org helper branch (archive own file, skip hygiene+commit; orphaned-helper lifts the git ban). - ai --helper launcher: roster → assign+export id → launch with helper opener. Plus the Emacs surface (ai-term.el) via an .emacs.d cross-project handoff. - Hygiene-pass live-helper gate: todo-cleanup.el / lint-org.el / wrap-org-table.el check session-context.d/ and pause+ask on live helper files. - todo-cleanup.el backup-to-/tmp backstop (lint-org and wrap-org-table already conform). - Manual validation drills with Craig (the live two-session test + the corruption drill). Stand up a drill rig before the gated work; build against it, don't touch synced paths until the live drill passes. DEPENDENCY QUESTION (Craig, 2026-06-15, resolved 2026-06-24 — see below): doesn't helper-instance support depend on generic agent runtime support? Starting point: the spec frames this work as Phase 1.5, "Independent of the spec's phases 2-6 (runtime-neutral refactor), which stay gated on their own go/no-go," and the body claims it sits only on the already-shipped session-context split. The separate =Generic agent runtime support — Codex spec v0= task (#C, below) is that phases-2-6 arc. So the spec's stated answer is "no, 1.5 is independent" — but confirm that's actually true for every wiring slice (does ai --helper, the roster branch, or helper-mode routing secretly assume any runtime-manifest / multi-runtime machinery from 2-6?), or whether helper-instance should be sequenced after, or merged into, the generic-runtime task. *** 2026-06-24 Wed @ 00:30:32 -0400 RESOLVED — independent, unblocked (keyword VERIFY → TODO) Craig's call (2026-06-24): helper-instance is independent of the generic-runtime refactor and builds on its own. The shipped pieces and the remaining wiring are all shared-file concurrency-safety (two Edit writers, one file), orthogonal to which LLM runtime launches — none of it assumes the runtime-manifest / multi-runtime machinery of phases 2-6. One caveat: =ai --helper= overlaps the launcher refactor the generic-runtime arc plans, so keep that launcher change small and contained so the later refactor doesn't fight it. Now a buildable [#B] task behind its own three-ring gate (bats → sandbox drills → live pilot). ** TODO [#B] Wrap-up routing — manual end-to-end validation :test: :PROPERTIES: :LAST_REVIEWED: 2026-07-13 :END: What we're verifying: a real keeper routes through a live wrap and the destination actually files it. The task-routing build shipped IMPLEMENTED 2026-07-04 (spec [[id:00b47414-2213-4a99-be35-48ceb266fc08][wrapup-routing]]); this confirms it works end to end across a real cross-project wrap. A failed check promotes to a bug. - In a project session, let process-inbox file a handoff whose home is a different project; confirm the local task carries =:ROUTE_CANDIDATE: =. - Run wrap-it-up; at the router sub-step, confirm the candidate is surfaced with the right destination + confidence, then choose "go". - Confirm a =from-= handoff landed in the destination's =inbox/= and the keeper was removed from the local =todo.org=. - Open the destination project; confirm its startup/process-inbox files the handoff into its =todo.org= per its own conventions. Expected: the task ends up in the destination's =todo.org=, gone from the source, with no foreign =todo.org= written directly. Not =:solo:= — needs a real cross-project wrap and the destination's next session. ** TODO [#D] Wrap-up routing — transcript filing (vNext) :feature:no-sync: File a meeting recording into the destination =assets/= per =working-files.md=, batch go/skip mirroring the task router. Gated on the source-location decision (spec D4). Spec: [[id:00b47414-2213-4a99-be35-48ceb266fc08][wrapup-routing-spec.org]] (Phase 5). ** TODO [#C] Multiple agent-source improvements :spec: :PROPERTIES: :CREATED: [2026-06-23 Tue] :LAST_REVIEWED: 2026-07-13 :END: Make the tooling agent-agnostic instead of Claude-specific. Three threads from Craig (roam 2026-06-23): (1) give the agent a name so workflows don't say "Claude" everywhere — a non-Claude agent (Codex) reading "you are Claude" gets confused; evaluate whether naming resolves the confusion or whether other spots also leak Claude-specificity. (2) Pull agent-neutral content out of Anthropic-specific files (=CLAUDE.md=) into a shared source that each agent's own entry file points to, so Codex (which runs more literal) reads the same rules; or link =CLAUDE.md= and the Codex equivalent to one source. Have Codex review the workflows for literal-reading wording gaps. (3) Send =.emacs.d= a note (inbox-send) to let =ai-term= launch Claude / Codex / a local ollama LLM, switchable seamlessly at session start. Spec-shaped — needs design before build. From the roam inbox 2026-06-23 (deferred from the 2026-06-21 session). *** 2026-06-24 Wed @ 00:21:20 -0400 Partial — agent-neutral wording sweep + thread-3 note landed Thread 2's wording half shipped in 6ad0442 (=refactor(rules): use agent-neutral language in shared rules=): agent-as-actor phrasing replaced with "the agent" across interaction.md, cross-project.md, triggers.md, working-files.md. Thread 3's note reached =.emacs.d=, whose 2026-06-23 inbox FYI confirms it received and filed the "multi-LLM support" ai-term handoff. Remaining and still TODO: thread 1 (give the agent a name), and thread 2's structural half (extract agent-neutral content into a shared source with a Codex entry-file pointer, then have Codex review the workflows for literal-reading gaps). *** 2026-07-13 Mon @ 16:04:04 -0500 Thread 2's entry-file half landed via the runtime-portability build The Codex entry-file pointer now exists: =claude-templates/AGENTS.md= (thin pointer at protocols.org + rules + /name resolution), linked to =~/.codex/AGENTS.md= by =make install= and seeded per-project by =install-ai.sh= (see the generic-agent-runtime parent's 2026-07-13 children). Remaining here: thread 1 (agent naming — the entry file's "you are this project's agent" phrasing is a start, not the whole answer) and the Codex literal-reading review of workflows. ** TODO [#C] Flashcard tooling improvements :feature: :PROPERTIES: :CREATED: [2026-06-28 Sun] :LAST_REVIEWED: 2026-07-13 :END: Three flashcard-tooling tasks that all edit =flashcard-to-anki.py= and/or =flashcard-stats.py=, grouped so they get built together instead of colliding on the same files (prior sessions flagged the conflict risk). The Anki =#+TITLE= deck-name fix already landed (commit 060a938), so any preserved pre-fix script copy gets re-derived against the current canonical, never copied wholesale. The three children each ship independently. *** TODO [#C] apkg → org-drill converter :feature:solo: :PROPERTIES: :CREATED: [2026-06-22 Mon] :LAST_REVIEWED: 2026-06-24 :END: Inverse of =flashcard-to-anki.py=: read an Anki =.apkg= (zip → =collection.anki2=/=.anki21= sqlite) and emit an org-drill =.org= in the house canonical shape. Recovers orphaned decks (=deepsat-fundamentals.apkg= has no saved =.org= source) and enables phone→org round-trip. Mapping: deck name → =#+TITLE=; each note → =** :drill:= with Back as body; card tag → =* Section= grouping (best-effort); Back HTML → org (=
= → newlines, unescape entities, strip =
=); fresh =:ID:= UUID per card. Edge cases for tests: multiple decks per apkg, non-basic note types (skip/warn), HTML entities, empty back, media refs, =.anki2= vs =.anki21= schema. Lives beside the flashcard-* family in =claude-templates/.ai/scripts/= (a new file must be built in canonical — downstream =.ai/scripts/= is wiped by startup =--delete=). PEP 723 uv-run, stdlib =zipfile= + =sqlite3= (no genanki for reading). Acceptance: round-trip a known org-drill source through =flashcard-to-anki.py= then back, assert cards match. Build request: [[file:docs/design/2026-06-21-apkg-to-orgdrill-buildreq.org][buildreq]]. Backlog, not urgent. From home 2026-06-21. *** TODO [#C] flashcard-stats refutation / claim-prompt mode :feature: :PROPERTIES: :CREATED: [2026-06-22 Mon] :LAST_REVIEWED: 2026-06-28 :END: A refutation card (heading is a bare false claim, body is the rebuttal) is valid org-drill but trips two BLOCKING =flashcard-stats.py= checks as false positives: non-prompt-heading (a declarative claim has no =?= or imperative verb) and answer-leakage (claim words reappear in the rebuttal). =flashcard-sync='s gate then blocks the whole deck. Design (Craig, 2026-06-28, supersedes the two proposed options): make the exemption *generic*, not refutation-specific — more card kinds like this will come. When the org header declares the relevant info, the gate honors it rather than blocking. So a general file-level header keyword (a card-kind / check-exemption declaration) tells =flashcard-stats.py= which checks not to apply, instead of a hardcoded =#+DECK_KIND: refutation= keyword or a per-card =:claim:= tag. Document the mechanism in =flashcard-review.org= and add tests (a header-declared exemption file passes despite declarative headings + claim/answer overlap). Edits =flashcard-stats.py= — coordinate with the multi-tag reconcile, same file. Proposal: [[file:docs/design/2026-06-21-flashcard-stats-refutation-proposal.org][proposal]] (its two-option fix is superseded by this generic header approach). Backlog. From home 2026-06-21. *** TODO [#C] Reconcile flashcard multi-tag tooling into canonical :chore:quick:solo: :PROPERTIES: :CREATED: [2026-06-20 Sat] :LAST_REVIEWED: 2026-06-24 :END: The work project edited two synced scripts locally as a stopgap (2026-06-17) and asked rulesets to fold them into the canonical so the next sync doesn't revert them. Preserved bundle: [[file:docs/design/2026-06-17-flashcard-multitag-note.md][note]], [[file:docs/design/2026-06-17-flashcard-multitag-to-anki.py][to-anki.py]], [[file:docs/design/2026-06-17-flashcard-multitag-stats.py][stats.py]]. Change: support a second org tag on drill headings (=:fundamental:drill:=) for curated subset decks. =flashcard-to-anki.py= — broaden =CARD_RE= to match a trailing tag block (a heading is a card when =drill= is among its tags), bound the card body by any L1/L2 heading, add =--tag-filter = (emit only cards carrying that tag) and =--guid-salt = (separate GUID space so a subset deck imports non-empty without disturbing the full deck's SRS state). =flashcard-stats.py= — same =CARD_RE=/=HEADING_RE= broadening plus a drill-membership guard. Use the preserved to-anki.py (the 0953 version: dropped an unused =heading_tags()= helper, tightened =CARD_RE= =(.*?)=→=(.+?)= for parity with stats). Apply to both =.ai/scripts/= and =claude-templates/.ai/scripts/=, add a multi-tag bats case to =flashcard-sync.bats= (a =:foo:drill:= heading parses; =--tag-filter foo= returns only those), verify the full deck still parses to 465 and =--tag-filter fundamental= returns 100, then sync-check + make test. Shared-asset change, so review-gated. Note (2026-06-24): the Anki =#+TITLE= deck-name fix landed (commit 060a938) — =default_deck_name= is now =default_deck_name(input_path, org_text)= with a new docstring. The preserved 2026-06-17 =to-anki.py= predates that, so *don't* copy it wholesale (it would revert the title-fix). Re-derive the multi-tag changes against the current canonical =flashcard-to-anki.py= and keep the =#+TITLE= behavior. ** TODO [#C] coverage-summary.el documented as a local-only helper :chore:quick:solo: :PROPERTIES: :CREATED: [2026-06-22 Mon] :LAST_REVIEWED: 2026-07-13 :END: The elisp bundle installs =coverage-summary.el= into =.claude/scripts/=, gitignored in code projects, so CI can't run =make coverage-summary= against it. Decision (Craig, 2026-06-28): keep it in =.claude/scripts/= and document it as a local-only helper — don't ship it to a tracked =scripts/= dir, don't expect CI to run it. Remaining work (docs only, no move): state the local-only status in the script's header comment and wherever =make coverage-summary= is described, so the gitignored install reads as intentional rather than a gap. Note: emacs-wttrin rewrote its copy's header to claim a tracked =scripts/= home, which now contradicts this decision and should be reverted on their side. Surfaced 2026-06-21 during the coverage-summary autoloads bugfix (commit fb86736). ** TODO [#C] Agent-KB / memory-sync — work + unknown-project write refusal :test: :PROPERTIES: :LAST_REVIEWED: 2026-07-13 :END: Residual manual validation from the memory-sync task (closed 2026-07-04, implementation IMPLEMENTED). Two checks need live sessions in other project contexts: - In the work project, a durable-storage request produces no KB write and the refusal report names the fact. - In an unknown project (outside =~/code/=, =~/projects/=, =~/.emacs.d=), the agent refuses or asks rather than guessing. Expected: both refusal checks behave per the spec; any miss promotes to a bug. Not =:solo:= — needs sessions in the work and an unknown project. ** TODO [#C] Token-rotation helper for =@a-bonus/google-docs-mcp= OAuth refresh :feature:quick: :PROPERTIES: :LAST_REVIEWED: 2026-07-13 :END: When a Google refresh token gets revoked (re-grant scopes, removed Connected App, account password reset), recovery is currently manual: run =npx -y @a-bonus/google-docs-mcp= with the right env, follow the URL in a browser, kill the process, base64-encode the new =token.json=, decrypt =secrets.env.gpg=, replace the var, re-encrypt. A small =mcp/refresh-google-docs-token.sh = would chain that into one command. *** Sketch #+begin_src bash # usage: mcp/refresh-google-docs-token.sh personal profile="$1" gpg -d ... | grep -v "GOOGLE_DOCS_${profile^^}_TOKEN_B64" > /tmp/secrets.env.tmp GOOGLE_MCP_PROFILE="$profile" npx -y @a-bonus/google-docs-mcp & xdg-open # wait for ~/.config/google-docs-mcp/$profile/token.json to land kill %1 echo "GOOGLE_DOCS_${profile^^}_TOKEN_B64=$(base64 -w0 ~/.config/google-docs-mcp/$profile/token.json)" >> /tmp/secrets.env.tmp gpg -c --cipher-algo AES256 -o mcp/secrets.env.gpg.new /tmp/secrets.env.tmp mv mcp/secrets.env.gpg.new mcp/secrets.env.gpg rm /tmp/secrets.env.tmp #+end_src The flow tonight worked but took a handful of manual steps. One script collapses it. Decision (Craig, 2026-05-31): *hold until a token rotation is imminent.* The OAuth re-grant is a browser step that can't be triggered without revoking a live token, so the script can't be verified in isolation. Not marked =:solo:= — when a token actually needs rotating, write and verify in one pass (solo at that point). ** TODO [#D] Generic agent runtime support — Codex spec v0 :spec:design: :PROPERTIES: :LAST_REVIEWED: 2026-06-28 :END: Codex drafted a v0 design doc for making rulesets runtime-neutral rather than Claude-Code-specific. Motivating cases: offline operation with a local LLM, and two LLMs running in the same project at the same time without trampling each other's session-context. Spec at [[file:docs/design/2026-05-28-generic-agent-runtime-spec.org]] (moved here from inbox on intake). Immediate correctness issue Codex flagged: the singleton .ai/session-context.org is unsafe under simultaneous agents. Codex recommends starting with Phase 1 only — add AI_AGENT_ID + session-context.d/.org without renaming the rest. Broader refactor proposes runtimes/ adapter manifests, generic install commands, language-bundle split (common/ + runtimes//), launcher refactor, local model service via llama.cpp/ollama. Big surface area, six phases. 2026-06-12 spec review complete: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org][Codex review]] rubric for the whole spec is =Not ready=. Phase 1 is already shipped, and Phase 1.5 is tracked separately as the helper-instance task. Before any phases 2-5 implementation, decide whether to commit to the larger arc and answer the blocker decisions: generic instruction-file strategy, default local runtime/server, first supported local editing CLI, adapter scope, and compatibility behavior for existing =CLAUDE.md= / =.claude/= projects. *** 2026-06-10 Wed @ 14:13:55 -0500 Noted Phase 1 already shipped; narrowed scope to the phases 2-6 decision Phase 1 (the correctness fix) is live: protocols.org documents the AI_AGENT_ID-scoped session-context path (=.ai/session-context.d/.org=) and =.ai/scripts/session-context-path= resolves it. The singleton race Codex flagged is closed. What remains is the spec review plus a go/no-go on the broader runtime-neutral refactor: runtimes/ adapter manifests, generic install commands, language-bundle split, launcher refactor, local model service. *** 2026-06-11 Thu @ 19:26:26 -0500 Spec amended with the helper-instance slice; implementation split out Craig's motivating case (a second Claude in the same project for lookups and safe task updates) was under-specified in v0 — it had identity and message targeting but no spawn mechanics and no write-safety contract for the shared files the session-context split doesn't isolate. Added the "Concurrent same-project agents (helper instances)" section (subagent boundary, identity/spawn via =ai --helper=, the tiered read/write contract, light startup, helper wrap-up) and Phase 1.5 to the migration plan. Implementation filed as its own [#B] task ("Helper-instance support"); this task stays scoped to the phases 2-6 go/no-go. *** 2026-06-12 Fri @ 02:09:10 -0500 Independent spec review complete Codex ran the spec-review workflow. Outcome: the combined spec is =Not ready= because phases 2-5 still require product decisions and current external-runtime/model verification. Phase 1.5 can proceed only as the already-split helper task, with rollout/manual-validation caveats accepted and no accidental template-wide release before sandbox/pilot drills pass. Review file: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org]]. *** 2026-06-12 Fri @ 02:39:38 -0500 Second review after response pass Codex re-ran spec-review after the dispositions were folded in. Outcome by arc: Phase 1.5 helper instances =Ready with caveats=; phases 2-5 remain =Not ready= behind the explicit decisions/reverification gate. No new blocking findings for the helper slice. Review file updated in place: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org]]. *** 2026-07-13 Mon @ 13:26:57 -0500 Gap assessment decomposed into child tasks Craig asked what's left to run ChatGPT or a local LLM as the agent. Assessment: the =.ai/= layer (protocols, workflows, scripts, inbox, todo, session anchors) is already runtime-neutral — plain org + bash, and a Codex session has run in it (2026-06-13). The Claude-bound remainder decomposed into the child tasks below; each overlapping spec-blocker decision is named in its body. The phases 2-5 go/no-go above still gates any big build, but several children are useful standalone. *** 2026-07-13 Mon @ 16:04:04 -0500 Instruction bootstrap built — thin-pointer AGENTS.md, both install paths Craig picked the thin-pointer shape (Decisions: option 1, definitively). Shipped TDD (bats red → green): canonical =claude-templates/AGENTS.md= (you-are-this-project's-agent + read protocols.org + rules locations + the /name resolution rule from the skill-parity finding + degrade-per-fallback, never skip gates); =make install= links it to =~/.codex/AGENTS.md= (new CODEX_DIR stanza, house skip/WARN/link idiom, covered by NEW =scripts/tests/install-agents-entry.bats=, 3 tests); =install-ai.sh= seeds a project-owned copy at bootstrap, never overwriting (+2 tests in install-ai.bats); rulesets root gets a tracked symlink as dogfood. Resolves the spec's "generic instruction-file strategy" blocker. velox picks up the global link automatically — startup Phase A.0 runs =make install= every session. Existing projects get seeded on demand (no auto-sweep in v1). *** 2026-07-13 Mon @ 14:52:38 -0500 Skill parity resolved — one resolution rule, no per-skill matrix Analysis in [[file:docs/design/2026-07-13-runtime-portability-inventories.org]] (Skill and command parity section). All 29 artifacts (11 skills + 18 commands) are markdown bodies; a single resolution sentence in the bootstrap entry file ("a /name reference resolves to the skill/command file — read and follow it") makes the library portable to any file-reading harness. Auto-invocation degrades to by-name invocation (the publish flow already invokes by name), native slash registration is an optional install nicety, flush is explicitly excluded (session-plumbing child owns it). Folds into the instruction-bootstrap child's build. *** 2026-07-13 Mon @ 13:34:17 -0500 Hook parity inventoried — only two hooks carry real porting work Full mapping in [[file:docs/design/2026-07-13-runtime-portability-inventories.org]]. AskUserQuestion deny is moot off Claude (no popup tool to deny); PostToolUse validators survive via the bundles' git pre-commit hooks; clear-resume folds into the session-plumbing child; session-title is cosmetic. Real gaps: PreCompact priority-save (prose downgrade) and Stop wrap-teardown (Codex notify / manual elsewhere) — decisions in the VERIFY below. *** 2026-07-13 Mon @ 23:21:08 -0500 Interactive agent picker — bare =ai= asks which brain first Craig's ask: the fzf flow should offer the LLMs before the projects. Bare =ai= now runs a runtime picker (claude first so Enter-Enter keeps the old muscle memory; codex labeled ChatGPT; one =local:= line per ollama model, live-queried with a 3s timeout — a dead server just drops the local lines), then the familiar annotated project multi-select. =--runtime= / =AI_RUNTIME= skip the pick; single-dir mode unchanged. New =--print-runtimes= test seam; 9/9 launcher bats, suite 441/0. This substantially delivers the "easy lightweight way to change agents / agentically democratic" roam ask — the launcher-hardening task keeps the deeper refactor. *** 2026-07-13 Mon @ 23:04:21 -0500 Local runtime wired — ai --runtime local runs codex --oss over ollama The reserved lane went live the same day: =local= maps to =codex --oss --local-provider=ollama -m $AI_LOCAL_MODEL= (default gpt-oss:120b; qwen3-coder:30b via the env var). Verified end to end: =codex exec --oss --local-provider=ollama -m gpt-oss:120b= returned a correct completion through the local model (~7K tokens). The explicit provider flag avoids config.toml dependence (a root-level =oss_provider= key would also work; appending to the file lands in the last TOML table and silently does nothing — learned live). Dependency check keys on AGENT_BIN (codex) now that AGENT_CMD carries flags. This partially answers the spec's "first supported local editing CLI" blocker: codex-over-ollama is the de-facto v1. The model-floor child's live trial (a takuzu session under =ai --runtime local=) is the next step. *** 2026-07-13 Mon @ 16:39:41 -0500 Launcher runtime flag built — ai --runtime claude|codex Shipped TDD (new =scripts/tests/ai-launcher-runtime.bats=, 6 tests red→green): =--runtime= flag + =AI_RUNTIME= env on =bin/ai=, runtime→CLI mapping (claude default, codex 1:1 — both take the opening line as a positional prompt), runtime-aware dependency check, =local= reserved with a clear not-wired-yet error (pending the model-floor evaluation), and a =--print-launch= mode as the test seam (prints the pane launch command, no tmux/fzf). Kept small per the 2026-06-24 helper-task caveat — dispatch pre-parse only, no launcher restructure. The Emacs-side equivalent (ai-term multi-LLM) remains .emacs.d's June handoff. Live smoke: correct commands for both runtimes against real projects. *** 2026-07-13 Mon @ 17:05:00 -0500 Roam capture folded — the agent-switching ask Two roam items (2026-07-13) asked for lightweight agent selection (claude, qwen, chatgpt, ollama — "agentically democratic"). Partly shipped the same day: =--runtime claude|codex= (04c3b29; codex is the ChatGPT-side CLI). The ollama/qwen choice is the reserved =local= runtime, landing with the model-floor eval below. An interactive runtime picker rides the new launcher-hardening task ([#C] :refactor:solo:, filed from the same capture). *** 2026-07-13 Mon @ 16:41:14 -0500 Session plumbing assessed — no build needed Analysis in [[file:docs/design/2026-07-13-runtime-portability-inventories.org]] (Session plumbing section). session-context-path is runtime-aware by design; the anchor cycle is plain files any agent drives identically; self-inject.sh is harness-agnostic (only its PAYLOAD is Claude-shaped — a codex auto-flush is a payload variant whose second injected line carries the resume instruction itself, no hook needed); session-clear-resume.sh stays Claude-only and the payload variant obsoletes it off Claude. Wire the codex variant the day a codex session wants it. *** 2026-07-13 Mon @ 13:34:17 -0500 Memory story confirmed — KB is already the cross-agent store Details in [[file:docs/design/2026-07-13-runtime-portability-inventories.org]]. Auto-memory stays Claude-owned; non-Claude agents use the org-roam KB + file artifacts (todo/notes/session anchors), all runtime-neutral already. One wording gap: knowledge-base.md's capture-then-promote names harness memory as the capture layer — a one-sentence addition (session log as the capture layer for agents without harness memory) closes it, pending approval in the VERIFY below. *** 2026-07-13 Mon @ 13:34:17 -0500 MCP portability checked — portable except paging Details in [[file:docs/design/2026-07-13-runtime-portability-inventories.org]]. Nine locally-configured servers (linear, notion, figma, slack-deepsat, google-calendar, google-docs x2, drawio, google-keep) port mechanically to any MCP-speaking harness. claude.ai-managed connectors (Gmail + claude.ai Calendar/Drive) don't travel but are redundant with local servers / cmail-action. The real finding: signal-mcp is NOT locally configured anywhere — the protocols.org paging path is claude.ai-side only, so off Claude there is no page channel. The Signal-pager [#C] task's signal-cli runbook is the fix; add runtime-portability as motivation there (VERIFY below). *** 2026-07-13 Mon @ 14:40:00 -0500 Four inventory decisions — Craig approved all four Recorded in [[file:docs/design/2026-07-13-runtime-portability-inventories.org][the inventories doc]]: prose-only PreCompact downgrade off Claude; Stop-teardown via Codex notify where available, manual elsewhere; runtime-portability note added to the Signal-pager task; capture-layer sentence added to knowledge-base.md (non-Claude runtimes capture into the session log and promote from there). *** TODO Local model floor evaluation The workflows assume long-context instruction-following (startup's multi-file read; the commits.md publish chain). Establish the minimum viable local tier (likely strong-70B+/MoE, 100k+ context), and what compensations a weaker model needs: shortened protocols, more checklist gates, more hook-level enforcement. Feeds the spec's "default local runtime/server" and "first supported local editing CLI" blocker decisions. Environment inventory done 2026-07-13 (KB node "Local LLM inference inventory — daily drivers"): ratio is the inference box — Strix Halo iGPU + 125 GiB unified RAM. velox is out of scope (Iris Xe, 60 GiB, no ollama). Environment BUILT and verified, evening of 2026-07-13: ollama 0.31.2 as a systemd service, Vulkan/RADV backend forced via systemd override (ROCm loaded a 61 GB model at <25 MB/s — 40+ min, unusable; Vulkan loads it in 44 s), models swapped to the MoE shape this platform wants: gpt-oss:120b (44 s load, 37.9 tok/s, 100% GPU) and qwen3-coder:30b (5 s load, 76 tok/s). All four legacy dense models dropped; the orphaned ~/.ollama user store purged. Gotcha for the eval harness: pass num_ctx 8-32K — gpt-oss's native 128K default balloons the load. Remaining work is now purely the evaluation: drive a scripted startup read + a publish-flow transcript through gpt-oss:120b (and qwen3-coder as the fast comparator), grade instruction-following against the protocol stack, and answer the spec's default-local-runtime + first-supported-CLI blockers. ** TODO [#C] Docs-lifecycle convention — manual validation :test: :PROPERTIES: :LAST_REVIEWED: 2026-07-13 :END: The human-eyes half of the docs-lifecycle acceptance surface. The convention shipped IMPLEMENTED 2026-07-04 (spec [[id:80b0787b-4a60-4c82-8a16-b383d3e3c8f2][docs-lifecycle]]); these checks confirm the human-facing behavior. A failed check promotes to a bug. *** Startup nudge appears and clears What we're verifying: the Phase A probe + Phase C nudge fire exactly once per project. - Open a session in a project with an unsorted docs/design (before its sort) and read the startup output. Expected: one line offering "run spec-sort"; after the pilot stamps :LAST_SPEC_SORT:, the next session shows nothing. *** Moved-spec links click through in Emacs What we're verifying: the pilot's relink pass left todo.org and docs links working for the human reader, not just the residue grep. - After the Phase 3 pilot, open todo.org in Emacs and click three links that point at moved specs (including one from a dated log entry). Expected: each opens the spec at its new docs/specs/ path. ** TODO [#D] Docs lifecycle vNext — org-agenda spec-status view :feature:no-sync: Once specs carry lifecycle TODO keywords under =docs/specs/=, add a custom org-agenda view that lists =DRAFT= / =READY= / =DOING= / terminal specs by status. Deferred from [[id:80b0787b-4a60-4c82-8a16-b383d3e3c8f2][the docs-lifecycle spec]]; not part of v1 because the grep board is sufficient until the status headings exist. ** TODO [#C] Wrap-it-up summary mode — keep or cut :feature: :PROPERTIES: :LAST_REVIEWED: 2026-07-13 :END: From Craig via the roam inbox (2026-07-02, routed by archsetup). Teardown-by-default already shipped (bare "wrap it up" closes the window; "with summary" keeps it). Craig's follow-on: "maybe we cut the summary altogether. help me think through when I'd want a summary and how I would recognize it before confirming and then having it close." Run that think-through with him (brainstorm-shaped, not solo), then adjust wrap-it-up.org's Step 6 + trigger phrases to the outcome. ** TODO [#C] triage-intake.org auto mode — push each sweep to phone (ntfy) :feature:solo: :PROPERTIES: :CREATED: [2026-06-20 Sat] :LAST_REVIEWED: 2026-07-13 :END: The work project (2026-06-18) added a "Push each sweep to Craig's phone (ntfy) — the primary delivery" subsection under "Trigger and delivery" in triage-intake.org auto mode, and asks to fold it into the canonical engine plus re-sync. Preserved bundle: [[file:docs/design/2026-06-18-triage-intake-phone-push-note.org][note]] + [[file:docs/design/2026-06-18-triage-intake-phone-push-workflow.org][edited workflow]]. Auto mode is the away-from-desk / vacation mode, so phone-notify becomes the primary delivery each sweep (fuller end-of-sweep output: per-source deltas, open-PR/Linear state, awaiting-ack list, one-line verdict, timestamp; SCAN FAILED banner on any source failure), plus phone-recv polling each sweep for Craig's replies. Falls back to inline when phone-notify is absent. Transport re-pointed 2026-07-13: ntfy is retired; agent-page (shipped today) is the send channel, so the push half is buildable now — substitute agent-page for phone-notify throughout. The reply-polling half (phone-recv) waits on the Signal-pager runbook's read-replies deliverable. Shared template-workflow change, so review-gated. ** TODO [#D] Fully-unattended scheduled inbox check (/schedule cron pass) :feature: :PROPERTIES: :CREATED: [2026-06-23 Tue] :LAST_REVIEWED: 2026-06-28 :END: vNext from the inbox-consolidation spec. =auto inbox zero= (v1) is the interactive =/loop= recurring check that waits for Craig's yes before executing. A fully-unattended =/schedule= cron pass that fires while Craig is away needs its own contract before it can ship: read-only vs may-mutate =todo.org= / =~/org/roam/inbox.org=, how a find surfaces asynchronously when Craig isn't at the session, how dedup state persists across runs that don't share a session, and what session/auth context a cron run carries. From the inbox-consolidation spec-review (Codex finding 1). See [[id:a7fe2a10-dfa8-4ba3-a11a-e7b1288b7573][spec]]. Update 2026-06-28: the "design after v1 consolidation lands" precondition is cleared — the inbox engine consolidation (24ca58d) and the monitor-inbox 15-min loop (edb545d) both shipped. Now actionable backlog rather than blocked; design the unattended contract when prioritized. ** TODO [#D] Warn-only pre-commit hook for tooling-path enumeration :feature: :PROPERTIES: :CREATED: [2026-06-22 Mon] :END: Optional enforcement teeth for the no-attribution / no-tooling-artifacts tightening landed 2026-06-22 (commit 91217d9), which is documentation-only. A warn-only (not blocking) pre-commit hook could scan the commit subject + body for tooling-path enumeration (=CLAUDE.md=, =.claude/=, =.ai/=, =todo.org=, =notes.org=, =session-context=) and AI-attribution language, with the two exemptions baked in: a commit whose change IS one of those files, and private single-user repos. Must warn, not block — a rigid grep false-positives on legit subject mentions. Deferred: Craig chose docs-only for now. ** TODO [#D] Build =create-documentation= skill for high-quality project/product docs :feature: :PROPERTIES: :LAST_REVIEWED: 2026-06-15 :END: Create a Claude skill named =create-documentation= that can plan, write, refresh, and review software documentation across README files, project docs, developer guides, API docs, operational docs, and generated/published doc sites. This is broader than =arch-document=. =arch-document= should remain the architecture-specific arc42 skill. =create-documentation= should know when to delegate to it for architecture documentation, but its main job is the full documentation system around a product or repo: onboarding, tutorials, how-to guides, reference, explanation, operations, troubleshooting, contribution, release/upgrade, and publication format. *** Why this matters The repo currently has strong skills for architecture, testing, review, debugging, and workflow. It does not have a general documentation skill that: - Chooses the right documentation type for the user need. - Audits existing docs against code and expected user journeys. - Creates a coherent doc map instead of dumping everything into =README.md=. - Writes in a consistent technical style. - Decides source/publish format intentionally (=.md=, =.org=, generated =.html=, OpenAPI, etc.). - Treats docs as a maintained product surface with verification, ownership, navigation, accessibility, and freshness checks. *** Research notes **** Documentation frameworks and best-practice sources - Diataxis separates documentation by reader need: - Tutorials: learning-oriented, take the reader by the hand. - How-to guides: task-oriented, solve a specific real problem. - Reference: information-oriented, accurate and complete lookup material. - Explanation: understanding-oriented, concepts, background, tradeoffs. Source: [[https://diataxis.fr/][Diataxis]] and the official guidance around tutorials/how-to/reference/explanation. - Django explicitly documents this same organization and teaches readers how to navigate it: tutorials for beginners, topic guides for concepts, reference for APIs, how-to guides for recipes. This is a major reason the docs feel navigable despite large scope. Source: [[https://docs.djangoproject.com/en/5.2/][Django documentation]] - Kubernetes separates concepts, tasks, tutorials, and reference. It also has current/previous-version docs, localization, contribution paths, and task-focused landing pages. Its docs are good at answering "what is this?" separately from "how do I do one thing?" Sources: [[https://kubernetes.io/docs/home/][Kubernetes docs home]], [[https://kubernetes.io/docs/tasks/][Kubernetes tasks]], [[https://kubernetes.io/docs/tutorials/][Kubernetes tutorials]] - Write the Docs emphasizes docs that are precursory, participatory, exemplary, consistent, current, discoverable, addressable, cumulative, and comprehensive. Especially important: incorrect docs are worse than missing docs, and examples should cover common use cases without overwhelming the reference. Source: [[https://www.writethedocs.org/guide/writing/docs-principles/][Write the Docs principles]] - Google developer docs guidance emphasizes project-specific style first, clarity and consistency, conversational but not frivolous tone, active voice, second person, descriptive links, global audience, accessibility, sentence case headings, numbered lists for procedures, code font for code, and alt text for images. Sources: [[https://developers.google.com/style/][Google developer documentation style guide]], [[https://developers.google.com/style/highlights][Google style highlights]], [[https://developers.google.com/style/accessibility][Google accessible docs]] - Google's doc best-practices page adds a pragmatic maintenance principle: minimum viable documentation, update docs with code, delete dead docs, prefer good over perfect, tell the story of code, and avoid duplication. Source: [[https://google.github.io/styleguide/docguide/best_practices.html][Google documentation best practices]] - The Good Docs Project is useful as a template source, especially for README, how-to, tutorial, concept, reference, troubleshooting, contributor, and release-note patterns. Do not vendor wholesale; use as prior art. Source: [[https://www.thegooddocsproject.dev/][The Good Docs Project]] **** Praised project docs to analyze and steal from ***** Django Why it works: - It labels the doc types directly and explains when to use each. - It has a beginner path, advanced tutorials, topic guides, API reference, how-to recipes, deployment, security, testing, release notes, and community help in one coherent index. - It is versioned, so readers know which framework version the docs target. - It cross-links introductory material to deeper references without making the first page a wall of every detail. Patterns to use: - Make the top-level docs home a routing page by reader intent. - Put "How these docs are organized" near the top when the doc set is large. - Split concept, task, tutorial, and reference instead of mixing them. - Include "getting help" and "not found?" paths so the docs have an exit ramp. Source: [[https://docs.djangoproject.com/en/5.2/][Django documentation]] ***** Kubernetes Why it works: - It has a large, complex product but maintains separate lanes for Concepts, Tasks, Tutorials, Reference, and Contribute. - Task pages are short sequences for one operation; tutorials are larger goals with several sections. This prevents "one page tries to teach everything." - It exposes version state clearly, including static old versions and current docs. - It supports localization and documentation contribution, which makes the docs a product surface rather than a side artifact. Patterns to use: - For platform or infrastructure docs, include Concepts / Tasks / Tutorials / Reference as first-class folders. - Create version/freshness metadata when docs are tied to released software. - Add doc contribution guidance for projects with external contributors. - Make operational tasks discoverable by category, not just search. Sources: [[https://kubernetes.io/docs/home/][Kubernetes docs home]], [[https://kubernetes.io/docs/tasks/][Kubernetes tasks]] ***** Rust Why it works: - Rust has a "bookshelf" rather than one overloaded manual: The Book, Rust by Example, standard library API reference, Reference, Cargo Guide, Error Index, Rustonomicon, release notes, platform support, policies, etc. - The learning path is honest about audience: "assume programmed before, not in any specific language." - Reference and learning material are separated. Advanced unsafe guidance gets its own book. - Offline docs via =rustup doc= are treated as part of the product. Patterns to use: - For broad ecosystems, create a documentation bookshelf rather than a single mega-doc. - Separate beginner path, examples, formal reference, advanced/unsafe topics, tooling docs, error index, release notes, and policies. - Document assumptions about reader experience. - Consider offline/local docs for CLI/library ecosystems. Source: [[https://doc.rust-lang.org/][Rust documentation]] ***** Stripe API docs Why it works: - The API reference is organized around resources and common cross-cutting concerns: authentication, errors, idempotency, pagination, request IDs, versioning, metadata, connected accounts. - It pairs prose with concrete request/response examples and client-library language selection. - It exposes test-mode vs live-mode distinctions early. - It offers "Copy for LLM" / "View as Markdown", which acknowledges modern consumption patterns without sacrificing normal docs UX. - Its reputation comes from matching developer mental models and making the common path implementable quickly, not just visual polish. Patterns to use: - API docs should be generated from or checked against OpenAPI/JSON schema or source annotations wherever possible. - Keep cross-cutting API behavior near the front, before endpoint lists. - Include runnable examples, auth, errors, pagination, versioning, idempotency, and sandbox/test data. - Consider LLM-friendly exports (=llms.txt=, "view as Markdown", stable anchors), but do not make the docs only for AI. Source: [[https://docs.stripe.com/api][Stripe API Reference]] ***** FastAPI Why it works: - Documentation is part of the framework's value proposition: OpenAPI and JSON Schema drive interactive Swagger UI and ReDoc automatically. - It reduces manual drift for API reference by deriving docs from typed code. - It integrates examples and tutorial-style explanations with standards-based generated reference. Patterns to use: - Prefer generated API reference from code/specs over hand-maintained endpoint tables. - Generated docs need human-written overview, concepts, authentication, examples, and operational guidance around them. - The skill should identify when an OpenAPI/Swagger/ReDoc/Scalar route already exists and improve metadata/schema quality instead of creating duplicate manual docs. Source: [[https://fastapi.tiangolo.com/features/][FastAPI features]] *** Format and presentation decisions **** Default source format: Markdown Use =.md= as the default for shared project documentation when: - The repo is on GitHub/GitLab/Forgejo and readers browse docs in the web UI. - The project already uses MkDocs, Docusaurus, VitePress, Sphinx+MyST, Jekyll, GitHub Pages, or plain README-driven docs. - Contributors are expected to edit docs without Emacs-specific tooling. - The docs need easy static-site publishing. - The content is README, tutorial, how-to, reference, troubleshooting, contributing, release notes, runbooks, or ordinary prose + code blocks. Markdown source works well because it is low-friction, reviewable in diffs, rendered by repository hosts, and supported by documentation site generators. MkDocs is a good reference point: Markdown source, YAML config, built-in dev server, static HTML output, and easy hosting. Source: [[https://www.mkdocs.org/][MkDocs]] **** Use Org when the document is Emacs-native or personal/planning-heavy Use =.org= when: - The user's workflow is explicitly Emacs/org-mode. - The document contains TODO states, schedules, priorities, tags, agenda integration, property drawers, clocking, or personal planning. - The document is an internal strategy/planning artifact such as V2MOM, research notes, meeting notes, task triage, or a living personal operating document. - The output may later be exported, but the source of truth is intended to be edited in org-mode. Do not default team-facing documentation to =.org= unless the team already uses org-mode. Org can export to HTML, but that does not make it the right authoring format for non-Emacs contributors. Sources: [[https://orgmode.org/org.html][Org manual]], [[https://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html][Org publish HTML tutorial]] **** Use HTML as generated/published output, rarely as hand-authored source Use =.html= when: - The deliverable is a published static documentation site. - The document needs interactive widgets, embedded API consoles, custom layout, or generated navigation/search. - The project already publishes docs as a website. - The target audience needs searchable, browsable, linkable pages rather than repo-local files. Prefer generated HTML from Markdown/Org/reStructuredText/AsciiDoc/OpenAPI over hand-authored HTML. Hand-edit HTML only for standalone artifacts, custom landing pages, or cases where the project already treats HTML templates as docs source. **** Consider generated/spec-backed formats Use generated reference when possible: - API reference: OpenAPI/Swagger/ReDoc/Scalar from code/spec. - CLI reference: generated from command parser/help output. - Library API reference: language-native doc tools such as rustdoc, pydoc, TypeDoc, JSDoc, Go doc, Sphinx autodoc, etc. - Config reference: generated from schema, types, or validated defaults. The skill should not duplicate generated reference by hand. It should improve source comments, schema descriptions, examples, front matter, and surrounding guides. **** Presentation requirements Every generated doc set should have: - A docs home or README that routes by reader intent. - Stable headings and anchors for addressability. - Descriptive link text, no "click here." - Search/navigation plan when docs exceed a handful of pages. - Version/freshness metadata when tied to released software. - Ownership/review cadence for docs likely to rot. - Accessible structure: semantic headings, alt text, no image-only info, tables only when appropriate, left-aligned text, readable code blocks. - Copyable commands and code examples. - "What changed?" / release notes / migration path when docs describe a new or changed behavior. - Troubleshooting path for common failures. - Clear prerequisites before procedures. - Verification steps after procedures. - Support/escalation path when the docs do not answer the question. - Optional LLM-friendly surfaces for larger doc sets: =llms.txt=, "copy as Markdown" equivalents, concise page summaries, and stable anchors. *** Proposed skill design **** Skill name and trigger Name: =create-documentation= Trigger when the user asks to: - create documentation, docs, README, guide, manual, runbook, tutorial, quickstart, API docs, CLI docs, troubleshooting docs, contributor docs, architecture-adjacent docs, release notes, upgrade guide, or doc site; - improve, audit, reorganize, or publish existing docs; - decide documentation structure or format for a project. Do not trigger for: - architecture-only arc42 docs when =arch-document= is the direct fit; - ADR creation (=arch-decide=); - design docs before implementation shape is known (=brainstorm= or =arch-design=); - prose polishing only (future writing/humanizer skill); - inline code comments/docstrings only, unless the user asks to create docs from them. **** V1 should be one orchestrating skill, not many separate skills Build v1 as one skill with explicit phases and subcommands rather than a set of separate skills. Rationale: - Documentation tasks often start ambiguous; the first job is classification. - Splitting too early creates command-discovery burden. - A single skill can dispatch to existing specialized skills (=arch-document=, =c4-diagram=, =security-check=, =playwright-js/py= for doc-site verification) without making users choose the internal pipeline. Support discoverable subcommands inside one skill: #+begin_example /create-documentation audit /create-documentation plan /create-documentation write /create-documentation refresh /create-documentation publish /create-documentation review #+end_example The default =/create-documentation = runs audit -> plan -> write -> review, asking for confirmation before broad rewrites. **** Future split if v1 gets too large If the skill grows past a manageable size, split into a discoverable =documentation-*= chain. Names and order: 1. =documentation-audit= — inventory existing docs, code/docs drift, reader journeys, missing doc types, stale/generated docs. 2. =documentation-plan= — choose audiences, doc map, formats, source of truth, publishing path, ownership, and freshness policy. 3. =documentation-write= — write or update the selected docs. 4. =documentation-reference= — generate or improve API/CLI/config/library reference from source/spec. 5. =documentation-publish= — configure MkDocs/Docusaurus/Sphinx/GitHub Pages or equivalent, build static HTML, verify links/search. 6. =documentation-review= — quality gate for accuracy, style, navigation, accessibility, examples, and freshness. Keep =create-documentation= as the orchestrator and user-facing entry point. The chain is discoverable because every helper starts with =documentation-= and the orchestrator prints the next command at each handoff. *** V1 workflow details **** Phase 1: Intake and classification Ask only what is missing from local context: - Who is the reader? New user, evaluator, integrator, maintainer, operator, contributor, auditor, support engineer? - What is the reader trying to do or understand? - Is this for a public project, internal team, personal workflow, regulated audience, or customer-facing product? - Is the output repo-browsed, web-published, printed/exported, or Emacs-native? - Is there existing code, existing docs, an API spec, generated reference, or only a concept? - What is the maintenance expectation? One-off, release-maintained, continuously updated? Classify the work into one or more doc types: - README / landing page. - Quickstart. - Tutorial. - How-to guide. - Concept/explanation. - API reference. - CLI reference. - Configuration reference. - Architecture docs (delegate to =arch-document= if arc42/C4/ADR-driven). - Operations/runbook. - Troubleshooting/FAQ. - Upgrade/migration/release notes. - Contributor/development docs. - Security/compliance docs. - Examples/cookbook. **** Phase 2: Audit existing material Inventory: - =README*=, =docs/=, =doc/=, =site/=, =mkdocs.yml=, =docusaurus.config.*=, =vitepress=, =sphinx=, =docs.rs=, =pkg.go.dev=, OpenAPI specs, generated docs folders, GitHub Pages config, ADRs, architecture docs, examples, scripts, CLI help, package metadata. - Existing doc type coverage: tutorial/how-to/reference/explanation. - Broken links, stale version numbers, commands that no longer exist, screenshots that may be stale, code snippets not exercised, doc/code drift. - Source of truth for generated docs. Flag generated files; do not hand-edit them until source is known. - Reader journey gaps: "new user can install?", "first success path?", "operator can recover?", "contributor can run tests?", "API consumer can authenticate and handle errors?" Use =rg= first. For API/CLI reference, prefer structured sources: OpenAPI/JSON Schema, package metadata, command =--help= output, docstrings, or language-native documentation tooling. **** Phase 3: Documentation plan Write a short plan before broad edits: - Audiences and priority order. - Proposed doc map/tree. - Doc type for each page. - Source format decision: =.md= / =.org= / generated spec / generated HTML. - Publishing target, if any. - Existing docs to preserve, move, merge, or delete. - Generated-reference strategy. - Ownership and freshness policy. - Verification plan. Stop for confirmation when the plan moves or rewrites more than one file. **** Phase 4: Write or update docs Writing rules: - Lead with the reader's goal, not the implementation history. - Put prerequisites before steps. - Use numbered lists for procedures. - Use bullets for non-ordered choices. - Use active voice and second person for instructions. - Keep sentences short and globally readable. - Define acronyms on first use. - Use code font for commands, file names, env vars, API names, and literals. - Use descriptive links. - Prefer examples that cover the common path and one meaningful edge/error path. - Separate examples/tutorials from dense reference. - Avoid stale duplication: link to canonical generated reference instead of copying it. - Include expected output after commands where it helps verification. - Include cleanup/rollback steps when procedures change state. - Include troubleshooting for common failures. - Avoid marketing voice in technical docs. State capability and constraints plainly. - No AI attribution in docs, examples, comments, generated pages, footers, or screenshots. Page skeletons: README / docs home: #+begin_example # ## Start here - New user: - Existing user with a task: - API lookup: - Maintainer/operator: ## Quick example ... ## Documentation map ... ## Support / contributing ... #+end_example Tutorial: #+begin_example # Tutorial: ## What you'll build ## Prerequisites ## Step 1 ... ## Checkpoint ## Step 2 ... ## What you learned ## Next #+end_example How-to: #+begin_example # How to ## When to use this ## Prerequisites ## Steps ## Verify ## Troubleshooting ## Related #+end_example Reference: #+begin_example # reference ## Summary ## Parameters / options / fields ## Behavior ## Errors ## Examples ## Version notes #+end_example Explanation: #+begin_example # ## Problem it solves ## Mental model ## How it fits with related concepts ## Tradeoffs and constraints ## Further reading #+end_example Runbook: #+begin_example # Runbook: ## Scope ## Preconditions ## Normal procedure ## Verification ## Rollback ## Alerts and escalation ## Post-incident notes #+end_example **** Phase 5: Presentation and publishing If docs are repo-local only: - Ensure links render on GitHub/GitLab. - Keep relative links stable. - Add an index if more than 4-5 docs exist. If docs are web-published: - Detect existing generator and follow it. - Prefer project-native tooling over introducing MkDocs/Docusaurus/Sphinx. - If no tooling exists and user wants a site, choose conservatively: - Python/simple repo: MkDocs Material is a pragmatic default. - JS/React ecosystem: Docusaurus or VitePress if already in stack. - Python libraries: Sphinx or MkDocs depending on existing ecosystem. - API docs: ReDoc/Swagger/Scalar from OpenAPI. - Build locally if dependencies exist. - Check links, nav, search, mobile viewport, and accessibility basics. - Do not commit generated =site/= output unless the project already does. **** Phase 6: Verification Verification should match doc type: - Commands in quickstarts/how-tos: run them or mark not run with reason. - Code snippets: compile/run where feasible, or use fenced language and note assumptions. - API docs: validate OpenAPI/spec if tooling exists. - Links: run link checker if configured; otherwise sample-check changed links. - Published site: build docs and inspect output. - Screenshots: verify current UI if included. - Generated docs: regenerate from source and confirm no unexpected diff. Final report must say: - Files created/changed. - Doc types covered. - Format/source-of-truth decisions. - What was verified. - What could not be verified. - Known gaps/follow-ups. *** Relationship to existing skills - =arch-document=: use when the requested docs are specifically architecture docs from brief + ADRs + C4/arc42. =create-documentation= may call it, then wrap the output in a broader docs map. - =c4-analyze= / =c4-diagram=: use for diagrams in architecture or concept docs when visual structure helps. - =brainstorm=: use before =create-documentation= when the product/feature itself is still unclear. - =arch-design= / =arch-decide=: use when documentation reveals missing architectural choices. - =security-check=: use when docs include security guidance, auth, secrets, deployment, or compliance claims. - =playwright-js= / =playwright-py=: use to verify published doc sites, interactive docs, screenshots, and browser-rendered examples. - =codify=: use after a documentation session reveals reusable project-specific documentation rules. *** Quality bar and anti-patterns The skill should reject: - A giant README that mixes tutorial, reference, architecture, and operations. - Duplicating generated API/CLI/config reference by hand. - Unverified commands in quickstarts without a "not run" note. - Screenshots with no alt text or no update path. - Tables used for layout instead of actual tabular data. - "Overview" pages that do not route readers to tasks. - Tutorials that become reference dumps. - How-to guides that explain concepts for pages before giving steps. - Reference pages that hide required options in prose. - Marketing claims without concrete examples. - Docs that mention local private paths, personal tooling, or AI attribution in public artifacts. - Publishing generated HTML as source unless the project explicitly owns HTML docs that way. *** Acceptance criteria for building the skill - [ ] Directory =create-documentation/= with =SKILL.md=. - [ ] Frontmatter description includes positive and negative triggers. - [ ] Skill body includes the V1 phases above. - [ ] Includes a source-format decision table for =.md= / =.org= / =.html= / generated spec/reference. - [ ] Includes doc-type classifier based on Diataxis plus README/runbook/API additions. - [ ] Includes examples/skeletons for README, tutorial, how-to, reference, explanation, runbook, troubleshooting, contributor docs, and API overview. - [ ] Includes audit checklist for existing repos. - [ ] Includes publishing guidance without hardcoding one static-site tool. - [ ] Includes verification checklist and "unable to verify" reporting. - [ ] Cross-references =arch-document=, =brainstorm=, =security-check=, =playwright-js=, =playwright-py=, and =codify=. - [ ] Adds =references/= only if needed; suggested files: - =references/doc-type-decision.md= - =references/style-guide.md= - =references/format-decision.md= - =references/page-skeletons.md= - =references/doc-audit-checklist.md= - [ ] Keep =SKILL.md= concise enough to load; move long skeletons/checklists to references for progressive disclosure. - [ ] Run =./scripts/lint.sh= after adding the skill. *** Open design questions before implementation - Should the user-facing command be exactly =/create-documentation= while internal helper names use =documentation-*=, or should all names share the =create-documentation = form? Recommendation: one skill with subcommands for v1. - Should Markdown be the hard default for team docs? Recommendation: yes, unless the project already uses org/reST/AsciiDoc or the output is personal Emacs-native planning. - Should the skill create a docs site automatically? Recommendation: no. It should propose a site when the doc set exceeds README-scale or when search, versioning, or public publishing is required. Ask before adding tooling. - Should it write docs before code exists? Recommendation: yes for specs, user journeys, and design docs, but route unclear feature/product decisions through =brainstorm= or =arch-design= first. - Should it include LLM-specific docs surfaces? Recommendation: optional for public/library/API docs: =llms.txt= or markdown export is valuable, but normal human navigation remains primary. ** TODO [#D] Build /research-writer — clean-room synthesis for research-backed long-form :feature: :PROPERTIES: :LAST_REVIEWED: 2026-06-15 :END: Gap in current rulesets: between =brainstorm= (idea refinement → design doc) and =arch-document= (arc42 technical docs), there's no skill for research-backed long-form prose — blog posts, essays, white papers, proposals with data backing, article-length content with citations. Craig writes documents across many contexts (defense-contractor work, personal, technical, proposals). The gap is real. *Evaluated 2026-04-19:* ComposioHQ/awesome-claude-skills has a =content-research-writer= skill (540 lines, 14 KB) that attempts this. *Not adopting:* - Parent repo has no LICENSE file — reuse legally ambiguous - Bloated: 540 lines of prose-scaffolding with no tooling - No citation-style enforcement (APA/Chicago/IEEE/MLA) - No source-quality heuristics (primary vs secondary, peer-review, recency) - Fictional example citations in the skill itself (models the hallucination failure mode a citation-focused skill should prevent) - No citation-verification step - Overlaps with =humanizer= at polish with no composition guidance *Patterns worth lifting clean-room (from their better parts):* - Folder convention =~/writing//= with =outline.md=, =research.md=, versioned drafts, =sources/= - Section-by-section feedback loop (outline validated → per-section research validated → per-section draft validated) - Hook alternatives pattern (generate three hook variants with rationale) *Additions for the clean-room version (v1):* - Citation-style selection (APA / Chicago / MLA / IEEE / custom) with style-specific examples and a pick-one step up front - Source-quality heuristics: primary > secondary; peer-reviewed; recency thresholds by domain; publisher reputation; funding transparency - Citation-verification discipline: fetch real sources, never fabricate, mark unverifiable claims with =[citation needed]= rather than inventing - Composition hand-off to =/humanizer= at the polish stage - Classification awareness: if the working directory or context signals defense / regulated territory, flag any sentence that might touch CUI or classified material before emission *Target:* ~150-200 lines, clean-room per blanket policy. *When to build:* wait for a real research-writing task to validate the design against actual document patterns. Building preemptively risks tuning for my guess at Craig's workflow rather than his real one. Triggers that would prompt "let's build it now": - Starting a white paper / proposal that needs citation discipline - Writing a technical blog post with external references - A pattern of hitting the same research-writing friction 3+ times Upstream reference (do not vendor): ComposioHQ/awesome-claude-skills =content-research-writer/SKILL.md=. ** TODO [#D] Revisit =c4-*= rename if a second notation skill ships :chore: :PROPERTIES: :LAST_REVIEWED: 2026-06-15 :END: Current naming keeps =c4-analyze= and =c4-diagram= as-is (framework prefix encodes the notation; "C4" is a discoverable brand). Suite membership is surfaced via the description footer, not the name. If a second notation-specific skill ever lands (=uml-*=, =erd-*=, =arc42-*=), the compound pattern =arch-analyze-= / =arch-diagram-= starts paying off: alphabetical clustering under 'a' amortizes across three+ skills, and the hierarchy becomes regular. At that point, rename all notation skills together in one pass. Trigger: adding skill #2 in the notation family. Don't pre-rename. Candidate future notation skills (not yet in scope — noted for when a real need arrives, not pre-emptively): - *UML* (Unified Modeling Language): OO design notation, 14 diagram types in practice dominated by class / sequence / state / component. Common in DoD / safety-critical / enterprise-architecture contexts. Tooling: PlantUML (text-to-diagram), Mermaid UML, draw.io. Would likely split into =uml-class=, =uml-sequence=, =uml-state= rather than one monolith — different audiences, different inputs. - *ERD* (Entity-Relationship Diagram): database schema modeling — entities, attributes, cardinality. Crow's Foot notation dominates practice; Chen is academic; IDEF1X is DoD-standard. Tooling: dbdiagram.io, Mermaid ERD, PlantUML, ERAlchemy (code-to-ERD for SQL). Natural fit as =erd-analyze= (extract from schema/migrations) and =erd-diagram= (generate from prose/model definitions). - *arc42*: already partially covered by =arch-document= (which emits arc42-structured docs). A standalone =arc42-*= skill would be redundant unless the arc42-specific visualizations need separation. Each answers a different question: - C4 → "What systems exist and how do they talk, at what zoom?" - UML class/sequence → "What does the code look like / what happens when X runs?" - ERD → "What's the database shape?" - arc42 → "What's the full architecture document?" Deferred pending an actual need that's blocked on not having one of these. *** DoD-specific notations (DeepSat context) Defense-contractor work uses a narrower, different notation set than commercial software. Document the trigger conditions and starting point so a future decision to build doesn't have to re-derive the landscape. **** SysML (Systems Modeling Language) UML 2 profile, dominant in DoD systems engineering. Six diagrams account for ~all practical use: - *Block Definition Diagram (BDD)* — structural; like UML class but for system blocks (components, subsystems, hardware). - *Internal Block Diagram (IBD)* — parts within a block and how they connect (flow ports, interfaces). - *Requirement diagram* — unique to SysML; traces requirements to satisfying blocks. Essential in regulated environments. - *Activity diagram* — behavioral flow. - *State machine* — same shape as UML. - *Sequence diagram* — same shape as UML. SysML v1.x is in the field; v2 is emerging but not yet adopted at scale (as of 2026-04). Tooling dominated by Cameo Systems Modeler / MagicDraw and Enterprise Architect. Text-based option: PlantUML + =plantuml-sysml= (git-friendly, growing niche). *Candidate skills*: =sysml-bdd=, =sysml-ibd=, =sysml-requirement=, =sysml-sequence=. Three or more in this cluster triggers the =arch-*-= rename discussion from the parent entry. **** DoDAF / UAF (architecture frameworks) Not notations themselves — frameworks that specify *which* viewpoints a program must deliver. Viewpoints are rendered using UML/SysML diagrams. - *DoDAF (DoD Architecture Framework)* — legacy but still contract-required on many programs. - *UAF (Unified Architecture Framework)* — DoDAF/MODAF successor, SysML-based. Gaining adoption on newer contracts. Common required viewpoints (formal CDRL deliverables or PDR/CDR review packages): - *OV-1* — High-Level Operational Concept Graphic. The "cartoon" showing the system in operational context with icons, arrows, surrounding actors/environment. *Universally asked for — informal or formal.* Starting point for any DoD diagram skill. - *OV-2* — Operational resource flows (nodes and flows). - *OV-5a/b* — Operational activities. - *SV-1* — Systems interfaces. Maps closely to C4 Container. - *SV-2* — Systems resource flows. - *SV-4* — Systems functionality. - *SV-10b* — Systems state transitions. *Informal ask ("send me an architecture diagram") → OV-1 + SV-1 satisfies 90% of the time.* Formal CDRL asks specify the viewpoint set contractually. *C4 gap*: C4 is rare in DoD. C4 System Context ≈ OV-1 in intent but not in visual convention. C4 Container ≈ SV-1. Expect a mapping step or reviewer pushback if delivering C4-shaped artifacts to a DoD audience. *Candidate skills*: =dodaf-ov1=, =dodaf-sv1= first (highest-value); =uaf-viewpoint= if newer contracts require UAF. **** IDEF1X (data modeling) FIPS 184 — federal standard for data modeling. Used in classified DoD data systems, intelligence databases, and anywhere the government specifies the data model. Same shape language as Crow's Foot but with different adornments and notation conventions. *Rule of thumb*: classified DoD data work → IDEF1X; unclassified contractor work → Crow's Foot unless the contract specifies otherwise. *Candidate skills*: =idef1x-diagram= / =idef1x-analyze= (parallel to a future =erd-diagram= / =erd-analyze= pair). **** Tooling baseline - *Cameo Systems Modeler / MagicDraw* (Dassault) — commercial SysML dominant in DoD programs. - *Enterprise Architect (Sparx)* — widely used for UML + SysML + DoDAF. - *Rhapsody (IBM)* — SysML with code generation; strong in avionics / embedded (FACE, ARINC). - *Papyrus (Eclipse)* — open source SysML; free but clunkier. - *PlantUML + plantuml-sysml* — text-based, version-controllable. Fits a git-centric workflow better than any GUI tool. **** Highest-value starting point If DeepSat contracts regularly require architecture deliverables, the highest-ROI first skill is =dodaf-ov1= (or whatever naming convention the rename discussion lands on). OV-1 is the universal currency in briefings, proposals, and reviews; it's the one artifact that shows up in every program regardless of contract specifics. Trigger for building: an actual DoD deliverable that's blocked on not 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. * Rulesets Resolved ** CANCELLED [#C] ntfy phone channel as general two-way agent-comms :feature:spec: CLOSED: [2026-07-13 Mon] :PROPERTIES: :CREATED: [2026-06-20 Sat] :LAST_REVIEWED: 2026-06-24 :END: Killed at the 2026-07-13 task review: home retired and tore down the ntfy channel on 2026-07-04, so this proposal's transport no longer exists. Its living successors are the Signal pager ([#B] task above — one identity on velox, runbook pending) and agent-page (shipped 2026-07-13), which cover the send half; two-way (read-replies) rides the Signal runbook. Proposal from the home project (2026-06-17): promote the self-hosted ntfy-over-Tailscale phone channel it built and verified on ratio into a general two-way agent-comms tool rulesets owns. Full proposal: [[file:docs/design/2026-06-17-ntfy-agent-comms-proposal.org]] (as-built runbook stays in the home project at =working/phone-notifications/spec.org=). What rulesets would decide: canonicalize =phone-notify= (send) plus a new =phone-recv= (check-since) as synced bin scripts; the per-machine config/secret convention (token in =~/.config/phone-notify/config= chmod 600 today, vs GPG-encrypted in dotfiles); a reference =ntfy-inbound-handler= plus systemd user-unit for event-driven delivery (Tier A subscriber routes inbound to inbox/notify, Tier B inbound spawns an agent session, Tier C notify a live session — harness research); approval-button workflows for the commits.md gates when Craig is away from the desk (tap-to-approve, the high-value concrete use); and the relationship to the retired cross-agent-comms scripts (ntfy may be the transport they lacked). Worked via =spec-create=. Blocks the triage-intake phone-push task below.