aboutsummaryrefslogtreecommitdiff
path: root/todo.org
Commit message (Collapse)AuthorAgeFilesLines
* chore(ai): archive session recordCraig Jennings2026-06-021-31/+27
| | | | Promoted the flush workflow into rulesets as a /flush skill plus a canonicalized SessionStart(clear) hook, then ran the four open :solo: tasks: start-work Justify and Approach gate additions, a task-review chain on task-audit, and lint-org follow-ups reconcile-on-write.
* feat(lint-org): reconcile follow-ups on write instead of appendingCraig Jennings2026-06-021-1/+2
| | | | | | | | | | Every run appended a fresh dated "lint-org follow-ups" section with line-number-keyed entries, so the follow-ups file grew an unbounded pile of near-duplicate sections, kept entries whose finding had since resolved, and broke whenever the target file's line numbers shifted. Running an audit against a large todo.org surfaced exactly that drift: dead-link flags pointing at docs that now exist, and three stacked dated runs for one file. Now lint-org rewrites the current file's section from the current run. Findings that no longer reproduce simply are not re-emitted, re-runs dedupe to one section, and entries key on checker plus message with the line as a trailing annotation, so a finding survives line shifts as the same entry. Other files' sections are left intact, and the strip step tolerates the old dated-header shape so existing follow-ups files migrate on first run. This changes the follow-ups file from an append-only log to the current outstanding findings per file. task-audit's Phase C link-hygiene step now also reaps a matching dead-link entry when it fixes or verifies the link, scoped strictly to dead-link entries, so the audit and the follow-ups file stop drifting between lint runs. Five follow-ups tests cover record-by-content, dedupe across runs, drop-on-resolve, and preserve-other-files. Mirrors synced.
* feat(task-audit): chain a task-review pass as the final phaseCraig Jennings2026-06-021-1/+2
| | | | A task audit verified the surviving tasks are factually honest but left their relevance and priority untouched, so keeping the list lean still needed a separate task-review run. Added Phase F: after the audit stamps :LAST_AUDIT:, run task-review on the oldest-unreviewed batch in the same pass. The two stay distinct (audit owns facts and :LAST_AUDIT:, review owns relevance and the per-task :LAST_REVIEWED:); chaining just refreshes both markers in one invocation. open-tasks does not invoke task-review, so nothing there needed to change. Mirror synced.
* feat(start-work): add a spec-prerequisite check to the Approach gateCraig Jennings2026-06-021-1/+2
| | | | The Approach gate planned tests, migration, and commits but never asked whether the work needs a design spec it does not yet have. Added item 5: a spec is warranted for large or wide-surface work, unresolved design questions, or a new interface others build on. For a big task it is never a silent skip — the approach summary must state why no spec is needed, so the call is visible and challengeable at the gate. Small contained tasks pass without comment.
* feat(start-work): add "reasons not to do this" to the Justify gateCraig Jennings2026-06-021-1/+2
| | | | The Justify gate covered Downsides and Alternatives but had no forced verdict on whether the work should happen at all. Added item 9: surface the top three objections when real ones exist, or say so in one line when none rise to a genuine objection, rather than manufacturing three. Building the case against the work is cheapest at this gate.
* chore(todo): tag the autonomous batch :solo:Craig Jennings2026-06-021-3/+3
|
* chore(todo): task-review stamps + :quick: tags on start-work tasksCraig Jennings2026-06-021-5/+17
|
* chore(todo): file start-work Approach-gate spec-check taskCraig Jennings2026-06-021-0/+3
|
* chore(ai): archive session recordCraig Jennings2026-06-021-29/+28
|
* docs: add cross-project pattern catalog specCraig Jennings2026-06-021-0/+3
|
* docs(mcp): note signal-cli + Google Voice dependency for signal-mcpCraig Jennings2026-06-021-2/+3
|
* chore: file lint-followups reconcile and start-work justify-gate tasksCraig Jennings2026-06-021-0/+9
|
* chore: file task for task-review pass at end of task-auditCraig Jennings2026-06-021-49/+52
|
* fix(workflows): commit template-sync churn deterministicallyCraig Jennings2026-05-311-6/+6
| | | | | | | | Phase A's startup rsync copies template updates from rulesets into each project's .ai/, but nothing committed that churn, so it accumulated across sessions and eventually blocked Phase A.0's auto-fast-forward (git won't ff a dirty tree). Two projects hit it the same day. I added a Step 4.0 to wrap-it-up.org that commits the churn as its own chore commit before the session-work commit, guarded so it only auto-commits synced .ai paths matching rulesets canonical byte-for-byte and surfaces anything that doesn't. startup.org Phase C now surfaces leftover churn at session start as the crashed-session safety net. Both skip the rulesets repo, where .ai/ is a committed mirror. I also moved four misplaced PROPERTIES drawers in todo.org (DONE tasks) from after the resolution prose to immediately under the CLOSED line, so org parses them as real drawers.
* chore(ai): archive session record + sweep resolved tasksCraig Jennings2026-05-311-178/+169
| | | | Move the completed solo-batch, rename-tool, and coverage-fan-out tasks into Resolved, and file the lint-org judgment items for the next daily-prep.
* feat(typescript): add coverage-summary to the TypeScript bundleCraig Jennings2026-05-311-2/+11
| | | | | | | | | | Last language in the coverage-summary fan-out, after Elisp, Python, and Go. Same kernel: count every source file on disk that's absent from the coverage report as 0% and weight the project number by file, so an untested file stays visible instead of being averaged away. The script at languages/typescript/claude/scripts/coverage-summary.js parses an Istanbul json-summary report (the coverage-summary.json that c8, Vitest, and Jest all emit), takes per-file statements covered over total, and reports a file-weighted number plus the missing files. It walks the source dir for .ts/.js, skipping test files, declarations, and node_modules. Node built-ins only, so it runs via node with no install, and it doesn't reimplement the per-file table nyc already prints. Tests are black-box, run with node's own test runner: a temp tree plus a json-summary report, the script invoked via node, output asserted. They cover missing-file detection, all-tracked, test-file and node_modules exclusion, and the missing-report error. make test gained a node --test discovery path for languages/*/tests, guarded so environments without Node skip it cleanly. As with Python, the TypeScript bundle had no gitignore-add.txt, which would have left the script un-gitignored on install, so I added one. This finishes the fan-out: coverage-summary now ships in all four bundles, each parsing its own tool's report behind the same file-weighted, missing-as-0% kernel. I proved the Go and TypeScript scripts by running them (Go against a live profile, TS against a synthetic report and the CLI). Python and TypeScript weren't run against a live coverage tool, since neither coverage.py nor nyc is installed here, so the first adopter of each should check against a real report.
* feat(go): add coverage-summary as a Go bundle coverage sliceCraig Jennings2026-05-311-7/+6
| | | | | | | | | | Third language in the coverage-summary fan-out, after Elisp and Python. Same kernel: count every source file on disk that's absent from the coverage profile as 0% and weight the project number by file, so an untested file stays visible instead of being averaged away. The script at languages/go/claude/scripts/coverage-summary.go parses a cover.out profile, maps each import-path-qualified entry back to an on-disk relative path using the module path from go.mod, and reports a file-weighted number plus the missing files. It's standard library only, so it runs anywhere via go run, and it doesn't reimplement the per-function table that go tool cover -func already prints. I proved it against a real go test -coverprofile run, not just a synthetic fixture, since the Go toolchain is installed here. Two findings to flag. Modern go test ./... already lists every module package in the profile at 0% even when untested, so for in-module code the missing-file list is usually empty. The detection earns its keep on build-tagged files and dirs outside ./.... And this is a coverage-only slice of a Go bundle that doesn't otherwise exist yet: there's no go.md rule file, so sync-language-bundle.sh can't fingerprint it (detection keys on a bundle's own .claude/rules). The script installs via make install-lang LANG=go but won't be sync-maintained until the Go bundle gets real rules and a CLAUDE.md. Building that out is the natural companion task. Tests are black-box: a Go test in its own throwaway module runs the script via go run against temp fixtures and checks output, so the shipped script dir stays test-free. They cover missing-file detection, all-tracked, _test.go exclusion, and the missing-report error. make test gained a go test discovery path for languages/*/tests, guarded so environments without Go skip it cleanly.
* feat(python): add coverage-summary to the Python bundleCraig Jennings2026-05-311-6/+7
| | | | | | | | | | Second language in the coverage-summary fan-out, after the Elisp pilot. Same kernel: a module no test imports never appears in coverage.py's report, so a line-weighted total skips it silently and the suite looks healthier than it is. This counts every source file on disk that's absent from the report as 0% and weights the project number by file, so untested modules stay visible. The script at languages/python/claude/scripts/coverage-summary.py parses coverage.py's JSON (files[path].summary.covered_lines / num_statements), resolves report paths against the report's directory since coverage records them relative to where it ran, and recurses the source dir for *.py. Unlike the Elisp version it doesn't print a per-file table, because coverage.py's own coverage report already does. The script adds the missing-file accounting that report lacks. It uses only the standard library, parsing the report rather than importing coverage. The Python run confirmed the plumbing from the pilot is genuinely generic. install-lang and sync deliver the script and the project-owned coverage-makefile.txt with no Python-specific code. The one gap I had to close: the Python bundle shipped without a gitignore-add.txt, so the .claude/ footprint wasn't ignored and the script would have been committable. Added one mirroring the Elisp footprint plus Python artifacts (__pycache__, .coverage, coverage.json). make test gained a languages/*/tests/test_*.py discovery path alongside the existing Elisp ERT one. Tests: 12 pytest covering the parser, the file-weighted number, and the missing-file detection including subpackage recursion, plus an install-lang check that the script lands in the gitignored footprint. I proved it against a report matching coverage.py's documented schema and the CLI end to end, but not against a live coverage json run, because coverage.py isn't installed in this repo's env. The first project to adopt it should sanity-check against a real report.
* feat(elisp): add coverage-summary to the Elisp bundle with missing-file ↵Craig Jennings2026-05-311-1/+17
| | | | | | | | | | | | | | detection A line-weighted coverage total has a blind spot: a module no test loads never shows up in the SimpleCov report, so it can't drag the number down. The suite looks healthier than it is. This adds a summary that counts every source file on disk against the report and treats an absent file as 0%, weighting the project number by file instead of by line so untested modules stay visible. The script ships at languages/elisp/claude/scripts/coverage-summary.el, self-contained on stock Emacs (just the built-in json). It parses the undercover SimpleCov shape directly rather than depending on the editor's coverage engine, so it runs anywhere the bundle lands. I proved it against a real 103-file report: 93 tracked, 27 untested modules surfaced, project number 66.4%. Delivery follows the bundle convention. The script lives under the gitignored .claude/ footprint and gets auto-fixed on drift by sync-language-bundle.sh, which I made generic for any claude/scripts/* rather than coverage-specific. The Makefile targets ship as a project-owned fragment (languages/elisp/coverage-makefile.txt) that install-lang.sh seeds at the project root and sync drops into .ai/inbox/ when that convention exists. The bundle never edits the project's own Makefile. Tests: 12 ERT for the kernel (Normal/Boundary/Error per function), wired into make test via a new languages/*/tests/ discovery path, plus bats for the sync auto-fix and the inbox-drop guards. This is the Elisp pilot. The pattern is proven, so fanning out to Python, Go, and TypeScript is now a follow-up. Each one needs only its own parser and fragment. The plumbing is already generic.
* refactor(workflows): restructure startup and triage-intake into reading lanesCraig Jennings2026-05-311-1/+4
| | | | | | | | | | I split each into lanes so a reader can stop at the level that answers the question: Summary for "what does this do and what does it produce", Execution for the steps to follow, Reference for examples and edge cases, History for old decisions. Both files are large enough that an agent loading them at routing time pays for context it doesn't need yet. startup.org keeps Summary, Execution, and Reference (workflow discovery and common mistakes moved under Reference). triage-intake.org gets all four, including a History lane for its design notes. Every instruction is preserved. The triage reorder ran through a content-preservation check that compared the multiset of content lines before and after, so only heading depth and lane grouping moved. Nothing was dropped or reworded. workflow-integrity.py now counts "Summary" as a valid orientation heading, since that's the new top section both files lead with. This is the pilot from the codex backlog, scoped to the two largest workflows. Whether the lanes actually cut session token use gets evaluated before any wider rollout.
* refactor(daily-prep): delegate triage to the triage-intake engineCraig Jennings2026-05-311-1/+3
| | | | | | daily-prep's Phase 3 re-implemented email/Slack/Linear/PR scanning inline (sub-steps 3b-3g, ~280 lines): the same fan-out, classify, and reactive-task work the triage-intake engine has owned since its 2026-05-26 plugin refactor. I collapsed those to four steps: 3b runs the engine, 3c surfaces today's reactive items as Day's Priorities thin links, 3d re-sorts by urgency, 3e writes the audit footer from the engine's per-source coverage. Source coverage carries because the engine's Phase 0 globs both .ai/workflows/ and .ai/project-workflows/ plugins, so the work account's Gmail/Slack/Linear/GHE plugins are still scanned, and a source change now lives in one plugin instead of being duplicated here. I adapted the downstream references (the Prep-Doc-Structure rule, the Heads-up FYI source, the Recommended Approach Pattern reframed as engine-applied), dropped the orphaned Linear-digest note, and added a Living Document entry. The file goes 825 to 576 lines, and the prep-doc contract (Day's Priorities, Heads-up, Sources-checked footer) is unchanged.
* chore(rules): resolve category-3 deepsat rule copies as left-aloneCraig Jennings2026-05-311-1/+3
| | | | Diffed the testing.md / verification.md copies in the deepsat coding-rulesets and orchestration_dashboard_mvp trees against canonical. Both are byte-identical to each other and stale (testing 221 lines behind, verification 40), with only 5 lines unique to the copies. Left untouched per the standing decision: they're team-owned, and canonicalizing would create a cross-repo dependency on the private rulesets, with the orchestration copy team-visible. Audit-only; no files modified.
* chore(rules): audit language-rule duplication, leave copies project-localCraig Jennings2026-05-311-1/+5
| | | | | | Audited the python-testing / typescript-testing / elisp rule copies across the project mirrors. Four are in sync with canonical; gloss and chime are byte-identical to each other and purely stale (44 + 1 lines behind, with zero project-specific additions). No intentional divergence exists anywhere. Disposition: leave them project-local. The language-rule copies in code projects are the bundle's deliberate copy-and-sync model, and sync-language-bundle.sh auto-fixes drifted bundle rules on each startup, so gloss and chime self-heal on their next boot. Symlinking would fight that model, and the work/deepsat copies stay untouched as team territory. Audit-only; findings recorded in the task.
* feat(aiignore): add .aiignore and the recursive-read conventionCraig Jennings2026-05-311-1/+3
| | | | | | Agents (and any future inventory tool) doing a naive recursive read of a project pick up node_modules, __pycache__, build output, and token artifacts even when those are gitignored, because a recursive read sees the disk, not git. I added a gitignore-syntax .aiignore at the repo root with the default skip list, and a protocols.org "Recursive Reads" subsection documenting the convention, the defaults to assume absent a file, and the lockfile policy (skip on agent reads, independent of git-tracking). I did not wire the walking scripts (audit.sh, diff-lang.sh, sync-language-bundle.sh): they do targeted finds over .ai/.claude/bundle dirs, never whole-tree walks, so honoring .aiignore there would be dead code. That belongs in a future catalog tool.
* feat(scripts): add workflow-integrity checker + testsCraig Jennings2026-05-311-1/+2
| | | | | | Startup's drift check catches index-vs-directory mismatches. This goes deeper: scripts/workflow-integrity.py runs six checks over the canonical .ai/workflows/: each file is indexed-or-a-plugin-of-an-indexed-engine, each index entry resolves to a file, each .ai/scripts/ reference resolves, each plugin maps to an indexed parent, each non-plugin workflow has an orientation section, and no trigger phrase is claimed by two workflows. Exit 1 on any finding. scripts/tests/workflow-integrity.bats covers the clean canonical state plus a fixture per breakage class. make test already globs scripts/tests/*.bats, so it's wired in. I calibrated against the 38 current workflows (clean). The orientation check accepts the real heading variety (Overview / Purpose / When to Use|Run / Status) and exempts plugins.
* chore(todo): tag solo-capable tasks and record their decisionsCraig Jennings2026-05-311-7/+13
| | | | Reviewed the open-task list for solo-ness (whether I can complete a task end to end and verify it without input). Tagged seven :solo: — five that already qualified (workflow test harness, daily-prep delegation, rule-duplication audit, .aiignore, coverage-summary) and two unblocked by a decision today: the category-3 rule copies (leave team-tree copies alone, don't reach into team repos) and the token-tier pilot (approved the four-lane structure for both startup.org and triage-intake.org). The google-docs token-rotation helper stays unmarked, held until a real rotation lets me write and verify in one pass. Each decision is recorded in its task body.
* docs(spec-review): enumerate implementation tasks in Phase 6Craig Jennings2026-05-311-1/+3
| | | | From a pearl handoff: Phase 6 logged deferred and v1 work only in passing, so the implementer handoff was a re-read of the spec rather than a paste. I added a step that lifts the spec's Implementation phases section into a drop-in todo.org block: one [#B] TODO per phase plus a test-surface entry mirroring the Acceptance criteria. A spec with no phase decomposition fails the step, surfacing the shape problem as a finding before Ready rather than inventing phases. Added Exit Criterion 6 and a review-history entry.
* chore(ai): archive session record and resolved tasksCraig Jennings2026-05-311-39/+37
|
* feat(session-context): resolve the active path per AI_AGENT_IDCraig Jennings2026-05-301-1/+3
| | | | | | A single .ai/session-context.org races when two agents share a project: each agent's writes clobber the other's session log. I added .ai/scripts/session-context-path, which resolves the active path from AI_AGENT_ID: unset gives the legacy .ai/session-context.org singleton (so every existing one-agent session is unchanged), set gives .ai/session-context.d/<id>.org with the id sanitized to filename-safe characters. This is Codex's Phase 1 slice from the runtime-neutral spec: the race fix on its own, no broader refactor. startup.org's existence check and wrap-it-up.org's rename now resolve through the helper, each with a singleton fallback so older checkouts that haven't synced the script still work. Wrap folds the agent id into the archive name so two agents wrapping in the same minute don't collide. protocols.org documents the rule. Verified with 5 bats cases and a two-agent simulation showing distinct paths per id.
* fix(startup): skip the .ai/ template sync when rulesets has uncommitted WIPCraig Jennings2026-05-301-1/+3
| | | | | | From jr-estate's handoff: Phase A's =rsync -a --delete= copies the rulesets working tree by disk presence, so a downstream session that starts while rulesets has in-flight WIP pulls that WIP into its own =.ai/workflows/= and =.ai/scripts/=, where it reads as drift the user never authored. I guarded the three rsyncs behind a =git status --porcelain= check on the synced source paths (=claude-templates/.ai/{protocols.org,workflows/,scripts/}=). It syncs when those are clean and skips with a message when dirty, catching up on the next clean session. The check is scoped to those paths, so unrelated rulesets dirt (a stray session-context.org, scratch files) doesn't block the sync. The handoff's secondary anomaly (two workflow files that didn't reach jr-estate) was a timeline artifact, not a Phase A bug. Both were added in 664bf01 on 2026-05-29, after jr-estate's rsync had already run, so they correctly didn't exist to copy yet.
* chore(todo): fix lint findings on todo.orgCraig Jennings2026-05-301-9/+7
| | | | Relocate two LAST_REVIEWED property drawers to sit directly under their headings (and after the CLOSED line on the DONE task) so org reads them as real properties instead of inert body text. Convert the dangling #16 custom-id link to a fuzzy heading link, since the target heading carries no CUSTOM_ID. The two remaining misplaced-heading warnings are verbatim org markup inside prose, so they're false positives and stay as-is.
* chore(intake): file startup-rsync-dirty TODO, stamp :LAST_INBOX_PROCESS:, ↵Craig Jennings2026-05-291-0/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | clear processed inbox The process-inbox workflow walked the four inbox arrivals (one from home, one from jr-estate, two from health): - 2026-05-28-0858 home spec-naming-convention: implemented in bb28cfa. Deleted. - 2026-05-29-0832 jr-estate startup-rsync-carried-dirty: filed as [#B] :feature: TODO under Rulesets Open Work. Three options captured (skip-when-dirty, clean-files-only, clean-ref-based) with my recommendation noted. Deleted. - 2026-05-29-1111 health org-drill-anki initial: superseded by 1114. Deleted without filing. - 2026-05-29-1114 health org-drill-anki updated: implemented in 506ab6e. Deleted. The startup-rsync-dirty TODO also captures an anomaly the jr-estate handoff flagged: even with --delete, two files that DO exist in rulesets canonical (cross-project-broadcast.org, page-signal.org) did NOT propagate. This is likely a timing issue (those files were added after the jr-estate Phase A rsync ran). The anomaly is worth confirming when the TODO is picked up. notes.org Workflow State stamped :LAST_INBOX_PROCESS: 2026-05-29. Inbox now empty.
* docs(todo): file [#C] :spec: TODO to build Craig's writing voice profile ↵Craig Jennings2026-05-291-0/+52
| | | | | | | | | | | | | | | | | | | | | | | | | | from real corpora Files a TODO under Rulesets Open Work to mine Craig's actual writing (sent email across all three accounts, commit messages, PR bodies, org files he authored, slack threads, long-form artifacts) into a grounded voice profile. The voice/SKILL.md patterns today are observation-derived. Some are spot-on. Others are intuition. A corpus pass would tell us which patterns are genuinely Craig's voice, which were guesses, and which Craig-specific positive traits the current ruleset misses entirely. Output: voice/references/voice-profile.org with findings cited to evidence samples, plus a reconciliation pass against voice/SKILL.md to confirm, strengthen, weaken, add, or remove patterns based on what the corpus shows. Approach phased into corpus assembly, analysis (subagent-friendly), draft profile, reconcile-with-user. The body includes a privacy note: raw corpus stays out of commits if the project's remote ever stops being private. There's no urgency. The work is useful but optional, hence [#C].
* docs(todo): schedule Signal MCP server install for 2026-05-29Craig Jennings2026-05-291-112/+132
| | | | | | | | | | | | | | | | | | | | | | | Files a [#B] :feature: TODO under Rulesets Open Work to install rymurr/signal-mcp as an MCP server. The MCP gives Claude native tool access to send_message_to_user, send_message_to_group, and receive_message instead of shelling out to the page-signal wrapper. The differentiator is receive_message. Claude can listen for replies and act on them, enabling page-as-confirm flows and structured Q&A across devices. Dependency: signal-cli has to be registered with the Google Voice number first. Sending from Craig's primary number to itself doesn't notify (Signal treats it as one account on linked devices). The MCP server takes --user-id at startup, one account per instance, so it has to point at the GV account. Implementation touches mcp/servers.json (stdio entry), mcp/README.org (dependency note), and possibly mcp/secrets.env.gpg if any auth material needs encrypting. Verification: make install-mcp followed by make check-mcp shows signal-mcp ok. Smoke-test via a tool call. The task is scheduled for 2026-05-29.
* feat(mcp): add uninstall + --check + README section for MCP pipelineCraig Jennings2026-05-281-2/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | Three coupled additions close the MCP pipeline thread. mcp/install.py grew --uninstall and --check modes via argparse. The default install behavior is unchanged. --uninstall iterates over servers.json and runs `claude mcp remove <name> -s user` for each, skipping anything not registered. Idempotent. --check is the dry-run drift report. For each server, classify as ok (in both servers.json and `claude mcp list`), MISSING (configured but not registered), or EXTRA (registered but not in servers.json). Exit non-zero only on MISSING since EXTRA entries are often deliberate (the claude.ai web servers register out-of-band). Smoke test against the live config: 9 ok, 0 missing, 3 EXTRA, exit 0. Two new Makefile targets: - make uninstall-mcp invokes the --uninstall mode. - make check-mcp invokes the --check mode. README.org gained an MCP section under Two install modes covering all three targets, the OAuth-token-on-disk story, and a pointer to mcp/README.org for the full pipeline. Closes TODO #7 (uninstall + --check) and TODO #8 (README MCP section).
* fix(sync-check): ignore generated python and elisp artifactsCraig Jennings2026-05-281-1/+2
| | | | | | | | | | | | | | Pre-commit caught a false-positive on its first real-world run. The .ai/scripts/__pycache__ directory created by make test (pytest writes .pyc and .pytest_cache, emacs writes .elc) was flagged as drift against the canonical's clean tree. Added matching --exclude patterns to the diff -rq check and the --fix rsync calls. Patterns: __pycache__, *.pyc, *.pyo, .pytest_cache, *.elc. The --fix excludes prevent rsync's --delete from wiping the mirror's __pycache__ when the canonical has none. Four new bats tests cover the exclusions. All 12 pass.
* feat(status): add `make status` for compact health summaryCraig Jennings2026-05-281-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | scripts/status.sh prints a six-line summary composing existing checks: - audit + doctor (one call, since audit.sh runs doctor internally) - canonical/mirror sync state via sync-check.sh - open todo count under * <Project> Open Work - inbox count (excluding .gitkeep and PROCESSED- prefixes) - git working-tree state with ahead/behind upstream Sample output: rulesets status — 2026-05-28 09:13 CDT audit Summary: 41 ok, 0 warnings, 2 failures sync canonical = mirror todo 22 open inbox 1 unprocessed git main dirty — in sync with origin/main The script adds no new logic beyond formatting. `make status` is the entry point. The scope here is limited per the triage disposition for codex item #12. The rest of #12 was rejected. `make sync` duplicates the existing sync flow, `make health` wraps existing checks without adding signal, `make bootstrap-project` duplicates `install-ai` + `install-lang`.
* feat(sync-check): canonical/mirror drift detection + pre-commit hookCraig Jennings2026-05-281-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | scripts/sync-check.sh diffs claude-templates/.ai/{protocols.org, workflows,scripts} against the .ai/ mirror. Exits 0 when clean, 1 with a diff report on drift, 2 outside a rulesets-shaped repo or git checkout. --fix mode rsyncs canonical -> mirror and re-checks, then prompts to re-stage. githooks/pre-commit wraps the script. Commits abort on drift so the issue surfaces at publish time, not at the next session's startup rsync. Two new Makefile targets: - make sync-check [FIX=1] runs the script (FIX=1 passes --fix through). - make install-githooks sets core.hooksPath=githooks (idempotent). scripts/tests/sync-check.bats holds 8 tests covering clean, drift-per-path, --fix, extra-file removal, missing canonical, and outside-git. All eight pass. This catches the exact drift I had to fix manually during this morning's audit pass. The mirror's open-tasks.org PROPERTIES drawer sat below a sub-heading because the mirror commit was older than canonical.
* feat(open-tasks): archive-done sweep at start of Phase ACraig Jennings2026-05-281-1/+2
| | | | | | | | | | | | | | | | | | open-tasks.org Phase A now runs `emacs --batch -q -l .ai/scripts/todo-cleanup.el --archive-done todo.org` as a pre-step before the parallel read batch. A level-2 task that completed during the session sits as ** DONE under Open Work until something archives it, which means Next Mode would surface it as a "what's next" candidate between cleanups. The pre-step ensures Phase A's read of todo.org reflects current state. The pre-step skips only in an explicit read-only or dry-run context. Default is always to sweep. Common Mistake #13 records "recommending a freshly-DONE task" with the pointer back to the pre-step. The proposal came from a pearl handoff on 2026-05-28.
* chore(intake): triage codex backlog into 5 actionable TODOs + dispositionsCraig Jennings2026-05-281-12/+79
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Walked the 14-item codex enhancement backlog with Craig and recorded dispositions in docs/design/2026-05-28-rulesets-enhancement-backlog.org under a new "Triage Dispositions" section. The triage TODO closed. Accept (filed below as TODOs): - Item #8 .aiignore for agent inventory exclusions ([#C] :chore:) - Item #10 Workflow test harness for drift and integrity tests ([#C] :feature:) Pilot or scope-limit (filed below): - Item #5 Token-tier pilot on startup.org and triage-intake.org ([#C] :feature:) - Item #7 Canonical/mirror drift detection via pre-commit hook or make sync-check ([#C] :feature:quick:solo:). Rejected the wholesale dedupe. The dual source is a feature. - Item #12 make status only ([#C] :feature:quick:solo:). Rejected the rest of #12. Convention, not tracked: - Item #11 script interface normalization (adopt as scripts are touched) - Item #13 ADR layer (watch-and-wait on growth signal) Reject with rationale (recorded in the backlog doc): - Item #1 broader runtime-neutral arc. Heavy infrastructure for marginal payoff at current use. - Item #3 INDEX.org compression. Already token-efficient. Parallel layer adds drift risk. - Item #4 universal catalog.json. Looks valuable on paper, rots fast in practice. - Item #6 install manifest JSON. Current Makefile pattern works. Data layer adds indirection. - Item #9 project-facts.org. Duplicates notes.org's role. - Item #14 local model profiles. Premature without a real use case. Item #2 (per-agent live session files) was already filed earlier today as the Codex Phase 1 [#B] TODO, slicing the broader item #1 arc.
* chore(intake): file codex enhancement backlog as docs/design + triage TODOCraig Jennings2026-05-281-0/+22
| | | | | | | | | | | | | | | | | | Codex left a 14-item enhancement backlog for rulesets at inbox/enhancements.org overnight. Moved it to docs/design/2026-05-28-rulesets-enhancement-backlog.org as the canonical reference and filed a single [#C] :spec: TODO to walk the items and decide accept-as-TODO, fold, defer, or reject for each. Two of the 14 already have homes: item #1 (runtime-neutral core) aligns with the existing Generic agent runtime support spec (#16), and item #2 (per-agent live session files) is exactly the Codex Phase 1 [#B] TODO filed earlier today. The triage focuses on the remaining 12. Also cleared the last-session PROCESSED-prefixed inbox file (open-tasks-hybrid-friction-cascade). The cascade+friction restructure it tracked landed in this morning's open-tasks.org edits, so the reference is no longer needed.
* fix(todo): move task #15 PROPERTIES drawer above sub-headingsCraig Jennings2026-05-281-4/+4
| | | | | | | | The dated sub-entry added in the audit pass left the LAST_REVIEWED line below the first level-3 heading, where the staleness checker can't see it (it scans only between the level-2 heading and the next heading of any depth). The fix moves the PROPERTIES drawer to its standard org-mode placement, immediately after the level-2 heading.
* chore(audit): task-audit pass + pearl intake from 2026-05-28 morningCraig Jennings2026-05-281-29/+76
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | All 16 open tasks bucketed and updated. 14 received autonomous Phase C edits (13 type-tag additions per the new scheme plus #15's body refresh for the accumulating pearl signal). Phase D adjudicated two priority bumps and the morning's inbox spillover. Phase E stamped :LAST_AUDIT: in notes.org Workflow State. Autonomous Phase C: - Tagged tasks 1-11 and 13-14 with their type tag (:feature:, :chore:, :spec:), bumped LAST_REVIEWED to 2026-05-28. Tasks 12, 15, 16 already carried type tags. - Refreshed task #15 body to reference the four pearl pattern-catalog notes now in docs/design/ (six worked patterns total). Phase D adjudication: - #15 (cross-project pattern catalog) bumped [#C] to [#B]. Pearl shipped 6 worked examples plus a synthesizing principle and is asking for spec-review iterations. Design questions still open but evidence is past the tipping point. - Filed new [#B] :feature: TODO for the codex Phase 1 race-fix (AI_AGENT_ID + session-context.d/<id>.org), lifted from the broader runtime spec (#16). Phase 1 alone is low-risk and fixes a real correctness issue under simultaneous agents. Pearl intake (4 inbox files from this morning): - Moved 0155 (patterns 4-5) and 0303 (pattern 6) into docs/design/ alongside the prior two pattern-catalog notes. Referenced from #15. - Filed new [#C] :chore:quick:solo: TODO for pearl 0138's --archive-done sweep at the start of open-tasks.org Phase A. - Filed new [#C] :feature:solo: TODO for pearl 0226's spec-review.org Phase 6 implementation-task enumeration. - Deleted 0124. Already implemented this session as the audit-warranted pre-step plus the LAST_AUDIT stamp now live in the workflow files.
* docs(todo): add priority and tag schemeCraig Jennings2026-05-281-0/+27
| | | | | | | | | | | | | | | | Adds an explicit [#A]-[#D] legend at the top of todo.org defining what each priority level means in practice. Type and effort tag conventions live alongside, since task-audit enforces both. [#A] now requires a SCHEDULED or DEADLINE date. A task that can't be dated isn't really [#A]. It belongs at [#B]. Tags split two ways. Type tags (:feature:, :chore:, :spec:, :bug:) are mandatory. Effort and autonomy tags (:quick:, :solo:) are optional and orthogonal. Both can apply to the same task. Seeds a Workflow State section in notes.org for the :LAST_AUDIT: marker that open-tasks.org Next Mode reads to decide whether to offer a task-audit run. The marker starts unset. The first task-audit run populates it.
* feat(workflows): backfill iteration history in spec workflowsCraig Jennings2026-05-281-1/+2
| | | | | | Closes the org-drill backfill TODO. Both workflow files now carry a bottom "Review and iteration history" section with four entries: Draft 1 (linear-emacs origin, 2026-05-23, placeholder timestamp), Review-and-Fold (commit 7f2aea1, 2026-05-23), Requirement addition (commit 55adf6e, 2026-05-28), and this backfill commit. Canonical and mirror updated together. Working directory working/spec-workflows-iteration-history-backfill/ removed on this commit. The spec-response cycle on the working draft (two Codex reviews, three rulesets responses) validated the entry-shape and the content before splice. Codex caught file-history conflation that would have made per-file provenance inaccurate. Craig's direct rationale on the Iteration 1 and Iteration 3 Why lines replaced the original INFERRED markers.
* docs(todo): clarify what blocks the iteration-history backfill TODOCraig Jennings2026-05-281-1/+1
| | | | The earlier body listed two reasons to wait: a file-conflict block (correct, since spec-review.org and spec-response.org have uncommitted edits) and a guess that the entry-shape spec might still change (inference without evidence). The revised dependency drops the guess. The read-only research portion can run in parallel without touching the files.
* chore(intake): file org-drill iteration-history backfill as TODOCraig Jennings2026-05-281-0/+17
| | | | The org-drill inbox asks rulesets to backfill =Review and iteration history= sections on spec-review.org and spec-response.org. It lands as a follow-up TODO because the requirement itself is still being established in uncommitted WIP.
* chore(intake): file pearl pattern-catalog and codex runtime spec as TODOsCraig Jennings2026-05-281-0/+33
| | | | Moved three inbox notes into docs/design/ so the task body links survive: pearl's two pattern-catalog handoffs and codex's v0 generic-agent-runtime spec. Added two corresponding TODOs under Rulesets Open Work, both [#C].
* chore(todo): full review pass — re-stamp, drop stale schedules, refresh ↵Craig Jennings2026-05-261-20/+19
| | | | | | daily-prep task Walked all 14 open tasks. Re-stamped LAST_REVIEWED to 2026-05-26, dropped the past SCHEDULED dates from the research-writer and Skill-Seekers wait-for-trigger tasks, tagged the Makefile consolidation :quick:solo:, and refreshed the daily-prep delegation task to reflect the triage-intake engine/plugin split.
* chore(todo): add coverage-summary language-bundle taskCraig Jennings2026-05-251-0/+29
|