aboutsummaryrefslogtreecommitdiff
path: root/.ai/session-context.org
blob: 2cb293b89fff0537f207afd2d73b9b54313261ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#+TITLE: Session — language-bundle startup self-sync
#+DATE: 2026-05-22

* Summary

** Active Goal

Build =scripts/sync-language-bundle.sh=: a per-project language-bundle freshness check wired into startup Phase A. Detect the installed bundle by fingerprint, auto-fix rulesets-owned files (=.claude/rules/*.md=, =.claude/hooks/*=, =githooks/*=), surface drift in project-customizable files (=settings.json=, =CLAUDE.md=) without writing.

** Decisions

- Per-project self-sync is a *script called from startup with an absolute rulesets path*, not a make target. A make target on the boot path adds a Makefile-parse + target-interface layer for no benefit; calling the script directly is the same accepted dependency the =.ai/= rsync already has.
- Bundle detection is *fingerprint-based, no marker file*: a project "has" language =<lang>= if any of =languages/<lang>/claude/rules/*.md= (the distinguishing rules, e.g. =elisp.md=, =python-testing.md=) exist in the project's =.claude/rules/=. Naturally scopes to opted-in projects.
- Auto-fix scope = rulesets-owned files only (=.claude/rules/*.md=, =.claude/hooks/*=, =githooks/*=). Surface-only = =settings.json=, =CLAUDE.md= (project may customize). User chose to fold hooks into auto-fix.
- Exit codes: 0 = no bundle / clean / auto-fixed; 3 = manual action recommended (settings/CLAUDE drift); 1 = usage error. Quiet when clean (like =task-review-staleness.sh=).

** Data Collected / Findings

- =install-lang.sh= COPIES (cp), does not symlink — so there are no per-project language symlinks, only content drift. The only real symlinks are machine-global =~/.claude/= (handled by =make doctor=/=install=).
- =diff-lang.sh= already walks the installer's file set (generic rules, language =.claude/= tree, githooks); reused its comparison shape.
- bats tests live in =scripts/tests/*.bats=; =make test= runs them. Style mirrored from =audit.bats= (temp HOME/project, real script, real =languages/= source).

** Files Modified

- =scripts/sync-language-bundle.sh= (new) — the self-sync script.
- =scripts/tests/sync-language-bundle.bats= (new) — 11 tests, all green.
- =claude-templates/.ai/workflows/startup.org= + =.ai/workflows/startup.org= mirror — Phase A step 12 + Phase C surfacing bullet.

Shipped: =1ceed70 feat(startup): sync language bundles per project on session launch=, pushed to =origin/main=.

Two ripe-fruit follow-ups (committed locally, not yet pushed):
- =a785f54 docs(workflows): document GitHub-family assumption in wrap-it-up Step 3.5= (item #1, =:quick:= [#A]).
- =a4389e8 docs(skills): keep review-code praise honest and unforced= (item #2 + Craig's adjacent "don't explain praise" edit, bundled per Craig's choice).
- =1477642 chore(todo): close GH-assumption and review-code strengths tasks=.

Mid-session rule change: Craig edited =claude-rules/commits.md= (still uncommitted) to *decouple voice patterns from the approval gate* — publish artifacts always run =/voice personal= (39 patterns) regardless of =.ai/= tracking; the =.ai/=-tracking check now decides only whether the gate fires. Applied to item #2 onward. The feature commit + item #1 predate it (used =/voice= general); item #1 is effectively compliant anyway (already first-person + contractions, no semicolons).

All pushed to origin/main (=1ceed70..6c91a4e=), tree clean except the live session-context. =6c91a4e docs(commits): decouple voice patterns from the approval gate= committed Craig's rule edit; it's symlinked into =~/.claude/rules/= so it's already live.

** Audit-pass cluster (2026-05-04) — in progress, area-by-area

Approach: area-by-area, my choice of order, check-in between batches, freshness-check each item against current reality (humanizer→voice, skills→commands all happened since the audit). Inventory confirmed nearly every referenced artifact still exists (as skill, command, or rule file); only =humanizer= refs are genuinely stale.

Done (all pushed through =1825226=):
- *Code review* (3) — three-strengths, CI-trust scoping, CLAUDE.md citation modes.
- *PR responses* (4) — respond-to-review commit-language + thread-resolution; two respond-to-cj-comments items moot (path already gone, humanizer/emacsclient superseded by /voice + VERIFY).
- *Browser testing* (1 of 3) — headed/headless decision tables in both playwright skills (2e9d5b0). DEFERRED: #1 networkidle/locator refactor (touches helper code, no tests) and #3 emoji sweep (~30 occurrences, 7 files) — both spread-heavy, held for focused passes given the concurrent-edit warning.
- *Debugging/RCA* (3) — debug env/recent-change capture, root-cause-trace boundary-only defense, five-whys evidence+counterfactual per link (3916dc4).

** Next Steps

- Continue the cluster, next area my choice (~29 items left across ~12 areas; Browser testing, Security, Global rules, Hooks, Languages, Architecture, C4, etc.).
- The 3 real bundle-bearing projects (chime, gloss = elisp; work = python) self-heal language-bundle drift at their own next startup via step 12 — Craig opted to let them.

* Session Log

** Setup + investigation

Session opened in rulesets. Startup ran clean (40 ok doctor, 0 .ai/ drift after a fleet =make audit APPLY=1= synced 27 projects). Earlier this session: reconciled all 26 AI projects (pushed emacs-wttrin's pending commit, committed google-contacts.el's .gitignore).

Design discussion converged on a per-project language-bundle self-sync for startup. Confirmed via reading =install-lang.sh= / =diff-lang.sh= that bundles are copied (not symlinked) and detectable by fingerprint rule files. User approved option-2 behavior with hooks folded into auto-fix.

Now implementing TDD: bats test first, then the script, then wire into startup Phase A (canonical =claude-templates/.ai/workflows/startup.org= + rsync mirror).

** Implementation + smoke test

Wrote the bats test (10 cases) red, then the script green. One scaffold bug: the test helper didn't seed CLAUDE.md, so the elisp bundle (which ships one) tripped the surface check. Fixed the helper — all green.

Smoke-tested against a *copy* of chime's real =.claude/= (no writes to the real project): it correctly auto-fixed 6 stale generic rules + a drifted =validate-el.sh=, but flagged =CLAUDE.md (missing)= → exit 3 on every run. That's wrong: CLAUDE.md is seed-only in install-lang (never overwritten without FORCE), so a missing/differing one isn't actionable via =make install-<lang>=, and =diff-lang.sh= already skips it. Dropped CLAUDE.md from the surface set entirely (settings.json only), added a regression test asserting an absent CLAUDE.md is not drift. Re-smoke: chime copy converges silently on re-run, exit 0. 11 tests green, shellcheck clean, =make lint= clean, full =make test= green (302 pytest + ERT + all bats).