diff options
Diffstat (limited to '.ai')
| -rw-r--r-- | .ai/scripts/lint-org.el | 27 | ||||
| -rw-r--r-- | .ai/scripts/tests/test-lint-org.el | 26 | ||||
| -rw-r--r-- | .ai/sessions/2026-06-21-02-44-launcher-fix-kb-feature-wrapup-routing.org | 110 | ||||
| -rw-r--r-- | .ai/workflows/inbox-zero.org | 2 | ||||
| -rw-r--r-- | .ai/workflows/process-inbox.org | 2 | ||||
| -rw-r--r-- | .ai/workflows/startup.org | 16 | ||||
| -rw-r--r-- | .ai/workflows/triage-intake.org | 4 | ||||
| -rw-r--r-- | .ai/workflows/wrap-it-up.org | 4 |
8 files changed, 190 insertions, 1 deletions
diff --git a/.ai/scripts/lint-org.el b/.ai/scripts/lint-org.el index 8f55cc6..3633dba 100644 --- a/.ai/scripts/lint-org.el +++ b/.ai/scripts/lint-org.el @@ -368,6 +368,31 @@ Emits one judgment item per violating table." (string-join violations "; "))))))))) ;;; --------------------------------------------------------------------------- +;;; level-2 dated-header check (claude-rules/todo-format.md) +;; +;; A completed task or resolved VERIFY at level 2 must carry a terminal +;; keyword (DONE/CANCELLED + CLOSED:), never a dated heading. A `** <date>' +;; header has no keyword, so todo-cleanup's --archive-done can never archive +;; it (it accumulates in Open Work forever) and task-review drops it from +;; selection. Judgment-only, never auto-fixed: the repair needs a +;; DONE-vs-CANCELLED call and the original heading text, which is a judgment +;; the sweep can't make. Targets todo/task files; a dated-log-format org +;; file using `** <date>' headings intentionally will false-positive here, in +;; which case the human dismisses the judgment item. + +(defun lo--check-level2-dated-headers () + "Flag level-2 headings whose text begins with a YYYY-MM-DD date. +Emits one judgment item per offending heading (checker +`level-2-dated-header')." + (save-excursion + (goto-char (point-min)) + (while (re-search-forward + "^\\*\\* \\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)" nil t) + (lo--emit-judgment + 'level-2-dated-header (line-number-at-pos) + "level-2 dated header is a completion defect (todo-format.md): a ** task or VERIFY closes with DONE/CANCELLED + CLOSED:, not a dated heading — convert it so --archive-done can archive it")))) + +;;; --------------------------------------------------------------------------- ;;; File processing (defun lo--backup (file) @@ -401,6 +426,8 @@ left unmodified and mechanical entries are recorded with :preview t." ;; After org-lint items: the custom table-standard scan. Runs on the ;; post-fix buffer; judgment-only, so order doesn't perturb fixes. (lo--check-tables) + ;; Same shape: flag level-2 dated headers (completion defects). + (lo--check-level2-dated-headers) (when (and (not lo-check-only) (buffer-modified-p)) (save-buffer))) (with-current-buffer buf (set-buffer-modified-p nil)) diff --git a/.ai/scripts/tests/test-lint-org.el b/.ai/scripts/tests/test-lint-org.el index 3a83602..242c35c 100644 --- a/.ai/scripts/tests/test-lint-org.el +++ b/.ai/scripts/tests/test-lint-org.el @@ -659,5 +659,31 @@ missing-rules violation." (judgments (lo-test--judgments (plist-get run :issues)))) (should-not (memq 'org-table-standard (lo-test--checkers judgments))))) +;;; --------------------------------------------------------------------------- +;;; level-2 dated-header check (claude-rules/todo-format.md) + +(ert-deftest lo-level2-dated-header-is-judgment () + "A level-2 heading beginning with a YYYY-MM-DD date is flagged." + (let* ((out (lo-test--run + "* Open Work\n\n** 2026-06-20 Sat @ 10:00:00 -0500 Something resolved\nBody.\n")) + (res (plist-get out :result)) + (judgments (lo-test--judgments (plist-get out :issues)))) + (should (= 0 (plist-get out :fixes))) ; judgment-only, never auto-fixed + (should (member 'level-2-dated-header (lo-test--checkers judgments))))) + +(ert-deftest lo-level2-done-task-not-flagged () + "A level-2 task closed with a terminal keyword + CLOSED: is fine." + (let* ((out (lo-test--run + "* Open Work\n\n** DONE [#B] Something resolved\nCLOSED: [2026-06-20 Sat]\nBody.\n")) + (judgments (lo-test--judgments (plist-get out :issues)))) + (should-not (member 'level-2-dated-header (lo-test--checkers judgments))))) + +(ert-deftest lo-level3-dated-entry-not-flagged () + "A dated event-log entry at level 3 is the correct sub-task shape, not a defect." + (let* ((out (lo-test--run + "* Open Work\n\n** TODO [#B] Parent task\n*** 2026-06-20 Sat @ 10:00:00 -0500 sub-entry landed\nBody.\n")) + (judgments (lo-test--judgments (plist-get out :issues)))) + (should-not (member 'level-2-dated-header (lo-test--checkers judgments))))) + (provide 'test-lint-org) ;;; test-lint-org.el ends here diff --git a/.ai/sessions/2026-06-21-02-44-launcher-fix-kb-feature-wrapup-routing.org b/.ai/sessions/2026-06-21-02-44-launcher-fix-kb-feature-wrapup-routing.org new file mode 100644 index 0000000..935e61d --- /dev/null +++ b/.ai/sessions/2026-06-21-02-44-launcher-fix-kb-feature-wrapup-routing.org @@ -0,0 +1,110 @@ +#+TITLE: Session Context +#+DATE: 2026-06-20 + +* Summary + +** Active Goal + +Started as "~/.dotfiles not showing in the ai launcher," then ran long across tooling and convention work: the launcher fix, a level-2 VERIFY completion rule change, the KB-contribution feature + a new lint checker, an eight-project conversion broadcast, and the wrap-up routing spec taken through review + response to Ready with a task breakdown. + +** Decisions + +- ~/.dotfiles → track mode for its .ai/ (private cjennings.net remote, so no leak concern) — the durable fix so the scaffold travels to every machine instead of needing per-machine bootstrap. +- Level-2 (=**=) VERIFY completes task-shaped (DONE/CANCELLED + CLOSED:), never a dated header; dated rewrites are =***=+ only (from .emacs.d; applied across 4 producers + a lint checker). +- KB-contribution spec ratified, plus a new decision D6 (read-side startup consult-nudge — the counterpart to the write-side encouragement the spec lacked). +- Wrap-up routing redesigned (Craig's challenge): deliver routable keepers via =inbox-send= to the destination's inbox, not a direct cross-repo =todo.org= move. Spec now Ready, [9/9] decisions. +- ratio's diverged rulesets commit f118905 (stty-susp "fix") discarded — its premise (LAUNCH_PREFIX breaks launch) was not reproducible; backed up to a patch first. + +** Data Collected / Findings + +- A gitignore-mode .ai/ scaffold is per-machine — it doesn't travel via git, so a project bootstrapped on one machine fails the launcher's marker check on another. (Promoted to KB.) +- inbox-send's resolve_roots REPLACES the built-in roots when ~/.claude/inbox-roots.txt exists, so parent roots must be re-listed alongside single-$HOME project dirs. +- Several ~/code projects lacked an inbox/ dir entirely (little-elisper, rsyncshot, winvm, chime, yt-sync) — created during the conversion broadcast. +- chime and yt-sync have inbox/ but no todo.org — which clinched the wrap-up routing redesign (direct-move would silently drop keepers headed there; inbox-route delivers). +- stty susp undef exits 0 in a pty on both machines; the exact tmux send-keys launch path runs clean — no reproducible launch bug. + +** Files Modified + +- rulesets (committed + pushed): claude-templates/bin/ai (launcher line, f5609ec); todo-format.md + respond-to-cj-comments.md + process-inbox.org + 2 dated-header repairs (8a50088); KB-contribution spec + startup/triage-intake/inbox-zero/wrap-it-up prompts (76e5559); lint-org.el level-2-dated-header + tests + lint-org.md (f6dde4e); 3 filed-handoff tasks + design bundles (d9d3be9); wrap-up routing spec-review (23fac08), spec-response redesign (af15fae), task breakdown (df1555d). +- ~/.dotfiles (e4a7cee): .ai/ converted to track mode. ratio: dotfiles converged, rulesets reset to origin. +- ~/.claude/inbox-roots.txt (velox-local): added ~/.emacs.d + ~/.dotfiles so inbox-send reaches them. +- org-roam KB: best-practices node + 2 lesson nodes (gitignored-.ai-per-machine, inbox-over-foreign-edit). +- Handoffs sent: home + work (3 filed tasks), .emacs.d (VERIFY rule applied), and conversion handoffs to 8 ~/code projects. + +** Next Steps + +- RECOMMENDED NEXT SESSION: build the wrap-up routing feature. Spec is Ready ([[file:../docs/design/wrapup-routing-spec.org]]); 4 =:solo:= tasks under the parent at todo.org (recommendation engine + discovery, =:ROUTE_CANDIDATE:= marker in process-inbox, the wrap-it-up router sub-step, the test surface) plus 1 manual end-to-end validation. A clean fresh-session build. +- Pending Craig review: the home "spec-response readiness-gate" proposal sitting in rulesets/inbox/ (deferred from this session — it's a proposal needing review). +- The 8 ~/code conversion handoffs apply on each project's own next session. +- Backlog filed this session: ntfy agent-comms, flashcard reconcile, triage-intake phone-push (all [#C], the latter two depend on decisions). + +KB: promoted 2 / consulted yes + +* Session Log + +** Dotfiles launcher discovery — full resolution + +- Root cause was two-part (launcher line missing + .ai/ gitignored so the bootstrap didn't travel). velox: applied launcher line (f5609ec), bootstrapped .ai/, then converted ~/.dotfiles to track mode (.ai/ now tracked, dotfiles commit e4a7cee) so the scaffold travels via git. velox fully working. +- ratio: dotfiles converged to tracked .ai/ (ff-pull after removing a blocking untracked inbox/.gitkeep). But ratio's ~/code/rulesets is DIVERGED: local commit f118905 (1 ahead) vs my f5609ec (1 behind). f118905 = ratio's local fix for "stty susp undef; LAUNCH_PREFIX prevents ai launch" — but it's broken (printf split across two lines = bash syntax error), reverts C-z protection wholesale, and includes experimental "Mr. Moto" agent-id content. NOT pushable as-is. Left untouched pending Craig's decision. +- Possible real bug flagged: LAUNCH_PREFIX="stty susp undef; " may actually break `ai` launch (ratio symptom). Needs proper verify/fix on velox canonical, separate from ratio's broken commit. +- RESOLVED (option 1): launch bug not reproducible. Tested stty susp undef in a pty (velox + ratio, zsh + bash, coreutils 9.11) → exit 0; tested the exact tmux send-keys launch path on both → command runs (LAUNCHED-OK). f118905 misdiagnosed it (or hit a transient half-synced bin/ai on Jun 17), bundled with a broken printf split + experimental "Mr. Moto" build_instructions. Canonical needs no change; LAUNCH_PREFIX/C-z protection stays. +- ratio fixed: backed up f118905 to ~/0001-fixing-the-stty-susp-undef-*.patch (recoverable), git reset --hard origin/main → HEAD f5609ec, launcher line present, 0/0 with origin, build_candidates lists ~/.dotfiles. Untracked ratio inbox handoffs left in place (ratio's own session concern). +- Both machines now: ~/.dotfiles shows in the launcher picker. Done. + +** Processed ratio's stranded rulesets inbox (11 files, same project) + +Copied ratio's untracked ~/code/rulesets/inbox/ handoffs to velox, examined, none done in canonical. Three batches, all filed + preserved + originals deleted on both machines (commit d9d3be9): +- B1 ntfy agent-comms proposal (from home, 2026-06-17): [#C] task + docs/design/2026-06-17-ntfy-agent-comms-proposal.org. +- B2 flashcard multi-tag tooling (from work, 2026-06-17): [#C] reconcile task + docs/design/2026-06-17-flashcard-multitag-{note.md,to-anki.py,stats.py} (kept 0953 over superseded 0924). +- B3 triage-intake auto-mode phone push (from work, 2026-06-18): [#C] task (depends on B1) + docs/design/2026-06-18-triage-intake-phone-push-{note,workflow}.org (kept 1515; 1512 identical). +Replied to home + work confirming filed. ratio gets the todo/docs on its next launch (same project, pulled). + +** Processed: .emacs.d level-2 VERIFY completion rule change (commit 8a50088) + +.emacs.d directive: a level-2 (**) VERIFY must complete task-shaped (DONE/CANCELLED + CLOSED:), never a dated header; dated rewrites are ***+ only. Reason: a ** dated header has no keyword, so todo-cleanup --archive-done can't archive it and task-review drops it. Skeptical-reviewed → sound, agreed. +Applied all four producer locations: claude-rules/todo-format.md (dropped the attached edited version; diff confirmed it touched only the 3 VERIFY-completion passages), .claude/commands/respond-to-cj-comments.md (3 edits + the "resolved body" nicety), claude-templates/.ai/workflows/process-inbox.org Park step (+ mirror via sync-check). Also repaired two pre-existing ** dated headers in rulesets todo.org (line 179 Phase E, line ~2698 new-personal-projects) → DONE + CLOSED. And fixed the dotfiles VERIFY I dated earlier this session (todo.org:37) → DONE [#B] + CLOSED. +Verified: make test exit 0, sync-check clean. Replied to .emacs.d by hand-writing into ~/.emacs.d/inbox/ (inbox-send can't reach .emacs.d — no ~/.claude/inbox-roots.txt on velox). Inbox files deleted. + +** Fixed: inbox-send can't reach .emacs.d / .dotfiles + +Created ~/.claude/inbox-roots.txt (velox-local) listing ~/projects, ~/code, ~/.emacs.d, ~/.dotfiles. inbox-send's resolve_roots REPLACES defaults when the file exists, so the parent roots had to be re-listed alongside the single-$HOME project dirs. Verified: inbox-send --list now shows 10 projects incl .emacs.d + .dotfiles. Machine-local — ratio needs its own if Craig sends from there. + +** Investigated: KB lessons-learned strength (wrap-up write + startup read) + +Findings for Craig's recommendation ask: wrap-up HAS a Step-1 KB-promotion check + mandatory "KB: promoted N / consulted yes-no" receipt, but it's NOT effective — last ~5 session receipts all "promoted 0 / consulted no" (one "promoted 1"); KB's newest node is 2026-06-15 and most growth came from explicit memory-sweeps, not the wrap habit. Startup has NO KB-read step at all (only the roam *task* inbox nudge; the agent KB at ~/org/roam/agents/ is never surfaced). Existing spec docs/design/2026-06-16-encourage-kb-contribution-spec.org + DOING task todo.org:198 address the write side (4 prompts + best-practices node) but its 5 decisions are unratified AND it omits Craig's read-side ask (surfacing relevant lessons at startup). KB has 30 nodes. + +** Built: KB-contribution feature + read-side + lint checker (all 3 of Craig's asks) + +Craig approved all six decisions (5 spec + D6 new). Shipped: +- inbox-send fix: ~/.claude/inbox-roots.txt (covered above). +- Spec amended: docs/design/2026-06-16-encourage-kb-contribution-spec.org — 5 decisions ratified, D6 (read-side consult nudge) added + threaded through Design/Phase 2/acceptance/history, status draft→approved. +- Best-practices KB node: ~/org/roam/agents/20260620232112-agent-kb-best-practices.org (8 sections, links how-kb-works node, defers boundary to knowledge-base.md). Committed+pushed to roam (48e50f1), findable by the documented rg. +- 4 workflow prompts (canonical+mirror): startup.org Phase A KB-surface step + 2 Phase C nudges (D1 contribute link, D6 consult titles, both roam-gated); triage-intake + inbox-zero conditional end-of-flow capture reminders; wrap-it-up early reflection at top of Step 1 feeding the existing receipt. Commit 76e5559. +- Lint checker: lint-org.el level-2-dated-header judgment check (custom, like org-table-standard) + 3 ERT tests + lint-org.md doc + mirrors. Commit f6dde4e. +- Closed DONE: todo.org:200 "Encourage org-roam KB contribution" (parent DONE+CLOSED, sub-VERIFY → dated entry). Not yet committed (rides wrap-up). +Verified: make test exit 0 (350+54+12 pytest, all bats, 36 ERT), sync-check clean. All pushed. + +** ~/code AI-project conversion broadcast + worktree cleanup + page + +Surveyed all ~/code AI projects for project-owned tooling currency (todo.org/Priority Scheme, .claude/CLAUDE.md, .ai layout). Sent tailored conversion handoffs to 7 behind projects: emacs-wttrin, archangel, website (via inbox-send); little-elisper, rsyncshot, winvm, chime (direct write — they had NO inbox/ dir, so created inbox/ + .gitkeep first, which is itself a gap fixed). Each handoff lists only that project's actual gaps. Fully-current already: auto-dim-other-buffers.el, archsetup, pearl. +- emacs-wttrin's first send (23:37) vanished from its inbox (dir mtime 23:40, likely a live emacs-wttrin session swept it); re-delivered at 23:44, verified persists. +- yt-sync: Craig confirmed convert it (reversing the 2026-06-12 no-todo call). Delivered the full conversion handoff (created inbox/ first; no todo.org/.claude/CLAUDE.md, old layout). 8 of 8 behind projects now handed off. +Worktree cleanup (Craig's request, so downstream can pull rulesets): committed todo.org KB-task closure (9bcc8d1), pushed, origin 0/0, tracked tree clean. Left untracked: .ai/session-context.org (live anchor, not wrapping up) + a new home handoff (2026-06-20-2339 spec-response-readiness-gate-proposal — a proposal, left for next session's review). Paged Craig via notify --persist (23:46). + +** Running spec-review on wrapup-routing-spec (Craig's inbox-route challenge) + +Craig picked option 2 (spec-review) and raised a strong design challenge: why does the router move keepers directly into the destination's todo.org (spec D2 = atomic cross-project move helper) rather than inbox-send them to the destination's inbox/ (file-per-task or one file), letting the destination's own process-inbox file them? The inbox route reuses the sanctioned cross-project path (cross-project.md), avoids cross-repo todo.org writes (the data-loss-adjacent risk), and makes a wrong-confidence destination recoverable (receiving session rejects) instead of corrupting another tracker. Dispatched a fresh-context adversarial reviewer to evaluate this as the headline finding and write docs/design/wrapup-routing-spec-review.org. Note also surfaced this session: several ~/code projects lacked inbox/ entirely (created during the conversion broadcast), which bears on the inbox-route's "destination must have an inbox" precondition. + +** spec-response: wrap-up routing redesigned to inbox-send, now Ready (af15fae) + +Ran spec-response on wrapup-routing-spec. Accepted the review's H1 (inbox-route) + H2 (tag-at-file-time); one modify (D9: local source removal + reject-flow undo, closing the review's vague source-handling). Superseded D2/D3; added D7/D8/D9; rewrote Summary/Goals/mechanics/Phases/Acceptance for inbox-send delivery. Decisions [9/9], Status Ready. Deleted the review file. Updated todo.org:187 task body (removed its cj comment — instruction satisfied; added dated sub-entry). cj comment in the spec also removed (processed). Pending: spec-response Phase 6 (implementation-task breakdown into todo.org) on Craig's go — offered, deferrable given it's ~2am. + +** Session-scoped instruction + +Craig: always commit and push this session — don't ask for push confirmation. (2026-06-20) + +* Session Log + +** Diagnosing dotfiles-not-in-launcher + +Startup ran clean (no crash anchor, empty inbox). Craig reported ~/.dotfiles missing from the ai launcher list. Traced to two independent causes documented above. Craig chose to fix both. diff --git a/.ai/workflows/inbox-zero.org b/.ai/workflows/inbox-zero.org index aa7c273..8c4719b 100644 --- a/.ai/workflows/inbox-zero.org +++ b/.ai/workflows/inbox-zero.org @@ -69,6 +69,8 @@ The roam inbox lives in a git repo (=~/org/roam=, auto-synced by the =roam-sync= Report: moved (with their new priorities and tags), folded, dropped-as-done. Then the residue: foreign items (left for their owners, count only) and unowned items (count plus the headings that appear related to this project, for manual claim or prefix). Same "summarize what we kept" shape. +If triaging this batch surfaced a durable, cross-project fact (a reference pointer worth keeping, a pattern worth recording), consider writing it to the agent KB as one =:agent:= node (see =knowledge-base.md=; personal projects only). Skip silently when nothing durable came up — never pad an empty run with a KB line. + * Skip conditions - No =~/org/roam/inbox.org= → silent no-op. diff --git a/.ai/workflows/process-inbox.org b/.ai/workflows/process-inbox.org index af406ee..687767e 100644 --- a/.ai/workflows/process-inbox.org +++ b/.ai/workflows/process-inbox.org @@ -191,7 +191,7 @@ Rename in place to =inbox/PROCESSED-<original-filename>= and add a brief comment ** Park (Skeptical Review in a no-approvals session) -Move the proposal file into =working/<task-slug>/= alongside the prepared diff, file the =[#B]= VERIFY per the Skeptical Review section, reply to the sender that it's parked for Craig's review, and delete the inbox file. On Craig's approval the apply is mechanical: apply the prepared edits, run the normal verify-and-publish flow, rewrite the VERIFY to a dated log entry per =todo-format.md=, and send the sender the acceptance reply. On rejection, the reject-from-another-project flow above runs unchanged. +Move the proposal file into =working/<task-slug>/= alongside the prepared diff, file the =[#B]= VERIFY per the Skeptical Review section, reply to the sender that it's parked for Craig's review, and delete the inbox file. On Craig's approval the apply is mechanical: apply the prepared edits, run the normal verify-and-publish flow, close the parked =**= VERIFY per =todo-format.md= (a top-level VERIFY resolves to =DONE= + =CLOSED:=, not a dated header), and send the sender the acceptance reply. On rejection, the reject-from-another-project flow above runs unchanged. * Phase E — Close out diff --git a/.ai/workflows/startup.org b/.ai/workflows/startup.org index fe7778f..7540787 100644 --- a/.ai/workflows/startup.org +++ b/.ai/workflows/startup.org @@ -151,6 +151,20 @@ These calls have no dependencies on each other. Issue them all together in one m 8. =[ -f todo.org ] && .ai/scripts/task-review-staleness.sh todo.org 7 || true= — count top-level tasks overdue for review (the daily task-review habit's startup nudge). The =[ -f todo.org ]= guard skips projects without a root todo.org; =|| true= keeps Phase A from failing if the script isn't synced yet. Threshold 7 days is one review cycle of slack — softer than the wrap-up health check's 30-day alarm. 9. =bash ~/code/rulesets/scripts/sync-language-bundle.sh "$PWD" 2>/dev/null || true= — language-bundle freshness for the current project. Fingerprint-detects which bundle (if any) the project has, auto-fixes drifted rulesets-owned files (=.claude/rules/*.md=, =.claude/hooks/*=, =githooks/*=), and surfaces drift in =settings.json= without writing it (a project may have customized it). =CLAUDE.md= is deliberately left untracked — it's seed-only in =install-lang= and project-owned afterward, mirroring how =diff-lang= skips it. Quiet when there's no bundle or everything's clean. Hardcodes the rulesets path because =languages/= is the canonical source and lives only there — the same absolute-path dependency the rsyncs already carry. =|| true= keeps Phase A from failing on older checkouts where the script isn't present yet. The =.ai/= rsyncs and this call write to disjoint paths (=.ai/= vs =.claude/=/=githooks/=), so the batch stays parallel-safe. 10. =[ -f "$HOME/org/roam/inbox.org" ] && grep -cE '^\*\* ' "$HOME/org/roam/inbox.org" || true= — count items in the roam global inbox (=~/org/roam/inbox.org=), the inbox-zero startup nudge. Silent if the roam clone isn't on this machine. Phase C reads the file when the count is non-zero, splits total vs items related to this project, and surfaces the offer (see =inbox-zero.org=). Read-only; never files at startup. +11. KB surface prep (the read + contribute startup nudges; see =docs/design/2026-06-16-encourage-kb-contribution-spec.org=). Gated on the agent KB clone. Counts =:agent:= nodes, lists up to 5 whose content matches the current project basename (titles only; a few most-recent nodes as a fallback when nothing matches), and resolves the best-practices node path. Read-only; silent when the clone is absent. Phase C surfaces the relevant titles (consult) and the best-practices link (contribute). + + #+begin_src bash + ra="$HOME/org/roam/agents" + if [ -d "$ra" ]; then + proj=$(basename "$PWD") + echo "kb-total: $(rg -l '#\+filetags:.*:agent:' "$ra" 2>/dev/null | wc -l)" + echo "kb-bestpractices: $(rg -l 'agent-kb-best-practices' "$ra" 2>/dev/null | head -1)" + matches=$(rg -il "$proj" "$ra" 2>/dev/null | head -5) + [ -z "$matches" ] && matches=$(\ls -t "$ra"/*.org 2>/dev/null | head -3) + echo "kb-relevant-titles:" + for f in $matches; do rg -m1 '^#\+title:' "$f" 2>/dev/null | sed 's/^#+title:/ -/'; done + fi + #+end_src Notes on the rsync commands: - Trailing slashes on both source and destination matter — they tell rsync to sync /contents/ rather than nest a directory inside. @@ -183,6 +197,8 @@ This phase touches the user and runs sequentially: - Briefly note significant template updates noticed during sync (new workflows, protocol changes). - *Task-review nudge.* If the Phase A staleness count (step 11) is greater than zero, surface one line: "=<N>= top-level tasks unreviewed for >7 days — say 'let's do a task review' to run a cycle." If zero, say nothing. - *Roam inbox nudge.* If the Phase A roam-inbox count is greater than zero, read =~/org/roam/inbox.org=, split total vs items related to this project (claimed by the =<project>:= prefix, plus any unprefixed item whose topic plainly concerns this project), and surface one line: "Roam inbox: =<N>= total, =<M>= appear related to this project — say 'inbox zero' to file them." Offer it as a priority option; never auto-file. If the count is zero or the file is absent, say nothing. See =inbox-zero.org=. + - *KB consult nudge (read side).* If the Phase A KB-surface prep returned any =kb-relevant-titles=, surface one line listing them (capped 5): "KB lessons that may be relevant: =<title>=; =<title>=… — open the node before related work." The titles are declarative, so the list alone tells you whether to open one. Gated on the roam clone; silent when the clone is absent or nothing relevant surfaced. See the best-practices node and =knowledge-base.md=. + - *KB contribute nudge (write side).* Once per session, surface one line pointing at the best-practices node (the =kb-bestpractices= path from Phase A): "Learned something durable? See =<path>= for how to write a KB node — contributing cross-project facts is welcome (personal projects only; work/unknown projects never write per =knowledge-base.md=)." Light encouragement, never a gate. Gated on the roam clone; silent when absent. - *Language-bundle sync.* If the Phase A step-12 call (=sync-language-bundle.sh=) printed anything, surface it. =fixed= lines are informational — the drift was already repaired (note that =.claude/= is now dirty if the project commits it). A =drift= line on =settings.json= is surface-only and needs the printed =make install-<lang> PROJECT=.= to reconcile; flag it so the user can decide. If the call was silent, say nothing. - *Newly-installed symlinks.* If the Phase A.0 =make install= step printed any =link= / =relink= / =WARN= line, surface it. A =link= line means a skill, rule, hook, or script added to rulesets is now linked into =~/.claude= for the first time on this machine. For a newly-linked *skill*, check the agent's available-skills list: if the harness already registered it mid-session, note it's available and move on; if it's absent, stop and tell Craig to restart the agent so it loads (whether a mid-session reload works is harness-version-dependent). For a newly-linked *hook*, note that the harness reads hooks at session start — it fires from the next session (or after Craig opens =/hooks= once); its settings.json wiring travels with the tracked file, so the link is usually the only missing piece. A =WARN ... not a symlink= line is a real collision at the target path — surface it; it needs a human. If the step printed only "nothing new to link", say nothing. - *Template-sync churn (safety net).* Check whether Phase A's rsync left uncommitted churn in the synced =.ai/= paths — accumulated from a prior session that crashed before wrap-up, or freshly added this session when rulesets advanced. Without surfacing, it builds up silently until it blocks Phase A.0's auto-ff (git won't ff a dirty tree). Skip in the rulesets repo itself (there =.ai/= is a committed mirror, kept honest by the pre-commit hook). The check is sequential here, after the rsync has finished — not a Phase A step, to keep that batch race-free. diff --git a/.ai/workflows/triage-intake.org b/.ai/workflows/triage-intake.org index 9e9e3dd..7241017 100644 --- a/.ai/workflows/triage-intake.org +++ b/.ai/workflows/triage-intake.org @@ -167,6 +167,10 @@ If Craig has been silent for a while after Phase D and the surface looks closed- This rule prevents the failure mode where the workflow self-declares done and the next exchange has to relitigate what state things are in. +*** KB capture (only if the sweep surfaced something durable) + +If this sweep surfaced a durable, cross-project fact — a recurring pattern across sources, a reference pointer worth keeping, an environment gotcha — consider writing it to the agent KB as one =:agent:= node (see the best-practices node and =knowledge-base.md=; personal projects only, work never writes). One line of judgment, not a step: an all-quiet sweep surfaces nothing and writes nothing. Never blocking, never padded onto a no-signal run. + * Auto mode (unattended monitoring) diff --git a/.ai/workflows/wrap-it-up.org b/.ai/workflows/wrap-it-up.org index 139d612..b1560eb 100644 --- a/.ai/workflows/wrap-it-up.org +++ b/.ai/workflows/wrap-it-up.org @@ -33,6 +33,10 @@ The absence of =.ai/session-context.org= is the signal that the last session wra ** Step 1: Finalize the Summary +*** Early KB reflection (capture while fresh, before the Summary) + +Before distilling the Summary, while the session is still fresh, ask: what did this session learn worth remembering, for yourself or a future agent? Reflect and stage any candidate durable facts — a decision and its why, an environment gotcha, a reference pointer, a transferable lesson. Self-answer silently; this adds no interactive turn (Craig already authorized the wrap). The candidates flow straight into the KB promotion check below, which does the actual writing and the receipt — this is the capture half, that is the commit half, one pipeline, one receipt. Reflecting here rather than reconstructing learnings after the Summary is the point: the early ask is what keeps the receipt from defaulting to "promoted 0" out of fatigue. + Read through the =* Session Log= in =.ai/session-context.org=. Populate (or refine) the =* Summary= section: - *Active Goal* — one or two sentences describing the session's focus |
