@joshuafolkken/kit 1.1136.0 → 1.1166.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 (165) hide show
  1. package/.claude/settings.json +4 -4
  2. package/.claude/skills/epic-commands/SKILL.md +27 -239
  3. package/.claude/skills/epic-commands/epic-bundle.md +115 -0
  4. package/.claude/skills/epic-commands/execution-waves.md +126 -0
  5. package/.claude/skills/workflow-commands/SKILL.md +48 -194
  6. package/.claude/skills/workflow-commands/background-commands.md +1 -1
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +12 -123
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +11 -60
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +10 -8
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -173
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +155 -0
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +64 -144
  13. package/.claude/skills/workflow-commands/backlogrun.md +5 -4
  14. package/.claude/skills/workflow-commands/chain-rule.md +3 -2
  15. package/.claude/skills/workflow-commands/delegation.md +2 -2
  16. package/.claude/skills/workflow-commands/entry-sequence.md +62 -0
  17. package/.claude/skills/workflow-commands/followup.md +104 -181
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +8 -9
  19. package/.claude/skills/workflow-commands/fullrun.md +16 -73
  20. package/.claude/skills/workflow-commands/halfrun.md +10 -36
  21. package/.claude/skills/workflow-commands/into-target.md +4 -4
  22. package/.claude/skills/workflow-commands/issue-comments.md +7 -8
  23. package/.claude/skills/workflow-commands/issue-scout.md +6 -6
  24. package/.claude/skills/workflow-commands/kickoff.md +6 -6
  25. package/.claude/skills/workflow-commands/needs-human-review.md +6 -6
  26. package/.claude/skills/workflow-commands/observation-filing.md +21 -172
  27. package/.claude/skills/workflow-commands/observation-ledger.md +150 -0
  28. package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -93
  29. package/.claude/skills/workflow-commands/prerequisite.md +6 -6
  30. package/.claude/skills/workflow-commands/progress-watcher.md +90 -0
  31. package/.claude/skills/workflow-commands/prrun.md +5 -5
  32. package/.claude/skills/workflow-commands/retrospective.md +9 -9
  33. package/.claude/skills/workflow-commands/split-assessment.md +2 -2
  34. package/.claude/skills/workflow-commands/target-repository.md +2 -2
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +7 -5
  36. package/.codex/hooks.json +4 -4
  37. package/AGENTS.md +1 -6
  38. package/CLAUDE.md +58 -120
  39. package/GEMINI.md +1 -6
  40. package/dist/CLAUDE.md +58 -120
  41. package/dist/hooks/batch-guard.js +4 -4
  42. package/dist/hooks/{chunk-NFZGFGOR.js → chunk-5KTCMCOT.js} +14 -1
  43. package/dist/hooks/{chunk-LJBLGHEH.js → chunk-A6P7PN7P.js} +4 -6
  44. package/dist/hooks/{chunk-FO2I7UT7.js → chunk-ANJ2WGFD.js} +1 -1
  45. package/dist/hooks/{chunk-GDU26K3J.js → chunk-DYAVAM6S.js} +563 -126
  46. package/dist/hooks/{chunk-RFWWUI5F.js → chunk-ENA7P5FB.js} +3 -3
  47. package/dist/hooks/{chunk-KBXZLMRH.js → chunk-GU5MATVE.js} +213 -65
  48. package/dist/hooks/chunk-GYNGP7HI.js +56 -0
  49. package/dist/hooks/{chunk-HBKZLITF.js → chunk-URJA6XY4.js} +4 -4
  50. package/dist/hooks/{chunk-KOKOAV6D.js → chunk-V2BTOZHT.js} +6 -4
  51. package/dist/hooks/{chunk-JKKTVDAG.js → chunk-ZDZ555YH.js} +100 -20
  52. package/dist/hooks/codex-hook-adapter.js +10 -10
  53. package/dist/hooks/duplicate-read-guard.js +5 -5
  54. package/dist/hooks/format-edited.js +2 -2
  55. package/dist/hooks/inputs.json +193 -192
  56. package/dist/hooks/investigation-guard.js +5 -5
  57. package/dist/hooks/pretool-guard.js +11 -10
  58. package/dist/hooks/stop-guard.js +5 -5
  59. package/dist/josh.js +25 -2
  60. package/dist/version/index.js +5 -1
  61. package/package.json +2 -1
  62. package/prompts/collaboration-workflow/file-edits.md +11 -10
  63. package/prompts/collaboration-workflow/gh-rest.md +2 -4
  64. package/prompts/collaboration-workflow/glossary.md +1 -1
  65. package/prompts/collaboration-workflow/issue-citation.md +5 -9
  66. package/prompts/collaboration-workflow/issue-template.md +40 -115
  67. package/prompts/collaboration-workflow/operating-rules.md +4 -5
  68. package/prompts/collaboration-workflow/output-bounds.md +12 -78
  69. package/prompts/collaboration-workflow/overview.md +7 -13
  70. package/prompts/collaboration-workflow/plan-comment.md +11 -39
  71. package/prompts/collaboration-workflow/principles.md +3 -4
  72. package/prompts/collaboration-workflow/report-format.md +28 -74
  73. package/prompts/collaboration-workflow/residency.md +12 -109
  74. package/prompts/collaboration-workflow/rule-delivery.md +98 -97
  75. package/prompts/collaboration-workflow/shell-body.md +3 -13
  76. package/prompts/collaboration-workflow/turn-batching.md +14 -88
  77. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -14
  78. package/prompts/collaboration-workflow/wip-cap.md +6 -45
  79. package/prompts/collaboration-workflow.md +1 -13
  80. package/prompts/review-rubric.md +8 -71
  81. package/prompts/review.md +25 -55
  82. package/prompts/testing-guide.md +18 -67
  83. package/scripts/agent/agent-role-profile.ts +1 -1
  84. package/scripts/agent/codex-hooks.ts +3 -12
  85. package/scripts/backlog/backlog-budget.ts +1 -1
  86. package/scripts/backlog/backlog-drive-cli.ts +4 -3
  87. package/scripts/backlog/backlog-drive-offer-argv.ts +10 -1
  88. package/scripts/backlog/backlog-offer.ts +6 -6
  89. package/scripts/behavior/behavior-rules.ts +11 -4
  90. package/scripts/delegation/investigation-reads.ts +5 -5
  91. package/scripts/discovery/repo-discovery.ts +21 -7
  92. package/scripts/discovery/repo-origin.ts +26 -0
  93. package/scripts/discovery/repo-party.ts +42 -1
  94. package/scripts/document/backlogrun-parent-read-set.ts +14 -15
  95. package/scripts/document/document-byte-budget.ts +34 -20
  96. package/scripts/document/entry-read-budget.ts +21 -9
  97. package/scripts/document/lane-child-read-set.ts +12 -14
  98. package/scripts/document/read-set-cli.ts +4 -4
  99. package/scripts/document/read-set-point-of-use.ts +10 -2
  100. package/scripts/document/resident-budget.ts +47 -0
  101. package/scripts/epic/epic-shape.ts +10 -13
  102. package/scripts/epic/epic-solo.ts +1 -1
  103. package/scripts/exports/unused-members-cli.ts +7 -3
  104. package/scripts/gh/git-gh-api-path.ts +7 -0
  105. package/scripts/hooks/pretool-guard-cli.ts +2 -2
  106. package/scripts/hooks/pretool-guard.ts +45 -2
  107. package/scripts/hooks/run-hook.sh +41 -0
  108. package/scripts/init/hook-command-rewrite.ts +18 -35
  109. package/scripts/init/hook-launch.ts +21 -32
  110. package/scripts/issue/issue-auto-ok.ts +95 -0
  111. package/scripts/issue/issue-file-cli.ts +53 -7
  112. package/scripts/issue/issue-file.ts +28 -5
  113. package/scripts/issue/issue-labels.ts +12 -12
  114. package/scripts/issue/issue-rank.ts +1 -1
  115. package/scripts/issue/issue-read-cli.ts +3 -3
  116. package/scripts/issue/issue-read.ts +2 -2
  117. package/scripts/issue/issue-scout-cli.ts +2 -2
  118. package/scripts/issue/issue-state-cli.ts +1 -1
  119. package/scripts/issue/issue-state.ts +2 -2
  120. package/scripts/issue/issue-wip.ts +70 -0
  121. package/scripts/josh/hook-decision.ts +17 -0
  122. package/scripts/josh/josh-commands-development.ts +10 -0
  123. package/scripts/josh/josh-commands-issue.ts +2 -2
  124. package/scripts/lines/bytes-command.ts +29 -6
  125. package/scripts/observations/observation-ledger-line.ts +1 -1
  126. package/scripts/release/release-progress.ts +167 -0
  127. package/scripts/release/release-publish.ts +19 -8
  128. package/scripts/release/release-tag.ts +22 -8
  129. package/scripts/rules/decision-oracle-stage.ts +1 -1
  130. package/scripts/rules/decision-oracle.ts +6 -6
  131. package/scripts/rules/delivered-rules.ts +11 -11
  132. package/scripts/rules/direct-pr-create.ts +110 -0
  133. package/scripts/rules/file-body.ts +98 -42
  134. package/scripts/rules/filing-cap.ts +2 -2
  135. package/scripts/rules/filing-offer.ts +1 -1
  136. package/scripts/rules/gh-api.ts +18 -1
  137. package/scripts/rules/implementation-cut.ts +3 -1
  138. package/scripts/rules/lane-background.ts +67 -10
  139. package/scripts/rules/permission-guards.ts +10 -2
  140. package/scripts/rules/stop-rules.ts +4 -4
  141. package/scripts/rules/test-declared-commit.ts +1 -1
  142. package/scripts/rules/third-party-write.ts +56 -12
  143. package/scripts/run/run-cut-handoff.ts +21 -1
  144. package/scripts/run/run-entry-cli.ts +11 -3
  145. package/scripts/run/run-hold-cli.ts +16 -2
  146. package/scripts/run/run-label.ts +50 -0
  147. package/scripts/run/run-merge-steps.ts +8 -3
  148. package/scripts/run/run-merge.ts +1 -1
  149. package/scripts/run/run-prep-cli.ts +6 -2
  150. package/scripts/run/run-prep.ts +17 -0
  151. package/scripts/run/run-ship-preflight.ts +34 -3
  152. package/scripts/run/run-ship-review-steps.ts +1 -1
  153. package/scripts/run/run-ship-review.ts +26 -5
  154. package/scripts/run/run-step-cli.ts +20 -7
  155. package/scripts/run/run-wake-driver.ts +24 -1
  156. package/scripts/run/run-wake-session.ts +2 -1
  157. package/scripts/test/test-declared-logic.ts +1 -1
  158. package/scripts/time-runtime/time-batch-guard.ts +52 -16
  159. package/scripts/time-runtime/time-density-hook.ts +20 -2
  160. package/scripts/time-runtime/time-density.ts +4 -3
  161. package/scripts/time-runtime/time-markers.ts +15 -4
  162. package/scripts/version/npm-registry.ts +11 -1
  163. package/templates/workflows/ci.yml +9 -1
  164. package/.claude/skills/workflow-commands/followup-reference.md +0 -118
  165. package/dist/hooks/chunk-HANSKHES.js +0 -464
@@ -1,4 +1,4 @@
1
- # Filing an Issue — `SKILL.md` §2e's procedure
1
+ # Filing an Issue — the procedure
2
2
 
3
3
  Read this file when an Issue title exists and before the `pnpm josh issue:file` call that files it.
4
4
  Every filing asks whether the work already exists and which epic owns it; the command runs the
@@ -25,19 +25,19 @@ pnpm josh issue:file "<title>" --body-file <complete-draft.md> --depth <n> --dis
25
25
  line, named in `--distinct`, and the filing carries on.
26
26
  - **`none` is an answer.** The command reports no candidate rather than the closest miss.
27
27
  - **`Epic:` front-loads the placement.** Its recommendation is `epic:bundle`'s, which makes
28
- `add_to_epic` / `create_epic` Tier A and `ask` a stop, in exactly the reading `SKILL.md` → §2a's
28
+ `add_to_epic` / `create_epic` Tier A and `ask` a stop, in exactly the reading `into-target.md`'s
29
29
  `into <target>` suffix would have given by hand. Where the user typed `into <target>`, that naming wins.
30
30
  - **`Epic: not asked` is not `Epic: none`.** The epic half decides from the issue numbers the body
31
31
  names. **Cite `#N` in the body whenever the work follows an existing Issue** — one line is enough,
32
32
  and naming the epic itself (`part of epic #<E>`) is answered with that epic.
33
33
  - **`epic:bundle` then runs on the new Issue, in the same call.** Act on its printed answer; a `⚠`
34
- means rerun `pnpm josh epic:bundle <N>` — the Issue exists, so never refile.
35
- - **Every filing route goes through it** — §2d's prerequisite, §2i's observation and the review round
34
+ means rerun `pnpm josh epic:bundle <N>` — the Issue exists, so never refile; a placing answer
35
+ reads the `epic-commands` skill.
36
+ - **Every filing route goes through it** — `prerequisite.md`'s prerequisite, `observation-filing.md`'s observation and the review round
36
37
  cap's branch-2 filing alike; the guard refuses any other filing call
37
38
  (`prompts/collaboration-workflow/rule-delivery.md`).
38
39
  - **A `#N` entry point does not file *the Issue it was handed*.** `fullrun #N` / `halfrun #N` /
39
- `kickoff #N` are given an Issue that already exists. That says nothing about an Issue such a run goes
40
- on to file later, which the bullet above covers.
40
+ `kickoff #N` are given an Issue that already exists; one such a run files later still goes through it.
41
41
  - **The split path files each child through the same command.** The epic is created with
42
42
  `pnpm josh epic` over children that were scanned.
43
43
 
@@ -1,10 +1,10 @@
1
1
  # `kickoff` — Planning phase only (plan → Issue → Telegram notify → stop)
2
2
 
3
- - `kickoff #<N>`: **First `pnpm josh run:entry <N> --to kickoff`** (`SKILL.md` → §2k) — it claims
3
+ - `kickoff #<N>`: **First `pnpm josh run:entry <N> --to kickoff`** (`docs/how-to/run-issues.md`) — it claims
4
4
  nothing and prints the stage line alone; `start: reached` means the Issue is already planned or further
5
5
  up the ladder, so report the stage line and **stop**. Otherwise read existing Issue #N **and every comment on it** — `pnpm josh issue:read <N>`; a
6
6
  decision recorded after the body was written lives only in a comment, and the later text is the
7
- agreement in force (`SKILL.md` → §2g, which also carries the two answers that stop the run instead) →
7
+ agreement in force (`issue-comments.md`, which also carries the two answers that stop the run instead) →
8
8
  **normalize the title**: if the title is not in English or can be phrased more clearly, derive a
9
9
  better English title and run `gh api -X PATCH repos/{owner}/{repo}/issues/<N> -f title="<title>"` →
10
10
  analyze requirements → **scope assessment per `split-assessment.md`** → post the plan to the Issue (if
@@ -28,11 +28,11 @@
28
28
  is one branch, one index and one uncommitted diff; this command reads the Issue, normalizes the title,
29
29
  posts the plan, notifies and stops — every one of those against GitHub, none against the tree. So a
30
30
  `fullrun` running in this checkout never stops a `kickoff`, and a `kickoff` never touches the record
31
- that run is holding. It claims nothing, so it must not release anything either. `SKILL.md` → §2f is the
31
+ that run is holding. It claims nothing, so it must not release anything either. `working-tree-hold.md` is the
32
32
  single source.
33
33
 
34
34
  **The target repository is named in front of the Issue reference** — `kickoff kit#new`,
35
- `kickoff joshuafolkken/kit#412`. The definition is `SKILL.md` → §2c, whose body is `target-repository.md`. `kickoff` is the entry that needs
35
+ `kickoff joshuafolkken/kit#412`. The definition is `target-repository.md`, whose body is `target-repository.md`. `kickoff` is the entry that needs
36
36
  no checkout: name the target repository in the path of every `gh api` call — reads included — and never
37
37
  clone. The one exception is the split path's epic, since `pnpm josh epic` writes only the repository it
38
38
  runs in — and the promote arm has no remote fallback at all, so it stops when that repository is not
@@ -52,11 +52,11 @@ split is found.
52
52
  title. (2) Create Issue: `pnpm josh issue:file "<title>" --body-file <body-file> --depth <n>` (body
53
53
  per `prompts/collaboration-workflow/issue-template.md`) — its duplicate scan runs first, and a
54
54
  candidate that covers the same work stops the run rather than filing a second Issue (`SKILL.md` →
55
- §2e). Capture `<N>`. (3)
55
+ `issue-scout.md`). Capture `<N>`. (3)
56
56
  Post the plan in the session language, using the same body/comment logic as `kickoff #<N>`. (4) Send
57
57
  Telegram notification. (5) **Stop** — do not implement. **Multi-issue split path**: (1) For each
58
58
  independent deliverable, derive a focused English title and create a separate Issue with the
59
- `route:split` label (its duplicate scan is read per `SKILL.md` → §2e): `pnpm josh issue:file
59
+ `route:split` label (its duplicate scan is read per `issue-scout.md`): `pnpm josh issue:file
60
60
  "<sub-title>" --body-file <body-file> --depth <n> --route split`. Capture each Issue number. **When the split is filed into a repository other than
61
61
  the one this session is running in**, every child body gets the `## Origin` backlink described in the
62
62
  cross-package rule the AI documents keep resident, the epic body carries the same link as prose or a
@@ -1,14 +1,14 @@
1
1
  # `needs-human-review` — the child that stops before its commit
2
2
 
3
- **This is the body of `SKILL.md` §2z, relocated here so the entry read carries the trigger and the
4
- pointer, not the procedure** (joshuafolkken/kit#2189). `SKILL.md` §2z is the resident stub;
5
- `fullrun.md`, `halfrun.md` and `backlogrun.md` route here for the definition. It is read at its point
3
+ **This file is the single source, so the entry read carries the trigger and the pointer, not the
4
+ procedure** (joshuafolkken/kit#2189). `SKILL.md` → §2's table keeps the trigger;
5
+ `entry-sequence.md` and `backlogrun.md` route here for the definition. It is read at its point
6
6
  of use — the moment `pnpm josh issue:state <N>` answers `human_review: yes`.
7
7
 
8
8
  An issue carrying **`needs-human-review`** is degraded to a `halfrun`-shaped stop, whichever entry
9
9
  point reached it — `fullrun` or `backlogrun`. It is `auto-ok`'s opposite: that label widens
10
- unattended execution past an epic's edge, this one withholds its last step, and both may be applied
11
- **only by a person**. It exists because some work's quality is not something a test can judge — a
10
+ unattended execution past an epic's edge, this one withholds its last step, and this one may be
11
+ applied **only by a person**. It exists because some work's quality is not something a test can judge — a
12
12
  **published artifact** whose unit tests say nothing about the writing, or **a choice that was a
13
13
  person's to make** such as picking one of several generated candidates.
14
14
 
@@ -43,7 +43,7 @@ pnpm josh issue:state <N> # state, labels, and human_review
43
43
  pnpm josh issue:state <N> --repo <owner/repo> # a child in another repository
44
44
  ```
45
45
 
46
- **Never apply or remove it**, exactly as strongly as `auto-ok`: a mark a run can clear for itself is
46
+ **Never apply or remove it**: a mark a run can clear for itself is
47
47
  not a mark. Everything but typing the command on an explicit instruction in the current turn is a
48
48
  proposal, written as an Issue comment and left for the person. The label itself is created once per
49
49
  repository, by a person:
@@ -1,18 +1,17 @@
1
- # The observation filing procedure — `SKILL.md` §2i's body
1
+ # The observation filing procedure
2
2
 
3
- **This is `SKILL.md` → §2i's procedure, and it is read when an observation turns up — not at the
4
- entry** (joshuafolkken/kit#1797). §2i keeps the rule itself: file it without asking, apply the depth
5
- test, record what the test turns away, and carry the run on. Everything that decides *how* — the
6
- depth table and its labels, the depth-0 share, the ledger's grammar and commit path, the promotion on
7
- a second sighting, and what a delegated child does instead — is here, because none of it binds until
8
- a run has actually found something worth filing. A `fullrun` that never finds one never reads it, and
9
- the one that does reads it in full, in the same turn, before it files.
3
+ **Read when an observation turns up — not at the entry** (joshuafolkken/kit#1797). `SKILL.md` → §2's
4
+ table keeps the rule itself: file it without asking, apply the depth test, record what the test turns
5
+ away, and carry the run on. This file is the depth table, the `issue:file` flags and what a delegated
6
+ child does instead. **An observation the depth test turns away, and the kind of miss behind a
7
+ user-reported bug, are recorded by `observation-ledger.md` — read it only then**, in the turn that
8
+ appends (joshuafolkken/kit#3176).
10
9
 
11
10
  **The trigger is the judgement, not the run's progress** — an ended run, a `kickoff` and a mid-talk
12
11
  turn all file; an offer to file is sent back by the `Stop` hook (joshuafolkken/kit#2422).
13
12
 
14
13
  **A run that judges something worth filing files it, and does not ask.** An upstream defect stops the
15
- run, a split replaces it, and a prerequisite goes in front of it (`SKILL.md` → §2d). An ordinary
14
+ run, a split replaces it, and a prerequisite goes in front of it (`prerequisite.md`). An ordinary
16
15
  observation changes none of those: it carries no `route:` label, causes no stash or park, and the run
17
16
  continues. A first-party target is Tier A, decided by `pnpm josh repo:party`; a third-party target is
18
17
  Tier C (`CLAUDE.md`). Name what was filed in the completion report. An observation nobody would act
@@ -28,7 +27,7 @@ new Issue so it is offered by its epic; an `auto-ok` epic adds it to the backlog
28
27
  `pnpm josh issue:fold` first; the guard refuses that filing without the fold
29
28
  (`split-assessment.md` → "The same two questions decide the filing-time fold").
30
29
 
31
- The detail below is read at the filing decision, and the marker suite pins the rules here.
30
+ The marker suite pins the rules below.
32
31
 
33
32
  ### The depth test — a discretionary filing cites the product work it blocked
34
33
 
@@ -44,7 +43,7 @@ The detail below is read at the filing decision, and the marker suite pins the r
44
43
  (joshuafolkken/kit#1729). `depth:0`, `depth:1` and `depth:2` are the three, defined once in
45
44
  `scripts/issue/issue-labels.ts` and carrying no definition of their own — **the table above is the
46
45
  single source**, and a label description that paraphrased it would be a second copy of the rule.
47
- **Every filing route applies one**, this route and the other three of §2d's table alike: a `new`
46
+ **Every filing route applies one**, this route and the other three of `prerequisite.md`'s table alike: a `new`
48
47
  entry point, a `route:tier-a` prerequisite, a `route:interrupt`, a split child and a review round
49
48
  cap's branch-2 filing all pass through a `pnpm josh issue:file` call, and the depth goes in it as
50
49
  `--depth <n>` beside whatever `--route` that call already carries.
@@ -54,21 +53,15 @@ pnpm josh issue:file "<title>" --body-file <body-file> --depth 1
54
53
  gh api repos/{owner}/{repo}/issues/<N>/labels -f 'labels[]=depth:1' # an Issue already filed
55
54
  ```
56
55
 
57
- **Create the three once per repository**, before the first filing that applies one — REST auto-creates
58
- a missing label with a generated color and no description, and the three lines below are what give
59
- each a stable color a reader can scan a listing by. `DEPTH_LABELS` in `scripts/issue/issue-labels.ts`
60
- is the single source of the colors and descriptions, and `scripts/rules/issue-depth-label.test.ts` keys
61
- these lines to it so the two cannot drift.
62
-
63
- ```bash
64
- gh api repos/{owner}/{repo}/labels -f name=depth:0 -f color=0e8a16 -f description="Depth 0 — what a consumer of this package touches (SKILL.md §2i)" --silent 2>/dev/null || true
65
- gh api repos/{owner}/{repo}/labels -f name=depth:1 -f color=fbc02d -f description="Depth 1 — the run orchestration that executes an Issue (SKILL.md §2i)" --silent 2>/dev/null || true
66
- gh api repos/{owner}/{repo}/labels -f name=depth:2 -f color=c5def5 -f description="Depth 2 — what measures a run (SKILL.md §2i)" --silent 2>/dev/null || true
67
- ```
56
+ **A repository missing the three gets them from `issue:file` itself** — it creates any missing
57
+ workflow label, with the color and description `DEPTH_LABELS` in `scripts/issue/issue-labels.ts`
58
+ defines, before the create call (joshuafolkken/kit#3176).
68
59
 
69
60
  - **It is read off the subject, exactly as the table is** — so applying it is not a judgement and not
70
61
  a person's to make, which is what separates it from `auto-ok` and `needs-human-review`. Those two
71
- decide what a run may do; this one records what an Issue is about and withholds nothing.
62
+ decide what a run may do (`auto-ok` by `issue:file`'s default for a filing found by opted-in work —
63
+ `backlogrun-steps.md` → "What one invocation approves"); this one records what an Issue is about
64
+ and withholds nothing.
72
65
  - **Applied at filing, not at completion.**
73
66
  - **An Issue carrying more than one counts as the lowest depth present**, the one closest to the
74
67
  consumer.
@@ -80,7 +73,7 @@ Rationale: `docs/maintainers/observation-filing-rationale.md` → "Why the depth
80
73
 
81
74
  - **A discretionary observation at depth 1 or deeper is filed only where it can cite the depth-0 work
82
75
  it stopped or delayed** — named as an Issue number or a run, never as "this would slow runs down".
83
- **Cannot cite one, it is not filed**: it goes to the ledger below, and what files it later is
76
+ **Cannot cite one, it is not filed**: it goes to the ledger (`observation-ledger.md`), and what files it later is
84
77
  either the blockage arriving or a second sighting of the same thing. Pull rather than push — the
85
78
  fix follows the jam or the repeat, never the lone sighting.
86
79
  - **A depth-0 observation does not take this test.** That is the product, and the two ceilings above
@@ -96,7 +89,7 @@ Rationale: `docs/maintainers/observation-filing-rationale.md` → "Why the depth
96
89
  - **Which way it tips** — what range of the number selects which choice. A number that selects the
97
90
  same action whatever it turns out to be changes no decision, and a filing that cannot write this
98
91
  line is describing one.
99
- - **Cannot write both, it is not filed** — the same exit the depth-0 gate takes: the ledger below,
92
+ - **Cannot write both, it is not filed** — the same exit the depth-0 gate takes: the ledger,
100
93
  pulled into an Issue by the jam arriving or the second sighting, never pushed by the lone idea.
101
94
  - **This narrows depth 2 alone, and the exemptions above carry over unchanged.** `route:tier-a` and
102
95
  `route:interrupt` do not take this requirement any more than they take the depth-0 citation, a
@@ -105,7 +98,7 @@ Rationale: `docs/maintainers/observation-filing-rationale.md` → "Why the depth
105
98
 
106
99
  Rationale: `docs/maintainers/observation-filing-rationale.md` → "Why depth gates a discretionary filing".
107
100
 
108
- **It governs this route only — the fourth row of §2d's table.** A review finding routed to branch 2
101
+ **It governs this route only — the fourth row of `prerequisite.md`'s table.** A review finding routed to branch 2
109
102
  of `prompts/review.md` → "Review round cap" is filed under that section's own bar — a confirmed
110
103
  defect reaching a runtime path, with a written failure scenario — and **does not take the depth
111
104
  test**: it has already cleared a bar this route has not, so gating it on a citation as well would
@@ -146,150 +139,6 @@ Rationale: `docs/maintainers/observation-filing-rationale.md` → "Why the depth
146
139
  of it, and setting a target value, are both deliberately out of scope until the current value has
147
140
  been measured the same way more than once (joshuafolkken/kit#1729 → 範囲外).
148
141
 
149
- ### The ledger — where an observation that cannot cite a blockage goes
150
-
151
- **An observation the depth test turns away is recorded in the ledger, not discarded**
152
- (joshuafolkken/kit#1728). Rationale: `docs/maintainers/observation-filing-rationale.md` → "Why the
153
- ledger exists".
154
-
155
- - **The destination is the `docs/maintainers/observations/` directory in the repository the
156
- observation is about** — the same repository the Issue would have been filed into — **one file per
157
- issue** (joshuafolkken/kit#2919): append to `<N>.md` for the issue the run is executing (the number
158
- its branch leads with, a lane's included), or to `<YYYY-MM-DD>.md` for a line written on the
159
- default branch outside any issue's run. Parallel lanes therefore write different files, and their
160
- pull requests never conflict on the ledger. **The count and the append are both run in that
161
- repository's checkout** — in this repository, the work tree the run is in, a lane's inside a lane —
162
- resolved the way §2c (`target-repository.md`) resolves any cross-repository target, and the
163
- directory is created on the first append where that repository has none. **The subject decides, never the
164
- working directory**: an observation about this package's own orchestration, seen while a run is
165
- inside a repository that consumes it, is recorded here rather than there — the append follows the
166
- subject, never the working directory. **A third-party target gets no line either** — Tier C covers
167
- the ledger exactly as it covers the Issue that would otherwise have been filed there.
168
- - **It is append-only.** A line is never edited and never deleted, because the count of lines
169
- carrying one key is what says whether an observation has recurred; a second sighting is a second
170
- line, not a rewrite of the first. **A merge conflict in it is resolved by keeping both sides** —
171
- one file per issue should keep it from arising, but a repeated key is the whole signal, so
172
- dropping either side destroys exactly what the ledger is for.
173
- - **The completion report keeps its line too.** The ledger is what the next run can read; the report
174
- is what this run's reader sees. Neither replaces the other.
175
- - **The append is not the end of it** — a line only becomes readable to anyone else once it has
176
- merged, and "The commit path" below is how it gets there.
177
-
178
- **One observation is one line: five fields, each separated from the next by a vertical bar with one
179
- space on either side.**
180
-
181
- ```
182
- - k:<slug> | d<n> | <YYYY-MM-DD> | <where> | <what>
183
- ```
184
-
185
- | Field | What it holds |
186
- | -------------- | ------------------------------------------------------------------------------------------------------------------------- |
187
- | `k:<slug>` | The identity key — lowercase letters and digits, in words joined by `-`. This is what makes a repeat machine-readable |
188
- | `d<n>` | The depth of the subject — `d1`, `d2`, or whatever deeper depth the table above may one day name. **There is no `d0` line**: a depth-0 observation is filed outright and never reaches the ledger |
189
- | `<YYYY-MM-DD>` | The date of **this** sighting |
190
- | `<where>` | One file path or one command — where the thing was seen |
191
- | `<what>` | The phenomenon, one sentence, carrying no vertical bar of its own |
192
-
193
- A sample, in the shape a real entry takes:
194
-
195
- ```
196
- - k:example | d1 | 2026-09-10 | pnpm josh run:progress | The report printed a fill-in placeholder where a clock time belonged
197
- ```
198
-
199
- **`k:example` is reserved for this sample and is never used by a real observation**, so the count
200
- below can be run over the whole ledger without the sample answering for one. **The grammar is defined
201
- here rather than in the ledger** (`docs/maintainers/observation-filing-rationale.md` → "Why the
202
- ledger exists").
203
-
204
- **The identity key is the whole of the repeat test — never a similarity judgement about the prose.**
205
- Choose the key from the phenomenon rather than from the run, then count what the ledger already holds
206
- for it, in that repository's checkout rather than the working directory. **Every file of the
207
- directory is counted**, because a recurrence is a recurrence whichever issue's file each sighting
208
- sits in. **The `|| true` is not decoration**: `grep -c` exits non-zero on a count of zero, which is
209
- the first-sighting branch and the common one, so without it the step reads as a failed command
210
- wherever an exit status is being watched. **A missing directory is still a first sighting** — `cat`
211
- complains on standard error and the count is zero; the append below creates the directory.
212
-
213
- ```bash
214
- cat <that repository's checkout>/docs/maintainers/observations/*.md | grep -c '^- k:<slug> |' || true
215
- ```
216
-
217
- Free-text comparison is what the key exists to replace, so two lines that read alike under different
218
- keys are two observations, and a mis-keyed entry is corrected by appending a correctly-keyed line
219
- rather than by editing the one already written.
220
-
221
- **The depth gate is not withdrawn, and this is not a way around it.** An observation that *can* cite
222
- the depth-0 work it stopped is filed exactly as it was before — this route is only for the ones that
223
- could not.
224
-
225
- ### The commit path — how an appended line reaches the default branch
226
-
227
- **An append nobody commits is an append nobody can count** (joshuafolkken/kit#1756). Rationale:
228
- `docs/maintainers/observation-filing-rationale.md` → "Why the ledger has a commit path".
229
-
230
- - **A run's appended lines ride its own commit** (joshuafolkken/kit#2763). `pnpm josh git` stages
231
- `docs/maintainers/observations/` with the run's other changes, in the one staging step every entry
232
- point goes through (`scripts/git/git-staging.ts`), so the lines are reviewed and merged with the
233
- pull request of the run that recorded them, and the run's CI is the only wait they cost.
234
- **Record before the commit, not after the merge:** a finding recorded with `pnpm josh review:record`
235
- before `pnpm josh git -y` is carried; the time while CI runs is for the records that need no CI
236
- result — filing an observation Issue, drafting the completion report.
237
- - **A line that breaks the grammar is not carried** (joshuafolkken/kit#2123). The staging step parses
238
- every file of the ledger first — after moving lines still on an old single-file path
239
- (joshuafolkken/kit#2724, joshuafolkken/kit#2919) — and on a broken line leaves the ledger out of the
240
- commit and says so; the commit itself goes ahead.
241
- - **`pnpm josh followup` commits a line appended after the run's commit onto the pull request, before
242
- the merge** (joshuafolkken/kit#2919) — a second review round's record is the usual case. After the
243
- merge gates and before the CI wait, `followup` reads the tree and, **only when the ledger holds a
244
- pending append**, stages the ledger paths alone, commits them and pushes the branch; the CI wait
245
- that follows covers the pushed commit. A broken line refuses the merge, because the line would
246
- otherwise be lost with the branch. A run whose lines rode its commit pays nothing.
247
- - **A lane carries its own lines, in its own pull request** (joshuafolkken/kit#2919). Its writers
248
- append to its own tree's `<N>.md`, so the two steps above take them to the default branch exactly as
249
- they do for a run in the primary checkout. **Nothing is held in the primary checkout for later.**
250
- - **`pnpm josh observations:flush` is left for a line written outside any issue's run** — the
251
- date-named file a retrospective or a hand append on the default branch writes. It stages the ledger
252
- and nothing else, commits it on a branch of its own, opens a docs-only pull request, waits on the
253
- same required checks every other pull request waits on, merges it and returns the checkout to the
254
- default branch; a single run's `run:tail` runs it after the merge. It refuses off the default branch
255
- and refuses a working tree holding anything besides the ledger, so a run in progress cannot be
256
- flushed out from under. **Nothing is committed to the default branch directly.**
257
- - **Nothing to flush is an answer, not a failure.** With the ledger matching the commit it sits on
258
- the command prints `clean` and exits 0 — most cycles append nothing, and a command that errored
259
- there would be one nobody runs.
260
- - **The count the promotion below reads is a count of the default branch**, which is what this route
261
- buys: a ledger line that merged is one every later run, every other machine and every fresh clone
262
- can see, and only then can a second sighting be recognized as one.
263
-
264
- ### The second sighting is what files it
265
-
266
- **A repeat is the citation**, so the gate has a second way through, and it is counted rather than
267
- judged (rationale: `docs/maintainers/observation-filing-rationale.md` → "Why a second sighting
268
- files"):
269
-
270
- - **On the count answering exactly `1`, the observation is filed**, at depth 1 or deeper, with no
271
- depth-0 citation — `1` and not "1 or more", because a higher count means the Issue was already
272
- opened by the sighting that answered `1`. The ledger line is appended as well, because the ledger
273
- stays append-only.
274
- - **The Issue quotes the ledger's own dates — the first sighting's and this one's** — so the reader
275
- can check the promotion against the file instead of taking the run's word for it.
276
- - **Both ceilings still apply**, exactly as they do above: the 10-per-run cap counts a promoted
277
- filing, and the WIP cap still bites, since a promoted observation blocks nothing and is therefore
278
- still discretionary.
279
-
280
- **A third and later sighting appends a line and files nothing more.** The Issue from the second one
281
- is already open, and `pnpm josh issue:scout` is what finds it; the extra lines are evidence for that
282
- Issue, not new ones.
283
-
284
- ### A user-found bug is recorded by its kind of miss (user-found)
285
-
286
- **A user-reported bug is fixed or filed as always; this records the *kind of miss* alongside so the
287
- category never recurs as a first sighting** (joshuafolkken/kit#2246). The key is the **category of
288
- oversight** — `k:missed-case-worktree` — so a second bug of the same kind counts against the first.
289
- **Depth `d1`, never `d0`**: the *kind of miss* is what a run fails to enumerate, which the table puts
290
- at depth 1. Nothing else changes; the `<what>` field leads with `User-reported:`, and no second
291
- ledger, format or threshold is added.
292
-
293
142
  ### A delegated child does not take this route
294
143
 
295
144
  **A delegated child files `route:tier-a` and `route:interrupt` only.** Its discretionary
@@ -305,6 +154,6 @@ count and writes the line. **The 10-per-run ceiling for this route is the parent
305
154
  Rationale: `docs/maintainers/observation-filing-rationale.md` → "Why a delegated child neither files
306
155
  nor appends".
307
156
 
308
- **This file is the single source of every procedure above**, and `SKILL.md` → §2i is the single
309
- source of the rule they carry out; nothing under `prompts/collaboration-workflow/` restates either
157
+ **This file is the single source of every procedure above**, and `SKILL.md` → §2's table carries the
158
+ trigger of the rule they carry out; nothing under `prompts/collaboration-workflow/` restates either
310
159
  (joshuafolkken/kit#1649, joshuafolkken/kit#1797).
@@ -0,0 +1,150 @@
1
+ # The observation ledger — grammar, commit path and promotion
2
+
3
+ **Read only when the depth test in `observation-filing.md` turns an observation away, or a user
4
+ reports a bug** (its kind of miss, below), in the turn that appends the line (joshuafolkken/kit#3176).
5
+ A run that files outright, or finds nothing, never reads it. This file is the single source of the ledger's grammar, its commit path and the
6
+ second-sighting promotion.
7
+
8
+ ## The ledger — where an observation that cannot cite a blockage goes
9
+
10
+ **An observation the depth test turns away is recorded in the ledger, not discarded**
11
+ (joshuafolkken/kit#1728). Rationale: `docs/maintainers/observation-ledger-rationale.md` → "Why the
12
+ ledger exists".
13
+
14
+ - **The destination is the `docs/maintainers/observations/` directory in the repository the
15
+ observation is about** — the same repository the Issue would have been filed into — **one file per
16
+ issue** (joshuafolkken/kit#2919): append to `<N>.md` for the issue the run is executing (the number
17
+ its branch leads with, a lane's included), or to `<YYYY-MM-DD>.md` for a line written on the
18
+ default branch outside any issue's run. Parallel lanes therefore write different files, and their
19
+ pull requests never conflict on the ledger. **The count and the append are both run in that
20
+ repository's checkout** — in this repository, the work tree the run is in, a lane's inside a lane —
21
+ resolved the way `target-repository.md` (`target-repository.md`) resolves any cross-repository target, and the
22
+ directory is created on the first append where that repository has none. **The subject decides, never the
23
+ working directory**: an observation about this package's own orchestration, seen while a run is
24
+ inside a repository that consumes it, is recorded here rather than there — the append follows the
25
+ subject, never the working directory. **A third-party target gets no line either** — Tier C covers
26
+ the ledger exactly as it covers the Issue that would otherwise have been filed there.
27
+ - **It is append-only.** A line is never edited and never deleted, because the count of lines
28
+ carrying one key is what says whether an observation has recurred; a second sighting is a second
29
+ line, not a rewrite of the first. **A merge conflict in it is resolved by keeping both sides** —
30
+ one file per issue should keep it from arising, but a repeated key is the whole signal, so
31
+ dropping either side destroys exactly what the ledger is for.
32
+ - **The completion report keeps its line too.** The ledger is what the next run can read; the report
33
+ is what this run's reader sees. Neither replaces the other.
34
+ - **The append is not the end of it** — a line only becomes readable to anyone else once it has
35
+ merged, and "The commit path" below is how it gets there.
36
+
37
+ **One observation is one line: five fields, each separated from the next by a vertical bar with one
38
+ space on either side.**
39
+
40
+ ```
41
+ - k:<slug> | d<n> | <YYYY-MM-DD> | <where> | <what>
42
+ ```
43
+
44
+ | Field | What it holds |
45
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------- |
46
+ | `k:<slug>` | The identity key — lowercase letters and digits, in words joined by `-`. This is what makes a repeat machine-readable |
47
+ | `d<n>` | The depth of the subject — `d1`, `d2`, or whatever deeper depth `observation-filing.md`'s depth table may one day name. **There is no `d0` line**: a depth-0 observation is filed outright and never reaches the ledger |
48
+ | `<YYYY-MM-DD>` | The date of **this** sighting |
49
+ | `<where>` | One file path or one command — where the thing was seen |
50
+ | `<what>` | The phenomenon, one sentence, carrying no vertical bar of its own |
51
+
52
+ A sample, in the shape a real entry takes:
53
+
54
+ ```
55
+ - k:example | d1 | 2026-09-10 | pnpm josh run:progress | The report printed a fill-in placeholder where a clock time belonged
56
+ ```
57
+
58
+ **`k:example` is reserved for this sample and is never used by a real observation**, so the count
59
+ below can be run over the whole ledger without the sample answering for one. **The grammar is defined
60
+ here rather than in the ledger** (`docs/maintainers/observation-ledger-rationale.md` → "Why the
61
+ ledger exists").
62
+
63
+ **The identity key is the whole of the repeat test — never a similarity judgement about the prose.**
64
+ Choose the key from the phenomenon rather than from the run, then count what the ledger already holds
65
+ for it, in that repository's checkout rather than the working directory. **Every file of the
66
+ directory is counted**, because a recurrence is a recurrence whichever issue's file each sighting
67
+ sits in. **The `|| true` is not decoration**: `grep -c` exits non-zero on a count of zero, which is
68
+ the first-sighting branch and the common one, so without it the step reads as a failed command
69
+ wherever an exit status is being watched. **A missing directory is still a first sighting** — `cat`
70
+ complains on standard error and the count is zero; the append below creates the directory.
71
+
72
+ ```bash
73
+ cat <that repository's checkout>/docs/maintainers/observations/*.md | grep -c '^- k:<slug> |' || true
74
+ ```
75
+
76
+ Free-text comparison is what the key exists to replace, so two lines that read alike under different
77
+ keys are two observations, and a mis-keyed entry is corrected by appending a correctly-keyed line
78
+ rather than by editing the one already written.
79
+
80
+ **The depth gate is not withdrawn, and this is not a way around it.** An observation that *can* cite
81
+ the depth-0 work it stopped is filed exactly as it was before — this route is only for the ones that
82
+ could not.
83
+
84
+ ## The commit path — how an appended line reaches the default branch
85
+
86
+ **An append nobody commits is an append nobody can count** (joshuafolkken/kit#1756). Rationale:
87
+ `docs/maintainers/observation-ledger-rationale.md` → "Why the ledger has a commit path".
88
+
89
+ - **A run's appended lines ride its own commit** (joshuafolkken/kit#2763). `pnpm josh git` stages
90
+ `docs/maintainers/observations/` with the run's other changes, in the one staging step every entry
91
+ point goes through (`scripts/git/git-staging.ts`), so the lines are reviewed and merged with the
92
+ pull request of the run that recorded them, and the run's CI is the only wait they cost.
93
+ **Record before the commit, not after the merge:** a finding recorded with `pnpm josh review:record`
94
+ before `pnpm josh git -y` is carried; the time while CI runs is for the records that need no CI
95
+ result — filing an observation Issue, drafting the completion report.
96
+ - **A line that breaks the grammar is not carried** (joshuafolkken/kit#2123). The staging step parses
97
+ every file of the ledger first — after moving lines still on an old single-file path
98
+ (joshuafolkken/kit#2724, joshuafolkken/kit#2919) — and on a broken line leaves the ledger out of the
99
+ commit and says so; the commit itself goes ahead.
100
+ - **`pnpm josh followup` commits a line appended after the run's commit onto the pull request, before
101
+ the merge** (joshuafolkken/kit#2919) — a second review round's record is the usual case. After the
102
+ merge gates and before the CI wait, `followup` reads the tree and, **only when the ledger holds a
103
+ pending append**, stages the ledger paths alone, commits them and pushes the branch; the CI wait
104
+ that follows covers the pushed commit. A broken line refuses the merge, because the line would
105
+ otherwise be lost with the branch. A run whose lines rode its commit pays nothing.
106
+ - **A lane carries its own lines, in its own pull request** (joshuafolkken/kit#2919). Its writers
107
+ append to its own tree's `<N>.md`, so the two steps above take them to the default branch exactly as
108
+ they do for a run in the primary checkout. **Nothing is held in the primary checkout for later.**
109
+ - **`pnpm josh observations:flush` is left for a line written outside any issue's run** — the
110
+ date-named file a retrospective or a hand append on the default branch writes. It stages the ledger
111
+ and nothing else, commits it on a branch of its own, opens a docs-only pull request, waits on the
112
+ same required checks every other pull request waits on, merges it and returns the checkout to the
113
+ default branch; a single run's `run:tail` runs it after the merge. It refuses off the default branch
114
+ and refuses a working tree holding anything besides the ledger, so a run in progress cannot be
115
+ flushed out from under. **Nothing is committed to the default branch directly.**
116
+ - **Nothing to flush is an answer, not a failure.** With the ledger matching the commit it sits on
117
+ the command prints `clean` and exits 0 — most cycles append nothing, and a command that errored
118
+ there would be one nobody runs.
119
+ - **The count the promotion below reads is a count of the default branch**, which is what this route
120
+ buys: a ledger line that merged is one every later run, every other machine and every fresh clone
121
+ can see, and only then can a second sighting be recognized as one.
122
+
123
+ ## The second sighting is what files it
124
+
125
+ **A repeat is the citation**, so the gate has a second way through, and it is counted rather than
126
+ judged (rationale: `docs/maintainers/observation-ledger-rationale.md` → "Why a second sighting
127
+ files"):
128
+
129
+ - **On the count answering exactly `1`, the observation is filed**, at depth 1 or deeper, with no
130
+ depth-0 citation — `1` and not "1 or more", because a higher count means the Issue was already
131
+ opened by the sighting that answered `1`. The ledger line is appended as well, because the ledger
132
+ stays append-only.
133
+ - **The Issue quotes the ledger's own dates — the first sighting's and this one's** — so the reader
134
+ can check the promotion against the file instead of taking the run's word for it.
135
+ - **Both ceilings still apply**, exactly as `observation-filing.md` states them: the 10-per-run cap counts a promoted
136
+ filing, and the WIP cap still bites, since a promoted observation blocks nothing and is therefore
137
+ still discretionary.
138
+
139
+ **A third and later sighting appends a line and files nothing more.** The Issue from the second one
140
+ is already open, and `pnpm josh issue:scout` is what finds it; the extra lines are evidence for that
141
+ Issue, not new ones.
142
+
143
+ ## A user-found bug is recorded by its kind of miss (user-found)
144
+
145
+ **A user-reported bug is fixed or filed as always; this records the *kind of miss* alongside so the
146
+ category never recurs as a first sighting** (joshuafolkken/kit#2246). The key is the **category of
147
+ oversight** — `k:missed-case-worktree` — so a second bug of the same kind counts against the first.
148
+ **Depth `d1`, never `d0`**: the *kind of miss* is what a run fails to enumerate, which the table puts
149
+ at depth 1. Nothing else changes; the `<what>` field leads with `User-reported:`, and no second
150
+ ledger, format or threshold is added.