diff options
| -rw-r--r-- | .ai/sessions/2026-05-15-23-10-stale-cleanup-and-audit-install-ai-bats.org | 87 | ||||
| -rw-r--r-- | todo.org | 91 |
2 files changed, 131 insertions, 47 deletions
diff --git a/.ai/sessions/2026-05-15-23-10-stale-cleanup-and-audit-install-ai-bats.org b/.ai/sessions/2026-05-15-23-10-stale-cleanup-and-audit-install-ai-bats.org new file mode 100644 index 0000000..0e485f9 --- /dev/null +++ b/.ai/sessions/2026-05-15-23-10-stale-cleanup-and-audit-install-ai-bats.org @@ -0,0 +1,87 @@ +#+TITLE: Session Context — stale todo cleanup + protocols pull-ordering doc +#+AUTHOR: Craig Jennings & Claude +#+DATE: 2026-05-15 + +* Summary + +** Active Goal + +Started as stale-entry cleanup (=/lint-org= at =todo.org:1292= was shipped 2026-05-14 but never flipped). Surfaced one partially-stale entry at =todo.org:36= during the audit; chose to actually do the remaining protocols.org pull-ordering documentation work rather than defer it. Then took the =[#C]= sibling at =todo.org:1766= (bats test harness for =make audit= + =make install-ai= edge cases) as the evening task. A cross-project handoff from a parallel dotemacs session landed during commit staging and got absorbed as its own commit. + +** Decisions + +- =/lint-org= and the pull-ordering doc task were both genuinely stale → flipped to =DONE= with retroactive =CLOSED:= dates. +- Pull-ordering entry at =todo.org:36= was partially stale (step 1 shipped, step 2 hadn't). Option 1: rewrite the body to reflect post-fold framing (no separate claude-templates pull anymore) and do the protocols.org documentation work in this session. +- Test harness location =scripts/tests/= (colocate with the scripts being tested), not =.ai/scripts/tests/= as the TODO body said — the TODO body was carried forward from the wrong mental model. Audit and install-ai are rulesets-only utilities, not =.ai/= templates. +- Test framework: bats 1.13.0 (parallels the elisp ERT pattern for =todo-cleanup= and =lint-org=). +- Test isolation: redirect =HOME= per test, scaffold synthetic project trees under =HOME/code/=, leave canonical pointing at the real one (resolved relative to each script's =$0=). PATH stubs for =fzf= and =find= cover the interactive and race-condition edges. +- The =.ai/-missing= FAIL branch in =audit.sh:161= is a defensive race-condition guard that can't be timed by black-box test. Exercised via a PATH-stubbed =find= that injects a fabricated path; the loop hits the FAIL branch on the ghost and continues to the real project. +- Cross-project handoff disposition (cj-scan nested-fence fix from dotemacs): three-commit split — dotemacs fix first (separate concern), test harness, then todo updates. Handoff file deleted after processing (the work is captured in git + the =DONE [#C]= entry in =Rulesets Resolved=). + +** Data Collected / Findings + +- bats 1.13.0 is installed at =/usr/bin/bats=. +- =make test= now totals 352 green: 296 pytest + 1 skipped + 22 lint-org ERT + 23 todo-cleanup ERT + 6 audit bats + 5 install-ai bats. Up from 341. +- Phase A inbox scan only looks at =./inbox/= at the project root. Post-fold the canonical's inbox lives at =claude-templates/inbox/=, which Phase A doesn't see. The dotemacs handoff dropped there earlier today; my 18:25 startup missed it. Surfaced only when staging commits at 22:50. Filed as a =[#B]= bug. +- Auto-push observed: =origin/main= advanced from =8577a88= → =7ef200a= at 23:04:39, 26 seconds after committing 7ef200a. No =PostCommit= hook in =~/.claude/= or =.git/hooks/=. No =git push= in this session's command history between the early-session push and the pre-push reconcile. Source unknown — likely a Magit =after-save-hook= or a parallel Claude session. +- Canonical pytest with the cj-scan fix: 302 passed, 1 skipped (matches the handoff's verification). + +** Files Modified + +Rulesets (5 commits pushed to =origin/main=): +- =cdf3909 docs(protocols): add startup pull-ordering rule= — new =** Startup Pull Ordering — Rulesets Before Project= subsection under =IMPORTANT - MUST DO= in both canonical (=claude-templates/.ai/protocols.org=) and project copy (=.ai/protocols.org=). +- =8577a88 docs(todo): close /lint-org and pull-ordering doc tasks= — todo flips on =/lint-org= (retroactive =CLOSED: [2026-05-14 Thu]=) and the pull-ordering doc task. +- =dc1661c fix(cj-scan): suppress detection inside nested non-cj begin_* blocks= — dotemacs handoff absorbed. =claude-templates/.ai/scripts/cj-scan.py= gains a =wrapper_type= state machine; =test_cj_scan.py= gains =TestCjScanNestedFencesIgnored= (6 tests); =todo.org= =Rulesets Resolved= gets a new DONE entry. +- =7ef200a test(scripts): add bats harness for audit + install-ai edge cases= — =scripts/tests/audit.bats= (140 lines, 6 tests), =scripts/tests/install-ai.bats= (103 lines, 5 tests), Makefile =test:= target extended with a bats stanza. +- =ea5e55d docs(todo): close test harness; file Phase A inbox-scan bug= — test-harness task flipped to DONE; new =[#B]= filed at line ~1792 for the Phase A inbox-scan blind spot. + +Working-tree artifacts: +- =claude-templates/inbox/2026-05-15-handoff-from-dotemacs-cj-scan-nested-fence-fix.org= — deleted (one-time signal absorbed). +- =claude-templates/inbox/= directory removed (was empty). + +** Next Steps + +- =[#B]= open at =todo.org:~1792= (post-archive): extend Phase A inbox discovery to also scan =claude-templates/inbox/= when the canonical is in-repo. Also settle whether cross-project handoffs file into =./inbox/= or stay in =claude-templates/inbox/= — the =inbox-send= script's target-project logic is where to decide. +- Investigate the auto-push source. The pre-push reconcile caught it cleanly tonight, but a non-trivial divergence at the wrong moment could surface as a non-fast-forward push abort. Could be Magit, =git config push.autoSetupRemote=, a parallel Claude session, or something else. +- Carryover still open: =[#C]= Consolidate =claude-templates/Makefile= after fold; =DOING [#A]= memory-sync (pending VERIFY on stow approach); =[#A]= =/update-skills=, =create-documentation=, 2026-05-04 audit review pass. + +* Session Log + +** Startup (18:25 CDT) + +Clean startup — previous session wrapped cleanly (no =session-context.org=), inbox absent, no cross-agent traffic, no reminders, no pending decisions. Read the 5 most recent session Summaries. Last session (today, 15:13–18:19) closed the /Consolidate .ai/ template infrastructure/ epic. Surfaced one stale entry at =todo.org:1292= (=/lint-org=, shipped 2026-05-14 but never flipped) and offered top open A items. + +** Stale entry cleanup + +Craig asked to fix the stale entry and then check for others. Flipped =/lint-org= at =todo.org:1292= → =DONE [#A]= with =CLOSED: [2026-05-14 Thu]= per the depth-based completion rule (level-2 → keyword flip + CLOSED line + body retained). + +Audit of remaining open level-2 entries against recent commits surfaced one partially-stale entry at =todo.org:36= (=Document rulesets + claude-templates pull-before-project ordering in protocols.org=). Body listed two action items: step 1 (rulesets pull in =startup.org= Phase A.0) had shipped 2026-05-15 as part of the claude-templates fold; step 2 (state the rule in =protocols.org=) had not. Also the framing was outdated — post-fold there's no separate claude-templates pull anymore. + +Craig picked option 1 (rewrite the body to reflect step 1 done + drop the claude-templates framing). Rewrote the heading to =Document startup pull-ordering rule in protocols.org= and trimmed the body to isolate the remaining work. + +** Did the remaining work — protocols.org paragraph + +Edited canonical =claude-templates/.ai/protocols.org= first (per canonical-source rule), then rsynced into =.ai/protocols.org=. Added new =** Startup Pull Ordering — Rulesets Before Project= subsection under =IMPORTANT - MUST DO=, placed between "Always Check the Time" and "Session Context File" (chronologically lining up with Phase A.0 firing first at session start). Three paragraphs: the ordering + what each pull lands, the dirty/merge resolution rule with the no-auto-stash/merge/rebase guardrail, pointer back to =startup.org= Phase A.0 for the mechanics. + +Flipped =todo.org:36= → =DONE [#B]= with =CLOSED: [2026-05-15 Fri]= and a one-line resolution note pointing at the new subsection. + +** Commit + push + +Step 0 reconcile clean (0/0). Voice-mode check showed =.ai/notes.org= tracked → general-voice mode, no approval gate. Two commits: + +- =cdf3909 docs(protocols): add startup pull-ordering rule= — both =.ai/protocols.org= copies, +16 lines total. =/voice= fired #3 (-ing analysis) and #27 (passive → active). +- =8577a88 docs(todo): close /lint-org and pull-ordering doc tasks= — todo flips. =/voice= fired #30 (fragment in prose) and #31 (noun-ified verb). + +Pre-push reconcile 0 behind / 2 ahead; pushed cleanly to =origin/main=. + +** Test harness for audit + install-ai (option 4) + +Craig picked the =[#C]= sibling at =todo.org:1766= for the bats test harness. Flipped to =DOING=. Phase 0 walk: bats 1.13.0 available, no existing harness in tree, scripts under =scripts/= (not =.ai/scripts/=). Proposed Phase 2 design with five points: location =scripts/tests/= (corrects the TODO body which said =.ai/scripts/tests/= — those scripts are rulesets-only, not template content), bats as the tool, HOME-redirect per test for isolation, fzf stub for the interactive case, ~8 tests covering the three deferred edges plus happy-path sanity. Craig: "proceed." + +Built two bats files. =scripts/tests/audit.bats= — 6 tests covering clean-sweep, drift detection, =--apply= convergence, dirty-skip, =--apply --force= clobber, and the .ai/-missing loop-continuation edge. The .ai/-missing race-condition guard at line 161 of audit.sh can't be timed by black-box test, so the test stubs =find= via PATH override to inject a fabricated =.ai/= path and confirms the loop hits the FAIL branch and continues to the real project. =scripts/tests/install-ai.bats= — 5 tests covering happy path with explicit PROJECT, =--track= gitkeep stubs, refusal on existing =.ai/=, notes.org placeholder substitution, and the fzf-pick form with a stubbed fzf (=head -n 1=). + +Extended =Makefile= =test:= target with a third stanza globbing =scripts/tests/*.bats=. Description updated from "Run the .ai/scripts/ test suites (pytest + ERT)" to "Run all test suites (pytest + ERT + bats)". + +Verification: =make test= runs clean — 296 pytest + 1 skipped + 22 lint-org ERT + 23 todo-cleanup ERT + 6 audit bats + 5 install-ai bats = 352 green, no regressions. Each new bats file ran independently first before the full suite run, so failures wouldn't get masked by upstream noise. + +Flipped =todo.org:1766= → =DONE [#C]= with =CLOSED: [2026-05-15 Fri]=. @@ -33,16 +33,6 @@ commit + push archsetup. After that, every machine running =stow= picks up the same memory tree. *** VERIFY Approve stow-based sync of ~/.claude/projects via archsetup/dotfiles/common/ -** DONE [#B] Document startup pull-ordering rule in protocols.org -CLOSED: [2026-05-15 Fri] - -Phase A.0 of =startup.org= now pulls rulesets ff-only before the project repo -(shipped 2026-05-15 as part of the claude-templates fold — after the subtree -merge, there's no separate claude-templates pull, just rulesets-then-project). -The protocols.org paragraph stating the ordering and "resolve any issues -before proceeding" rule shipped 2026-05-15 in the =** Startup Pull Ordering= -subsection under =IMPORTANT - MUST DO=. - ** TODO [#A] Build =create-documentation= skill for high-quality project/product docs Create a Claude skill named =create-documentation= that can plan, write, @@ -1280,28 +1270,6 @@ See also the DoD-specific notations section under the later TODO starting point across the DoD notation landscape (SysML, DoDAF/UAF, IDEF1X). This entry is the execution plan for that starting point. -** DONE [#A] Build =/lint-org= skill + wrap-up integration -CLOSED: [2026-05-14 Thu] - -Spec: [[file:.ai/specs/lint-org-skill-spec.md]] - -A two-mode skill (=interactive=, =mechanical-only=) that runs =org-lint=, -auto-fixes safe categories (item-number, missing-language-in-src-block, -misplaced-planning-info, markdown-bold → single-asterisk), and walks judgment -items (broken local-file links, invalid fuzzy links, verbatim-asterisk false -positives, suspicious-language blocks) inline. - -Wrap-up integration: =wrap-it-up.org= invokes -=/lint-org todo.org --mode=mechanical-only= after the existing -=todo-cleanup.el --archive-done= pass. Judgment items defer to a -carry-forward file that the next morning's daily-prep merges in, so -wrap-up never blocks on a judgment call. - -Baseline that motivated this: the 2026-05-14 manual pass took =todo.org= -from 55 → 1 lint warnings across two commits (=0d10458= signal, -=9ad5b30= cosmetic). A nightly mechanical sweep keeps the count near -zero forever — each day's drift is small. - ** TODO [#A] Build =/update-skills= skill for keeping forks in sync with upstream The rulesets repo has a growing set of forks (=arch-decide= from @@ -1763,21 +1731,6 @@ The four canonical rules (=commits=, =testing=, =verification=, =subagents=) are The Elisp pair is the most suspicious — three repos using essentially the same rules. Audit: diff these across the projects, check for drift, then decide whether to canonicalize them under =~/code/rulesets/claude-rules/languages/<lang>/= and symlink, or leave them as project-local. -** DONE [#C] Test harness for =make audit= + =make install-ai= edge cases :test: -CLOSED: [2026-05-15 Fri] - -Three edge cases from the fold-epic test plan were not exercised because they're destructive on real projects: - -- =audit --force= clobbers uncommitted =.ai/= work — needs a project with intentionally dirty =.ai/= to verify the override path. -- =audit= reports =FAIL= when =.ai/= is missing — needs a project where the directory was deleted to verify the loop continues past the failure. -- =install-ai= fzf-pick form (no =PROJECT= arg) — needs interactive testing. - -Build a self-contained test harness under =.ai/scripts/tests/= that spins up =/tmp/audit-test-projects/= with a known matrix of project states (clean, dirty, missing =.ai/=, pristine, etc.), runs the audit + install-ai targets against it, and asserts expected outputs. The harness should clean up after itself. - -Pattern reference: bats or shell-based assertions (similar to the elisp ERT suites for =todo-cleanup= and =lint-org=, but for shell scripts). - -Triggered by: 2026-05-15 fold-epic, child 4 test plan; commits =94782ee= (audit) + =d364cf2= (install-ai). - ** TODO [#C] Consolidate =claude-templates/Makefile= after fold :chore: Sibling follow-up from the fold child (2026-05-15). After the subtree merge, =rulesets/claude-templates/Makefile= still has its standalone =install= / =uninstall= / =list= / =test-scripts= targets. The =install= target's =bin/ai= logic is now duplicated in =rulesets/Makefile=. Both work; the redundancy is harmless but worth cleaning up. @@ -2162,3 +2115,47 @@ After local fold + audit + install-ai are working, propagate to ratio. **** Adjacent: cross-machine memory sync The =[#A] DOING= memory-sync investigation (todo.org:10) is adjacent. Both involve "make my Claude setup portable across machines." Coordinate so the memory-sync stow approach (if approved) doesn't conflict with this fold's symlink mechanics. +** DONE [#B] Document startup pull-ordering rule in protocols.org +CLOSED: [2026-05-15 Fri] + +Phase A.0 of =startup.org= now pulls rulesets ff-only before the project repo +(shipped 2026-05-15 as part of the claude-templates fold — after the subtree +merge, there's no separate claude-templates pull, just rulesets-then-project). +The protocols.org paragraph stating the ordering and "resolve any issues +before proceeding" rule shipped 2026-05-15 in the =** Startup Pull Ordering= +subsection under =IMPORTANT - MUST DO=. +** DONE [#A] Build =/lint-org= skill + wrap-up integration +CLOSED: [2026-05-14 Thu] + +Spec: [[file:.ai/specs/lint-org-skill-spec.md]] + +A two-mode skill (=interactive=, =mechanical-only=) that runs =org-lint=, +auto-fixes safe categories (item-number, missing-language-in-src-block, +misplaced-planning-info, markdown-bold → single-asterisk), and walks judgment +items (broken local-file links, invalid fuzzy links, verbatim-asterisk false +positives, suspicious-language blocks) inline. + +Wrap-up integration: =wrap-it-up.org= invokes +=/lint-org todo.org --mode=mechanical-only= after the existing +=todo-cleanup.el --archive-done= pass. Judgment items defer to a +carry-forward file that the next morning's daily-prep merges in, so +wrap-up never blocks on a judgment call. + +Baseline that motivated this: the 2026-05-14 manual pass took =todo.org= +from 55 → 1 lint warnings across two commits (=0d10458= signal, +=9ad5b30= cosmetic). A nightly mechanical sweep keeps the count near +zero forever — each day's drift is small. +** DONE [#C] Test harness for =make audit= + =make install-ai= edge cases :test: +CLOSED: [2026-05-15 Fri] + +Three edge cases from the fold-epic test plan were not exercised because they're destructive on real projects: + +- =audit --force= clobbers uncommitted =.ai/= work — needs a project with intentionally dirty =.ai/= to verify the override path. +- =audit= reports =FAIL= when =.ai/= is missing — needs a project where the directory was deleted to verify the loop continues past the failure. +- =install-ai= fzf-pick form (no =PROJECT= arg) — needs interactive testing. + +Build a self-contained test harness under =.ai/scripts/tests/= that spins up =/tmp/audit-test-projects/= with a known matrix of project states (clean, dirty, missing =.ai/=, pristine, etc.), runs the audit + install-ai targets against it, and asserts expected outputs. The harness should clean up after itself. + +Pattern reference: bats or shell-based assertions (similar to the elisp ERT suites for =todo-cleanup= and =lint-org=, but for shell scripts). + +Triggered by: 2026-05-15 fold-epic, child 4 test plan; commits =94782ee= (audit) + =d364cf2= (install-ai). |
