aboutsummaryrefslogtreecommitdiff
path: root/todo.org
blob: d4b3c1c57f1fcf90c3afd9907af71d54d474f638 (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
#+TITLE: Rulesets — Work
#+AUTHOR: Craig Jennings
#+DATE: 2026-04-19

Tracking TODOs for the rulesets repo that span more than one commit.
Project-scoped (not the global =~/org/roam/inbox.org= list).

* Rulesets Priority Scheme

** Priority

- =[#A]= *Urgent risk or current workflow blocker.* Credential exposure, data loss, destructive behavior, startup breakage, failing tests that block work, or a feature/refactor that unblocks a core daily workflow. =[#A]= requires a =SCHEDULED:= or =DEADLINE:= date — if it can't be dated, it isn't really =[#A]=.
- =[#B]= *Important planned work.* Concrete bugs, high-leverage architecture cleanup, brittle load-order or test gaps, dependency failures, or feature work with clear design and expected near-term use.
- =[#C]= *Useful but optional.* Low-risk cleanup, ergonomics, smoke tests, investigations with limited current impact, or feature work that would improve the setup but isn't yet a committed workflow.
- =[#D]= *Someday or watchlist.* Speculative features, tiny polish, upstream tracking, optimizations without current pain, deferred ideas that shouldn't compete with active maintenance.

The scheme is importance-driven with optional urgency lift. Priority signals "does this matter and when," not "how big" — effort lives in the tags.

** Tags

Every task carries one *type tag* from this set:

- =:feature:= — adds new capability.
- =:chore:= — meta or housekeeping (tooling, sync, version bump, mechanical cleanup).
- =:spec:= — design document, brainstorm output, or research-backed proposal that precedes implementation.
- =:bug:= — fix to incorrect behavior.

Optional *effort and autonomy tags* — orthogonal to type, both can apply on the same task:

- =:quick:= — likely to take ≤30 minutes from start through verification.
- =:solo:= — Claude can complete the work end to end, including verification, without input from Craig.

Optional *dependency tags* — cross-project, both plain tags with the which-project detail in the task body (per =todo-format.md=):

- =:blocked:= — the task can't advance until another project delivers the work named in its body. =open-tasks.org= pulls =:blocked:= tasks out of the cascade and surfaces them on their own. Distinct from =VERIFY= (which waits on Craig).
- =:blocker:= — this task owes work that's blocking another project (named in its body). =open-tasks.org= surfaces =:blocker:= tasks first, since clearing one unblocks the other project.

Tags are assigned and refreshed by =task-audit=; =task-review= keeps them honest in passing.

* Rulesets Open Work

** TODO [#C] KB orphan-node review pass :chore:
:PROPERTIES:
:CREATED: [2026-07-01 Wed]
:END:
The 2026-07-01 kb-hygiene report listed 42 agent KB nodes with no inbound id: links (of 53 agent nodes; 0 conflicts, no duplicate titles). Orphan-ness alone isn't a defect — agent nodes are found by rg, not only by links — but a periodic pass is worth doing: prune nodes that aged out, merge near-duplicates, add id: links where clusters exist. Regenerate the list with the kb-hygiene script rather than trusting the snapshot. Propose deletions/merges to Craig before applying (auto-cleanup allowed only for :agent:-tagged nodes after approval, per knowledge-base.md).

** DONE [#B] wrap-it-up teardown + "wrap it up and shutdown" :feature:
CLOSED: [2026-07-01 Wed]
:PROPERTIES:
:CREATED: [2026-06-23 Tue]
:LAST_REVIEWED: 2026-06-24
:END:
Two additions to =wrap-it-up.org=, designed by Craig (home, 2026-06-23). Item 1: bare "wrap it up" also tears down the session — kill the =aiv-<proj>= tmux session (takes =claude= with it), kill the vterm buffer, restore geometry. Teardown is the default; "wrap it up with summary" wraps without teardown (keeps the buffer readable). Must fire from a Stop/SessionEnd hook via a sentinel file, decoupled and last, so the valediction flushes before the session dies, and strictly after commit+push is verified. Item 2: "wrap it up and shutdown" → wrap, then a hard blocking gate (abort unless this is the only live =aiv-*= session), then an abort-able 10→1 countdown, then =sudo shutdown now=. Countdown can't run through the Bash tool (stdout buffers — prints all ten at once); needs a detached tty writer or an Emacs =run-at-time= timer. Companion: =cj/ai-term-quit= (and optional =cj/ai-term-live-count=) must live in =.emacs.d/modules/ai-term.el= — route there via inbox-send when building so both sides land together. Open decisions for Craig first: qualifier wording ("with summary" vs "and summarize"), countdown home (tty script vs Emacs timer), session-count mechanism (=tmux ls= / =pgrep claude= / helper). Shared-asset, review-gated. Proposal: [[file:docs/design/2026-06-23-wrap-teardown-shutdown-proposal.org][proposal]]. From home 2026-06-23.

*** 2026-06-23 Tue @ 23:31:59 -0400 Built the rulesets side; companion routed to .emacs.d
Craig's three decisions (2026-06-23): non-destructive qualifier is *both* "with summary" and "and summarize"; countdown is an Emacs =run-at-time= timer; the gate uses =cj/ai-term-live-count=. Built and pushed: =hooks/ai-wrap-teardown.sh= (Stop hook, sentinel-gated, 8 bats tests green), =hooks/settings-snippet.json= Stop wiring, =wrap-it-up.org= Teardown-mode section + Step 6 + checklist, INDEX trigger update. Architecture: both teardown and shutdown fire from the Stop hook via a basename-keyed sentinel (=/tmp/ai-wrap-teardown-<proj>=, =/tmp/ai-wrap-shutdown-<proj>=) dropped only at the end of Step 6 after commit+push, so the valediction flushes first. No bin script — the gate/countdown/teardown are all =emacsclient= calls into the companion. Companion spec (=cj/ai-term-quit=, =cj/ai-term-live-count=, =cj/ai-term-shutdown-countdown=) routed to .emacs.d via inbox-send. Remaining: .emacs.d lands the three functions, then the manual end-to-end validation below. Task stays DOING until both sides verify.

*** 2026-06-23 Tue @ 23:40 .emacs.d received + filed the companion spec
Per a roam-inbox FYI from .emacs.d (2026-06-23 23:38): both ai-term handoffs (multi-LLM support + this wrap-teardown companion spec) landed and are filed as .emacs.d tasks. The teardown one is flagged for its own focused session to land alongside the rulesets half. Part (c) is now in progress on the .emacs.d side.

*** 2026-06-24 Wed @ 06:51:13 -0400 Unblocked — .emacs.d companion landed; feature now live
The three companion functions are in =.emacs.d/modules/ai-term.el= (=cj/ai-term-quit= 1068, =cj/ai-term-live-count= 1087, =cj/ai-term-shutdown-countdown= 1109), matching the contract — double-checked the bodies: quit kills session+buffer+restores layout idempotently, live-count returns the gate integer, shutdown-countdown re-checks the gate (TOCTOU guard), runs an abort-able =run-at-time= countdown (C-g cancels), then a configurable =cj/ai-term-shutdown-command=. 13 ERT tests, headless-verified live (.emacs.d FYI 2026-06-24 06:44). Dropped =:blocked:= / =:BLOCKED_BY:= — the build dependency is resolved; only the manual end-to-end validation below remains. NOTE: with the Stop hook wired and the companion present, the feature is now functional — the next bare "wrap it up" will actually tear the session down. Run the validation below before relying on it.

*** 2026-07-01 Wed @ 21:52:15 -0400 Plumbing pre-flight re-verified; only the eyes-on tests remain
Fresh pre-flight, all green: Stop hook block in =~/.claude/settings.json= points at =~/.claude/hooks/ai-wrap-teardown.sh=, the symlink resolves to the rulesets canonical, no stale =/tmp/ai-wrap-teardown-*= sentinel, and all three companion functions are live in the daemon (=(t t t)=). Three =aiv-*= sessions live right now (=_emacs_d=, =archsetup=, =rulesets=), so the shutdown-gate refusal test has its multi-session condition available. Everything left in the checklist below needs Craig's eyes on a scratch session: buffer teardown + geometry restore, the qualifier opt-outs, the countdown render + C-g, and the push-failure guard.

*** 2026-07-01 Wed @ 21:59:43 -0400 Manual end-to-end validation passed — all five tests, Craig's live run
Craig ran the full checklist in a live Emacs/tmux ai-term setup: (1) bare "wrap it up" tore down after the valediction rendered, geometry restored, no lingering sentinel; (2) "with summary" / "and summarize" both wrapped without teardown, buffer stayed readable; (3) "wrap it up and shutdown" with another aiv-* session live refused the shutdown, named the other session, fell back to a normal wrap; (4) as the sole session, the 10→1 echo-area countdown rendered one-per-second, C-g cancelled cleanly, and a full run fired the (stubbed) shutdown command; (5) with the push made to fail, the wrap stopped at the failure and no sentinel was dropped. Works great — feature validated and live. Both sides complete: rulesets Stop hook + wrap-it-up Teardown mode, .emacs.d companion functions.

** TODO [#B] Helper-agent instance support — concurrent same-project Claude :feature:spec:
:PROPERTIES:
:CREATED: [2026-06-11 Thu]
:LAST_REVIEWED: 2026-06-24
:END:
SPEC REVIEWED 2026-06-12: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org][Codex review]] now rates Phase 1.5 =Ready with caveats=. Before any build, keep the Emacs integration as a cross-project handoff to =~/.emacs.d=, preserve the three-ring gate (bats → sandbox drills → pilot project), and do not let startup/helper changes reach synced template paths until the live drills pass.

Implement Phase 1.5 of the generic-agent-runtime spec ([[file:docs/design/2026-05-28-generic-agent-runtime-spec.org][spec]], amended 2026-06-11 with the "Concurrent same-project agents" section). Craig's case: spawn a second Claude in the same project to look things up or update tasks safely while the primary works. The session-context split (AI_AGENT_ID + session-context.d/) already shipped; this builds the rest:

- =agent-roster= detection script (the load-bearing piece, replaces operator action entirely): pgrep + /proc cwd match within project root + self-ancestry exclusion; verified live 2026-06-11 with 4 concurrent agents. Bats coverage.
- Startup detection-first: the roster check runs before Phase A.0's pulls; not-alone routes to the new =helper-mode.org= role contract and runs nothing else; alone keeps crashed-vs-fresh anchor logic (the roster also disambiguates crashed primary from live primary).
- =helper-mode.org= template workflow: identity self-assignment (helper-<rand4>, recorded in its own .d/ context file), the read/write tiers, light start, helper wrap-up. Auto-routed, no trigger phrase.
- =ai --helper= as the deterministic spawn path (Craig's shell-script point: a script can't skip the check): roster → id export → launch with the helper-mode opener; warn-and-run-primary on empty roster. The startup roster check stays as the safety net for raw launches.
- Wrap-up ordering: helper wrap-up re-runs the roster — orphaned helper (primary already gone) assumes full closing duties incl. commit+push (the git ban is concurrency-scoped and lifts when alone; otherwise its edits strand as a dirty tree); primary wrap-up with live helpers pauses at the commit and asks (commit helper WIP / wait / leave closing to the helper).
- Shared-file read/write contract into protocols.org pointing at helper-mode.org (helper: scoped single-heading org edits only; file-wide passes, inbox processing, and all git mutation stay primary-only); helper branches in startup.org (light path, no pulls/rsync) and wrap-it-up.org (archive own file, skip hygiene + commit).
- Bats: launcher id assignment/sanitization, helper-vs-primary resolution, two simultaneous context files.
- Data-integrity items (spec second pass, 2026-06-11): live-helper gate before any file-wide hygiene pass (todo-cleanup/lint-org/wrap-org-table check session-context.d/, pause + ask on live files, surface stale ones); todo-cleanup.el brought up to the backup-to-/tmp invariant (lint-org and wrap-org-table already conform — verified); log-before-write journaling for helper shared-file edits; memory writes primary-only (MEMORY.md has no heading anchors — helpers log candidates instead); agent id in helper-originated inbox-send slugs (minute-resolution filenames can collide).
- Manual validation with Craig: live helper against a live primary — lookup, one scoped todo.org edit, wrap-up, primary commits the helper's edit cleanly. Then the corruption drill: primary attempts wrap-up while the helper is mid-task and the hygiene gate visibly pauses.

Independent of the spec's phases 2-6 (runtime-neutral refactor), which stay gated on their own go/no-go.

*** 2026-06-15 progress — detection + contract landed (inert); wiring is what's left
RESUME NOTE. Before picking this back up as the big item, re-read what it is, does, and why first — don't dive straight into the next slice. The orientation, in one breath: this lets Craig open a second Claude in the *same project* while a primary session is running (a second terminal, to look something up or make a small task edit) without the two sessions clobbering each other's files. The whole risk it manages is two Edit-tool writers on one shared file (todo.org, notes.org) losing each other's writes, last-write-wins, silently. The design's answer: a singleton primary keeps the unisolated session-context.org; helpers get their own session-context.d/<id>.org, make only scoped single-heading edits to shared files, and never touch git. Full why-and-how in the spec ([[file:docs/design/2026-05-28-generic-agent-runtime-spec.org]], "Concurrent same-project agents" amendment) and the contract ([[file:.ai/workflows/helper-mode.org]]). A helper is NOT a subagent — subagents are for bounded dispatched lookups; this is for interactive parallel work Craig drives himself.

Done so far (shipped, pushed, inert until wiring routes to them):
- agent-roster (commit f8bdf30): the detection primitive. pgrep -x claude → /proc cwd → keep in-project → drop own ancestry. Exit 0 alone / 1 others / 2 unavailable. Injectable boundary (ROSTER_PGREP/PROC/SELF_PID), 11 bats, live-verified against 4 real sessions. [[file:.ai/scripts/agent-roster]].
- helper-mode.org (commit 0b681dc): the canonical contract — read/write tiers, four data-integrity rules, light startup, helper wrap-up. Triggerless INDEX entry, protocols.org pointer.
- Already shipped earlier: the AI_AGENT_ID + session-context.d/ split, and (2026-06-14) the epoch-on-the-tail id convention.

What's next — the WIRING, all behind the spec's three-ring gate (bats → sandbox drills → live pilot), none of it sync'd to live template paths until the two-session drill passes:
- Startup roster-detection branch: roster runs first; not-alone routes to helper-mode.org, alone keeps crashed-vs-fresh anchor logic. (Edits startup.org — synced, gated.)
- wrap-it-up.org helper branch (archive own file, skip hygiene+commit; orphaned-helper lifts the git ban).
- ai --helper launcher: roster → assign+export id → launch with helper opener. Plus the Emacs surface (ai-term.el) via an .emacs.d cross-project handoff.
- Hygiene-pass live-helper gate: todo-cleanup.el / lint-org.el / wrap-org-table.el check session-context.d/ and pause+ask on live helper files.
- todo-cleanup.el backup-to-/tmp backstop (lint-org and wrap-org-table already conform).
- Manual validation drills with Craig (the live two-session test + the corruption drill).

Stand up a drill rig before the gated work; build against it, don't touch synced paths until the live drill passes.

DEPENDENCY QUESTION (Craig, 2026-06-15, resolved 2026-06-24 — see below): doesn't helper-instance support depend on generic agent runtime support? Starting point: the spec frames this work as Phase 1.5, "Independent of the spec's phases 2-6 (runtime-neutral refactor), which stay gated on their own go/no-go," and the body claims it sits only on the already-shipped session-context split. The separate =Generic agent runtime support — Codex spec v0= task (#C, below) is that phases-2-6 arc. So the spec's stated answer is "no, 1.5 is independent" — but confirm that's actually true for every wiring slice (does ai --helper, the roster branch, or helper-mode routing secretly assume any runtime-manifest / multi-runtime machinery from 2-6?), or whether helper-instance should be sequenced after, or merged into, the generic-runtime task.

*** 2026-06-24 Wed @ 00:30:32 -0400 RESOLVED — independent, unblocked (keyword VERIFY → TODO)
Craig's call (2026-06-24): helper-instance is independent of the generic-runtime refactor and builds on its own. The shipped pieces and the remaining wiring are all shared-file concurrency-safety (two Edit writers, one file), orthogonal to which LLM runtime launches — none of it assumes the runtime-manifest / multi-runtime machinery of phases 2-6. One caveat: =ai --helper= overlaps the launcher refactor the generic-runtime arc plans, so keep that launcher change small and contained so the later refactor doesn't fight it. Now a buildable [#B] task behind its own three-ring gate (bats → sandbox drills → live pilot).

** DOING [#B] Wrap-up inbox/transcript routing to destination projects :feature:spec:
:PROPERTIES:
:CREATED: [2026-06-13 Sat]
:LAST_REVIEWED: 2026-06-24
:END:
Optional wrap-up step that surfaces filed keepers belonging to another project, recommends a destination, and routes each to that project's =inbox/= via =inbox-send= (the destination's own =process-inbox= files it; transcript filing deferred to vNext). Spec: [[file:docs/specs/wrapup-routing-spec.org]] — Ready, [9/9] decisions. Source proposal: [[file:docs/design/2026-06-13-wrapup-inbox-transcript-routing-proposal.org]].

*** 2026-06-21 Sun @ 02:06:37 -0400 Spec-review + spec-response complete — Ready
Craig's review challenge reshaped the design from a direct cross-repo =todo.org= move to =inbox-send= delivery into the destination's inbox (safer: reuses the sanctioned cross-project path, gets provenance + per-project filing for free, degrades gracefully where a destination has an =inbox/= but no =todo.org=). D2/D3 superseded; D7 (inbox-send delivery), D8 (=:ROUTE_CANDIDATE:= marker at file time), D9 (local source removal + reject-flow recovery) added. Spec-review file consumed and deleted. Implementation-task breakdown filed below (spec-response Phase 6).

*** 2026-06-24 Wed @ 00:21:20 -0400 Reconcile — marker sub-task repointed at inbox.org
The 2026-06-23 inbox consolidation (24ca58d) merged =process-inbox= + =monitor-inbox= + =inbox-zero= into one =inbox.org= engine (process/monitor/roam modes) and deleted the three old files. The =:ROUTE_CANDIDATE:= marker sub-task targeted =process-inbox.org='s Phase D — repointed it to =inbox.org= process mode (core §3 "File as TODO"). No build has started, so this is a target-rename only; the spec design is unaffected.

*** 2026-06-28 Sun @ 13:02:42 -0400 Built the recommendation engine + destination discovery
Added =.ai/scripts/route_recommend.py= (canonical + mirror): pure =recommend(item, projects) → (destination, confidence)= with strong (name/path literal, word-boundary matched, dot-stripped alias aware), weak (distinctive name-token overlap), and none tiers; a multi-way top-tier tie downgrades to weak with a deterministic pick (most overlap, then alphabetical); empty list → none. The CLI (=--item=, =--exclude=) reuses =inbox-send.py='s =discover_projects= via importlib so the candidate set matches inbox-send's project universe. 13 tests (the five spec'd cases + boundary/path/strong-beats-weak + 3 sandboxed CLI integration tests), full =make test= green. Covers spec Phases 1 + 3. Next sub-tasks (=:ROUTE_CANDIDATE:= marker, wrap-up router) call this engine.

*** 2026-07-02 Thu @ 00:36:12 -0400 Phases 2 + 4 + test surface landed — marker, router, route-batch helper
inbox.org's "File as TODO" disposition now runs route_recommend on each keeper and stamps =:ROUTE_CANDIDATE: <destination>= on strong/weak matches (none stamps nothing; local keepers stay unstamped) — spec Phase 2 / D8. wrap-it-up.org Step 3 gained the optional router directly after the inbox sanity check, with the gate-vs-optional split named in the prose: surface the batch (task / destination / delivery mode / confidence, weak visibly labeled), go/skip, empty set = zero interaction — spec Phase 4 / D7 / D9. The go path is mechanical: new =.ai/scripts/route-batch= (--list read-only, --go extracts the subtree minus the marker with children riding along and headings promoted, delivers via inbox-send for provenance, removes the local subtree only after a successful send; a failed send leaves the task in place and exits non-zero). Test surface: engine unit tests existed (13); route-batch adds a 9-test bats suite (list/backlog-exclusion, empty-set silence, list-modifies-nothing = skip semantics, delivery + provenance + children, local-task survival, drawer-minus-marker, inbox-without-todo.org delivery, empty go, failed-send recovery). cross-project.md notes the router as a sanctioned cross-project write path. make test green, sync clean.

*** TODO [#B] Wrap-up routing — manual end-to-end validation :test:
What we're verifying: a real keeper routes through a live wrap and the destination actually files it.
- In a project session, let process-inbox file a handoff whose home is a different project; confirm the local task carries =:ROUTE_CANDIDATE: <dest>=.
- Run wrap-it-up; at the router sub-step, confirm the candidate is surfaced with the right destination + confidence, then choose "go".
- Confirm a =from-<thisproject>= handoff landed in the destination's =inbox/= and the keeper was removed from the local =todo.org=.
- Open the destination project; confirm its startup/process-inbox files the handoff into its =todo.org= per its own conventions.
Expected: the task ends up in the destination's =todo.org=, gone from the source, with no foreign =todo.org= written directly. Not =:solo:= — needs a real cross-project wrap and the destination's next session.

*** TODO [#D] Wrap-up routing — transcript filing (vNext) :feature:no-sync:
File a meeting recording into the destination =assets/= per =working-files.md=, batch go/skip mirroring the task router. Gated on the source-location decision (spec D4). Spec: [[file:docs/specs/wrapup-routing-spec.org]] (Phase 5).

** TODO [#C] Multiple agent-source improvements :spec:
:PROPERTIES:
:CREATED: [2026-06-23 Tue]
:LAST_REVIEWED: 2026-06-24
:END:
Make the tooling agent-agnostic instead of Claude-specific. Three threads from Craig (roam 2026-06-23): (1) give the agent a name so workflows don't say "Claude" everywhere — a non-Claude agent (Codex) reading "you are Claude" gets confused; evaluate whether naming resolves the confusion or whether other spots also leak Claude-specificity. (2) Pull agent-neutral content out of Anthropic-specific files (=CLAUDE.md=) into a shared source that each agent's own entry file points to, so Codex (which runs more literal) reads the same rules; or link =CLAUDE.md= and the Codex equivalent to one source. Have Codex review the workflows for literal-reading wording gaps. (3) Send =.emacs.d= a note (inbox-send) to let =ai-term= launch Claude / Codex / a local ollama LLM, switchable seamlessly at session start. Spec-shaped — needs design before build. From the roam inbox 2026-06-23 (deferred from the 2026-06-21 session).

*** 2026-06-24 Wed @ 00:21:20 -0400 Partial — agent-neutral wording sweep + thread-3 note landed
Thread 2's wording half shipped in 6ad0442 (=refactor(rules): use agent-neutral language in shared rules=): agent-as-actor phrasing replaced with "the agent" across interaction.md, cross-project.md, triggers.md, working-files.md. Thread 3's note reached =.emacs.d=, whose 2026-06-23 inbox FYI confirms it received and filed the "multi-LLM support" ai-term handoff. Remaining and still TODO: thread 1 (give the agent a name), and thread 2's structural half (extract agent-neutral content into a shared source with a Codex entry-file pointer, then have Codex review the workflows for literal-reading gaps).

** TODO [#C] Flashcard tooling improvements :feature:
:PROPERTIES:
:CREATED: [2026-06-28 Sun]
:LAST_REVIEWED: 2026-06-28
:END:
Three flashcard-tooling tasks that all edit =flashcard-to-anki.py= and/or =flashcard-stats.py=, grouped so they get built together instead of colliding on the same files (prior sessions flagged the conflict risk). The Anki =#+TITLE= deck-name fix already landed (commit 060a938), so any preserved pre-fix script copy gets re-derived against the current canonical, never copied wholesale. The three children each ship independently.

*** TODO [#C] apkg → org-drill converter :feature:solo:
:PROPERTIES:
:CREATED: [2026-06-22 Mon]
:LAST_REVIEWED: 2026-06-24
:END:
Inverse of =flashcard-to-anki.py=: read an Anki =.apkg= (zip → =collection.anki2=/=.anki21= sqlite) and emit an org-drill =.org= in the house canonical shape. Recovers orphaned decks (=deepsat-fundamentals.apkg= has no saved =.org= source) and enables phone→org round-trip. Mapping: deck name → =#+TITLE=; each note → =** <Front> :drill:= with Back as body; card tag → =* Section= grouping (best-effort); Back HTML → org (=<br>= → newlines, unescape entities, strip =<hr id="answer">=); fresh =:ID:= UUID per card. Edge cases for tests: multiple decks per apkg, non-basic note types (skip/warn), HTML entities, empty back, media refs, =.anki2= vs =.anki21= schema. Lives beside the flashcard-* family in =claude-templates/.ai/scripts/= (a new file must be built in canonical — downstream =.ai/scripts/= is wiped by startup =--delete=). PEP 723 uv-run, stdlib =zipfile= + =sqlite3= (no genanki for reading). Acceptance: round-trip a known org-drill source through =flashcard-to-anki.py= then back, assert cards match. Build request: [[file:docs/design/2026-06-21-apkg-to-orgdrill-buildreq.org][buildreq]]. Backlog, not urgent. From home 2026-06-21.

*** TODO [#C] flashcard-stats refutation / claim-prompt mode :feature:
:PROPERTIES:
:CREATED: [2026-06-22 Mon]
:LAST_REVIEWED: 2026-06-28
:END:
A refutation card (heading is a bare false claim, body is the rebuttal) is valid org-drill but trips two BLOCKING =flashcard-stats.py= checks as false positives: non-prompt-heading (a declarative claim has no =?= or imperative verb) and answer-leakage (claim words reappear in the rebuttal). =flashcard-sync='s gate then blocks the whole deck.

Design (Craig, 2026-06-28, supersedes the two proposed options): make the exemption *generic*, not refutation-specific — more card kinds like this will come. When the org header declares the relevant info, the gate honors it rather than blocking. So a general file-level header keyword (a card-kind / check-exemption declaration) tells =flashcard-stats.py= which checks not to apply, instead of a hardcoded =#+DECK_KIND: refutation= keyword or a per-card =:claim:= tag. Document the mechanism in =flashcard-review.org= and add tests (a header-declared exemption file passes despite declarative headings + claim/answer overlap). Edits =flashcard-stats.py= — coordinate with the multi-tag reconcile, same file. Proposal: [[file:docs/design/2026-06-21-flashcard-stats-refutation-proposal.org][proposal]] (its two-option fix is superseded by this generic header approach). Backlog. From home 2026-06-21.

*** TODO [#C] Reconcile flashcard multi-tag tooling into canonical :chore:quick:solo:
:PROPERTIES:
:CREATED: [2026-06-20 Sat]
:LAST_REVIEWED: 2026-06-24
:END:
The work project edited two synced scripts locally as a stopgap (2026-06-17) and asked rulesets to fold them into the canonical so the next sync doesn't revert them. Preserved bundle: [[file:docs/design/2026-06-17-flashcard-multitag-note.md][note]], [[file:docs/design/2026-06-17-flashcard-multitag-to-anki.py][to-anki.py]], [[file:docs/design/2026-06-17-flashcard-multitag-stats.py][stats.py]]. Change: support a second org tag on drill headings (=:fundamental:drill:=) for curated subset decks. =flashcard-to-anki.py= — broaden =CARD_RE= to match a trailing tag block (a heading is a card when =drill= is among its tags), bound the card body by any L1/L2 heading, add =--tag-filter <tag>= (emit only cards carrying that tag) and =--guid-salt <s>= (separate GUID space so a subset deck imports non-empty without disturbing the full deck's SRS state). =flashcard-stats.py= — same =CARD_RE=/=HEADING_RE= broadening plus a drill-membership guard. Use the preserved to-anki.py (the 0953 version: dropped an unused =heading_tags()= helper, tightened =CARD_RE= =(.*?)=→=(.+?)= for parity with stats). Apply to both =.ai/scripts/= and =claude-templates/.ai/scripts/=, add a multi-tag bats case to =flashcard-sync.bats= (a =:foo:drill:= heading parses; =--tag-filter foo= returns only those), verify the full deck still parses to 465 and =--tag-filter fundamental= returns 100, then sync-check + make test. Shared-asset change, so review-gated.

Note (2026-06-24): the Anki =#+TITLE= deck-name fix landed (commit 060a938) — =default_deck_name= is now =default_deck_name(input_path, org_text)= with a new docstring. The preserved 2026-06-17 =to-anki.py= predates that, so *don't* copy it wholesale (it would revert the title-fix). Re-derive the multi-tag changes against the current canonical =flashcard-to-anki.py= and keep the =#+TITLE= behavior.

** TODO [#C] Guard against hardcoded host identity in synced files :feature:solo:
:PROPERTIES:
:CREATED: [2026-06-22 Mon]
:LAST_REVIEWED: 2026-06-24
:END:
A =CLAUDE.md= / notes file that asserts mutable environment identity as a fixed fact ("This machine is ratio", a current OS, an IP, "the laptop") is false on every machine the synced/tracked file lands on but one. It bit a real archsetup session: a stale "this machine is ratio" line made the agent reason backwards all session while on velox. Proposal: a claude-rule — don't assert mutable host/env identity as a fixed fact in a tracked/synced project file; derive it at runtime and name the command (=uname -n= for host; the =hostname= binary is often absent). Optionally a codify- or startup-time lint flagging "this machine is <name>" / "the current host is" style claims. Decide rule-only vs rule+lint. Proposal: [[file:docs/design/2026-06-21-host-identity-guard-proposal.org][proposal]]. From archsetup 2026-06-21.

** TODO [#C] coverage-summary.el documented as a local-only helper :chore:
:PROPERTIES:
:CREATED: [2026-06-22 Mon]
:LAST_REVIEWED: 2026-06-28
:END:
The elisp bundle installs =coverage-summary.el= into =.claude/scripts/=, gitignored in code projects, so CI can't run =make coverage-summary= against it. Decision (Craig, 2026-06-28): keep it in =.claude/scripts/= and document it as a local-only helper — don't ship it to a tracked =scripts/= dir, don't expect CI to run it. Remaining work (docs only, no move): state the local-only status in the script's header comment and wherever =make coverage-summary= is described, so the gitignored install reads as intentional rather than a gap. Note: emacs-wttrin rewrote its copy's header to claim a tracked =scripts/= home, which now contradicts this decision and should be reverted on their side. Surfaced 2026-06-21 during the coverage-summary autoloads bugfix (commit fb86736).

** VERIFY [#C] Check that memories are sync'd across machines via git :spec:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-28
:END:
v1 implemented end-to-end 2026-06-10 (Phases 0-4, all shipped + pushed). Implementation is complete. Remaining before DONE: the manual testing and validation child (below). The other personal machines' one-time =roam.git= clone + sync-timer setup is now confirmed on both daily drivers (velox + ratio, 2026-06-30).
*** 2026-05-14 Thu @ 19:14:11 -0500 Investigate current memory storage

Memory files live at
[[file:/home/cjennings/.claude/projects/-home-cjennings-code-rulesets/memory/][~/.claude/projects/-home-cjennings-code-rulesets/memory/]]
— four files including =MEMORY.md= and three individual entries
(=feedback_never_guess.md=, =project_ai_scripts_canonical_source.md=,
=reference_pdftools_venv.md=). The directory is a plain unmanaged dir
(no symlink, no enclosing git checkout). Neither
[[file:/home/cjennings/.claude/][~/.claude/]] itself nor any subtree
containing the project-memory dirs is tracked in
[[file:/home/cjennings/code/archsetup/][archsetup]] or
[[file:/home/cjennings/code/rulesets/][rulesets]]. Without a symlink
into a stowed or tracked location, memory files don't survive a new
machine setup or a dotfiles restore.

Proposed setup: stow =~/.claude/projects= →
=archsetup/dotfiles/common/.claude/projects/= (path doesn't exist yet
— it's the target location pending VERIFY).
Create the destination in archsetup, move existing per-project
=projects/<encoded-cwd>/memory/= dirs there, run =stow= to link, then
commit + push archsetup. After that, every machine running =stow=
picks up the same memory tree.

*** 2026-05-23 Sat @ 16:12:48 -0500 Decided: dedicated private repo, not stow
Worked through dotfiles → rulesets → dedicated repo. Dropped stow/dotfiles (machine config, wrong cadence) and rulesets (it's pulled first in every session, so memory edits would dirty its tree and skip the startup =git pull --ff-only=). Chose a dedicated private repo on cjennings.net: storage is unified there while recall stays per-project (the encoded-cwd subdirs), since pooling recall would hurt relevance and risk work-private facts surfacing in personal-project artifacts.

*** 2026-05-23 Sat @ 16:12:48 -0500 Shipped: claude-memory.git + folded symlinks
Created bare =git@cjennings.net:claude-memory.git=, cloned to =~/.claude-memory= (later deleted in the reversal below), moved all 7 per-project =memory/= dirs in (54 files; work has 40) and replaced each live =~/.claude/projects/<enc>/memory= with a folded dir-symlink so new memory lands in the clone and a push syncs it. Added =link-claude-memory.sh= (idempotent — recreates the symlinks on a new machine after clone) + README. Private repo, never GitHub (carries work/DeepSat memory). Initial import pushed (=f496370=).

*** 2026-05-24 Sun @ 01:53:35 -0500 Reversed the migration — back to unmanaged per-project memory
Cancelled the follow-up brainstorm and undid the dedicated-repo migration at Craig's call. Moved all 7 memory dirs back to =~/.claude/projects/<enc>/memory/= (content preserved), deleted the =~/.claude-memory= clone, and deleted the bare =claude-memory.git= on the server. Memory is back to its original at-risk state, so the task reopens at [#C] pending a direction. The brainstorm landed on a two-tier idea for whenever this resumes: promote general lessons into a rulesets-tracked file symlinked into =~/.claude/rules/= (loaded into every project natively, one repo), and keep project-specific memory under each project's own =.ai/memory/= (committed where =.ai/= is tracked, at-risk where it's gitignored). Not implemented.

*** 2026-06-05 Fri @ 05:57:35 -0500 Pivot: adopt the existing org-roam KB as the shared agent substrate
Pressure-tested the two-tier idea, then Craig redirected: a shared org-roam knowledge base any project can read and write makes this simpler. Ground truth verified: =~/sync/org/roam/= already exists (484 org files, curated since 2023, Syncthing-synced, not git). So cross-machine sync is already solved, and the task stops being "build a memory-sync system" and becomes "point agents at the KB that already syncs." The dedicated-repo and two-tier approaches are both superseded for the storage+sync half.

Wrote a one-page spec: [[file:docs/specs/agent-knowledge-base-spec.org][agent-knowledge-base-spec.org]] (originally docs/design/2026-06-05-org-roam-knowledge-base-spec.org; superseded by the 2026-06-10 spec-create rewrite at the new path). Five decisions, mechanics recommended: (1) KB is a queried substrate accessed as files (ripgrep + follow =[[id:]]= by grep), not via the org-roam package; (2) capture in harness memory, promote durable facts into the KB (same cadence as the pattern catalog) — resolves the at-risk problem since the valuable knowledge moves to the synced KB; (3) a =claude-rules/knowledge-base.md= pointer rule carries path/query/write-schema/boundary; (4) write schema = roam-valid node + =:agent:= filetag so agent notes stay distinguishable and index on the next =org-roam-db-sync=. The rules layer (=claude-rules/=, =CLAUDE.md=) is untouched — the KB replaces the memory tier, not the rules tier.

*** 2026-06-10 Wed @ 14:29:20 -0500 Spec ratified — write boundary is option C; rewritten to spec-create format
Craig answered via cj annotations in the spec (2026-06-10): DECISION 5 is option C (read-shared, write-scoped — work agents never write the KB). Syncthing does replicate ~/sync/ to a work machine and Craig is fine with how C handles it. Node granularity: per-fact nodes. Write review: agent writes land freely in the KB only — explicitly not permission to post to email, Linear, or any public channel without review and consent. The spec was rewritten into the spec-create format at [[file:docs/specs/agent-knowledge-base-spec.org][agent-knowledge-base-spec.org]] (old draft removed). Implementation explicitly held pending Craig's go-ahead; one decision still open (D7, next VERIFY).

*** 2026-06-10 Wed @ 14:35:40 -0500 Spec review — not ready
Review written at docs/agent-knowledge-base-spec-review.org (deleted on disposition completion; content summarized in the spec's Review dispositions). Rubric: =Not ready=. Blockers: resolve D7 (keep vs retire harness memory) and define the executable personal/work/unknown write-boundary classifier plus work-side write/refusal destination. Medium notes: use concrete ripgrep commands that exclude =*.sync-conflict-*= files, and define seed-node approval/rollback.

*** 2026-06-10 Wed @ 14:44:00 -0500 D7 resolved — keep harness memory as the capture layer
Craig ratified "keep" in chat (2026-06-10). Harness memory stays the ephemeral, auto-recalled capture layer; the KB holds promoted durable facts; Phase 3's wrap-up promotion cadence is mandatory. Spec D7 flipped to accepted; D2 stands as written.

*** 2026-06-10 Wed @ 14:44:00 -0500 Project classification defined — work-root denylist, unknown refuses
Resolved in the spec-response pass: =knowledge-base.md= carries an explicit work-root denylist (initially =~/projects/work=) as the source of truth. Personal = under a known project parent (=~/code/=, =~/projects/=, =~/.emacs.d=) and not denylisted → KB writes allowed. Work or unknown → no KB write; the agent reports the refusal with a one-line redacted summary of the fact. v1 adds no new work-side store — work projects keep their existing project-tree conventions. See the "Project classification and write routing" section of [[file:docs/specs/agent-knowledge-base-spec.org][the spec]]. Denylist completeness is the one open caveat (next VERIFY).

*** 2026-06-10 Wed @ 14:44:00 -0500 Codex review incorporated — spec ready with caveats
Spec-response pass processed the 2026-06-10 Codex review with D7 = keep as a pre-agreed input. Both blockers cleared (D7 accepted; classification/write-routing section added). Mediums accepted: canonical rg commands with conflict-file exclusion, Phase 2 seed-node approval/rollback mechanics, Makefile no-change note, Testing/Verification section. Three recommendations modified, none rejected — see the spec's Review dispositions. Review file deleted per the workflow. Rubric: ready with caveats (denylist confirmation). Implementation tasks broken out below; implementation itself awaits Craig's go.

*** 2026-06-10 Wed @ 17:29:37 -0500 Work-root denylist confirmed — ~/projects/work only
Craig confirmed (2026-06-10, in chat): the denylist is just =~/projects/work=. Archangel is not work-scoped. The spec's one caveat clears — status now ready. Phase 1 is unblocked, but implementation still awaits Craig's explicit go.

*** 2026-06-10 Wed @ 17:57:08 -0500 Spec amended — D8 git transport + migration/metrics/docs/maintenance folds
Craig's five design questions answered and folded into the spec, and D8 ratified (Shape A): the KB moves out of the =~/sync/org= Syncthing share into its own git repo on cjennings.net, with an =agents/= subdirectory for agent writes, a systemd auto-sync timer for Craig's edits, opt-in-by-clone replication (work machine doesn't clone), and the phone staying on the on-demand =~/sync/phone= pattern. Folded in: inclusion criteria + a Phase 1.5 guided memory sweep, a Success metrics section with a 30-day checkpoint, the seed node redefined as the KB's own documentation, and Phase 4 maintenance automation. Phases renumbered 0-4; tasks below updated. Implementation still held.

*** 2026-06-10 Wed @ 18:21:33 -0500 Phase 0 done — roam migrated to git
Backed up (~/roam-backup-2026-06-10.tar.gz), copied to =~/org/roam=, 63 conflict files deleted (424 org files), git repo with origin =git@cjennings.net:roam.git= (initial commit 515693d), old location replaced with a transition symlink. Emacs =roam-dir= updated in user-constants.el + live-reloaded (db rebuilt, 416 nodes); handoff to .emacs.d for the commit. =roam-sync.sh= (6 bats green) on a 15-min systemd user timer, installed + enabled + round-trip verified. Old-path references repointed (protocols task-list pointer, journal workflow, notes template). archsetup handoff covers dotfiles adoption + other-machine clones. rulesets commit fcf554a.

*** 2026-06-10 Wed @ 18:21:33 -0500 Phase 1 done — knowledge-base.md rule live
=claude-rules/knowledge-base.md= written (path, git discipline, query commands, agents/ write schema, denylist + refusal contract, inclusion criteria, capture-then-promote). =make install= linked it machine-wide; verified the link, a known-note query, and conflict-glob exclusion with a planted file. Commit d071f1f.

*** 2026-06-10 Wed @ 18:21:33 -0500 Phase 1.5 done — rulesets swept, 10 projects broadcast
Rulesets' 6 memories classified: 3 promoted as =agents/= nodes (notify-attention pattern, pdftools venv, gpg-agent SSH TTL trap), 2 kept local (rule-encoded in verification.md / interaction.md), 1 kept + de-staled (ai-scripts-canonical updated for the claude-templates subtree fold). Sweep handoff broadcast to the 10 other memory-bearing projects (archsetup, org-drill, pearl, .emacs.d, elibrary, finances, health, home, jr-estate, kit); work skipped by the boundary; the orphaned =linear-emacs= memory dir (project retired, likely pearl's predecessor) noted for Craig.

*** 2026-06-10 Wed @ 18:21:33 -0500 Phase 2 done — seed/doc node written and indexed
=agents/20260610181640-how-the-agent-knowledge-base-works.org= written: the KB's user-facing guide (what agents do, how it syncs, finding/pruning agent content, the rule pointer). Index verified programmatically: =org-roam-node-from-title-or-alias= resolves it with tags (agent reference); node count 416 → 420. Craig's visual check remains in the manual-testing child.

*** 2026-06-10 Wed @ 18:21:33 -0500 Phase 3 done — wrap-up promotes + records the KB receipt
wrap-it-up.org Step 1 gains the promotion check (inclusion-criteria bar) and the mandatory "KB: promoted N / consulted yes-no" Summary line; validation checklist enforces it. Mirror synced, integrity OK (44), parse OK. Commit 242b95e.

*** 2026-06-11 Thu @ 19:26:26 -0500 .emacs.d memory sweep complete (first broadcast response)
First of the 10 broadcast projects to report Phase 1.5 done (handoff 18:23). Inventory 7: promoted 3 to KB (no-make-frame-in-live-daemon, proton-bridge-headless-cert-mismatch, open-images-with-imv — roam commit a915760), kept 3 local at Craig's call (commit-flow-no-approval-gate per-project-scoped; two theme-scoped ones possibly superseded by the palette-columns spec), deleted 1 (superseded by canonical interaction.md rule). 9 projects' sweeps outstanding.

*** 2026-06-12 Fri @ 02:25:12 -0500 Five more sweeps complete via the home folds
Overnight handoffs from home closed five more broadcast targets, each swept at fold-time triage with Craig's approval: jr-estate 2 promoted (forms name-with-number, PDF-editing tooling split; roam 45d8e6c) / 3 kept with area attribution / 2 deleted as rule-encoded or duplicate; finances 0/1/0 (rosalea-daly contact fact kept local); elibrary 0/0/2, health 0/0/1, kit 1/0/2 (hand-prep-items-to-work-inbox promoted into home's memory; the rest duplicated rules or home memories). Nothing from these five met the KB bar that wasn't already encoded. All folded projects' session archives merged area-prefixed into home's .ai/sessions/, so session-harvest's first run sees them. Home covers its own and remaining areas' sweeps through ongoing discipline; still pending from the broadcast: archsetup and work.

*** VERIFY Agent KB — manual testing and validation :test:
What we're verifying: the v1 acceptance surface that needs Craig's eyes or a live cross-project session. Run after Phases 0-2 land.
- Seed node appears in org-roam (autosync) and in the =rg '#\+filetags:.*:agent:'= inventory.
- In the work project, a durable-storage request produces no write in the KB and the refusal report names the fact.
- In an unknown project (outside =~/code/=, =~/projects/=, =~/.emacs.d=), the agent refuses or asks rather than guessing.
- After Phase 0: an edit made on one machine appears on another within the auto-sync timer interval, no new sync-conflict files appear, and the work machine has no KB clone.
Expected: all four behave per the spec; any miss promotes to a bug task. (Agent-runnable checks — make install link, rg finds a known note, conflict-file exclusion — are verified inside Phases 0-2.)

*** 2026-06-10 Wed @ 18:21:33 -0500 Phase 4 done — monthly hygiene automation live
=scripts/kb-hygiene.sh= (6 bats green, shellcheck clean, read-only by design) inventories =:agent:= nodes, flags orphans / duplicate titles / conflict files, and writes an org report into the rulesets inbox; =roam-hygiene.timer= (monthly, Persistent) installed + enabled. Live run against the real KB verified (4 agent nodes, 428 files, 0 conflicts). Conditional vNext stays in the spec's scope tiers: a =/promote= command if the wrap-up prompt proves insufficient, an =:agent:inbox:= staging tag if free writes prove too noisy. Commit b014095.

*** 2026-06-30 Tue @ 13:53:34 -0400 ratio roam clone + sync-timer confirmed (cross-machine half done)
Verified ratio over tailscale ssh: =~/org/roam= is a clone of =git@cjennings.net:roam.git= (HEAD auto-synced 13:11 today), and =roam-sync.timer= is enabled and actively firing (last run 5 min prior, next in 10). Both unit files present. velox was already confirmed, so the one-time clone+timer setup is now done on both daily drivers — the (b) half of this VERIFY's remaining work. Only the manual-validation child (work/unknown-project refusal checks needing Craig's eyes) is left before DONE. Cleared the matching "Current open instance" line in =daily-drivers.md=.

*** 2026-07-01 Wed @ 21:52:15 -0400 Manual-validation checks 1 + 4 (velox half) verified; ratio unreachable
Check 1 (seed node in org-roam + rg inventory): 55 =:agent:= nodes found by the rg inventory AND 55 nodes under =agents/= indexed in the live org-roam DB (emacsclient query) — match. Check 4 (cross-machine edit): created a temporary probe node =agents/20260701214910-kb-sync-validation-probe.org=, triggered =roam-sync= — committed and pushed to origin within seconds (f0252bb), zero =sync-conflict= files. The ratio half could NOT be verified tonight: =tailscale ping ratio= pongs via DERP, but ssh to 100.71.182.1:22 times out (machine likely suspended). Probe left in place; when ratio is back, confirm with: ssh cjennings@100.71.182.1 'ls ~/org/roam/agents/ | grep kb-sync-validation-probe' — then delete the probe node. Checks 2 + 3 (work/unknown-project refusal) still need live sessions in those projects, and "work machine has no KB clone" needs the work machine named + checked.

** TODO [#C] Token-rotation helper for =@a-bonus/google-docs-mcp= OAuth refresh :feature:quick:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-28
:END:

When a Google refresh token gets revoked (re-grant scopes, removed Connected App, account password reset), recovery is currently manual: run =npx -y @a-bonus/google-docs-mcp= with the right env, follow the URL in a browser, kill the process, base64-encode the new =token.json=, decrypt =secrets.env.gpg=, replace the var, re-encrypt. A small =mcp/refresh-google-docs-token.sh <profile>= would chain that into one command.

*** Sketch

#+begin_src bash
# usage: mcp/refresh-google-docs-token.sh personal
profile="$1"
gpg -d ... | grep -v "GOOGLE_DOCS_${profile^^}_TOKEN_B64" > /tmp/secrets.env.tmp
GOOGLE_MCP_PROFILE="$profile" npx -y @a-bonus/google-docs-mcp &
xdg-open <captured-url>
# wait for ~/.config/google-docs-mcp/$profile/token.json to land
kill %1
echo "GOOGLE_DOCS_${profile^^}_TOKEN_B64=$(base64 -w0 ~/.config/google-docs-mcp/$profile/token.json)" >> /tmp/secrets.env.tmp
gpg -c --cipher-algo AES256 -o mcp/secrets.env.gpg.new /tmp/secrets.env.tmp
mv mcp/secrets.env.gpg.new mcp/secrets.env.gpg
rm /tmp/secrets.env.tmp
#+end_src

The flow tonight worked but took a handful of manual steps. One script collapses it.

Decision (Craig, 2026-05-31): *hold until a token rotation is imminent.* The OAuth re-grant is a browser step that can't be triggered without revoking a live token, so the script can't be verified in isolation. Not marked =:solo:= — when a token actually needs rotating, write and verify in one pass (solo at that point).

** TODO [#D] Generic agent runtime support — Codex spec v0 :spec:design:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-28
:END:
Codex drafted a v0 design doc for making rulesets runtime-neutral rather than Claude-Code-specific. Motivating cases: offline operation with a local LLM, and two LLMs running in the same project at the same time without trampling each other's session-context.

Spec at [[file:docs/design/2026-05-28-generic-agent-runtime-spec.org]] (moved here from inbox on intake).

Immediate correctness issue Codex flagged: the singleton .ai/session-context.org is unsafe under simultaneous agents. Codex recommends starting with Phase 1 only — add AI_AGENT_ID + session-context.d/<id>.org without renaming the rest.

Broader refactor proposes runtimes/ adapter manifests, generic install commands, language-bundle split (common/ + runtimes/<runtime>/), launcher refactor, local model service via llama.cpp/ollama. Big surface area, six phases.

2026-06-12 spec review complete: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org][Codex review]] rubric for the whole spec is =Not ready=. Phase 1 is already shipped, and Phase 1.5 is tracked separately as the helper-instance task. Before any phases 2-5 implementation, decide whether to commit to the larger arc and answer the blocker decisions: generic instruction-file strategy, default local runtime/server, first supported local editing CLI, adapter scope, and compatibility behavior for existing =CLAUDE.md= / =.claude/= projects.

*** 2026-06-10 Wed @ 14:13:55 -0500 Noted Phase 1 already shipped; narrowed scope to the phases 2-6 decision
Phase 1 (the correctness fix) is live: protocols.org documents the AI_AGENT_ID-scoped session-context path (=.ai/session-context.d/<id>.org=) and =.ai/scripts/session-context-path= resolves it. The singleton race Codex flagged is closed. What remains is the spec review plus a go/no-go on the broader runtime-neutral refactor: runtimes/ adapter manifests, generic install commands, language-bundle split, launcher refactor, local model service.

*** 2026-06-11 Thu @ 19:26:26 -0500 Spec amended with the helper-instance slice; implementation split out
Craig's motivating case (a second Claude in the same project for lookups and safe task updates) was under-specified in v0 — it had identity and message targeting but no spawn mechanics and no write-safety contract for the shared files the session-context split doesn't isolate. Added the "Concurrent same-project agents (helper instances)" section (subagent boundary, identity/spawn via =ai --helper=, the tiered read/write contract, light startup, helper wrap-up) and Phase 1.5 to the migration plan. Implementation filed as its own [#B] task ("Helper-instance support"); this task stays scoped to the phases 2-6 go/no-go.

*** 2026-06-12 Fri @ 02:09:10 -0500 Independent spec review complete
Codex ran the spec-review workflow. Outcome: the combined spec is =Not ready= because phases 2-5 still require product decisions and current external-runtime/model verification. Phase 1.5 can proceed only as the already-split helper task, with rollout/manual-validation caveats accepted and no accidental template-wide release before sandbox/pilot drills pass. Review file: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org]].

*** 2026-06-12 Fri @ 02:39:38 -0500 Second review after response pass
Codex re-ran spec-review after the dispositions were folded in. Outcome by arc: Phase 1.5 helper instances =Ready with caveats=; phases 2-5 remain =Not ready= behind the explicit decisions/reverification gate. No new blocking findings for the helper slice. Review file updated in place: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org]].

** DOING [#C] Spec storage location + lifecycle-status convention :spec:
:PROPERTIES:
:CREATED: [2026-06-15 Mon]
:LAST_REVIEWED: 2026-06-24
:SPEC_ID: 80b0787b-4a60-4c82-8a16-b383d3e3c8f2
:END:
Two coupled documentation conventions for rulesets to adopt, surfaced by .emacs.d while triaging ~28 design docs. Both land in =spec-create= ([[file:.ai/workflows/spec-create.org]]) and likely a new =docs-lifecycle= rule under =claude-rules/=. Source proposal: [[file:docs/design/2026-06-15-spec-storage-lifecycle-proposal.org]] (.emacs.d handoff 2026-06-15).

The two conventions:
- *Location split* — formal specs live in =docs/specs/=; =docs/design/= keeps working notes, brainstorms, inventories, reviews. A spec is a doc proposing a buildable change with a Decisions section and phases; everything else is a note.
- *Glanceable lifecycle status* — a spec's state (draft / doing / implemented / superseded / cancelled) is visible without opening the file, plus an authoritative in-file record.

We handle the task in priority order. Mechanism decided 2026-06-28; migrates into the spec when built.

*** Decisions (settled 2026-06-28 — migrate into the spec when built)
1. *Location split — adopt.* =docs/specs/= for formal specs, =docs/design/= for notes (brainstorms, inventories, reviews). A spec is a doc proposing a buildable change with a Decisions section and phases; everything else is a note. Document in spec-create and the docs-lifecycle rule.
2. *Status mechanism — org-keyword authoritative.* The spec's =#+TODO:= state on its top heading is authoritative (specs already carry =#+TODO: TODO | DONE SUPERSEDED CANCELLED=), mirrored in a =Status= field in the Metadata table. Drop the filename suffix entirely — it's redundant with the Status field and adds rename churn across a cross-linked, template-synced doc set. (Craig 2026-06-28, choosing org-keyword over his earlier filename-suffix lean.)
3. *Link safety — adopt =org-id= ([[id:...]]) for cross-doc spec links.* Decouples link stability from the status mechanism; good hygiene regardless.
4. *Generalize.* Capture the shape (lifecycle state authoritative-in-artifact, formal-vs-notes split, rename-safe links) as a general =docs-lifecycle= convention in =claude-rules/=, with spec-create as the first instance.
5. *Retrofit existing files across ALL projects* (Craig 2026-06-28). The convention is worthless if legacy docs stay misfiled — every project's existing =docs/design/= pile (the ~28 in .emacs.d that surfaced this) must be sorted: formal specs move to =docs/specs/=, notes stay in =docs/design/=, inbound =file:= links updated. This is a one-time per-project migration that template sync can't perform, so the spec must design the reach mechanism. Proposed shape: a synced classify-and-move helper under =.ai/scripts/= (heuristic: a doc with a Decisions section + phases/Metadata is a spec) that proposes moves for confirmation and relinks, plus a startup nudge gated on a per-project =:LAST_SPEC_SORT:= marker so each project runs it once. Classification is a judgment call — the helper proposes, a human confirms.

Follow-up once built: update spec-create to emit into =docs/specs/= with the org-keyword status; write the =docs-lifecycle= rule; ship the retrofit helper + startup nudge; retrofit rulesets' own =docs/design/= first as the pilot; send a note if .emacs.d should pilot before generalizing.

*** 2026-07-01 Wed @ 22:13:00 -0400 Spec drafted — first resident of docs/specs/, awaiting review
Wrote [[file:docs/specs/2026-07-01-docs-lifecycle-spec.org][the spec]] from the five settled decisions, dogfooding its own conventions: it lives in the new =docs/specs/=, opens with the =* DRAFT Docs lifecycle= status heading (org keyword authoritative, =:ID:= for id-links, dated history in the body), and drops the status filename suffix. It pins the one mechanism the decisions left open — where the keyword lives: a prepended top-level status heading with vocabulary =DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED=, additive and retrofittable, giving both the one-line =rg= board and free org-agenda scanning. Four build phases: rule + template updates → =spec-sort= helper (classify/confirm/move/relink, bats) → rulesets pilot (41 design files, 3 spec-spine candidates, 2 stray root specs) → startup nudge gated on =:LAST_SPEC_SORT:= + .emacs.d note. Status DRAFT until Craig's review flips it READY.

*** 2026-07-01 Wed @ 22:22:34 -0400 Codex spec-review complete — Not ready
Review findings live in [[file:docs/specs/2026-07-01-docs-lifecycle-spec.org::*Review findings][the spec]]. Four blockers before implementation: the proposed lifecycle =#+TODO:= line drops the =TODO=/=DONE= states needed by Decisions and Review findings cookies; =spec-sort= needs an exact relink/unsupported-residue contract; the sort marker/startup nudge must name the actual =.ai/notes.org= state surface and detection flow; and the stricter =docs/specs/= review precondition must not strand legacy specs before retrofit.

*** 2026-07-01 Wed @ 22:30:06 -0400 Second review merged + responder pass — all nine findings fixed
A fresh-context Claude reviewer independently rated the draft Not ready, converging on Codex's keyword-vocabulary blocker (adding the cross-sequence uniqueness wrinkle) and contributing five unique findings — the biggest: nobody owned the DOING→IMPLEMENTED flip, the exact mechanism whose failure produced this spec. Craig approved fixing all nine. Fixed in place: two-sequence collision-free keyword header (dogfooded in the spec's own header; org now computes the [5/5] and [9/9] cookies — verified in batch), transition-ownership table incl. spec-response's mandatory flip-to-IMPLEMENTED task + task-audit safety net, single classification predicate (Decisions AND Implementation phases), the -spec.org rename step, the full relink data-safety contract (rewritten roots / report-only surfaces / dry-run default / residue-grep gate), the =.ai/notes.org= marker + Phase A probe + Phase C nudge contract, the legacy-location compatibility rule, the org-id Emacs-resolution prerequisite for .emacs.d, and the three-line transition definition. Ledger + per-finding responses in the spec's Review findings section. Status stays DRAFT pending Craig's READY flip.

*** 2026-07-01 Wed @ 22:41:33 -0400 Codex spec-review rerun — Not ready
Fresh review after the response/READY flip added five new blocking findings in [[file:docs/specs/2026-07-01-docs-lifecycle-spec.org::*Review findings][the spec]] and demoted the spec back to DRAFT. Remaining blockers: shared helper/workflow edits must name the canonical =claude-templates/.ai/= + mirror sync contract; task-audit needs an explicit spec-to-task binding before it can police =DOING= specs; =spec-sort --apply= needs a failure-safe/rollback contract; the org-id Emacs prerequisite must be executable before link conversion; and lifecycle status confirmation must be evidence-based so the retrofit does not encode stale reality.

*** 2026-07-01 Wed @ 22:46:52 -0400 Second responder pass — all fourteen findings closed
Fixed Codex's five re-review findings: the canonical-placement contract now opens the retrofit section (helper + tests + workflow edits land in claude-templates first, sync-check --fix propagates, sync-check-clean is an acceptance criterion); spec-response stamps a =:SPEC_ID:= property on the build parent, and task-audit's query checks that parent's keyword — which dissolves the flip-task chicken-and-egg; =--apply= got the fail-safe contract (clean-tree preflight, validate-then-write from a recorded plan, named recovery recipe); id-link conversion is staged (pilot rewrites =file:= links only; =id:= conversion is a follow-up gated on the concrete .emacs.d id-index mechanism — Craig picked this fork); and status confirmation is evidence-based (evidence panel, conservative non-terminal default, terminal states need a stated reason). Also de-cookified bracket tokens in prose that org's cookie updater would mangle. Status stays DRAFT; the READY flip belongs to the reviewers this round — verify pass dispatched.

*** 2026-07-01 Wed @ 23:22:50 -0400 Codex spec-review rerun — Ready
Codex re-read the revised [[file:docs/specs/2026-07-01-docs-lifecycle-spec.org][docs lifecycle spec]] after the second responder pass. All fourteen findings are closed, decisions remain [5/5], and the remaining implementation contracts are concrete enough to build and test. Status flipped to READY in the spec; implementation can proceed.

*** 2026-07-01 Wed @ 23:34:15 -0400 Decomposed into build tasks; spec flipped READY → DOING
spec-response Phase 6 run: this parent now carries the =:SPEC_ID:= binding (the spec's status-heading UUID), the phase tasks below track the build, and the spec's status heading is DOING. Completeness pass done: all ten acceptance criteria have homes across the phase tasks; vNext (org-agenda view) was already filed as the [#D] task below.

*** 2026-07-01 Wed @ 23:39:10 -0400 Phase 1 landed — docs-lifecycle rule + four spec-workflow updates
claude-rules/docs-lifecycle.md written and linked machine-wide (make install). Canonical-side updates: spec-create Phase 5 + template (docs/specs/ location, two-sequence keyword header, DRAFT status heading with :ID:, transition mechanics), spec-review (location expectation with the legacy compatibility rule keyed on :LAST_SPEC_SORT:, plus the DRAFT→READY flip — and the demote-back-to-DRAFT path a failed re-review takes), spec-response Phase 6 (owns READY→DOING, stamps :SPEC_ID: on the build parent, always emits the flip-to-IMPLEMENTED task), task-audit Phase B (the :SPEC_ID: reconcile query, checking the parent's keyword rather than counting children). Mirror synced; make test green end to end.

*** 2026-07-01 Wed @ 23:57:44 -0400 Phase 2 landed — spec-sort helper + 30-test bats suite
Built claude-templates/.ai/scripts/spec-sort (Python, TDD — the 30-test bats suite written red-first in claude-templates/.ai/scripts/tests/spec-sort.bats) covering the full retrofit contract: spine classification with the -spec.org-name-without-spine anomaly case, evidence panel (Status field, cookies, linking todo.org task, dated history, artifact existence) with conservative non-terminal proposals, per-candidate --confirm/--skip gate with --reason required on terminal keywords, clean-worktree preflight (--allow-dirty prints what recovery loses), validate-then-write from a recorded plan file, relink across the rewritten roots (inbound AND the moved doc's own outbound relative links) with report-only for sessions + synced templates (naming the canonical claude-templates file), bare-path mentions blocking until --acknowledge-bare, named recovery on injected mid-apply failure, post-apply residue gate, idempotent :LAST_SPEC_SORT: stamp. Real-data dry run against rulesets' pile matched predictions: 5 candidates, 4 anomalies, 30 notes, 0 bare, 10 report-only (incl. the startup.org synced-template case Codex flagged). make test green; sync-check clean.

*** 2026-07-02 Thu @ 00:18:28 -0400 Phase 3 pilot ran — rulesets' pile sorted, board live
Craig confirmed all five proposed keywords as-is plus the IMPLEMENTED reason; spec-sort --apply moved the five specs to docs/specs/ (agent-knowledge-base IMPLEMENTED, inbox-workflow-consolidation READY, autonomous-batch-execution READY, encourage-kb-contribution READY, wrapup-routing DOING — joining the docs-lifecycle spec's DOING on the board), rewrote 12 todo.org links plus the moved specs' own outbound links, and stamped :LAST_SPEC_SORT: 2026-07-02. Acceptance verified: status board matches reality, all re-homed specs carry -spec.org, residue zero in the rewritten roots (one acknowledged self bare mention rode along inside inbox-workflow-consolidation-spec), no id: links emitted, make test green. Surfaced and left in place: the four -spec.org-named files in docs/design without a spec spine (generic-agent-runtime, pattern-catalog, daily-prep-template, auto-triage-intake) — notes by predicate, misleading names; rename or leave is a Craig call. Report-only references: 9 frozen session archives + the synced startup.org (canonical edit lands with Phase 4's nudge work).

*** 2026-07-02 Thu @ 00:23:32 -0400 Phase 4 landed — startup nudge live, .emacs.d notified
Added the spec-sort probe to startup.org Phase A (item 12) and the one-line nudge to Phase C's findings list, canonical-side, mirror synced. One refinement over the spec's sketch: the stray-root check uses find instead of compgen, because compgen is bash-only and zsh aborts on an unmatched glob — the original snippet false-negatived on stray root specs under zsh (spec snippet updated with a note). Fixture-verified in both shells: fires on an unsorted docs/design and on a stray docs/*-spec.org, silent with the marker stamped, silent with no docs at all. Also fixed startup.org's own stale reference to the moved encourage-kb-contribution spec (the pilot's report-only finding). Sent .emacs.d the convention-live note with its ~28-doc pile nudge and the id-index ask (org-id-extra-files enumeration or periodic org-id-update-id-locations, verify by clicking the docs-lifecycle spec's :ID:), asking it to tag the owning task :blocker: since rulesets' id-conversion task waits on it.

*** TODO id-link conversion pass — gated on .emacs.d id-index
After .emacs.d lands the id-index mechanism (Phase 4's ask) and a clicked id link verifiably resolves, run the conversion pass: rewrite spec-target file: links in the rewritten roots to id: form, per project. Not part of any sort run. Becomes :blocked: with the reciprocal handoff if picked up before .emacs.d delivers.

*** TODO Flip the spec to IMPLEMENTED
When the final implementation phase completes: flip the spec's status heading DOING → IMPLEMENTED with a dated history line and the Metadata mirror, per the transition-ownership table. This task is the tracked obligation that closes the loop; the parent stays open until it runs.

*** TODO Manual testing and validation :test:
What we're verifying: the human-eyes half of the acceptance surface.

**** Startup nudge appears and clears
What we're verifying: the Phase A probe + Phase C nudge fire exactly once per project.
- Open a session in a project with an unsorted docs/design (before its sort) and read the startup output.
Expected: one line offering "run spec-sort"; after the pilot stamps :LAST_SPEC_SORT:, the next session shows nothing.

**** Moved-spec links click through in Emacs
What we're verifying: the pilot's relink pass left todo.org and docs links working for the human reader, not just the residue grep.
- After the Phase 3 pilot, open todo.org in Emacs and click three links that point at moved specs (including one from a dated log entry).
Expected: each opens the spec at its new docs/specs/ path.

*** TODO [#D] Docs lifecycle vNext — org-agenda spec-status view :feature:
Once specs carry lifecycle TODO keywords under =docs/specs/=, add a custom org-agenda view that lists =DRAFT= / =READY= / =DOING= / terminal specs by status. Deferred from [[file:docs/specs/2026-07-01-docs-lifecycle-spec.org][the docs-lifecycle spec]]; not part of v1 because the grep board is sufficient until the status headings exist.

** DOING [#C] No-approvals speedrun — cross-project autonomous-batch mode :feature:spec:
:PROPERTIES:
:CREATED: [2026-06-15 Mon]
:LAST_REVIEWED: 2026-06-24
:SPEC_ID: 90f623cd-fdbe-4f5c-b63d-b2f84d9151cf
:END:
A named mode for coding projects: Craig names an ordered task set and says "speedrun" / "no approvals speedrun"; the set is worked autonomously, each task held to the full quality bar (TDD red→green, =/review-code=, =/voice= on the commit) and committed + pushed as its own logical commit, with all needed quick decisions gathered in one pre-flight Q&A (answer or "skip this") and a VERIFY filed for anything underspecified or needing deliberation, plus an end-of-set page listing completed + remaining + skipped tasks. Task size is not a gate — large tasks decompose into per-commit chunks. Surfaced by .emacs.d from a 2026-06-15 theme-studio session where the shape worked. Source proposal: [[file:docs/design/2026-06-15-fix-speedrun-workflow-proposal.org]] (.emacs.d handoff 2026-06-15). Build via =spec-create= when worked; we handle the task in priority order.

Skeptical-review read (open design questions to resolve in the spec, not settled here):
- *Is it a new workflow or a documented preset?* The proposal frames it as no-approvals + always-push session modes plus an end page. Decide whether it needs its own workflow file or is mostly documentation of a preset over the two existing modes.
- *Where/how the page fires* — every task vs end-of-set, and via what. The paging surface is in flux (=page-signal= removed 2026-06-12), so reconcile against =notify --persist= or whatever paging stands now.
- *Auto-pull vs explicit list* — whether the set comes from an explicit ordered list or a tag/priority query.
- *Guardrails* — must refuse to speedrun tasks needing design decisions or carrying data-loss risk without a checkpoint (the sender's biased-safe unused-tile flag is the worked example).

*** 2026-07-01 Wed @ 22:10:35 -0400 Phase 0 landed — hard tag definitions + review/audit enforcement
todo-format.md gained the "Hard definitions: :solo: and :quick:" subsection under the scheme header (fixed across projects: :solo: = buildable + agent-verifiable + no deliberation, with one-or-two upfront-answerable quick decisions allowed per the ratified spec; :quick: = ≤30-min effort hint, never a gate). task-review.org: the two tagging sections are now explicitly mandatory ("a review that skips them is incomplete") and gate 3 was realigned from "no upfront decision" to the spec's no-deliberation form — the stricter old wording predated the pre-flight-Q&A decision and would have wrongly excluded quick-question tasks. task-audit.org: the re-assess bullet is marked mandatory and points at the todo-format hard definitions as canonical. Phases 1-6 (work-the-backlog extraction, callers, commit gate, checklist/Q&A/page, metrics, synthesis) remain.

*** 2026-06-16 Tue @ 00:53:36 -0500 Spec written; design questions answered
Craig's "your call" (2026-06-16) answered in [[file:docs/specs/2026-06-16-autonomous-batch-execution-spec.org][the autonomous-batch execution spec]], which reconciles this with Phase E into one feature:
- *Most effective / workflow-vs-preset:* one dedicated =work-the-backlog.org= workflow holds the execution loop; "fix speedrun" is a thin named preset (no-approvals + always-push + end page) feeding it an explicit list, and the inbox-zero loop feeds it a tag query. Pros of the shared workflow: one execution loop to audit, inbox-zero's three callers stay clean, both input shapes reuse one guardrail set. Cons: one more workflow file and a caller-to-workflow indirection. The con list is shorter and lighter than the duplication cost of two separate features, which is why the shared workflow wins. The pros carry the more important entries (single audit surface, clean seam).
- *Paging:* end-of-set only, via =notify ... --persist= (reconciled past the removed page-signal wrapper).
- *Auto-pull vs explicit list:* both — explicit list for the preset, tag/priority query for the loop.
- *Effectiveness measurement (the trial Craig asked for):* the spec designs a per-task JSONL metrics log (=.ai/metrics/work-the-backlog.jsonl=), a corrections-in-next-session signal, and a periodic synthesis step that writes =:agent:metrics:= org-roam articles for later review — the "gather data + create org-roam articles" loop.
*** 2026-06-29 Mon @ 03:48:09 -0400 Ratified the autonomous-batch execution spec
Craig ratified all eight decisions in [[file:docs/specs/2026-06-16-autonomous-batch-execution-spec.org]] (revised this session — size gate removed, crisp four-item defer checklist, =:solo:= / =:quick:= definitions + task-review/audit enforcement, speedrun pre-flight Q&A). Spec Status → ready; implementation-ready across Phase 0–6. Decisions grew from six to eight during the revision.

*** 2026-07-02 Thu @ 00:44:59 -0400 spec-response decomposition — :SPEC_ID: bound, spec DOING
Stamped the spec's UUID on this parent, broke Phases 1-6 into the build tasks below (plus the flip task and a live-trial validation child), and flipped the spec's status heading READY → DOING per the transition-ownership table.

*** 2026-07-02 Thu @ 01:07:29 -0400 Phase 1 landed — execution loop extracted into work-the-backlog.org
work-the-backlog.org written (canonical + mirror): caller contract (task set + session mode + cap), five-outcome vocabulary, the loop, mechanical eligibility gate (TODO + :solo: per scheme header, safe-by-omission, no-scheme-header → don't run), four-item defer checklist, per-task quality bar, cap/kill-switch semantics, page + metrics stubs pointing at Phases 4-5. inbox.org's auto-mode per-cycle item 3 reverted to routing-only (yes-path execution removed; mode intro + closing line updated to match). INDEX.org entry added. make test green, sync clean; nothing invokes the new workflow yet.

*** 2026-07-02 Thu @ 01:13:33 -0400 Phase 2 landed — both callers wired
inbox.org auto-mode item 3 regained its "run this batch next?" ask, now chaining into work-the-backlog as an explicit second step after routing (eligibility query + file-only + paging off + cap 1). work-the-backlog.org gained the two caller sections: the auto-loop contract and the no-approvals speedrun preset (seven-step pre-flight → autonomous-commit + always-push + paging-on over an explicit list; finer Q&A mechanics deferred to Phase 4). Speedrun trigger phrases live in the workflow + INDEX; "speedrun" always routes to the preset, with a disambiguation note in no-approvals.org and its INDEX entry. Each caller independently exercisable.

*** 2026-07-02 Thu @ 01:18:07 -0400 Phase 3 landed — waiver-gated commit autonomy
Pinned the waiver format per D5: two marker lines in .ai/notes.org Workflow State — :COMMIT_AUTONOMY: yes (has the waiver) and :LOOP_MAY_COMMIT: yes (the unattended loop may also commit; requires the first). Absent or non-yes reads as no; the read is a fresh grep each run, never memory. Degrade contract written into work-the-backlog.org (surface in run intro + summary, never honor without the marker, never degrade silently); caller sections + Common Mistakes updated. Stamped rulesets' own :COMMIT_AUTONOMY: yes; :LOOP_MAY_COMMIT: deliberately not granted — Craig's call. .emacs.d holds the waiver too but its notes.org is its own scope; told via inbox-send to stamp its marker.

*** 2026-07-02 Thu @ 01:21:47 -0400 Phase 4 landed — checklist mechanics, pre-flight Q&A contract, page
The four-item checklist (in since Phase 1) gained its mechanics: a VERIFY-filing subsection (dedup against an existing sibling first — the deferred task stays TODO, so without the check every run re-files; placement/heading/body per todo-format.md) and a quick-question routing subsection (discriminator: one-line factual/preference pick vs tradeoff-weighing; three-plus questions = underspecified = file; item 2 data-loss never routes to Q&A). Preset section gained the batch-ask contract (one message, recommendation-first numbered options per interaction.md, answers recorded as dated lines in the task bodies before the run). Page section finalized (fires once on set-done or cap-hit; notify --persist is the paging surface). Common Mistakes 12-13 added. Checklist only ever reduces what runs; pre-flight fires only under the preset.

*** 2026-07-02 Thu @ 01:24:50 -0400 Phase 5 landed — per-task JSONL metrics log
Metrics section written into work-the-backlog.org: one record per task at outcome time, appended to the project's .ai/metrics/work-the-backlog.jsonl (git-tracked, append-only, dir+file created on first append). Full field table per the spec (ts, run_id, project, caller, task, outcome, defer_reason, upfront_decision, wall_clock_s, commit_sha, review_findings), outcome slugs mapped to the prose vocabulary, commit_sha flagged as the corrections-signal key (comma-separated when a task decomposed into several commits). Added the sixth outcome the spec's readiness section demanded but the enum missed: failed (tree left working, surfaced, run continues) — wired into the Outcomes vocabulary and loop step 4. A failed append warns in the run summary but never blocks, reorders, or aborts execution.

*** 2026-07-02 Thu @ 01:27:43 -0400 Phase 6 landed — synthesis step to org-roam
Synthesis section written into work-the-backlog.org (trigger "synthesize backlog metrics", INDEX row added): discover the JSONL union across project roots, classify each project per knowledge-base.md's denylist before reading, exclude work/unknown projects with the refusal contract, compute per-run rollups + trends, compute the corrections signal (later revert/fix commit touching the same files within ~14 days — a flag for human review, not a conviction), write one :agent:metrics: KB node under ~/org/roam/agents/ with [[id:...]] links to prior synthesis nodes, pull-before/commit-push-after. Read-only over the logs plus the single KB write; never mutates JSONL, todo.org, or any tree.

*** TODO [#C] Speedrun — live trial validation :test:
What we're verifying: the whole loop under a real run. Craig names a small ordered set in a coding project and says "no approvals speedrun": pre-flight Q&A fires once up front, each task lands as its own reviewed commit, ineligible/underspecified tasks get VERIFYs instead of half-work, the end-of-set page arrives via notify --persist, and the metrics JSONL carries one record per task. Not :solo: — needs Craig's set and his read on the run.

*** TODO [#C] Flip the autonomous-batch spec to IMPLEMENTED
When the final phase completes and the live trial validates: flip docs/specs/2026-06-16-autonomous-batch-execution-spec.org DOING → IMPLEMENTED with a dated history line and the Metadata mirror, per the transition-ownership table.

** TODO [#C] ntfy phone channel as general two-way agent-comms :feature:spec:
:PROPERTIES:
:CREATED: [2026-06-20 Sat]
:LAST_REVIEWED: 2026-06-24
:END:
Proposal from the home project (2026-06-17): promote the self-hosted ntfy-over-Tailscale phone channel it built and verified on ratio into a general two-way agent-comms tool rulesets owns. Full proposal: [[file:docs/design/2026-06-17-ntfy-agent-comms-proposal.org]] (as-built runbook stays in the home project at =working/phone-notifications/spec.org=). What rulesets would decide: canonicalize =phone-notify= (send) plus a new =phone-recv= (check-since) as synced bin scripts; the per-machine config/secret convention (token in =~/.config/phone-notify/config= chmod 600 today, vs GPG-encrypted in dotfiles); a reference =ntfy-inbound-handler= plus systemd user-unit for event-driven delivery (Tier A subscriber routes inbound to inbox/notify, Tier B inbound spawns an agent session, Tier C notify a live session — harness research); approval-button workflows for the commits.md gates when Craig is away from the desk (tap-to-approve, the high-value concrete use); and the relationship to the retired cross-agent-comms scripts (ntfy may be the transport they lacked). Worked via =spec-create=. Blocks the triage-intake phone-push task below.
** TODO [#C] triage-intake.org auto mode — push each sweep to phone (ntfy) :feature:solo:
:PROPERTIES:
:CREATED: [2026-06-20 Sat]
:LAST_REVIEWED: 2026-06-24
:END:
The work project (2026-06-18) added a "Push each sweep to Craig's phone (ntfy) — the primary delivery" subsection under "Trigger and delivery" in triage-intake.org auto mode, and asks to fold it into the canonical engine plus re-sync. Preserved bundle: [[file:docs/design/2026-06-18-triage-intake-phone-push-note.org][note]] + [[file:docs/design/2026-06-18-triage-intake-phone-push-workflow.org][edited workflow]]. Auto mode is the away-from-desk / vacation mode, so phone-notify becomes the primary delivery each sweep (fuller end-of-sweep output: per-source deltas, open-PR/Linear state, awaiting-ack list, one-line verdict, timestamp; SCAN FAILED banner on any source failure), plus phone-recv polling each sweep for Craig's replies. Falls back to inline when phone-notify is absent. Depends on the ntfy agent-comms task above (phone-notify/phone-recv must be canonicalized first). Shared template-workflow change, so review-gated.

** TODO [#D] Fully-unattended scheduled inbox check (/schedule cron pass) :feature:
:PROPERTIES:
:CREATED: [2026-06-23 Tue]
:LAST_REVIEWED: 2026-06-28
:END:
vNext from the inbox-consolidation spec. =auto inbox zero= (v1) is the interactive =/loop= recurring check that waits for Craig's yes before executing. A fully-unattended =/schedule= cron pass that fires while Craig is away needs its own contract before it can ship: read-only vs may-mutate =todo.org= / =~/org/roam/inbox.org=, how a find surfaces asynchronously when Craig isn't at the session, how dedup state persists across runs that don't share a session, and what session/auth context a cron run carries. From the inbox-consolidation spec-review (Codex finding 1). See [[file:docs/specs/inbox-workflow-consolidation-spec.org][spec]].

Update 2026-06-28: the "design after v1 consolidation lands" precondition is cleared — the inbox engine consolidation (24ca58d) and the monitor-inbox 15-min loop (edb545d) both shipped. Now actionable backlog rather than blocked; design the unattended contract when prioritized.

** TODO [#D] Warn-only pre-commit hook for tooling-path enumeration :feature:
:PROPERTIES:
:CREATED: [2026-06-22 Mon]
:END:
Optional enforcement teeth for the no-attribution / no-tooling-artifacts tightening landed 2026-06-22 (commit 91217d9), which is documentation-only. A warn-only (not blocking) pre-commit hook could scan the commit subject + body for tooling-path enumeration (=CLAUDE.md=, =.claude/=, =.ai/=, =todo.org=, =notes.org=, =session-context=) and AI-attribution language, with the two exemptions baked in: a commit whose change IS one of those files, and private single-user repos. Must warn, not block — a rigid grep false-positives on legit subject mentions. Deferred: Craig chose docs-only for now.

** TODO [#D] Build =create-documentation= skill for high-quality project/product docs :feature:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-15
:END:

Create a Claude skill named =create-documentation= that can plan, write,
refresh, and review software documentation across README files, project docs,
developer guides, API docs, operational docs, and generated/published doc
sites.

This is broader than =arch-document=. =arch-document= should remain the
architecture-specific arc42 skill. =create-documentation= should know when to
delegate to it for architecture documentation, but its main job is the full
documentation system around a product or repo: onboarding, tutorials, how-to
guides, reference, explanation, operations, troubleshooting, contribution,
release/upgrade, and publication format.

*** Why this matters

The repo currently has strong skills for architecture, testing, review,
debugging, and workflow. It does not have a general documentation skill that:

- Chooses the right documentation type for the user need.
- Audits existing docs against code and expected user journeys.
- Creates a coherent doc map instead of dumping everything into =README.md=.
- Writes in a consistent technical style.
- Decides source/publish format intentionally (=.md=, =.org=, generated
  =.html=, OpenAPI, etc.).
- Treats docs as a maintained product surface with verification, ownership,
  navigation, accessibility, and freshness checks.

*** Research notes

**** Documentation frameworks and best-practice sources

- Diataxis separates documentation by reader need:
  - Tutorials: learning-oriented, take the reader by the hand.
  - How-to guides: task-oriented, solve a specific real problem.
  - Reference: information-oriented, accurate and complete lookup material.
  - Explanation: understanding-oriented, concepts, background, tradeoffs.
  Source: [[https://diataxis.fr/][Diataxis]] and the official guidance around
  tutorials/how-to/reference/explanation.
- Django explicitly documents this same organization and teaches readers how
  to navigate it: tutorials for beginners, topic guides for concepts,
  reference for APIs, how-to guides for recipes. This is a major reason the
  docs feel navigable despite large scope.
  Source: [[https://docs.djangoproject.com/en/5.2/][Django documentation]]
- Kubernetes separates concepts, tasks, tutorials, and reference. It also has
  current/previous-version docs, localization, contribution paths, and
  task-focused landing pages. Its docs are good at answering "what is this?"
  separately from "how do I do one thing?"
  Sources: [[https://kubernetes.io/docs/home/][Kubernetes docs home]],
  [[https://kubernetes.io/docs/tasks/][Kubernetes tasks]],
  [[https://kubernetes.io/docs/tutorials/][Kubernetes tutorials]]
- Write the Docs emphasizes docs that are precursory, participatory,
  exemplary, consistent, current, discoverable, addressable, cumulative, and
  comprehensive. Especially important: incorrect docs are worse than missing
  docs, and examples should cover common use cases without overwhelming the
  reference.
  Source: [[https://www.writethedocs.org/guide/writing/docs-principles/][Write the Docs principles]]
- Google developer docs guidance emphasizes project-specific style first,
  clarity and consistency, conversational but not frivolous tone, active voice,
  second person, descriptive links, global audience, accessibility, sentence
  case headings, numbered lists for procedures, code font for code, and alt
  text for images.
  Sources: [[https://developers.google.com/style/][Google developer documentation style guide]],
  [[https://developers.google.com/style/highlights][Google style highlights]],
  [[https://developers.google.com/style/accessibility][Google accessible docs]]
- Google's doc best-practices page adds a pragmatic maintenance principle:
  minimum viable documentation, update docs with code, delete dead docs, prefer
  good over perfect, tell the story of code, and avoid duplication.
  Source: [[https://google.github.io/styleguide/docguide/best_practices.html][Google documentation best practices]]
- The Good Docs Project is useful as a template source, especially for
  README, how-to, tutorial, concept, reference, troubleshooting, contributor,
  and release-note patterns. Do not vendor wholesale; use as prior art.
  Source: [[https://www.thegooddocsproject.dev/][The Good Docs Project]]

**** Praised project docs to analyze and steal from

***** Django

Why it works:
- It labels the doc types directly and explains when to use each.
- It has a beginner path, advanced tutorials, topic guides, API reference,
  how-to recipes, deployment, security, testing, release notes, and community
  help in one coherent index.
- It is versioned, so readers know which framework version the docs target.
- It cross-links introductory material to deeper references without making the
  first page a wall of every detail.

Patterns to use:
- Make the top-level docs home a routing page by reader intent.
- Put "How these docs are organized" near the top when the doc set is large.
- Split concept, task, tutorial, and reference instead of mixing them.
- Include "getting help" and "not found?" paths so the docs have an exit ramp.

Source: [[https://docs.djangoproject.com/en/5.2/][Django documentation]]

***** Kubernetes

Why it works:
- It has a large, complex product but maintains separate lanes for Concepts,
  Tasks, Tutorials, Reference, and Contribute.
- Task pages are short sequences for one operation; tutorials are larger goals
  with several sections. This prevents "one page tries to teach everything."
- It exposes version state clearly, including static old versions and current
  docs.
- It supports localization and documentation contribution, which makes the
  docs a product surface rather than a side artifact.

Patterns to use:
- For platform or infrastructure docs, include Concepts / Tasks / Tutorials /
  Reference as first-class folders.
- Create version/freshness metadata when docs are tied to released software.
- Add doc contribution guidance for projects with external contributors.
- Make operational tasks discoverable by category, not just search.

Sources: [[https://kubernetes.io/docs/home/][Kubernetes docs home]],
[[https://kubernetes.io/docs/tasks/][Kubernetes tasks]]

***** Rust

Why it works:
- Rust has a "bookshelf" rather than one overloaded manual: The Book, Rust by
  Example, standard library API reference, Reference, Cargo Guide, Error Index,
  Rustonomicon, release notes, platform support, policies, etc.
- The learning path is honest about audience: "assume programmed before, not in
  any specific language."
- Reference and learning material are separated. Advanced unsafe guidance gets
  its own book.
- Offline docs via =rustup doc= are treated as part of the product.

Patterns to use:
- For broad ecosystems, create a documentation bookshelf rather than a single
  mega-doc.
- Separate beginner path, examples, formal reference, advanced/unsafe topics,
  tooling docs, error index, release notes, and policies.
- Document assumptions about reader experience.
- Consider offline/local docs for CLI/library ecosystems.

Source: [[https://doc.rust-lang.org/][Rust documentation]]

***** Stripe API docs

Why it works:
- The API reference is organized around resources and common cross-cutting
  concerns: authentication, errors, idempotency, pagination, request IDs,
  versioning, metadata, connected accounts.
- It pairs prose with concrete request/response examples and client-library
  language selection.
- It exposes test-mode vs live-mode distinctions early.
- It offers "Copy for LLM" / "View as Markdown", which acknowledges modern
  consumption patterns without sacrificing normal docs UX.
- Its reputation comes from matching developer mental models and making the
  common path implementable quickly, not just visual polish.

Patterns to use:
- API docs should be generated from or checked against OpenAPI/JSON schema or
  source annotations wherever possible.
- Keep cross-cutting API behavior near the front, before endpoint lists.
- Include runnable examples, auth, errors, pagination, versioning, idempotency,
  and sandbox/test data.
- Consider LLM-friendly exports (=llms.txt=, "view as Markdown", stable
  anchors), but do not make the docs only for AI.

Source: [[https://docs.stripe.com/api][Stripe API Reference]]

***** FastAPI

Why it works:
- Documentation is part of the framework's value proposition: OpenAPI and JSON
  Schema drive interactive Swagger UI and ReDoc automatically.
- It reduces manual drift for API reference by deriving docs from typed code.
- It integrates examples and tutorial-style explanations with standards-based
  generated reference.

Patterns to use:
- Prefer generated API reference from code/specs over hand-maintained endpoint
  tables.
- Generated docs need human-written overview, concepts, authentication,
  examples, and operational guidance around them.
- The skill should identify when an OpenAPI/Swagger/ReDoc/Scalar route already
  exists and improve metadata/schema quality instead of creating duplicate
  manual docs.

Source: [[https://fastapi.tiangolo.com/features/][FastAPI features]]

*** Format and presentation decisions

**** Default source format: Markdown

Use =.md= as the default for shared project documentation when:
- The repo is on GitHub/GitLab/Forgejo and readers browse docs in the web UI.
- The project already uses MkDocs, Docusaurus, VitePress, Sphinx+MyST,
  Jekyll, GitHub Pages, or plain README-driven docs.
- Contributors are expected to edit docs without Emacs-specific tooling.
- The docs need easy static-site publishing.
- The content is README, tutorial, how-to, reference, troubleshooting,
  contributing, release notes, runbooks, or ordinary prose + code blocks.

Markdown source works well because it is low-friction, reviewable in diffs,
rendered by repository hosts, and supported by documentation site generators.
MkDocs is a good reference point: Markdown source, YAML config, built-in dev
server, static HTML output, and easy hosting.
Source: [[https://www.mkdocs.org/][MkDocs]]

**** Use Org when the document is Emacs-native or personal/planning-heavy

Use =.org= when:
- The user's workflow is explicitly Emacs/org-mode.
- The document contains TODO states, schedules, priorities, tags, agenda
  integration, property drawers, clocking, or personal planning.
- The document is an internal strategy/planning artifact such as V2MOM,
  research notes, meeting notes, task triage, or a living personal operating
  document.
- The output may later be exported, but the source of truth is intended to be
  edited in org-mode.

Do not default team-facing documentation to =.org= unless the team already uses
org-mode. Org can export to HTML, but that does not make it the right authoring
format for non-Emacs contributors.
Sources: [[https://orgmode.org/org.html][Org manual]],
[[https://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html][Org publish HTML tutorial]]

**** Use HTML as generated/published output, rarely as hand-authored source

Use =.html= when:
- The deliverable is a published static documentation site.
- The document needs interactive widgets, embedded API consoles, custom layout,
  or generated navigation/search.
- The project already publishes docs as a website.
- The target audience needs searchable, browsable, linkable pages rather than
  repo-local files.

Prefer generated HTML from Markdown/Org/reStructuredText/AsciiDoc/OpenAPI over
hand-authored HTML. Hand-edit HTML only for standalone artifacts, custom landing
pages, or cases where the project already treats HTML templates as docs source.

**** Consider generated/spec-backed formats

Use generated reference when possible:
- API reference: OpenAPI/Swagger/ReDoc/Scalar from code/spec.
- CLI reference: generated from command parser/help output.
- Library API reference: language-native doc tools such as rustdoc, pydoc,
  TypeDoc, JSDoc, Go doc, Sphinx autodoc, etc.
- Config reference: generated from schema, types, or validated defaults.

The skill should not duplicate generated reference by hand. It should improve
source comments, schema descriptions, examples, front matter, and surrounding
guides.

**** Presentation requirements

Every generated doc set should have:
- A docs home or README that routes by reader intent.
- Stable headings and anchors for addressability.
- Descriptive link text, no "click here."
- Search/navigation plan when docs exceed a handful of pages.
- Version/freshness metadata when tied to released software.
- Ownership/review cadence for docs likely to rot.
- Accessible structure: semantic headings, alt text, no image-only info,
  tables only when appropriate, left-aligned text, readable code blocks.
- Copyable commands and code examples.
- "What changed?" / release notes / migration path when docs describe a new or
  changed behavior.
- Troubleshooting path for common failures.
- Clear prerequisites before procedures.
- Verification steps after procedures.
- Support/escalation path when the docs do not answer the question.
- Optional LLM-friendly surfaces for larger doc sets: =llms.txt=,
  "copy as Markdown" equivalents, concise page summaries, and stable anchors.

*** Proposed skill design

**** Skill name and trigger

Name: =create-documentation=

Trigger when the user asks to:
- create documentation, docs, README, guide, manual, runbook, tutorial,
  quickstart, API docs, CLI docs, troubleshooting docs, contributor docs,
  architecture-adjacent docs, release notes, upgrade guide, or doc site;
- improve, audit, reorganize, or publish existing docs;
- decide documentation structure or format for a project.

Do not trigger for:
- architecture-only arc42 docs when =arch-document= is the direct fit;
- ADR creation (=arch-decide=);
- design docs before implementation shape is known (=brainstorm= or
  =arch-design=);
- prose polishing only (future writing/humanizer skill);
- inline code comments/docstrings only, unless the user asks to create docs
  from them.

**** V1 should be one orchestrating skill, not many separate skills

Build v1 as one skill with explicit phases and subcommands rather than a set
of separate skills. Rationale:
- Documentation tasks often start ambiguous; the first job is classification.
- Splitting too early creates command-discovery burden.
- A single skill can dispatch to existing specialized skills
  (=arch-document=, =c4-diagram=, =security-check=, =playwright-js/py= for
  doc-site verification) without making users choose the internal pipeline.

Support discoverable subcommands inside one skill:

#+begin_example
/create-documentation audit <path>
/create-documentation plan <path-or-scope>
/create-documentation write <doc-type> <scope>
/create-documentation refresh <path>
/create-documentation publish <path>
/create-documentation review <path>
#+end_example

The default =/create-documentation <scope>= runs audit -> plan -> write ->
review, asking for confirmation before broad rewrites.

**** Future split if v1 gets too large

If the skill grows past a manageable size, split into a discoverable
=documentation-*= chain. Names and order:

1. =documentation-audit= — inventory existing docs, code/docs drift, reader
   journeys, missing doc types, stale/generated docs.
2. =documentation-plan= — choose audiences, doc map, formats, source of truth,
   publishing path, ownership, and freshness policy.
3. =documentation-write= — write or update the selected docs.
4. =documentation-reference= — generate or improve API/CLI/config/library
   reference from source/spec.
5. =documentation-publish= — configure MkDocs/Docusaurus/Sphinx/GitHub Pages
   or equivalent, build static HTML, verify links/search.
6. =documentation-review= — quality gate for accuracy, style, navigation,
   accessibility, examples, and freshness.

Keep =create-documentation= as the orchestrator and user-facing entry point.
The chain is discoverable because every helper starts with =documentation-= and
the orchestrator prints the next command at each handoff.

*** V1 workflow details

**** Phase 1: Intake and classification

Ask only what is missing from local context:
- Who is the reader? New user, evaluator, integrator, maintainer, operator,
  contributor, auditor, support engineer?
- What is the reader trying to do or understand?
- Is this for a public project, internal team, personal workflow, regulated
  audience, or customer-facing product?
- Is the output repo-browsed, web-published, printed/exported, or Emacs-native?
- Is there existing code, existing docs, an API spec, generated reference, or
  only a concept?
- What is the maintenance expectation? One-off, release-maintained,
  continuously updated?

Classify the work into one or more doc types:
- README / landing page.
- Quickstart.
- Tutorial.
- How-to guide.
- Concept/explanation.
- API reference.
- CLI reference.
- Configuration reference.
- Architecture docs (delegate to =arch-document= if arc42/C4/ADR-driven).
- Operations/runbook.
- Troubleshooting/FAQ.
- Upgrade/migration/release notes.
- Contributor/development docs.
- Security/compliance docs.
- Examples/cookbook.

**** Phase 2: Audit existing material

Inventory:
- =README*=, =docs/=, =doc/=, =site/=, =mkdocs.yml=, =docusaurus.config.*=,
  =vitepress=, =sphinx=, =docs.rs=, =pkg.go.dev=, OpenAPI specs,
  generated docs folders, GitHub Pages config, ADRs, architecture docs,
  examples, scripts, CLI help, package metadata.
- Existing doc type coverage: tutorial/how-to/reference/explanation.
- Broken links, stale version numbers, commands that no longer exist,
  screenshots that may be stale, code snippets not exercised, doc/code drift.
- Source of truth for generated docs. Flag generated files; do not hand-edit
  them until source is known.
- Reader journey gaps: "new user can install?", "first success path?",
  "operator can recover?", "contributor can run tests?", "API consumer can
  authenticate and handle errors?"

Use =rg= first. For API/CLI reference, prefer structured sources:
OpenAPI/JSON Schema, package metadata, command =--help= output, docstrings, or
language-native documentation tooling.

**** Phase 3: Documentation plan

Write a short plan before broad edits:
- Audiences and priority order.
- Proposed doc map/tree.
- Doc type for each page.
- Source format decision: =.md= / =.org= / generated spec / generated HTML.
- Publishing target, if any.
- Existing docs to preserve, move, merge, or delete.
- Generated-reference strategy.
- Ownership and freshness policy.
- Verification plan.

Stop for confirmation when the plan moves or rewrites more than one file.

**** Phase 4: Write or update docs

Writing rules:
- Lead with the reader's goal, not the implementation history.
- Put prerequisites before steps.
- Use numbered lists for procedures.
- Use bullets for non-ordered choices.
- Use active voice and second person for instructions.
- Keep sentences short and globally readable.
- Define acronyms on first use.
- Use code font for commands, file names, env vars, API names, and literals.
- Use descriptive links.
- Prefer examples that cover the common path and one meaningful edge/error
  path.
- Separate examples/tutorials from dense reference.
- Avoid stale duplication: link to canonical generated reference instead of
  copying it.
- Include expected output after commands where it helps verification.
- Include cleanup/rollback steps when procedures change state.
- Include troubleshooting for common failures.
- Avoid marketing voice in technical docs. State capability and constraints
  plainly.
- No AI attribution in docs, examples, comments, generated pages, footers, or
  screenshots.

Page skeletons:

README / docs home:
#+begin_example
# <Project>

<One-paragraph purpose>

## Start here
- New user: <quickstart>
- Existing user with a task: <how-to index>
- API lookup: <reference>
- Maintainer/operator: <operations/contributing>

## Quick example
...

## Documentation map
...

## Support / contributing
...
#+end_example

Tutorial:
#+begin_example
# Tutorial: <goal>

## What you'll build
## Prerequisites
## Step 1 ...
## Checkpoint
## Step 2 ...
## What you learned
## Next
#+end_example

How-to:
#+begin_example
# How to <task>

## When to use this
## Prerequisites
## Steps
## Verify
## Troubleshooting
## Related
#+end_example

Reference:
#+begin_example
# <Thing> reference

## Summary
## Parameters / options / fields
## Behavior
## Errors
## Examples
## Version notes
#+end_example

Explanation:
#+begin_example
# <Concept>

## Problem it solves
## Mental model
## How it fits with related concepts
## Tradeoffs and constraints
## Further reading
#+end_example

Runbook:
#+begin_example
# Runbook: <operation>

## Scope
## Preconditions
## Normal procedure
## Verification
## Rollback
## Alerts and escalation
## Post-incident notes
#+end_example

**** Phase 5: Presentation and publishing

If docs are repo-local only:
- Ensure links render on GitHub/GitLab.
- Keep relative links stable.
- Add an index if more than 4-5 docs exist.

If docs are web-published:
- Detect existing generator and follow it.
- Prefer project-native tooling over introducing MkDocs/Docusaurus/Sphinx.
- If no tooling exists and user wants a site, choose conservatively:
  - Python/simple repo: MkDocs Material is a pragmatic default.
  - JS/React ecosystem: Docusaurus or VitePress if already in stack.
  - Python libraries: Sphinx or MkDocs depending on existing ecosystem.
  - API docs: ReDoc/Swagger/Scalar from OpenAPI.
- Build locally if dependencies exist.
- Check links, nav, search, mobile viewport, and accessibility basics.
- Do not commit generated =site/= output unless the project already does.

**** Phase 6: Verification

Verification should match doc type:
- Commands in quickstarts/how-tos: run them or mark not run with reason.
- Code snippets: compile/run where feasible, or use fenced language and note
  assumptions.
- API docs: validate OpenAPI/spec if tooling exists.
- Links: run link checker if configured; otherwise sample-check changed links.
- Published site: build docs and inspect output.
- Screenshots: verify current UI if included.
- Generated docs: regenerate from source and confirm no unexpected diff.

Final report must say:
- Files created/changed.
- Doc types covered.
- Format/source-of-truth decisions.
- What was verified.
- What could not be verified.
- Known gaps/follow-ups.

*** Relationship to existing skills

- =arch-document=: use when the requested docs are specifically architecture
  docs from brief + ADRs + C4/arc42. =create-documentation= may call it, then
  wrap the output in a broader docs map.
- =c4-analyze= / =c4-diagram=: use for diagrams in architecture or concept
  docs when visual structure helps.
- =brainstorm=: use before =create-documentation= when the product/feature
  itself is still unclear.
- =arch-design= / =arch-decide=: use when documentation reveals missing
  architectural choices.
- =security-check=: use when docs include security guidance, auth, secrets,
  deployment, or compliance claims.
- =playwright-js= / =playwright-py=: use to verify published doc sites,
  interactive docs, screenshots, and browser-rendered examples.
- =codify=: use after a documentation session reveals reusable project-specific
  documentation rules.

*** Quality bar and anti-patterns

The skill should reject:
- A giant README that mixes tutorial, reference, architecture, and operations.
- Duplicating generated API/CLI/config reference by hand.
- Unverified commands in quickstarts without a "not run" note.
- Screenshots with no alt text or no update path.
- Tables used for layout instead of actual tabular data.
- "Overview" pages that do not route readers to tasks.
- Tutorials that become reference dumps.
- How-to guides that explain concepts for pages before giving steps.
- Reference pages that hide required options in prose.
- Marketing claims without concrete examples.
- Docs that mention local private paths, personal tooling, or AI attribution in
  public artifacts.
- Publishing generated HTML as source unless the project explicitly owns HTML
  docs that way.

*** Acceptance criteria for building the skill

- [ ] Directory =create-documentation/= with =SKILL.md=.
- [ ] Frontmatter description includes positive and negative triggers.
- [ ] Skill body includes the V1 phases above.
- [ ] Includes a source-format decision table for =.md= / =.org= / =.html= /
  generated spec/reference.
- [ ] Includes doc-type classifier based on Diataxis plus README/runbook/API
  additions.
- [ ] Includes examples/skeletons for README, tutorial, how-to, reference,
  explanation, runbook, troubleshooting, contributor docs, and API overview.
- [ ] Includes audit checklist for existing repos.
- [ ] Includes publishing guidance without hardcoding one static-site tool.
- [ ] Includes verification checklist and "unable to verify" reporting.
- [ ] Cross-references =arch-document=, =brainstorm=, =security-check=,
  =playwright-js=, =playwright-py=, and =codify=.
- [ ] Adds =references/= only if needed; suggested files:
  - =references/doc-type-decision.md=
  - =references/style-guide.md=
  - =references/format-decision.md=
  - =references/page-skeletons.md=
  - =references/doc-audit-checklist.md=
- [ ] Keep =SKILL.md= concise enough to load; move long skeletons/checklists to
  references for progressive disclosure.
- [ ] Run =./scripts/lint.sh= after adding the skill.

*** Open design questions before implementation

- Should the user-facing command be exactly =/create-documentation= while
  internal helper names use =documentation-*=, or should all names share the
  =create-documentation <subcommand>= form? Recommendation: one skill with
  subcommands for v1.
- Should Markdown be the hard default for team docs? Recommendation: yes,
  unless the project already uses org/reST/AsciiDoc or the output is personal
  Emacs-native planning.
- Should the skill create a docs site automatically? Recommendation: no. It
  should propose a site when the doc set exceeds README-scale or when search,
  versioning, or public publishing is required. Ask before adding tooling.
- Should it write docs before code exists? Recommendation: yes for specs,
  user journeys, and design docs, but route unclear feature/product decisions
  through =brainstorm= or =arch-design= first.
- Should it include LLM-specific docs surfaces? Recommendation: optional for
  public/library/API docs: =llms.txt= or markdown export is valuable, but normal
  human navigation remains primary.

** TODO [#D] Build /research-writer — clean-room synthesis for research-backed long-form :feature:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-15
:END:

Gap in current rulesets: between =brainstorm= (idea refinement → design doc)
and =arch-document= (arc42 technical docs), there's no skill for
research-backed long-form prose — blog posts, essays, white papers,
proposals with data backing, article-length content with citations.

Craig writes documents across many contexts (defense-contractor work,
personal, technical, proposals). The gap is real.

*Evaluated 2026-04-19:* ComposioHQ/awesome-claude-skills has a
=content-research-writer= skill (540 lines, 14 KB) that attempts this. *Not
adopting:*
- Parent repo has no LICENSE file — reuse legally ambiguous
- Bloated: 540 lines of prose-scaffolding with no tooling
- No citation-style enforcement (APA/Chicago/IEEE/MLA)
- No source-quality heuristics (primary vs secondary, peer-review, recency)
- Fictional example citations in the skill itself (models the hallucination
  failure mode a citation-focused skill should prevent)
- No citation-verification step
- Overlaps with =humanizer= at polish with no composition guidance

*Patterns worth lifting clean-room (from their better parts):*
- Folder convention =~/writing/<article-name>/= with =outline.md=,
  =research.md=, versioned drafts, =sources/=
- Section-by-section feedback loop (outline validated → per-section
  research validated → per-section draft validated)
- Hook alternatives pattern (generate three hook variants with rationale)

*Additions for the clean-room version (v1):*
- Citation-style selection (APA / Chicago / MLA / IEEE / custom) with
  style-specific examples and a pick-one step up front
- Source-quality heuristics: primary > secondary; peer-reviewed; recency
  thresholds by domain; publisher reputation; funding transparency
- Citation-verification discipline: fetch real sources, never fabricate,
  mark unverifiable claims with =[citation needed]= rather than inventing
- Composition hand-off to =/humanizer= at the polish stage
- Classification awareness: if the working directory or context signals
  defense / regulated territory, flag any sentence that might touch CUI
  or classified material before emission

*Target:* ~150-200 lines, clean-room per blanket policy.

*When to build:* wait for a real research-writing task to validate the
design against actual document patterns. Building preemptively risks
tuning for my guess at Craig's workflow rather than his real one.
Triggers that would prompt "let's build it now":
- Starting a white paper / proposal that needs citation discipline
- Writing a technical blog post with external references
- A pattern of hitting the same research-writing friction 3+ times

Upstream reference (do not vendor): ComposioHQ/awesome-claude-skills
=content-research-writer/SKILL.md=.

** TODO [#D] Revisit =c4-*= rename if a second notation skill ships :chore:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-15
:END:

Current naming keeps =c4-analyze= and =c4-diagram= as-is (framework prefix
encodes the notation; "C4" is a discoverable brand). Suite membership is
surfaced via the description footer, not the name.

If a second notation-specific skill ever lands (=uml-*=, =erd-*=, =arc42-*=),
the compound pattern =arch-analyze-<notation>= / =arch-diagram-<notation>=
starts paying off: alphabetical clustering under 'a' amortizes across three+
skills, and the hierarchy becomes regular. At that point, rename all
notation skills together in one pass.

Trigger: adding skill #2 in the notation family. Don't pre-rename.

Candidate future notation skills (not yet in scope — noted for when a
real need arrives, not pre-emptively):

- *UML* (Unified Modeling Language): OO design notation, 14 diagram types
  in practice dominated by class / sequence / state / component. Common
  in DoD / safety-critical / enterprise-architecture contexts. Tooling:
  PlantUML (text-to-diagram), Mermaid UML, draw.io. Would likely split
  into =uml-class=, =uml-sequence=, =uml-state= rather than one monolith
  — different audiences, different inputs.
- *ERD* (Entity-Relationship Diagram): database schema modeling —
  entities, attributes, cardinality. Crow's Foot notation dominates
  practice; Chen is academic; IDEF1X is DoD-standard. Tooling:
  dbdiagram.io, Mermaid ERD, PlantUML, ERAlchemy (code-to-ERD for SQL).
  Natural fit as =erd-analyze= (extract from schema/migrations) and
  =erd-diagram= (generate from prose/model definitions).
- *arc42*: already partially covered by =arch-document= (which emits
  arc42-structured docs). A standalone =arc42-*= skill would be
  redundant unless the arc42-specific visualizations need separation.

Each answers a different question:

- C4 → "What systems exist and how do they talk, at what zoom?"
- UML class/sequence → "What does the code look like / what happens when X runs?"
- ERD → "What's the database shape?"
- arc42 → "What's the full architecture document?"

Deferred pending an actual need that's blocked on not having one of these.

*** DoD-specific notations (DeepSat context)

Defense-contractor work uses a narrower, different notation set than
commercial software. Document the trigger conditions and starting point
so a future decision to build doesn't have to re-derive the landscape.

**** SysML (Systems Modeling Language)

UML 2 profile, dominant in DoD systems engineering. Six diagrams account
for ~all practical use:

- *Block Definition Diagram (BDD)* — structural; like UML class but for
  system blocks (components, subsystems, hardware).
- *Internal Block Diagram (IBD)* — parts within a block and how they
  connect (flow ports, interfaces).
- *Requirement diagram* — unique to SysML; traces requirements to
  satisfying blocks. Essential in regulated environments.
- *Activity diagram* — behavioral flow.
- *State machine* — same shape as UML.
- *Sequence diagram* — same shape as UML.

SysML v1.x is in the field; v2 is emerging but not yet adopted at scale
(as of 2026-04). Tooling dominated by Cameo Systems Modeler / MagicDraw
and Enterprise Architect. Text-based option: PlantUML + =plantuml-sysml=
(git-friendly, growing niche).

*Candidate skills*: =sysml-bdd=, =sysml-ibd=, =sysml-requirement=,
=sysml-sequence=. Three or more in this cluster triggers the
=arch-*-<notation>= rename discussion from the parent entry.

**** DoDAF / UAF (architecture frameworks)

Not notations themselves — frameworks that specify *which* viewpoints a
program must deliver. Viewpoints are rendered using UML/SysML diagrams.

- *DoDAF (DoD Architecture Framework)* — legacy but still
  contract-required on many programs.
- *UAF (Unified Architecture Framework)* — DoDAF/MODAF successor,
  SysML-based. Gaining adoption on newer contracts.

Common required viewpoints (formal CDRL deliverables or PDR/CDR
review packages):

- *OV-1* — High-Level Operational Concept Graphic. The "cartoon" showing
  the system in operational context with icons, arrows, surrounding
  actors/environment. *Universally asked for — informal or formal.*
  Starting point for any DoD diagram skill.
- *OV-2* — Operational resource flows (nodes and flows).
- *OV-5a/b* — Operational activities.
- *SV-1* — Systems interfaces. Maps closely to C4 Container.
- *SV-2* — Systems resource flows.
- *SV-4* — Systems functionality.
- *SV-10b* — Systems state transitions.

*Informal ask ("send me an architecture diagram") → OV-1 + SV-1 satisfies
90% of the time.* Formal CDRL asks specify the viewpoint set contractually.

*C4 gap*: C4 is rare in DoD. C4 System Context ≈ OV-1 in intent but not
in visual convention. C4 Container ≈ SV-1. Expect a mapping step or
reviewer pushback if delivering C4-shaped artifacts to a DoD audience.

*Candidate skills*: =dodaf-ov1=, =dodaf-sv1= first (highest-value);
=uaf-viewpoint= if newer contracts require UAF.

**** IDEF1X (data modeling)

FIPS 184 — federal standard for data modeling. Used in classified DoD
data systems, intelligence databases, and anywhere the government
specifies the data model. Same shape language as Crow's Foot but with
different adornments and notation conventions.

*Rule of thumb*: classified DoD data work → IDEF1X; unclassified
contractor work → Crow's Foot unless the contract specifies otherwise.

*Candidate skills*: =idef1x-diagram= / =idef1x-analyze= (parallel to a
future =erd-diagram= / =erd-analyze= pair).

**** Tooling baseline

- *Cameo Systems Modeler / MagicDraw* (Dassault) — commercial SysML
  dominant in DoD programs.
- *Enterprise Architect (Sparx)* — widely used for UML + SysML + DoDAF.
- *Rhapsody (IBM)* — SysML with code generation; strong in avionics /
  embedded (FACE, ARINC).
- *Papyrus (Eclipse)* — open source SysML; free but clunkier.
- *PlantUML + plantuml-sysml* — text-based, version-controllable. Fits a
  git-centric workflow better than any GUI tool.

**** Highest-value starting point

If DeepSat contracts regularly require architecture deliverables, the
highest-ROI first skill is =dodaf-ov1= (or whatever naming convention
the rename discussion lands on). OV-1 is the universal currency in
briefings, proposals, and reviews; it's the one artifact that shows up
in every program regardless of contract specifics.

Trigger for building: an actual DoD deliverable that's blocked on not
having a skill to generate or check OV-1-shaped artifacts. Don't build
speculatively — defense-specific notations are narrow enough that each
skill should be driven by a concrete contract need, not aspiration.

* Rulesets Resolved
** DONE [#C] Bash/shell language bundle :feature:
CLOSED: [2026-06-23 Tue]
:PROPERTIES:
:CREATED: [2026-06-23 Tue]
:END:
Built =languages/bash/= the same session it was filed: bash.md + bash-testing.md rules, a shellcheck PostToolUse validate hook (covers =.sh=, =.bash=, and extensionless shell scripts by shebang; 8 bats tests), a shellcheck pre-commit githook, settings.json wiring, gitignore-add.txt, and a "Bash/shell project" CLAUDE.md. shfmt left out of the blocking path on purpose (shell has no canonical style). Makefile test target now discovers =languages/*/tests/*.bats=.

No =languages/= bundle fits a shell-heavy project. archangel (437 =.sh= files) and archsetup are bash projects with nothing that matches; installing elisp/python gives them the wrong language rules. Build a =languages/bash/= bundle on the elisp/go pattern: =claude/rules/bash.md= (style — =set -euo pipefail=, quoting, =[[ ]]=, trap/cleanup) + =bash-testing.md= (bats conventions), a PostToolUse validate hook (=shellcheck= on edited =.sh=), a =githooks/pre-commit= running shellcheck on staged shell files, =settings.json= wiring, =gitignore-add.txt=, and its own =CLAUDE.md= headed "Bash/shell project." Urgency dropped 2026-06-23: install-lang now seeds the language-neutral default CLAUDE.md when a bundle ships none, so a bash project no longer gets a mislabeled "Elisp project" header — the bundle is now the accurate-rules win, not a mislabel fix. From archangel 2026-06-23 ([[file:docs/design/2026-06-23-install-lang-claude-md-gap.org][handoff]]).
** DONE [#B] Consolidate inbox/triage workflows + scheduled inbox check :chore:
CLOSED: [2026-06-23 Tue]
:PROPERTIES:
:CREATED: [2026-06-23 Tue]
:END:
Built per the Ready spec: =process-inbox= + =monitor-inbox= + =inbox-zero= merged into one =inbox.org= engine (shared core + process/monitor/roam modes + the interactive =auto inbox zero= =/loop= mode); =triage-intake= and =no-approvals= stay separate. Callers repointed (INDEX, protocols, startup Phase C, wrap-up Step 3), old files deleted, stale-ref grep clean, workflow-integrity + sync-check + full suite green. The fully-unattended =/schedule= cron pass is vNext (see the =[#D]= task above). [[file:docs/specs/inbox-workflow-consolidation-spec.org][spec]].
** DONE [#C] inbox-zero: delete empty roam entries on triage :feature:
CLOSED: [2026-06-23 Tue]
:PROPERTIES:
:CREATED: [2026-06-23 Tue]
:END:
Done in commit 3da2725 (empty-entry sweep folded into Phase D's reconcile, after capture-guard + pull, with the claimed-item removal) and carried into the consolidated =inbox.org= roam mode (Phase B =empty= bucket + Phase D sweep). From the roam inbox 2026-06-23.
** DONE [#C] Surface cross-project dependencies first in what's-next :feature:spec:
CLOSED: [2026-06-24 Wed]
:PROPERTIES:
:CREATED: [2026-06-24 Wed]
:END:
Tasks that depend on another project can sit for ages when the dependency is low-priority or needs its own spec process — e.g. wrap-teardown depends on =.emacs.d= for the =ai-term= companion. Craig's proposal (roam 2026-06-24): (1) an org-tag marking a task as blocked-by / depends-on another project (pick a short tag name); (2) several ways to bind dependencies into the what's-next (=open-tasks.org=) decision tree so blocked-by-dependency tasks surface first; (3) review the what's-next workflow as a whole, since many projects use it.

Built 2026-06-24 (tag name =:blocked:=, Craig's pick): the =:blocked:= tag + =:BLOCKED_BY: <project>: <what>= property convention in =todo-format.md=, and =open-tasks.org= Next Mode now excludes =:blocked:= tasks from the cascade and surfaces them in a dedicated "Blocked on other projects" section with an =inbox-send= nudge offer. Applied live to the wrap-teardown task above. Commits feat(tasks) cross-project-dependency.
** DONE [#C] Task-audit: consolidate adjacent / related tasks :feature:
CLOSED: [2026-06-24 Wed]
:PROPERTIES:
:CREATED: [2026-06-24 Wed]
:END:
The task-audit workflow should also consider combining related tasks when they're adjacent, so a spread-out effort reads as one whole. Craig's example (roam 2026-06-24): the agent-agnostic / agent-source work could collapse into one item, or at least a parent task with the related ones as children.

Built 2026-06-24: =task-audit.org= Phase C.5 reads the open-task set, spots semantic clusters by judgment, and proposes per cluster either a merge (same-work members fold into one) or a parent-with-children grouping (related-but-distinct), applied only on Craig's confirm — broader than Phase C's exact-duplicate fold. Commit feat(task-audit) consolidate.
** DONE [#B] Anki deck name from #+TITLE :bug:quick:solo:
CLOSED: [2026-06-24 Wed]
:PROPERTIES:
:CREATED: [2026-06-22 Mon]
:LAST_REVIEWED: 2026-06-24
:END:
flashcard-to-anki.py's =default_deck_name= returns =input_path.stem= (the filename), so every deck built through =flashcard-sync= (which passes no =--deck=) is named after the file, not the curated =#+TITLE=. =flashcard-review.org= already documents the intended behavior ("the #+TITLE line drives the Anki deck name"); the script never matched it. Fix: =default_deck_name(input_path, org_text)= scans for a =#+TITLE:= line (case-insensitive, trimmed) and returns it, basename fallback when absent; =main()= passes the already-read =org_text=. Edited script + test ready (validated, 29 pass); the staging =.py= files were removed after the fix landed (see below), rationale kept: [[file:docs/design/2026-06-21-anki-titlefix-proposal.org][proposal]]. Apply to both =.ai/scripts/= and =claude-templates/.ai/scripts/=, sync-check + make test. Migration caveat: deck ID derives from the name, so decks previously built without =--deck= land as new decks on next import (old basename-named decks keep history, delete by hand). Coordinate with "Reconcile flashcard multi-tag tooling into canonical" below — both edit =flashcard-to-anki.py=, build together to avoid conflicting edits. Shared-asset, review-gated. From home 2026-06-21.

Done 2026-06-24 (commit 060a938): applied the pre-staged script + test red-to-green (5 new =#+TITLE= tests, 29 pass total), synced both script dirs, full suite green. The two redundant staging =.py= files removed, the rationale proposal kept.
** CANCELLED [#C] Morning ops orchestrator pilot — read-only :feature:
CLOSED: [2026-06-24 Wed 05:46]
:PROPERTIES:
:CREATED: [2026-06-11 Thu]
:LAST_REVIEWED: 2026-06-15
:END:
A scheduled headless morning run chaining the existing pieces: startup checks, the triage-intake scan, a system health check — producing the prep doc plus a report and a notify ping, with all remediation propose-only. Staged adoption from the 2026-06-11 insights report's "Self-Healing Daily Ops Orchestrator": read-only first; promote individual routine remediations to auto only after each has a track record. Known blockers to design around: headless MCP auth (interactively-authenticated servers are absent in cron runs) and the consent boundary (triage Phase D, anything destructive).

The triage limb can reuse triage-intake's *auto mode* (added 2026-06-15, see [[file:.ai/workflows/triage-intake.org]]) — its accumulate-don't-mutate sweep is the propose-only behavior this orchestrator wants. Auto mode itself runs in-session (inherited MCP auth); the orchestrator is the durable headless schedule, so the headless-auth blocker above is the part still on this task to solve.