@joshuafolkken/kit 1.1005.0 → 1.1035.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/.claude/settings.json +1 -5
  2. package/.claude/skills/dependency-update/SKILL.md +6 -3
  3. package/.claude/skills/epic-commands/SKILL.md +46 -17
  4. package/.claude/skills/workflow-commands/SKILL.md +8 -23
  5. package/.claude/skills/workflow-commands/backlogrun-child.md +4 -2
  6. package/.claude/skills/workflow-commands/backlogrun.md +3 -12
  7. package/.claude/skills/workflow-commands/fullrun-steps.md +4 -3
  8. package/.claude/skills/workflow-commands/fullrun.md +1 -1
  9. package/.claude/skills/workflow-commands/halfrun.md +2 -1
  10. package/.claude/skills/workflow-commands/into-target.md +1 -1
  11. package/.claude/skills/workflow-commands/observation-filing.md +42 -43
  12. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  13. package/.codex/hooks.json +1 -5
  14. package/.github/workflows/sonar-qube.yml +1 -1
  15. package/AGENTS.md +4 -25
  16. package/CLAUDE.md +24 -38
  17. package/GEMINI.md +4 -24
  18. package/README.md +22 -58
  19. package/dist/CLAUDE.md +24 -38
  20. package/dist/hooks/batch-guard.js +4 -4
  21. package/dist/hooks/{chunk-WMIR5SNX.js → chunk-D67KVGGY.js} +3 -3
  22. package/dist/hooks/{chunk-EZLHXKJ6.js → chunk-EIFCAJRB.js} +70 -27
  23. package/dist/hooks/{chunk-KPZN42RT.js → chunk-GJT4BNVE.js} +3 -3
  24. package/dist/hooks/{chunk-PAXMLGSS.js → chunk-GLBDBJOK.js} +44 -24
  25. package/dist/hooks/{chunk-GBJUERYK.js → chunk-HOYJU5RM.js} +1 -1
  26. package/dist/hooks/{chunk-6PSTVOLH.js → chunk-HU66PWWL.js} +33 -57
  27. package/dist/hooks/{chunk-A2H5I2VD.js → chunk-KG6PZD72.js} +2 -2
  28. package/dist/hooks/{chunk-AWTFKKFW.js → chunk-XPLP27WA.js} +3 -8
  29. package/dist/hooks/{chunk-4GDR2YTV.js → chunk-Y27M6A7X.js} +4 -4
  30. package/dist/hooks/{chunk-56LGMJJV.js → chunk-ZXNE6NY3.js} +2 -2
  31. package/dist/hooks/codex-hook-adapter.js +10 -10
  32. package/dist/hooks/duplicate-read-guard.js +5 -5
  33. package/dist/hooks/format-edited.js +2 -2
  34. package/dist/hooks/investigation-guard.js +5 -5
  35. package/dist/hooks/pretool-guard.js +9 -9
  36. package/dist/hooks/stop-guard.js +11 -15
  37. package/dist/josh.js +38 -19
  38. package/dist/version/index.js +93 -41
  39. package/eslint/base.js +2 -11
  40. package/package.json +32 -6
  41. package/prompts/coding-standards.md +15 -290
  42. package/prompts/collaboration-workflow/cross-repo-epic.md +2 -51
  43. package/prompts/collaboration-workflow/epic-audit.md +2 -53
  44. package/prompts/collaboration-workflow/epic-bundle.md +2 -106
  45. package/prompts/collaboration-workflow/issue-template.md +4 -4
  46. package/prompts/collaboration-workflow/operating-rules.md +18 -75
  47. package/prompts/collaboration-workflow/principles.md +74 -0
  48. package/prompts/collaboration-workflow/residency.md +54 -14
  49. package/prompts/collaboration-workflow/rule-delivery.md +1 -11
  50. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  51. package/prompts/collaboration-workflow.md +22 -28
  52. package/scripts/adopt/adopt-logic.ts +2 -2
  53. package/scripts/adopt/adopt-toolkits.ts +1 -1
  54. package/scripts/adopt/adopt.ts +2 -2
  55. package/scripts/agent/agent-event.ts +2 -9
  56. package/scripts/agent/agent-exit-record.ts +2 -9
  57. package/scripts/backlog/backlog-budget-cli.ts +2 -6
  58. package/scripts/backlog/backlog-drive-cli.ts +20 -10
  59. package/scripts/backlog/backlog-drive.ts +50 -16
  60. package/scripts/backlog/backlog-offer-cli.ts +6 -5
  61. package/scripts/backlog/backlog-plan.ts +1 -1
  62. package/scripts/build/build-bin.ts +2 -1
  63. package/scripts/build/build-config-merge.ts +2 -1
  64. package/scripts/build/build-hooks.ts +24 -4
  65. package/scripts/build/build-managed-marker.ts +2 -1
  66. package/scripts/build/build-self-sync-guard.ts +2 -1
  67. package/scripts/build/build-version.ts +2 -1
  68. package/scripts/cases/cases-logic.ts +2 -6
  69. package/scripts/ci/pr-classification.ts +13 -11
  70. package/scripts/cost-runtime/cost-transcript.ts +4 -11
  71. package/scripts/doctor/doctor-consumer.ts +5 -12
  72. package/scripts/doctor/doctor-ports.ts +2 -2
  73. package/scripts/document/document-byte-budget.ts +8 -16
  74. package/scripts/document/document-section.ts +2 -6
  75. package/scripts/document/entry-read-budget.ts +1 -1
  76. package/scripts/{git/git-epic-add-body.ts → epic/epic-add-body.ts} +23 -23
  77. package/scripts/{git/git-epic-add-plan.ts → epic/epic-add-plan.ts} +23 -26
  78. package/scripts/{git/git-epic-add.ts → epic/epic-add.ts} +17 -17
  79. package/scripts/epic/epic-audit-cli.ts +4 -4
  80. package/scripts/epic/epic-audit-orphans.ts +2 -2
  81. package/scripts/epic/epic-audit-rationale.ts +1 -1
  82. package/scripts/epic/epic-audit.ts +1 -1
  83. package/scripts/{git/git-epic-body.ts → epic/epic-body.ts} +6 -6
  84. package/scripts/epic/epic-bundle-cli.ts +1 -1
  85. package/scripts/epic/epic-bundle.ts +2 -2
  86. package/scripts/epic/epic-candidate-confirm.ts +2 -1
  87. package/scripts/{git/git-epic-chains.ts → epic/epic-chains.ts} +4 -4
  88. package/{scripts-ai → scripts/epic}/epic-check.ts +5 -4
  89. package/{scripts-ai → scripts/epic}/epic-cli.ts +4 -4
  90. package/scripts/{git/git-epic-close-comment.ts → epic/epic-close-comment.ts} +9 -9
  91. package/scripts/{git/git-epic-close.ts → epic/epic-close.ts} +23 -19
  92. package/scripts/epic/epic-cross-repo.ts +21 -38
  93. package/scripts/{git/git-epic-decision.ts → epic/epic-decision.ts} +12 -14
  94. package/scripts/epic/epic-fetch.ts +3 -3
  95. package/scripts/epic/epic-graph.ts +3 -3
  96. package/scripts/epic/epic-index.ts +2 -2
  97. package/scripts/epic/epic-issue.ts +1 -1
  98. package/scripts/epic/epic-next.ts +3 -3
  99. package/scripts/{git/git-epic-parse.ts → epic/epic-parse.ts} +3 -3
  100. package/scripts/{git/git-epic-promote.ts → epic/epic-promote.ts} +10 -10
  101. package/scripts/{git/git-epic-read.ts → epic/epic-read.ts} +9 -9
  102. package/scripts/{git/git-epic-reconcile.ts → epic/epic-reconcile.ts} +18 -20
  103. package/scripts/{git/git-epic-reference.ts → epic/epic-reference.ts} +4 -23
  104. package/scripts/epic/epic-relation-recheck.ts +4 -3
  105. package/scripts/{git/git-epic-relations.ts → epic/epic-relations.ts} +5 -5
  106. package/scripts/{git/git-epic-remove-plan.ts → epic/epic-remove-plan.ts} +17 -19
  107. package/scripts/{git/git-epic-remove.ts → epic/epic-remove.ts} +13 -13
  108. package/scripts/{git/git-epic-run.ts → epic/epic-run.ts} +27 -27
  109. package/scripts/{git/git-epic-sections.ts → epic/epic-sections.ts} +6 -6
  110. package/scripts/{git/git-epic-shape.ts → epic/epic-shape.ts} +7 -7
  111. package/scripts/{git/git-epic-validate.ts → epic/epic-validate.ts} +13 -13
  112. package/{scripts-ai → scripts/epic}/epic.ts +17 -16
  113. package/scripts/gh/fix-gh-packages.ts +2 -1
  114. package/scripts/gh/gh-spawn.ts +12 -10
  115. package/scripts/git/constants.ts +1 -1
  116. package/scripts/git/git-branch.ts +10 -1
  117. package/scripts/git/git-command.ts +1 -1
  118. package/scripts/git/git-error.ts +2 -5
  119. package/{scripts-ai → scripts/git}/git-followup-finish.ts +7 -7
  120. package/scripts/git/git-followup-flush.ts +74 -48
  121. package/scripts/git/git-followup-issue-close.ts +2 -2
  122. package/scripts/git/git-followup-label.ts +1 -1
  123. package/scripts/git/git-followup-pending.ts +1 -1
  124. package/{scripts-ai → scripts/git}/git-followup-workflow.ts +23 -11
  125. package/scripts/git/git-gh-exec.ts +85 -26
  126. package/scripts/git/git-gh-issue-read.ts +2 -2
  127. package/scripts/git/git-gh-issue-rest.ts +2 -2
  128. package/scripts/git/git-gh-issue-write.ts +6 -6
  129. package/scripts/git/git-gh-pr-read.ts +0 -21
  130. package/scripts/git/git-gh-pr.ts +2 -23
  131. package/scripts/git/git-pr-followup-wrapup.ts +2 -6
  132. package/scripts/git/git-preflight.ts +3 -6
  133. package/scripts/git/git-staging.ts +21 -9
  134. package/{scripts-ai → scripts/git}/git-workflow.ts +11 -11
  135. package/scripts/git/github-issue-url.ts +1 -1
  136. package/scripts/git/issue-labels.ts +1 -1
  137. package/scripts/git/issue-reference.ts +19 -0
  138. package/scripts/git/main-merge.ts +2 -1
  139. package/scripts/git/main-sync.ts +3 -2
  140. package/scripts/git/schemas.ts +1 -1
  141. package/scripts/git/stash-pop-args.ts +7 -13
  142. package/scripts/git/stash-pop-cli.ts +2 -1
  143. package/{scripts-ai → scripts/git}/telegram-test-logic.ts +2 -2
  144. package/{scripts-ai → scripts/git}/telegram-test.ts +7 -7
  145. package/scripts/hooks/format-rewrite-notice.ts +2 -8
  146. package/scripts/init/init-ai-copy.ts +23 -14
  147. package/scripts/init/init.ts +8 -4
  148. package/scripts/init/start-steps.ts +2 -1
  149. package/scripts/init/start.ts +2 -1
  150. package/scripts/issue/issue-comment-cli.ts +2 -1
  151. package/scripts/issue/issue-file-cli.ts +2 -1
  152. package/scripts/issue/issue-fold-cli.ts +9 -16
  153. package/scripts/issue/issue-scout-cli.ts +8 -13
  154. package/scripts/issue/measure-rerun-cli.ts +7 -6
  155. package/scripts/josh/josh-commands-ai.ts +2 -2
  156. package/scripts/josh/josh-commands-backlog.ts +1 -1
  157. package/scripts/josh/josh-commands-development.ts +1 -1
  158. package/scripts/josh/josh-commands-workflow.ts +4 -4
  159. package/scripts/lane/lane-cli.ts +2 -1
  160. package/scripts/lane/lane-open.ts +3 -2
  161. package/scripts/lane/lane-registry.ts +3 -6
  162. package/scripts/lib/cli-flags.ts +20 -2
  163. package/scripts/lib/error-message.ts +9 -0
  164. package/scripts/lib/read-file.ts +26 -2
  165. package/scripts/observations/observation-ledger-home.ts +98 -26
  166. package/scripts/observations/observation-ledger-migrate.ts +26 -21
  167. package/scripts/observations/observation-ledger-prepare.ts +10 -20
  168. package/scripts/observations/observation-ledger.ts +58 -25
  169. package/scripts/observations/observations-flush-cli.ts +6 -23
  170. package/scripts/observations/observations-flush-landing.ts +2 -1
  171. package/scripts/observations/observations-flush.ts +29 -20
  172. package/scripts/package/package-scout-cli.ts +8 -16
  173. package/scripts/ports/port-command.ts +2 -1
  174. package/scripts/propagate/propagate-publish.ts +6 -7
  175. package/scripts/propagate/propagate-steps.ts +2 -1
  176. package/scripts/propagate/propagate.ts +3 -2
  177. package/scripts/refactor/import-graph.ts +2 -6
  178. package/scripts/registry-migration/migrate.ts +3 -2
  179. package/scripts/registry-migration/user-npmrc.ts +2 -2
  180. package/scripts/release/release-cli.ts +2 -1
  181. package/scripts/repo/repo-setting.ts +10 -8
  182. package/scripts/review/review-finding-ledger.ts +3 -3
  183. package/scripts/review/review-findings-cli.ts +4 -11
  184. package/scripts/review/review-record-cli.ts +14 -11
  185. package/scripts/review/review-record.ts +6 -16
  186. package/scripts/rules/decision-oracle.ts +2 -2
  187. package/scripts/rules/rule-body-guard.ts +2 -2
  188. package/scripts/rules/rule-value-cache.ts +99 -0
  189. package/scripts/rules/rule-value-cli.ts +10 -9
  190. package/scripts/rules/rule-value.ts +1 -1
  191. package/scripts/run/run-carry-args.ts +2 -6
  192. package/scripts/run/run-carry-cli.ts +5 -7
  193. package/scripts/run/run-cut-args.ts +7 -13
  194. package/scripts/run/run-ending-cli.ts +4 -7
  195. package/scripts/run/run-event-stream.ts +2 -5
  196. package/scripts/run/run-liveness-cli.ts +4 -7
  197. package/scripts/run/run-progress-args.ts +2 -6
  198. package/scripts/run/run-progress-cli.ts +2 -1
  199. package/scripts/run/run-tail-cli.ts +3 -3
  200. package/scripts/run/run-tidy-stashes.ts +7 -14
  201. package/scripts/run/run-wake-cli.ts +2 -6
  202. package/scripts/run/run-wake-driver.ts +15 -2
  203. package/scripts/run/run-wake-session.ts +14 -4
  204. package/scripts/safe-chain/project-config.ts +3 -6
  205. package/scripts/security/security-audit-provision.ts +6 -7
  206. package/scripts/sonar/sonar-hotspots-cli.ts +2 -1
  207. package/scripts/sync/directory-copy-guard.ts +2 -1
  208. package/scripts/sync/sync-ai-files.ts +3 -3
  209. package/scripts/sync/template-source-logic.ts +3 -4
  210. package/scripts/test/e2e-retry-check.ts +3 -6
  211. package/scripts/ui/ui-routes-cli.ts +3 -6
  212. package/scripts/version/bump-version.ts +2 -1
  213. package/scripts/version/version-remote.ts +18 -27
  214. package/scripts/version/version-targets.ts +3 -3
  215. package/.claude/skills/workflow-commands/rule-residency.md +0 -267
  216. package/evals/scenarios/consult-not-execute.json +0 -20
  217. package/evals/scenarios/no-implicit-workflow.json +0 -26
  218. package/evals/scenarios/overrides-both-locations.json +0 -29
  219. package/evals/scenarios/upstream-interrupt.json +0 -23
  220. package/evals/scenarios/workflow-skill-loaded.json +0 -16
  221. package/prompts/agent-lint-protocol.json +0 -79
  222. package/prompts/agent-rules.md +0 -63
  223. package/prompts/collaboration-workflow/consultation-vs-execution.md +0 -8
  224. package/prompts/collaboration-workflow/distributed-docs.md +0 -7
  225. package/prompts/collaboration-workflow/durable-rules.md +0 -24
  226. package/prompts/collaboration-workflow/latest-first.md +0 -14
  227. package/prompts/collaboration-workflow/no-clones.md +0 -11
  228. package/prompts/collaboration-workflow/simplicity-first.md +0 -9
  229. package/prompts/collaboration-workflow/single-source-rules.md +0 -13
  230. package/scripts/build/shim-shell.ts +0 -25
  231. package/scripts/claude/skill-meta.ts +0 -37
  232. package/scripts/document/document-scan.ts +0 -108
  233. package/scripts/document/generate-catalog.ts +0 -69
  234. package/scripts/document/retired-phrases.ts +0 -143
  235. package/scripts/document/review-agent-type.ts +0 -46
  236. package/scripts/document/single-source.ts +0 -73
  237. package/scripts/git/git-fixture-workspace.ts +0 -88
  238. package/scripts/hooks/format-edited-file-fixtures.ts +0 -109
  239. package/scripts/hooks/prompt-hooks.ts +0 -38
  240. package/scripts/init/hook-command-bootstrap.ts +0 -83
  241. package/scripts/issue/issue-logic.ts +0 -50
  242. package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +0 -1227
  243. package/scripts/josh/josh-script-reader.ts +0 -11
  244. package/scripts/package/production-dependency-graph.ts +0 -68
  245. package/scripts/retrospective/retrospective-cli.ts +0 -97
  246. package/scripts/retrospective/retrospective.ts +0 -127
  247. package/scripts/rules/delivered-rules-harness.ts +0 -72
  248. package/scripts/rules/top-level-scripts-guard.ts +0 -47
  249. package/scripts/run/run-carry-flush.ts +0 -58
  250. package/scripts/run/run-transcript.golden.txt +0 -57
  251. package/scripts/run/run-wake-work.ts +0 -108
  252. package/scripts/sync/dependabot-pin-logic.ts +0 -135
  253. package/scripts/test/classify-isolation.ts +0 -149
  254. package/scripts/test/http-fault-injection.ts +0 -79
  255. package/scripts/test/josh-harness-environment.ts +0 -260
  256. package/scripts/test/josh-harness.ts +0 -96
  257. package/scripts/test/pilot-files.ts +0 -452
  258. package/scripts/test/pilot-measure.ts +0 -78
  259. package/scripts/test/test-network-guard.ts +0 -453
  260. package/scripts/test/test-repository-guard.ts +0 -317
  261. package/scripts/test/test-state-guard.ts +0 -85
  262. package/scripts/test/test-stdout-guard.ts +0 -54
  263. package/scripts/test/test-telegram-guard.ts +0 -90
  264. package/scripts/test/unit-guard-environment.ts +0 -12
  265. package/scripts/test/unit-projects.ts +0 -139
  266. package/scripts/test/vitest-include-globs.ts +0 -12
  267. package/scripts/time-runtime/time-batch-guard-fixtures.ts +0 -66
  268. package/scripts-ai/completion-gate.ts +0 -13
  269. package/scripts-ai/environment-loader.ts +0 -9
  270. /package/{scripts-ai → scripts/epic}/epic-cli-argv.ts +0 -0
  271. /package/{scripts-ai → scripts/epic}/epic-cli-remove.ts +0 -0
  272. /package/{scripts-ai → scripts/git}/followup-issue-number.ts +0 -0
@@ -56,11 +56,7 @@
56
56
  "hooks": [
57
57
  {
58
58
  "type": "command",
59
- "command": "echo 'MANDATORY before writing any implementation code: present the two-layer work summary in the session language — 3 plain sentences (Now / Change / Check) a non-programmer can follow. Name the concrete subject in each line — subject-less prose is not acceptable; no file paths, function or type names, or CLI option flags — only internal identifiers are banned, not names the reader sees on screen. Then Details, then every change with its test. Ordinary markdown, never wrapped in a code fence. Required in fullrun/halfrun/backlogrun even when the Issue body was filled; presentation only, never a confirmation stop. Completion reports lead with Cause / Fix / Result. Tests are required for ALL changes; zero tests without explicit approval is a violation. Full rule: Code Change Rules Step 0 in CLAUDE.md.'"
60
- },
61
- {
62
- "type": "command",
63
- "command": "echo 'Deleting a git-tracked file is reversible, so it is NOT Tier C — do not ask for confirmation on reversibility grounds. Still inspect the target first and surface anything that contradicts the task.'"
59
+ "command": "echo 'MANDATORY before writing any implementation code: present the two-layer work summary (Now / Change / Check, then every change with its test). Full rule: Code Change Rules Step 0 in CLAUDE.md.'"
64
60
  },
65
61
  {
66
62
  "type": "command",
@@ -11,8 +11,10 @@ half: what you actually run to find out whether a command already touched them,
11
11
  one change that is expected. It applies after `pnpm update`, `josh latest`, `pnpm josh overrides`,
12
12
  a Dependabot merge, or any other command that can rewrite dependency versions.
13
13
 
14
- The canonical extended reference is `prompts/collaboration-workflow/operating-rules.md` → the overrides protection
15
- section; this skill is the operational procedure, and the two must agree.
14
+ This skill is the single source of the overrides protection's procedure;
15
+ `prompts/collaboration-workflow/operating-rules.md` only points here. Overrides were added on
16
+ purpose — for security, compatibility or a working guarantee (for example
17
+ `"esbuild@<=0.24.2": ">=0.25.0"` for Workers build compatibility).
16
18
 
17
19
  ## 1. Effective overrides live in the workspace — inspect both files
18
20
 
@@ -35,7 +37,8 @@ git diff -- pnpm-workspace.yaml package.json
35
37
  and confirm the effective `overrides:` block in `pnpm-workspace.yaml` and any historical
36
38
  `pnpm.overrides` declarations in `package.json` are untouched, **and** that `devDependencies`
37
39
  versions still respect the effective overrides. If any entry was removed, modified, or bumped past
38
- an override, restore it immediately.
40
+ an override, restore it immediately, investigate why it changed, and report that to the user — never
41
+ keep the change without explicit approval.
39
42
 
40
43
  `josh latest` prints its own verdict as its last overrides line (`✔ overrides unchanged (<n> from
41
44
  <file>)`, or a `⚠ overrides changed` warning), and `pnpm josh overrides` compares effective workspace
@@ -6,8 +6,9 @@ description: The procedures for the `josh epic:*` commands that make an epic run
6
6
  # The `josh epic:*` commands
7
7
 
8
8
  These three commands are what turn an epic from a list of issue numbers into something a run can
9
- execute unattended. The canonical extended reference is `prompts/collaboration-workflow/` — `epic-bundle.md`, `epic-audit.md` and `cross-repo-epic.md` between them; this
10
- skill is the operational procedure, and the two must agree.
9
+ execute unattended. **This skill is their single source**: `prompts/collaboration-workflow/` keeps
10
+ `epic-bundle.md`, `epic-audit.md` and `cross-repo-epic.md` only as pointers here, and the history
11
+ behind the rules is `docs/maintainers/epic-commands-rationale.md` (joshuafolkken/kit#2892).
11
12
 
12
13
  The workflow keywords themselves — `kickoff`, `fullrun`, `halfrun`, `backlogrun` — live in the
13
14
  `workflow-commands` skill.
@@ -80,9 +81,12 @@ adds is reading *inside* the children:
80
81
  | The search for those issues could not read the open backlog | **error** |
81
82
  | That search stopped before the end of the backlog | warning |
82
83
 
83
- **Only errors fail it.** The first check fires on a legitimate forward reference as readily as on a
84
- real missing dependency; failing on both would make design notes unwritable. A forward reference the
85
- other child *already depends on* is not reported at all.
84
+ **Only errors fail it** (exit 1); a warning leaves the exit code alone. The first check fires on a
85
+ legitimate forward reference as readily as on a real missing dependency; failing on both would make
86
+ design notes unwritable, so the reader judges and the machine only keeps it from being missed. A
87
+ forward reference the other child *already depends on* is not reported at all. Acceptance criteria
88
+ that require what a child free to run later produces cannot be met however anyone decides, which is
89
+ why that check is an error.
86
90
 
87
91
  **A pair with either child closed is a warning, not an error.** What makes an undeclared order a
88
92
  contradiction is that the criteria's child *can run first*, and one end closing is enough to make
@@ -92,11 +96,13 @@ audit forever, which stops every future run of that epic at the first step. It i
92
96
  dropped because dropping it hands the same pair to the first check, which reports it as an implicit
93
97
  dependency instead: the same one line, minus the detail that the name is in the acceptance criteria
94
98
  (joshuafolkken/kit#1010, widened from both-closed to either-closed by joshuafolkken/kit#1597 after a
95
- closed child citing an open sibling **as evidence** held an epic red at step one).
99
+ closed child citing an open sibling **as evidence** held an epic red at step one). **The demotion
100
+ needs the closed state confirmed**: `epic_issue.normalize_state` maps every state but `CLOSED`
101
+ (`MERGED` included) to `OPEN`, so a state that could not be confirmed stays an error.
96
102
 
97
103
  **Fixing what it finds is Tier A** — re-pointing a dependency or correcting prose is reversible and
98
- will otherwise stall the work. Park with `needs-decision` only when the contradiction is a design
99
- choice nobody has made.
104
+ will otherwise stall the work, so fix it without asking and record why on the issue. Park with
105
+ `needs-decision` only when the contradiction is a design choice nobody has made.
100
106
 
101
107
  **The two `orphan search` findings are the exception, because neither is a contradiction.** They are
102
108
  about the search itself rather than about anything the children say (joshuafolkken/kit#1033):
@@ -114,6 +120,8 @@ about the search itself rather than about anything the children say (joshuafolkk
114
120
  state or artifact, list the existing code referencing that concept and confirm some child owns
115
121
  updating it. Label names are single-sourced in `scripts/git/issue-labels.ts`.
116
122
 
123
+ History: `docs/maintainers/epic-commands-rationale.md` → "`epic:audit` — why the children are read across".
124
+
117
125
  ## `josh epic:next <E…>` — what is runnable
118
126
 
119
127
  Returns **every** runnable child, bundled per repository with the local checkout to run it in.
@@ -243,12 +251,12 @@ in `Dependencies` — is what a wave has to satisfy, and editing the body alone
243
251
  with nothing after it** — which is exactly what a hub is the moment the earlier wave has been chained
244
252
  into it. `chains_containing` finds several indices; `is_branching_after` does not hold, because it
245
253
  requires a successor in **every** chain naming the target and a hub has none in any of them; so
246
- `ambiguous_position_error` is raised (`scripts/git/git-epic-chains.ts`). **The first child of the
254
+ `ambiguous_position_error` is raised (`scripts/epic/epic-chains.ts`). **The first child of the
247
255
  next wave therefore goes into the declaration by hand**, with its `blocked-by` recorded to match.
248
256
  Once the hub has a successor, `--after <hub>` branches a new line and the rest of that wave goes in
249
257
  with it.
250
258
 
251
- **Nothing in the parsing or the consistency check forbids this.** `DECLARED_CHAIN_LINE` in `scripts/git/git-epic-parse.ts`
259
+ **Nothing in the parsing or the consistency check forbids this.** `DECLARED_CHAIN_LINE` in `scripts/epic/epic-parse.ts`
252
260
  asks only that a line be *nothing but* a chain, so there may be any number of chain lines and **one
253
261
  child may be an endpoint of several of them** — `parse_dependency_links` expands each line
254
262
  independently and flattens the result, dropping only self-loops. `find_anomalies` in
@@ -328,7 +336,11 @@ to implement.
328
336
  - **The epic auto-closes only when every cross-repository child's state could actually be read.** One
329
337
  unreadable child leaves it open, exactly as before.
330
338
  - **An epic in another repository must be referenced as `owner/repo#N`** — `backlogrun
331
- joshuafolkken/kit#858 --only`. A bare `#N` resolves to *this* repository's issue of that number.
339
+ joshuafolkken/kit#858 --only`, `epic:next joshuafolkken/kit#858 --repo joshuafolkken/app-kit`. A
340
+ bare `#N` resolves to *this* repository's issue of that number. A cross-repository epic exists in
341
+ one repository only.
342
+ - **`epic:next` prints each candidate's repository and local checkout** from joshuafolkken/kit#869's
343
+ map; a repository with no checkout prints `(no local checkout)` and is **never cloned on its own**.
332
344
 
333
345
  **A dependency that crosses a repository is not satisfied by the blocking issue closing.** Merging
334
346
  does not publish: the merge, the auto-tag and the publish run one after another, so a consumer told
@@ -341,12 +353,17 @@ default branch declares has appeared in the registry.
341
353
  wait on — so a closed blocker there resolves rather than waiting until the run's own eight-hour
342
354
  timeout with nothing an operator can edit to clear it. The answer is read from the blocker
343
355
  repository's own manifest and never from the registry: a registry 404 also means "this token may not
344
- see it", so resolving on one would start a consumer child before its blocker's release existed.
356
+ see it", so resolving on one would start a consumer child before its blocker's release existed. A
357
+ manifest read that fails (rather than answering 404) is told apart by HTTP status and still waits.
345
358
 
346
359
  **The evaluation is an AND in that order.** While the blocker is open the registry is never
347
360
  consulted, so a run never stalls on a publish from the moment it starts. The target is that exact
348
361
  version, never "something newer" — a consumer several releases behind would otherwise be satisfied by
349
- a publish that predates the change.
362
+ a publish that predates the change. **A child no longer bumps the version** (joshuafolkken/kit#1486):
363
+ the version moves only when `pnpm josh release` runs, so the target is the release that includes the
364
+ blocker, and the default branch's version just after its merge is the previous release, which would
365
+ satisfy the wait at once. The publish check shares `josh propagate`'s implementation; it is not
366
+ defined twice. History: `docs/maintainers/epic-commands-rationale.md` → "Cross-repository epics".
350
367
 
351
368
  ## `josh epic:bundle <N>` — does this new issue belong with one already filed?
352
369
 
@@ -373,14 +390,18 @@ all: `repos/{owner}/{repo}/issues/<N>` serves one too, and a merged PR does not
373
390
 
374
391
  **A number that does not exist is not a gap.** A typo, or another repository's number quoted in
375
392
  prose, is dropped in silence — neither a candidate nor something the command reports it could not
376
- read. Reported as a gap it puts `⚠ Could not read #N.` above the verdict, and the rule below stops an
377
- unattended run on exactly that, for a reference that never existed (joshuafolkken/kit#957). **The two
393
+ read. Reported as a gap it puts `⚠ Could not read #N.` above the verdict, and the could-not-answer rule
394
+ (`prompts/review.md` → "Three-way disposition after the cap") stops an unattended run on exactly that, for a reference that never existed (joshuafolkken/kit#957). **The two
378
395
  are told apart by HTTP status, never by `gh`'s wording**: 404 is nothing at that number, 403 and 429
379
396
  are a rate limit. GitHub answers 404 for an issue the token may not see as well, so as not to leak
380
397
  its existence — which does not reach this command, because it probes the repository whose open issues
381
398
  it has just listed. The probe costs one REST request and runs **only** when a read has already
382
399
  failed, and only on the path that needs the distinction: the backlog's own relation reads, up to two
383
- hundred of them, never pay it.
400
+ hundred of them, never pay it, and the referenced-number reads are capped at twenty. **Only the
401
+ subject's own body is followed** — the reverse direction would scan every closed issue, and a
402
+ follow-up already names its parent. The reference parsing is the same implementation as
403
+ `epic:audit`'s implicit-dependency check, applied to the backlog instead of one epic. The open backlog
404
+ is small enough to scan whole, so there is no index or cache.
384
405
 
385
406
  | Candidates | Do | Tier |
386
407
  | --- | --- | --- |
@@ -392,6 +413,11 @@ hundred of them, never pay it.
392
413
  | No strong signal | Nothing | — |
393
414
  | **The epic listing was cut short** | **Nothing** — every placing row above is withheld | — |
394
415
 
416
+ **`none` is a legitimate answer** — a self-review outside any workflow has no current issue to point
417
+ at, so the issue stays in the backlog: what the procedure requires is running the command and
418
+ following its answer, not landing every issue in an epic. The review-cap follow-up's filing and the
419
+ answer table it acts on are `prompts/review.md` → "Three-way disposition after the cap".
420
+
395
421
  **Every row that *places* the issue asserts a negative, so a cut epic listing withholds all of them**
396
422
  (joshuafolkken/kit#1697). "No epic already tracks this issue" — which `create_epic` asserts about the
397
423
  candidates too — is only as good as the listing it was read from, and an epic past the cut tracks its
@@ -399,7 +425,8 @@ children invisibly. **`add_to_epic` rests on it as much as `create_epic` does**:
399
425
  the epic a *candidate* sits in, while an unseen epic already tracks the issue itself, is the same
400
426
  duplicate by another route. The cut was already on standard error
401
427
  (`⚠ The epic listing …`) while standard output went on printing an executable
402
- instruction such as `Create an epic for these (Tier A — do it).` — and the rule below that reads a warning as "could not answer" is written for one above
428
+ instruction such as `Create an epic for these (Tier A — do it).` — and the rule that reads a warning as "could not answer" (`prompts/review.md` → "Three-way
429
+ disposition after the cap") is written for one above
403
430
  `Nothing to bundle.`, so it never reached this verdict. Acted on as Tier A, that is a **second epic
404
431
  over an already-tracked issue**, which the auto-close and `epic:next` cannot both be right about
405
432
  (joshuafolkken/kit#943). The verdict now says so itself:
@@ -462,3 +489,5 @@ Full behavior: `docs/josh-commands.md` → "`josh issue:file`".
462
489
  **When the relation carries an order, record it** in `blocked-by` and in the epic's `Dependencies` —
463
490
  on an addition as much as on a new epic. Without it the batch survives and the reason for it does
464
491
  not. An order **nobody declared is not invented**.
492
+
493
+ History: `docs/maintainers/epic-commands-rationale.md` → "`epic:bundle` — why issues filed apart are bundled afterwards".
@@ -28,16 +28,8 @@ resident in the AI documents, because it has to hold when this skill has *not* b
28
28
  - The rule applies even when the user authorized a related workflow in an earlier turn. Each
29
29
  invocation must be re-typed by the user in the current turn.
30
30
 
31
- **A session cut inside a declared budget is not a new invocation.** A `backlogrun` that is cut and
32
- resumed is still the one invocation a person typed — the keyword authorized the declared budget, and
33
- the cut is an execution detail of spending it. What this rule forbids is _inferring_ a workflow from a
34
- request's shape. **The reading covers `backlogrun` and it alone** — a `fullrun` cut still waits for
35
- the keyword, because a `fullrun` ends at one issue and has nothing to carry.
36
-
37
- **`backlogrun-steps.md` → "The session cut is inside the invocation" is the single source of the
38
- mechanism** — the record, the two commands, and what each answer means, and how a named-issue
39
- `backlogrun #N1 #N2 …` pins its list to what was typed while the issues it has finished live in the
40
- record's `done` field rather than shrinking the string.
31
+ **A session cut inside a declared budget is not a new invocation — for `backlogrun` alone**; its
32
+ single source is `backlogrun-steps.md` → "The session cut is inside the invocation".
41
33
 
42
34
  ## 1. Which file to read
43
35
 
@@ -62,7 +54,7 @@ lists `backlogrun.md` alone: its parent orchestrates and never implements, so `f
62
54
  Every procedure for *running* a `backlogrun` item — lanes (`backlogrun-lanes.md`), park-and-continue,
63
55
  the guards — stays `backlogrun.md`'s. The on-demand sections `into-target.md` (an `into` suffix) and `target-repository.md`
64
56
  (an `owner/repo#` prefix) are read only when their trigger is typed, and §3's residency procedure lives
65
- in `rule-residency.md`, reached only when a rule is placed, moved or retired.
57
+ in `prompts/collaboration-workflow/residency.md`, reached only when a rule is placed, moved or retired.
66
58
 
67
59
  ### The fetch is one `Read` call per file
68
60
 
@@ -251,15 +243,8 @@ there. A dispatched lane child never runs the retrospective.
251
243
 
252
244
  ## 3. What stays resident, and what is read from here
253
245
 
254
- **The residency criterion and its procedure are `rule-residency.md`, read only when a rule is being
255
- placed, moved or retired — never at any entry, and never during a run.** It carries question 0 (is the
256
- answer computable from mechanically readable inputs, so it is a decision oracle — `pnpm josh
257
- oracle:list`), the ordering question (does it decide *when or in what order* rather than *what*, so it
258
- goes in the run driver `pnpm josh run:step` — `prompts/collaboration-workflow/residency.md` → ordering
259
- question), the first question (can the trigger be named as one tool call, so the body moves out of
260
- `CLAUDE.md` to a hook via `prompts/collaboration-workflow/rule-delivery.md`), the second question
261
- (does it have to fire on a turn where no skill was loaded, so it stays in `CLAUDE.md`), and the
262
- procedure that decides how much of a resident rule is resident — the trigger-plus-pointer shape, the
263
- enumeration of every resident rule with an on-demand counterpart, and the retirement route and its
264
- three tests. `rule-residency.md` is the single source; the moment it binds is a turn spent editing
265
- these documents, never a turn spent executing an Issue.
246
+ **The residency criterion is `prompts/collaboration-workflow/residency.md`, its single source — read
247
+ only when a rule is being placed, moved or retired, never at any entry and never during a run.** Its
248
+ questions are asked there in order — question 0 (`pnpm josh oracle:list`), the ordering question
249
+ (`pnpm josh run:step`), the first and the second — beside how much of a resident rule stays and the
250
+ retirement route; none is restated here.
@@ -117,8 +117,10 @@ summary is bounded the way it is".
117
117
  discretionary observation has**: a child files `route:tier-a` and `route:interrupt` only, and the
118
118
  parent files what survives — `SKILL.md` → §2i, the single source. **What the parent does with the
119
119
  rest is append it, not drop it**: an observation that cannot cite the depth-0 work it blocked
120
- becomes one line in the observation ledger, and a second line under the same key files it. **The
121
- child never writes that file** — it cannot tell its observation from the sibling lane's.
120
+ becomes one line in the observation ledger, and a second line under the same key files it. **A
121
+ child appends only to its own issue's file, `docs/maintainers/observations/<N>.md`, in its own
122
+ lane** (joshuafolkken/kit#2919) — it merges with the child's pull request, and a sibling lane's
123
+ file is never one it touches.
122
124
  4. **Decisions taken and why**, where the decision was not already logged as an Issue comment.
123
125
  5. **What was left undone**, and under whose authority.
124
126
 
@@ -27,18 +27,9 @@ therefore runs exactly one epic's children and stops.
27
27
 
28
28
  ## Explicit invocation required (MANDATORY)
29
29
 
30
- **Never start a `backlogrun` unless the user has typed the keyword in the current turn's prompt.**
31
- This is the same rule the other entry points carry, at the same strength — `SKILL.md` → §0 is its
32
- single source, and `CLAUDE.md` → "Explicit invocation required (MANDATORY)" is where it stays resident
33
- so it binds on a turn where nothing here has been read. It matters more here than anywhere else,
34
- because this is the entry point with the widest authorization: a conversational "clear the backlog" is
35
- **not** an invocation, a confirmation question is no substitute for the keyword, and an earlier turn's
36
- authorization does not carry.
37
-
38
- **The keystroke starts the invocation; it does not have to land in every session that invocation
39
- spans.** A `backlogrun` cut mid-run and resumed is still that one invocation
40
- (`backlogrun-steps.md` → "The session cut is inside the invocation"). This reading covers `backlogrun`
41
- and it alone — a `fullrun` cut still waits for the keyword.
30
+ **Never start a `backlogrun` unless the user has typed the keyword in the current turn's prompt** —
31
+ `SKILL.md` → "0. The rule that fires before any of them — explicit invocation"; a cut and resumed run
32
+ is still that one invocation (`backlogrun-steps.md` → "The session cut is inside the invocation").
42
33
 
43
34
  ## The manifest — the ordered flow
44
35
 
@@ -55,7 +55,8 @@ that covers the same work stops the run rather than filing a second Issue (`SKIL
55
55
  `<N>`. (3) Add
56
56
  `in-progress` (as above). (4) Post the agreed plan in the session language: fill the body if blank,
57
57
  otherwise add a comment. (5) If the working tree already has staged or modified files,
58
- `git stash push -m "fullrun new: pre-existing changes"` first. (6) `git switch main && git pull`. (7)
58
+ `git stash push -m "fullrun new: pre-existing changes" -- ':!docs/maintainers/observations'` first
59
+ (joshuafolkken/kit#2919). (6) `git switch main && git pull`. (7)
59
60
  `pnpm josh latest:scope`; on `required` run `josh latest` and load the `dependency-update` skill; on
60
61
  `skip` neither runs (`latest-gate.md` is the single source). If you stashed in (5),
61
62
  `pnpm josh stash:pop "fullrun new: pre-existing changes"` — by message, never a positional `git stash
@@ -78,8 +79,8 @@ release:scope` and close the completion summary with what it answered** (`follow
78
79
  ## The release ask — the last step of either form
79
80
 
80
81
  **One call folds the post-merge bookkeeping** (joshuafolkken/kit#2372): after the merge, `pnpm josh
81
- run:tail <N>` commits the observation ledger (`observations:flush` — skipped by a dispatched lane child,
82
- whose `backlogrun` flushes once at `run:carry --end`; joshuafolkken/kit#2492), reads the completion citations
82
+ run:tail <N>` commits ledger lines written outside any issue's run (`observations:flush`,
83
+ joshuafolkken/kit#2919), reads the completion citations
83
84
  (`issue:cite`, given the closed issue and any follow-ups filed this run) and decides the release scope
84
85
  (`release:scope`) in one round trip, joining each under its own header. **On the clean path `run:tail`
85
86
  runs inside `pnpm josh ship`** as its report step (joshuafolkken/kit#2398), so it is a standalone call
@@ -46,7 +46,7 @@ call reports `hold`.
46
46
  `pnpm josh latest:scope` — update dependencies only on `required` (`latest-gate.md`), never on every
47
47
  run. `run:step` names every later action in order — the verification gate, `pnpm josh followup`,
48
48
  `pnpm josh ms`, the release ask — each read at the point-of-use doc the header lists, never
49
- re-narrated here (`residency.md` → ordering question).
49
+ re-narrated here (`residency.md` → "順序の問い").
50
50
 
51
51
  ## The progress step and the lane-child seam
52
52
 
@@ -59,7 +59,8 @@ back with fixes, treat each as a new round: implement, re-run `pnpm josh gate`,
59
59
  mirror `fullrun new` (1)–(8): derive an English title (or use the provided one) → create the Issue
60
60
  (`pnpm josh issue:file "<title>" --body-file <body-file> --depth <n>`, body per
61
61
  `prompts/collaboration-workflow/issue-template.md`; its duplicate scan is read per `SKILL.md` → §2e) → add `in-progress` → post the agreed plan → stash
62
- any pre-existing changes with `git stash push -m "halfrun new: pre-existing changes"`, popped by
62
+ any pre-existing changes with `git stash push -m "halfrun new: pre-existing changes" -- ':!docs/maintainers/observations'`
63
+ (the pathspec keeps the observation ledger in the tree for this run's commit; joshuafolkken/kit#2919), popped by
63
64
  message with `pnpm josh stash:pop "halfrun new: pre-existing changes"`, never a positional `git stash pop` →
64
65
  `git switch main && git pull` → `pnpm josh latest:scope` → implement → run the gate (as above, `pnpm
65
66
  josh test:e2e` run by **you**) → `pnpm josh run:hold <N> --halfrun-stop` → send the `confirmation`
@@ -39,7 +39,7 @@ new epic" when what gets created is often a single Issue.
39
39
  applies depends on what the target is, and promoting rewrites someone else's Issue into a container.
40
40
  - **A cross-repository target is written `owner/repo#N`** and inserted from that repository's
41
41
  checkout; run there, since `epic --add` reads and writes only the repository it runs from
42
- (`prompts/collaboration-workflow/cross-repo-epic.md`). A bare `#N` resolves to this repository's
42
+ (`.claude/skills/epic-commands/SKILL.md` → "Epics that span repositories"). A bare `#N` resolves to this repository's
43
43
  issue of that number.
44
44
  - **No suffix leaves the behavior exactly as it was.**
45
45
 
@@ -175,10 +175,15 @@ joshuafolkken/kit#1726 is the worked case: its own body says the depth test woul
175
175
  and it was filed anyway, because **discarding it was the only alternative on offer**
176
176
  (joshuafolkken/kit#1728).
177
177
 
178
- - **The destination is `docs/maintainers/observations.md` in the repository the observation is about** — the same
179
- repository the Issue would have been filed into. **The count and the append are both run in that
180
- repository's checkout**, resolved the way §2c (`target-repository.md`) resolves any cross-repository target, and the file is
181
- created on the first append where that repository has none. **The subject decides, never the
178
+ - **The destination is the `docs/maintainers/observations/` directory in the repository the
179
+ observation is about** — the same repository the Issue would have been filed into — **one file per
180
+ issue** (joshuafolkken/kit#2919): append to `<N>.md` for the issue the run is executing (the number
181
+ its branch leads with, a lane's included), or to `<YYYY-MM-DD>.md` for a line written on the
182
+ default branch outside any issue's run. Parallel lanes therefore write different files, and their
183
+ pull requests never conflict on the ledger. **The count and the append are both run in that
184
+ repository's checkout** — in this repository, the work tree the run is in, a lane's inside a lane —
185
+ resolved the way §2c (`target-repository.md`) resolves any cross-repository target, and the
186
+ directory is created on the first append where that repository has none. **The subject decides, never the
182
187
  working directory**: an observation about this package's own orchestration, seen while a run is
183
188
  inside a repository that consumes it, is recorded here rather than there — the append follows the
184
189
  subject, never the working directory. **A third-party target gets no line either** — Tier C covers
@@ -186,8 +191,8 @@ and it was filed anyway, because **discarding it was the only alternative on off
186
191
  - **It is append-only.** A line is never edited and never deleted, because the count of lines
187
192
  carrying one key is what says whether an observation has recurred; a second sighting is a second
188
193
  line, not a rewrite of the first. **A merge conflict in it is resolved by keeping both sides** —
189
- two lanes appending at once is the ordinary case, and a repeated key is the whole signal, so
190
- dropping either side destroys exactly what the file is for.
194
+ one file per issue should keep it from arising, but a repeated key is the whole signal, so
195
+ dropping either side destroys exactly what the ledger is for.
191
196
  - **The completion report keeps its line too.** The ledger is what the next run can read; the report
192
197
  is what this run's reader sees. Neither replaces the other.
193
198
  - **The append is not the end of it** — a line only becomes readable to anyone else once it has
@@ -215,21 +220,22 @@ A sample, in the shape a real entry takes:
215
220
  ```
216
221
 
217
222
  **`k:example` is reserved for this sample and is never used by a real observation**, so the count
218
- below can be run over the whole file without the sample answering for one. **The grammar is defined
223
+ below can be run over the whole ledger without the sample answering for one. **The grammar is defined
219
224
  here rather than in the ledger** because this skill is distributed to every repository that consumes
220
225
  the package and `docs/` is not — a rule that named a definition the reader never received would
221
226
  leave every consumer's ledger shaped by hand.
222
227
 
223
228
  **The identity key is the whole of the repeat test — never a similarity judgement about the prose.**
224
229
  Choose the key from the phenomenon rather than from the run, then count what the ledger already holds
225
- for it, in that repository's checkout rather than the working directory. **The `|| true` is not
226
- decoration**: `grep -c` exits non-zero on a count of zero, which is the first-sighting branch and the
227
- common one, so without it the step reads as a failed command wherever an exit status is being
228
- watched. **A missing file is not a count of zero, though** — there `grep` exits 2 and prints no
229
- number at all, so an empty answer means create the ledger, never that this is a first sighting.
230
+ for it, in that repository's checkout rather than the working directory. **Every file of the
231
+ directory is counted**, because a recurrence is a recurrence whichever issue's file each sighting
232
+ sits in. **The `|| true` is not decoration**: `grep -c` exits non-zero on a count of zero, which is
233
+ the first-sighting branch and the common one, so without it the step reads as a failed command
234
+ wherever an exit status is being watched. **A missing directory is still a first sighting** — `cat`
235
+ complains on standard error and the count is zero; the append below creates the directory.
230
236
 
231
237
  ```bash
232
- grep -c '^- k:<slug> |' <that repository's checkout>/docs/maintainers/observations.md || true
238
+ cat <that repository's checkout>/docs/maintainers/observations/*.md | grep -c '^- k:<slug> |' || true
233
239
  ```
234
240
 
235
241
  Free-text comparison is what the key exists to replace, so two lines that read alike under different
@@ -254,7 +260,7 @@ that is empty on every other machine**, and every sighting was a first one, whic
254
260
  joshuafolkken/kit#1728 created the ledger to end.
255
261
 
256
262
  - **A run's appended lines ride its own commit** (joshuafolkken/kit#2763). `pnpm josh git` stages
257
- `docs/maintainers/observations.md` with the run's other changes, in the one staging step every entry
263
+ `docs/maintainers/observations/` with the run's other changes, in the one staging step every entry
258
264
  point goes through (`scripts/git/git-staging.ts`), so the lines are reviewed and merged with the
259
265
  pull request of the run that recorded them, and the run's CI is the only wait they cost. Until
260
266
  #2763 the ledger was excluded there (joshuafolkken/kit#1756) and every run that appended a line
@@ -263,35 +269,28 @@ joshuafolkken/kit#1728 created the ledger to end.
263
269
  before `pnpm josh git -y` is carried; the time while CI runs is for the records that need no CI
264
270
  result — filing an observation Issue, drafting the completion report.
265
271
  - **A line that breaks the grammar is not carried** (joshuafolkken/kit#2123). The staging step parses
266
- the ledger first — after moving lines still on the old path (joshuafolkken/kit#2724) — and on a
267
- broken line leaves the ledger out of the commit and says so; the commit itself goes ahead.
268
- - **What no run's commit carried is flushed as a pull request of its own** — `pnpm josh
269
- observations:flush`: a lane's lines (next bullets) and a line appended after the commit, such as a
270
- second review round's record. It stages that one path and nothing else, commits it on a branch of
271
- its own, opens a docs-only pull request, waits on the same required checks every other pull request
272
- waits on, merges it and returns the checkout to the default branch. **Nothing is committed to the
273
- default branch directly.**
274
- - **`pnpm josh followup` runs that flush itself, so no run has to remember to** (joshuafolkken/kit#1810).
275
- After the merge and before it releases the working-tree hold, `followup` reads the tree, and **only
276
- when the ledger still holds a pending append** returns the checkout to the default branch
277
- (`pnpm josh ms`) and flushes. A run whose lines rode its commit pays nothing, and a lane skips it
278
- (next bullet). A flush that fails is reported and does not take the merge, the epic close or the
279
- hold release down with it. **A side effect: on a run that did flush, `followup` ends on the default
280
- branch.**
281
- - **A lane's writers use the primary checkout's ledger** (joshuafolkken/kit#2419): a lane refuses
282
- `pnpm josh ms`, so its own copy had no way out. `pnpm josh observations:flush` acts on the primary
283
- checkout from a lane. **A dispatched lane child does not flush at all** (joshuafolkken/kit#2492): its
284
- `run:tail` skips the step, and the `backlogrun` flushes every lane's lines once, in one pull request,
285
- at `pnpm josh run:carry --end`.
286
- - **A lane child's pull request does not carry the lines, and that is deliberate.** Lanes run side by
287
- side, and two pull requests that each append at the ledger's tail conflict with each other the
288
- moment the first merges — a conflict ends the other's CI wait. The batch's single flush at
289
- `run:carry --end` is already one pull request per batch, not one per child.
290
- - **Run by hand it goes in the primary checkout, once per cycle rather than once per observation** —
291
- but with the lines riding the run's commit and `pnpm josh followup` flushing the rest (above), a hand
292
- run is the exception rather than the rule. It refuses off the default branch and refuses a working tree holding anything besides
293
- the ledger, so a run in progress cannot be flushed out from under, and a lane's checkout is never
294
- the one it acts on.
272
+ every file of the ledger first — after moving lines still on an old single-file path
273
+ (joshuafolkken/kit#2724, joshuafolkken/kit#2919) — and on a broken line leaves the ledger out of the
274
+ commit and says so; the commit itself goes ahead.
275
+ - **`pnpm josh followup` commits a line appended after the run's commit onto the pull request, before
276
+ the merge** (joshuafolkken/kit#2919) — a second review round's record is the usual case. After the
277
+ merge gates and before the CI wait, `followup` reads the tree and, **only when the ledger holds a
278
+ pending append**, stages the ledger paths alone, commits them and pushes the branch; the CI wait
279
+ that follows covers the pushed commit. A broken line refuses the merge, because the line would
280
+ otherwise be lost with the branch. A run whose lines rode its commit pays nothing.
281
+ - **A lane carries its own lines, in its own pull request** (joshuafolkken/kit#2919). Its writers
282
+ append to its own tree's `<N>.md`, so the two steps above take them to the default branch exactly as
283
+ they do for a run in the primary checkout. Lanes once wrote to the primary checkout's single file
284
+ instead (joshuafolkken/kit#2419) and a `backlogrun` flushed them all at `run:carry --end`
285
+ (joshuafolkken/kit#2492); another run's stash of that checkout took the lines before the flush saw
286
+ them, so neither route remains. **Nothing is held in the primary checkout for later.**
287
+ - **`pnpm josh observations:flush` is left for a line written outside any issue's run** — the
288
+ date-named file a retrospective or a hand append on the default branch writes. It stages the ledger
289
+ and nothing else, commits it on a branch of its own, opens a docs-only pull request, waits on the
290
+ same required checks every other pull request waits on, merges it and returns the checkout to the
291
+ default branch; a single run's `run:tail` runs it after the merge. It refuses off the default branch
292
+ and refuses a working tree holding anything besides the ledger, so a run in progress cannot be
293
+ flushed out from under. **Nothing is committed to the default branch directly.**
295
294
  - **Nothing to flush is an answer, not a failure.** With the ledger matching the commit it sits on
296
295
  the command prints `clean` and exits 0 — most cycles append nothing, and a command that errored
297
296
  there would be one nobody runs.
@@ -18,7 +18,7 @@ another is the failure this section exists to prevent:
18
18
  | A defect originating in **another package** | File the upstream Issue and **stop** — Tier A for a first-party target; a third-party one is Tier C, recorded and drafted rather than filed (`CLAUDE.md` → "Cross-package problems"; `prompts/collaboration-workflow/upstream-interrupt.md`) |
19
19
  | This Issue was really **several** (a split) | File the children and the epic and **stop** — except under `backlogrun`, whose authorization already covers a batch, so the children are filed and run through (`split-assessment.md`) |
20
20
  | Another Issue in **this** repository has to land first (**a prerequisite**) | This section |
21
- | Something worth filing that is **none of the three** (**an observation**) | File it **without asking** — Tier A for a first-party target — and **carry the run straight on**: nothing is stashed, nothing is parked (§2i). **A delegated child does not file here**, and a filing at depth 1 or deeper cites the depth-0 work it blocked; one that cannot cite it goes to `docs/maintainers/observations.md` and is filed on its second sighting — all of them §2i's |
21
+ | Something worth filing that is **none of the three** (**an observation**) | File it **without asking** — Tier A for a first-party target — and **carry the run straight on**: nothing is stashed, nothing is parked (§2i). **A delegated child does not file here**, and a filing at depth 1 or deeper cites the depth-0 work it blocked; one that cannot cite it goes to the run's own `docs/maintainers/observations/<N>.md` and is filed on its second sighting — all of them §2i's |
22
22
 
23
23
  **File the prerequisite with the `route:tier-a` label**, so a Tier A filing made during implementation
24
24
  stays countable by filing route afterwards. **This paragraph belongs to the prerequisite row, not to
package/.codex/hooks.json CHANGED
@@ -41,11 +41,7 @@
41
41
  "hooks": [
42
42
  {
43
43
  "type": "command",
44
- "command": "echo 'MANDATORY before writing any implementation code: present the two-layer work summary in the session language — 3 plain sentences (Now / Change / Check) a non-programmer can follow. Name the concrete subject in each line — subject-less prose is not acceptable; no file paths, function or type names, or CLI option flags — only internal identifiers are banned, not names the reader sees on screen. Then Details, then every change with its test. Ordinary markdown, never wrapped in a code fence. Required in fullrun/halfrun/backlogrun even when the Issue body was filled; presentation only, never a confirmation stop. Completion reports lead with Cause / Fix / Result. Tests are required for ALL changes; zero tests without explicit approval is a violation. Full rule: Code Change Rules Step 0 in CLAUDE.md.'"
45
- },
46
- {
47
- "type": "command",
48
- "command": "echo 'Deleting a git-tracked file is reversible, so it is NOT Tier C — do not ask for confirmation on reversibility grounds. Still inspect the target first and surface anything that contradicts the task.'"
44
+ "command": "echo 'MANDATORY before writing any implementation code: present the two-layer work summary (Now / Change / Check, then every change with its test). Full rule: Code Change Rules Step 0 in CLAUDE.md.'"
49
45
  },
50
46
  {
51
47
  "type": "command",
@@ -36,7 +36,7 @@ jobs:
36
36
  fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
37
37
  - name: SonarQube Scan
38
38
  if: env.SONAR_TOKEN != ''
39
- uses: SonarSource/sonarqube-scan-action@ba9859eae8dd6bd29e412f25ddbbef3d032000f4 # v8.2.2
39
+ uses: SonarSource/sonarqube-scan-action@d209202bc7d53ff1cc128f7f907dac145c9d6ae9 # v8.3.0
40
40
  with:
41
41
  # Wait for the SonarCloud Quality Gate and fail this job (a required PR check) when the
42
42
  # gate is red, so a PR that introduces a Maintainability / code-smell finding cannot be
package/AGENTS.md CHANGED
@@ -1,29 +1,8 @@
1
1
  # Agent Instructions
2
2
 
3
3
  > **All rules for this repository live in [`CLAUDE.md`](./CLAUDE.md). Read it in full before doing
4
- > any work here, and follow every rule in it.** This file exists only to point at it.
4
+ > any work here, and follow every rule in it.** This file exists only to point at it. Nothing in
5
+ > `CLAUDE.md` is Claude-specific — it applies to whatever agent is doing the work.
5
6
 
6
- `CLAUDE.md` is the single source. It is named for the tool that reads it by default, but nothing in
7
- it is Claude-specific — the naming conventions, quality limits, code-change rules, verification
8
- gate, git rules and collaboration workflow apply to whatever agent is doing the work.
9
-
10
- Rules that only apply while a particular command is running are not in `CLAUDE.md` either. It routes
11
- to them, and the routing is part of the rules: read the `<name>` skill when
12
- `CLAUDE.md` tells you to, and `prompts/*.md` when it names one.
13
-
14
- There is no include directive here, only the sentence above. `GEMINI.md` carries an `@CLAUDE.md`
15
- line because Gemini CLI documents that syntax; the tools that read `AGENTS.md` document no
16
- equivalent, so inventing one would put a line in this file that no reader acts on. **The pointer is
17
- therefore prose an agent has to act on, and it has not been verified against Codex or Cursor** —
18
- only Claude is in use here, and that decision is recorded in joshuafolkken/kit#970 under
19
- `## Decisions`.
20
-
21
- ## Why this file is a pointer
22
-
23
- `AGENTS.md`, `GEMINI.md` and `CLAUDE.md` used to be three near-identical copies of the same rules,
24
- which meant one rule change had to be written three times and reviewed three times
25
- (joshuafolkken/kit#963). That is the clone the rules themselves prohibit — see "No clones —
26
- single-source" in `CLAUDE.md` — so the rules were single-sourced and these two became pointers.
27
-
28
- **Do not copy rules back into this file.** A rule added here is a fourth place to forget to update.
29
- Every change to how agents work in this repository belongs in `CLAUDE.md`.
7
+ **Do not copy rules back into this file.** Every change to how agents work in this repository belongs
8
+ in `CLAUDE.md`.