@joshuafolkken/kit 1.1136.0 → 1.1178.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.
- package/.claude/settings.json +4 -4
- package/.claude/skills/epic-commands/SKILL.md +27 -239
- package/.claude/skills/epic-commands/epic-bundle.md +115 -0
- package/.claude/skills/epic-commands/execution-waves.md +126 -0
- package/.claude/skills/workflow-commands/SKILL.md +48 -194
- package/.claude/skills/workflow-commands/background-commands.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-child.md +12 -123
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +14 -63
- package/.claude/skills/workflow-commands/backlogrun-park.md +16 -15
- package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -173
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +155 -0
- package/.claude/skills/workflow-commands/backlogrun-steps.md +65 -144
- package/.claude/skills/workflow-commands/backlogrun.md +5 -4
- package/.claude/skills/workflow-commands/chain-rule.md +3 -2
- package/.claude/skills/workflow-commands/delegation.md +2 -2
- package/.claude/skills/workflow-commands/entry-sequence.md +62 -0
- package/.claude/skills/workflow-commands/followup.md +104 -181
- package/.claude/skills/workflow-commands/fullrun-steps.md +8 -9
- package/.claude/skills/workflow-commands/fullrun.md +16 -73
- package/.claude/skills/workflow-commands/halfrun.md +10 -36
- package/.claude/skills/workflow-commands/into-target.md +4 -4
- package/.claude/skills/workflow-commands/issue-comments.md +7 -8
- package/.claude/skills/workflow-commands/issue-scout.md +6 -6
- package/.claude/skills/workflow-commands/kickoff.md +6 -6
- package/.claude/skills/workflow-commands/needs-human-review.md +6 -6
- package/.claude/skills/workflow-commands/observation-filing.md +21 -172
- package/.claude/skills/workflow-commands/observation-ledger.md +150 -0
- package/.claude/skills/workflow-commands/pre-gate-cut.md +35 -95
- package/.claude/skills/workflow-commands/prerequisite.md +6 -6
- package/.claude/skills/workflow-commands/progress-watcher.md +90 -0
- package/.claude/skills/workflow-commands/prrun.md +5 -5
- package/.claude/skills/workflow-commands/retrospective.md +9 -9
- package/.claude/skills/workflow-commands/split-assessment.md +2 -2
- package/.claude/skills/workflow-commands/target-repository.md +2 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +7 -5
- package/.codex/hooks.json +4 -4
- package/.github/workflows/ci.yml +15 -2
- package/AGENTS.md +1 -6
- package/CLAUDE.md +58 -120
- package/GEMINI.md +1 -6
- package/dist/CLAUDE.md +58 -120
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-NFZGFGOR.js → chunk-32GQTL4F.js} +14 -1
- package/dist/hooks/{chunk-HBKZLITF.js → chunk-DO6NWWHU.js} +4 -4
- package/dist/hooks/{chunk-KBXZLMRH.js → chunk-G6KRCKEC.js} +216 -76
- package/dist/hooks/{chunk-JKKTVDAG.js → chunk-GDS5N2KB.js} +186 -309
- package/dist/hooks/chunk-I4XSL4TT.js +56 -0
- package/dist/hooks/{chunk-GDU26K3J.js → chunk-S6X6WYKR.js} +886 -174
- package/dist/hooks/{chunk-FO2I7UT7.js → chunk-UAGLLIGZ.js} +1 -1
- package/dist/hooks/{chunk-RFWWUI5F.js → chunk-VESKRQOF.js} +3 -3
- package/dist/hooks/{chunk-KOKOAV6D.js → chunk-VQLLNFNT.js} +6 -4
- package/dist/hooks/{chunk-LJBLGHEH.js → chunk-ZAL3NRGL.js} +4 -6
- package/dist/hooks/codex-hook-adapter.js +10 -10
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +178 -177
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +11 -10
- package/dist/hooks/stop-guard.js +20 -6
- package/dist/josh.js +29 -3
- package/dist/version/index.js +5 -1
- package/package.json +2 -1
- package/prompts/collaboration-workflow/file-edits.md +11 -10
- package/prompts/collaboration-workflow/gh-rest.md +2 -4
- package/prompts/collaboration-workflow/glossary.md +1 -1
- package/prompts/collaboration-workflow/issue-citation.md +5 -9
- package/prompts/collaboration-workflow/issue-template.md +40 -115
- package/prompts/collaboration-workflow/operating-rules.md +4 -5
- package/prompts/collaboration-workflow/output-bounds.md +12 -78
- package/prompts/collaboration-workflow/overview.md +7 -13
- package/prompts/collaboration-workflow/plan-comment.md +11 -39
- package/prompts/collaboration-workflow/principles.md +3 -4
- package/prompts/collaboration-workflow/report-format.md +28 -74
- package/prompts/collaboration-workflow/residency.md +12 -109
- package/prompts/collaboration-workflow/rule-delivery.md +98 -97
- package/prompts/collaboration-workflow/shell-body.md +3 -13
- package/prompts/collaboration-workflow/turn-batching.md +14 -88
- package/prompts/collaboration-workflow/upstream-interrupt.md +12 -14
- package/prompts/collaboration-workflow/wip-cap.md +6 -45
- package/prompts/collaboration-workflow.md +1 -13
- package/prompts/review-rubric.md +8 -71
- package/prompts/review.md +25 -55
- package/prompts/testing-guide.md +18 -67
- package/scripts/agent/agent-role-profile.ts +1 -1
- package/scripts/agent/codex-hooks.ts +3 -12
- package/scripts/backlog/backlog-budget.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +4 -3
- package/scripts/backlog/backlog-drive-offer-argv.ts +10 -1
- package/scripts/backlog/backlog-next.ts +15 -4
- package/scripts/backlog/backlog-offer.ts +6 -6
- package/scripts/backlog/backlog-plan-cli.ts +6 -5
- package/scripts/backlog/backlog-rank.ts +18 -9
- package/scripts/backlog/backlog-restructure.ts +152 -0
- package/scripts/backlog/backlog-waves.ts +15 -17
- package/scripts/behavior/behavior-rules.ts +11 -4
- package/scripts/cost-runtime/context-cut-threshold.ts +1 -9
- package/scripts/cost-runtime/cost-verdict.ts +15 -28
- package/scripts/delegation/investigation-reads.ts +5 -5
- package/scripts/discovery/repo-discovery.ts +21 -7
- package/scripts/discovery/repo-origin.ts +26 -0
- package/scripts/discovery/repo-party.ts +42 -1
- package/scripts/document/backlogrun-parent-read-set.ts +14 -15
- package/scripts/document/document-byte-budget.ts +34 -20
- package/scripts/document/entry-read-budget.ts +21 -9
- package/scripts/document/lane-child-read-set.ts +12 -14
- package/scripts/document/read-set-cli.ts +4 -4
- package/scripts/document/read-set-point-of-use.ts +10 -2
- package/scripts/document/resident-budget.ts +47 -0
- package/scripts/epic/epic-shape.ts +10 -13
- package/scripts/epic/epic-solo.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +7 -3
- package/scripts/followup/git-followup-stages.ts +9 -0
- package/scripts/followup/git-pr-followup.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +7 -0
- package/scripts/gh/git-gh-issue.ts +5 -3
- package/scripts/gh/git-gh-pr-read.ts +4 -0
- package/scripts/gh/git-pr-checks-eval.ts +8 -0
- package/scripts/gh/git-pr-checks.ts +11 -1
- package/scripts/git/constants.ts +10 -0
- package/scripts/git/main-merge.ts +57 -21
- package/scripts/git/schemas.ts +2 -0
- package/scripts/hooks/pretool-guard-cli.ts +2 -2
- package/scripts/hooks/pretool-guard.ts +45 -2
- package/scripts/hooks/run-hook.sh +41 -0
- package/scripts/init/hook-command-rewrite.ts +18 -35
- package/scripts/init/hook-launch.ts +21 -32
- package/scripts/issue/issue-auto-ok.ts +95 -0
- package/scripts/issue/issue-file-cli.ts +53 -7
- package/scripts/issue/issue-file.ts +28 -5
- package/scripts/issue/issue-labels.ts +12 -12
- package/scripts/issue/issue-rank.ts +1 -1
- package/scripts/issue/issue-read-cli.ts +3 -3
- package/scripts/issue/issue-read.ts +2 -2
- package/scripts/issue/issue-scout-cli.ts +2 -2
- package/scripts/issue/issue-state-cli.ts +1 -1
- package/scripts/issue/issue-state.ts +2 -2
- package/scripts/issue/issue-wip.ts +70 -0
- package/scripts/josh/hook-decision.ts +17 -0
- package/scripts/josh/josh-commands-development.ts +11 -1
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/lane/lane-launch-cli.ts +21 -3
- package/scripts/lines/bytes-command.ts +29 -6
- package/scripts/notify/telegram-notify.ts +26 -1
- package/scripts/observations/observation-ledger-line.ts +1 -1
- package/scripts/release/release-progress.ts +167 -0
- package/scripts/release/release-publish.ts +19 -8
- package/scripts/release/release-tag.ts +22 -8
- package/scripts/rules/decision-oracle-stage.ts +1 -1
- package/scripts/rules/decision-oracle.ts +6 -6
- package/scripts/rules/delivered-rules.ts +11 -11
- package/scripts/rules/direct-pr-create.ts +110 -0
- package/scripts/rules/file-body.ts +98 -42
- package/scripts/rules/filing-cap.ts +2 -2
- package/scripts/rules/filing-offer.ts +1 -1
- package/scripts/rules/gh-api.ts +18 -1
- package/scripts/rules/implementation-cut.ts +3 -1
- package/scripts/rules/lane-background.ts +67 -10
- package/scripts/rules/permission-guards.ts +10 -2
- package/scripts/rules/pre-gate-cut.ts +2 -2
- package/scripts/rules/stop-rules.ts +4 -4
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +56 -12
- package/scripts/run/run-carry.ts +11 -5
- package/scripts/run/run-cut-cli.ts +1 -1
- package/scripts/run/run-cut-handoff.ts +21 -1
- package/scripts/run/run-cut-report.ts +2 -2
- package/scripts/run/run-entry-cli.ts +11 -3
- package/scripts/run/run-hold-cli.ts +16 -2
- package/scripts/run/run-label.ts +50 -0
- package/scripts/run/run-merge-steps.ts +8 -3
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-prep-cli.ts +6 -2
- package/scripts/run/run-prep.ts +17 -0
- package/scripts/run/run-ship-cli.ts +27 -6
- package/scripts/run/run-ship-next.ts +13 -0
- package/scripts/run/run-ship-pre-detach.ts +66 -0
- package/scripts/run/run-ship-preflight.ts +34 -3
- package/scripts/run/run-ship-return.ts +7 -4
- package/scripts/run/run-ship-review-steps.ts +1 -1
- package/scripts/run/run-ship-review.ts +26 -5
- package/scripts/run/run-ship-stage.ts +13 -0
- package/scripts/run/run-ship-steps.ts +10 -2
- package/scripts/run/run-ship-sync.ts +114 -0
- package/scripts/run/run-ship.ts +6 -0
- package/scripts/run/run-step-cli.ts +20 -7
- package/scripts/run/run-wake-cli.ts +8 -1
- package/scripts/run/run-wake-driver.ts +62 -8
- package/scripts/run/run-wake-session.ts +2 -1
- package/scripts/test/test-declared-logic.ts +1 -1
- package/scripts/test/test-red-logic.ts +17 -2
- package/scripts/test/test-red.ts +8 -7
- package/scripts/time-runtime/time-batch-guard.ts +52 -16
- package/scripts/time-runtime/time-density-hook.ts +20 -2
- package/scripts/time-runtime/time-density.ts +4 -3
- package/scripts/time-runtime/time-markers.ts +15 -4
- package/scripts/time-runtime/time-transcript-line.ts +27 -1
- package/scripts/version/npm-registry.ts +11 -1
- package/templates/workflows/ci.yml +9 -1
- package/.claude/skills/workflow-commands/followup-reference.md +0 -118
- package/dist/hooks/chunk-HANSKHES.js +0 -464
|
@@ -6,64 +6,40 @@ description: The procedures for the Issue-driven shorthand commands `kickoff`, `
|
|
|
6
6
|
# Issue-driven workflow commands
|
|
7
7
|
|
|
8
8
|
`kickoff`, `fullrun`, `halfrun`, `prrun` and `backlogrun` are the shorthand commands this
|
|
9
|
-
package's collaboration workflow is built on.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Each topic file under `prompts/collaboration-workflow/` sources its own rule; this skill sources the
|
|
13
|
-
procedures. Neither restates the other.
|
|
9
|
+
package's collaboration workflow is built on. **This file is their manifest — triggers and pointers,
|
|
10
|
+
never a procedure** (joshuafolkken/kit#3174): each rule is stated once, in the file its row names.
|
|
14
11
|
|
|
15
12
|
## 0. The rule that fires before any of them — explicit invocation
|
|
16
13
|
|
|
17
14
|
**Never start a `kickoff` / `halfrun` / `prrun` / `fullrun` / `backlogrun` workflow (including their
|
|
18
|
-
`#N` and `new` variants) unless the user has typed the keyword in the current turn's prompt.**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
invocations. Even if the task clearly fits one of these workflows, do not infer authorization from
|
|
23
|
-
the request shape.
|
|
24
|
-
- Do **NOT** ask confirmation questions like "May I proceed with `halfrun new`?" or "Shall I run
|
|
25
|
-
`fullrun`?". A confirmation prompt is not an acceptable substitute for explicit invocation.
|
|
26
|
-
- Instead, **prompt the user to type the command themselves**, with the exact phrasing: "Please run
|
|
27
|
-
\`<command>\` to start this task."
|
|
28
|
-
- The rule applies even when the user authorized a related workflow in an earlier turn. Each
|
|
29
|
-
invocation must be re-typed by the user in the current turn.
|
|
30
|
-
|
|
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".
|
|
15
|
+
`#N` and `new` variants) unless the user has typed the keyword in the current turn's prompt.** Its
|
|
16
|
+
single source is `CLAUDE.md` → "Explicit invocation required (MANDATORY)", resident because it holds
|
|
17
|
+
when this skill is not loaded. **A session cut inside a declared budget is not a new invocation — for `backlogrun`
|
|
18
|
+
alone**: `backlogrun-steps.md` → "The session cut is inside the invocation".
|
|
33
19
|
|
|
34
20
|
## 1. Which file to read
|
|
35
21
|
|
|
36
|
-
Read this file, then the
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
(`run:next` is its pre-implementation degenerate form) — and each step's detail is read on demand from
|
|
40
|
-
the file its pointer names (for `fullrun`, the step lists are `fullrun-steps.md`).
|
|
22
|
+
Read this file, then the files the typed command's row names. A command file is a **manifest** of
|
|
23
|
+
terse triggers and pointers; `pnpm josh run:step <N>` prints the run's next single action, computed
|
|
24
|
+
from the event stream, the carry record and the issue state, never the conversation.
|
|
41
25
|
|
|
42
26
|
| Typed keyword | Read |
|
|
43
27
|
| ---------------------------------------- | ------------------------------------------- |
|
|
44
28
|
| `kickoff` / `kickoff #N` / `kickoff new` | `kickoff.md` |
|
|
45
|
-
| `fullrun` / `fullrun #N` / `fullrun new` | `fullrun.md`
|
|
46
|
-
| `halfrun` / `halfrun #N` / `halfrun new` | `halfrun.md`
|
|
47
|
-
| `prrun` / `prrun #N` / `prrun new` | `prrun.md` — the difference over `fullrun.md`, read with it |
|
|
29
|
+
| `fullrun` / `fullrun #N` / `fullrun new` | `fullrun.md` + `entry-sequence.md` |
|
|
30
|
+
| `halfrun` / `halfrun #N` / `halfrun new` | `halfrun.md` + `entry-sequence.md` |
|
|
31
|
+
| `prrun` / `prrun #N` / `prrun new` | `prrun.md` — the difference over `fullrun.md`, read with it and `entry-sequence.md` |
|
|
48
32
|
| `backlogrun` / `backlogrun #N…` / `backlogrun #E…` | `backlogrun.md` — its dispatched child reads `fullrun.md` + `split-assessment.md` in its own unit, not the parent at entry |
|
|
49
33
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
lists `backlogrun.md` alone: its parent orchestrates and never implements, so `fullrun.md` and
|
|
54
|
-
`split-assessment.md` are read by a dispatched child in its own delegated unit (`backlogrun-child.md`).
|
|
55
|
-
Every procedure for *running* a `backlogrun` item — lanes (`backlogrun-lanes.md`), park-and-continue,
|
|
56
|
-
the guards — stays `backlogrun.md`'s. The on-demand sections `into-target.md` (an `into` suffix) and `target-repository.md`
|
|
57
|
-
(an `owner/repo#` prefix) are read only when their trigger is typed, and §3's residency procedure lives
|
|
58
|
-
in `prompts/collaboration-workflow/residency.md`, reached only when a rule is placed, moved or retired.
|
|
34
|
+
`entry-sequence.md` holds the entry sequence and stop branches `fullrun`, `halfrun` and `prrun` share;
|
|
35
|
+
each manifest carries only its difference. `split-assessment.md` → "The question" is read at the
|
|
36
|
+
entry as a section, its split-handling detail only when a split is found.
|
|
59
37
|
|
|
60
38
|
### The fetch is one `Read` call per file
|
|
61
39
|
|
|
62
|
-
**Fetch each file above with one `Read` call of its own — never `cat`,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
read a second time. `pnpm josh read:set [<keyword>]` prints the cap and marks every file that exceeds
|
|
66
|
-
it; `pnpm josh doc:read <file>` is the Bash-cap-safe whole-file read.
|
|
40
|
+
**Fetch each file above with one `Read` call of its own — never `cat`, never two in one command.** A
|
|
41
|
+
Bash result is capped at `BASH_MAX_OUTPUT_LENGTH` characters and truncates a longer document;
|
|
42
|
+
`pnpm josh doc:read <file>` is the cap-safe whole-file read.
|
|
67
43
|
|
|
68
44
|
### Four documents are read at the point of use, not at the entry
|
|
69
45
|
|
|
@@ -74,19 +50,13 @@ Each is fetched at its named scope, in the same turn, by the named command that
|
|
|
74
50
|
| ----------------------- | ------------------------------------------------------------------------------ |
|
|
75
51
|
| `latest-gate.md` | `pnpm josh latest:scope` answers `required` — before `josh latest` runs |
|
|
76
52
|
| `followup.md` → "Run `pnpm josh followup`" | Before issuing `pnpm josh followup`, in that same turn |
|
|
77
|
-
| `chain-rule.md` → "Run the review-to-merge chain" | Before the first `pnpm josh gate` launch (`fullrun` / `backlogrun`) — the
|
|
53
|
+
| `chain-rule.md` → "Run the review-to-merge chain" | Before the first `pnpm josh gate` launch (`fullrun` / `backlogrun`) — the gate starts overlapped with the review, so the section is read before the gate |
|
|
78
54
|
| `background-commands.md` → "Background the gate and push" | Before backgrounding `pnpm josh gate` — the first long-running command a run detaches (`fullrun` / `halfrun` / `backlogrun`) |
|
|
79
55
|
|
|
80
|
-
A `skip` answer from `latest:scope` reads nothing
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`followup-reference.md`, reached through a section pointer from `followup.md`.
|
|
85
|
-
|
|
86
|
-
**A lane child that parks reads `backlogrun-park.md` → "park and continue" at that point of use**, so
|
|
87
|
-
the pointer names that heading rather than the whole file: the entry read is charged for the park
|
|
88
|
-
procedure alone, and the rest of `backlogrun-park.md` is read only when it is reached
|
|
89
|
-
(joshuafolkken/kit#2189).
|
|
56
|
+
A `skip` answer from `latest:scope` reads nothing. **A lane child that parks reads
|
|
57
|
+
`backlogrun-park.md` → "park and continue" at that point of use**, and **every implementing run reads
|
|
58
|
+
`progress-watcher.md` → "Progress while the run is quiet"** before starting `pnpm josh run:progress
|
|
59
|
+
--wait` once its hold is claimed (joshuafolkken/kit#3172).
|
|
90
60
|
|
|
91
61
|
### A section reference is read as a section
|
|
92
62
|
|
|
@@ -97,162 +67,46 @@ pnpm josh doc:section <file.md> "<heading>" # the section, verbatim
|
|
|
97
67
|
pnpm josh read:set [<keyword>] # what an entry reads, and what it costs
|
|
98
68
|
```
|
|
99
69
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
derived from the table above and the documents themselves, not transcribed;
|
|
103
|
-
`scripts/document/entry-read-set.test.ts` pins the derivation and
|
|
104
|
-
`scripts/rules/entry-read-set-document-rule.test.ts` pins this rule.
|
|
70
|
+
A heading that does not resolve is refused, with the file's own headings listed. The set is derived
|
|
71
|
+
from the table above and the documents themselves, never transcribed.
|
|
105
72
|
|
|
106
73
|
## 2. What every one of them shares
|
|
107
74
|
|
|
108
75
|
Each shared rule is a **trigger, a one-line action, and the single source** the procedure is read
|
|
109
|
-
from
|
|
110
|
-
procedure.
|
|
76
|
+
from — read at that trigger, never restated here.
|
|
111
77
|
|
|
112
78
|
| Trigger | Action | Single source |
|
|
113
79
|
| --- | --- | --- |
|
|
80
|
+
| First call of any entry | `#N`: `pnpm josh run:entry <N> --to <command>` (claims the tree, except `kickoff`); `new` (not `kickoff`): `pnpm josh run:hold`; `busy` / `unknown` stop | `working-tree-hold.md` |
|
|
81
|
+
| `run:entry` prints its stage line | The command sets how far a run goes, the Issue where it starts; **`start: reached` redoes nothing** — stop (at `merged`, the next line answers) | `docs/how-to/run-issues.md` |
|
|
82
|
+
| Same turn as the hold (not a dispatched child, not `kickoff`) | `pnpm josh cost --cut`; `under` continues, `over` stops — `run:entry` notifies and runs `run:release` (by hand for `new`) | `backlogrun-progress.md` → "The hand-off" (shared 135,000 threshold) |
|
|
83
|
+
| An entry typed with an `owner/repo#` prefix or a short `repo#` name | Resolve the target and its checkout; an explicit foreign owner stops the run | `target-repository.md` |
|
|
84
|
+
| A `new` entry typed with an `into <target>` suffix | Insert the artifact into the named epic with `pnpm josh epic --add <E> <N>` | `into-target.md` |
|
|
85
|
+
| Before any work starts (every entry) | The split assessment; the default is not to split — separability **and** a scope clearly over one gate must hold together; a `fullrun` / `halfrun` that finds a split files the epic and **stops** | `split-assessment.md` → "The question" |
|
|
86
|
+
| Before implementing (every `#N` entry) | `pnpm josh issue:read <N>` — the body and the comments; the later of a body and a comment wins | `issue-comments.md` |
|
|
87
|
+
| `pnpm josh issue:state <N>` answers `human_review: yes` | Implement and gate, then stop before the commit; the label is applied only by a person | `needs-human-review.md` |
|
|
114
88
|
| Before implementing (every implementing entry) | `pnpm josh latest:scope`; on `required` read the doc and run `josh latest`, then load the `dependency-update` skill; `kickoff` never reaches it | `latest-gate.md` (read whole, only on `required`) |
|
|
115
|
-
|
|
|
116
|
-
|
|
|
89
|
+
| Before delegating any run step | `pnpm josh delegate <step>` decides eligibility, never you | `delegation.md` |
|
|
90
|
+
| The pre-implementation reading reaches 3 unedited files | Delegate the unread investigation; a file this run will edit is read in the main line | `delegation.md` → "The pre-implementation reading" |
|
|
91
|
+
| Immediately before implementation | Present the two-layer work summary (once per Issue); `kickoff` posts a plan instead | `prompts/collaboration-workflow/report-format.md` |
|
|
92
|
+
| While implementing | Re-run one check by name, not the whole gate — `pnpm josh lint:related`, `pnpm josh cspell:dot`, `pnpm josh test:related`; `pnpm josh review:brief` refuses a brief on a tree the last two were not green on | `chain-rule.md` |
|
|
93
|
+
| Implementation is done | Refactor → `pnpm josh main:merge` → `pnpm josh gate` beside a subagent `/code-review`, joined before the commit → round cap → PR → merge | `chain-rule.md` → "Run the review-to-merge chain" |
|
|
117
94
|
| A review has run | Its verdict counts only once `pnpm josh review:attest --check` answers `ok`; `missing` / `mismatch` are refusals `pnpm josh followup` blocks the merge on | `chain-rule.md` → "The brief names the checkout, and a review that read another one is refused" |
|
|
95
|
+
| A command can take minutes | Issue it in the background; the turn never ends at the push (`pnpm josh followup` stays foreground) | `background-commands.md` → "Background the gate and push" |
|
|
118
96
|
| E2E gate | The CI E2E job where the command ends in a PR (`fullrun` / `backlogrun`, enforced by `pnpm josh followup`); you run `pnpm josh test:e2e` yourself where it does not (`halfrun`) | `prompts/testing-guide.md` → "Closing the E2E gate without a human run" |
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
97
|
+
| Filing any new Issue | `pnpm josh issue:file` — it runs the `issue:scout` scan first; read its duplicate and epic answers | `issue-scout.md` |
|
|
98
|
+
| Another Issue here must land first | A prerequisite is a dependency, not a park — file it, stash, record the dependency; `fullrun` / `halfrun` stop, `backlogrun` continues | `prerequisite.md` |
|
|
99
|
+
| Something worth filing, none of the three | File it without asking (Tier A, first-party) and carry on; a delegated child returns it to the parent instead | `observation-filing.md` |
|
|
100
|
+
| A defect in kit's own verification turns up | It runs alone when all three conditions hold; a batch resumes once it merges | `backlogrun-lanes.md` → "Lanes — running more than one child at a time" |
|
|
122
101
|
| Under `backlogrun`, a stop that would end a batch, or a named non-epic item | Park one child and continue; run a named non-epic item as a `fullrun` | `backlogrun-park.md` → "park and continue"; `backlogrun-child.md` → "When `#N` is not an epic" |
|
|
123
102
|
| `backlogrun`'s authorization | The whole `auto-ok` opted-in pool as well as its named items; `pnpm josh backlog:next` offers them | `backlogrun.md` |
|
|
124
|
-
|
|
|
125
|
-
| Same turn as the hold (not a dispatched child, not `kickoff`) | `pnpm josh cost --cut`; `under` continues, `over` stops — `run:entry` notifies and runs `run:release` (by hand for `new`) | `backlogrun-progress.md` → "The hand-off" (shared 135,000 threshold) |
|
|
126
|
-
| Before any work starts (every entry) | The split assessment; the default is not to split — separability **and** a scope clearly over one gate must hold together; a `fullrun` / `halfrun` that finds a split files the epic and **stops** | `split-assessment.md` → "The question" |
|
|
127
|
-
| Another Issue here must land first | A prerequisite is a dependency, not a park (the third of four mid-run discoveries) | §2d → `prerequisite.md` |
|
|
128
|
-
| Something worth filing, none of the three | File it without asking (Tier A, first-party) and carry on; a delegated child returns it to the parent instead | §2i → `observation-filing.md` |
|
|
129
|
-
| `run:step` prints the retrospective step (a run drained its backlog and stopped, not a lane child) | Run what it prints once, file 0–2 improvements, then `pnpm josh run:carry --retrospective` | §2j → `retrospective.md` |
|
|
130
|
-
| The pre-implementation reading reaches 3 unedited files | Delegate it; a file this run will edit is read in the main line | §2b → "The pre-implementation reading" |
|
|
131
|
-
| Before implementing (every `#N` entry) | Read the Issue's comments — the later of a body and a comment wins | §2g → `issue-comments.md` |
|
|
132
|
-
| Immediately before implementation | Present the two-layer work summary (once per Issue); `kickoff` posts a plan instead | `prompts/collaboration-workflow/report-format.md` |
|
|
103
|
+
| `run:step` prints the retrospective step (a run drained its backlog and stopped, not a lane child) | Run what it prints once, file 0–2 improvements, then `pnpm josh run:carry --retrospective` | `retrospective.md` |
|
|
133
104
|
| Any artifact prose (Issue bodies, comments, Telegram) | Session language (`JOSH_SESSION_LANG`, default `ja`); Issue/PR titles stay English | `prompts/collaboration-workflow/overview.md` |
|
|
134
105
|
| Any mid-workflow stop | Send a `confirmation` Telegram first, so the user is alerted off-screen | `CLAUDE.md` → "Mid-workflow stop notification" |
|
|
135
106
|
|
|
136
|
-
## 2z. `needs-human-review` — the child that stops before its commit
|
|
137
|
-
|
|
138
|
-
**Trigger:** `pnpm josh issue:state <N>` answers `human_review: yes` — asked once, before implementing.
|
|
139
|
-
**Then:** implement and run the verification gate normally, but commit nothing — leave the tree
|
|
140
|
-
uncommitted and unstashed, send a `confirmation` Telegram with the resume command, and stop the whole
|
|
141
|
-
run (inside a `backlogrun` this is the one child stop that is *not* park-and-continue). **The label is
|
|
142
|
-
applied only by a person; never apply or remove it.** The full procedure — why it stops the *end* not
|
|
143
|
-
the *start*, why the repository stays held, and the resume — is `needs-human-review.md`, its single
|
|
144
|
-
source, read at that trigger.
|
|
145
|
-
|
|
146
|
-
## 2a. The `into <target>` suffix — where the new Issue lands
|
|
147
|
-
|
|
148
|
-
**The suffix and its procedure are `into-target.md`, read at its point of use — the moment a `new`
|
|
149
|
-
entry (`kickoff new` / `fullrun new` / `halfrun new`) is typed with an `into <target>` suffix.** It
|
|
150
|
-
names the epic the run's artifact joins, inserts it with `pnpm josh epic --add <E> <N>` as soon as the
|
|
151
|
-
artifact exists, and refuses a target that is not an epic. A run given a `#N` or a bare `new` never
|
|
152
|
-
reaches it. `into-target.md` is the single source.
|
|
153
|
-
|
|
154
|
-
## 2b. Delegating a step to a cheaper tier
|
|
155
|
-
|
|
156
|
-
**Before delegating any run step, ask `pnpm josh delegate <step>`; never decide eligibility yourself.**
|
|
157
|
-
Read `delegation.md` at the first delegation decision for its units and verification rules. An item
|
|
158
|
-
absent from the enumeration stays in the main line. A dispatched `epic-child` that returns open with
|
|
159
|
-
`human_review: yes` is an authorized stop, not a failed child (§2z).
|
|
160
|
-
|
|
161
|
-
### The pre-implementation reading — what goes to a unit, and from which file
|
|
162
|
-
|
|
163
|
-
**When the next pre-implementation read would reach 3 files this run will not edit, delegate the
|
|
164
|
-
unread investigation before that read.** Keep edit-target reads in the main line. The full procedure
|
|
165
|
-
and the `file:line` verification are in `delegation.md` → "The pre-implementation reading"; the
|
|
166
|
-
threshold is counted by `pnpm josh investigation:guard`.
|
|
167
|
-
|
|
168
|
-
## 2c. The `owner/repo#` prefix — which repository the run acts on
|
|
169
|
-
|
|
170
|
-
**The prefix and its procedure are `target-repository.md`, read at its point of use — the moment an
|
|
171
|
-
entry is typed with an `owner/repo#` prefix or a short `repo#` name.** It names the repository the run
|
|
172
|
-
acts on; a short name expands by the session owner and is first-party by construction, an explicit
|
|
173
|
-
foreign owner is a third-party target that stops the run, and an implementing entry resolves that
|
|
174
|
-
repository's checkout from `pnpm josh doctor` rather than cloning. No prefix leaves the target as the
|
|
175
|
-
session's own repository, so a run without one never reaches it. `target-repository.md` is the single
|
|
176
|
-
source.
|
|
177
|
-
|
|
178
|
-
## 2d. A prerequisite discovered mid-run — a dependency, not a park
|
|
179
|
-
|
|
180
|
-
**Trigger:** a run finds that another Issue in *this* repository has to land first. **Then:** it is
|
|
181
|
-
still one deliverable with another in front of it — file the prerequisite with the `route:tier-a` label
|
|
182
|
-
(scouted first, §2e), stash the work in progress with `git stash push -u` and record it on the Issue,
|
|
183
|
-
record the dependency in the epic, and — under `fullrun` / `halfrun` — **stop**, or — under
|
|
184
|
-
`backlogrun` — **continue** (`backlogrun-park.md` → "A prerequisite discovered mid-run"). It is the
|
|
185
|
-
third of four mid-run discoveries, distinct from an upstream defect, a split (`split-assessment.md`)
|
|
186
|
-
and an observation (§2i). The full table, the filing command, the `-u`/`stash:pop` steps and the
|
|
187
|
-
10-per-run cap are `prerequisite.md`, its single source, read at that trigger. **When the prerequisite
|
|
188
|
-
is the run's second filing, `pnpm josh issue:fold` runs first** (§2e), and `pnpm josh rule:guard`
|
|
189
|
-
refuses the second `pnpm josh issue:file` call until it has.
|
|
190
|
-
|
|
191
|
-
## 2e. Before filing a new Issue — `pnpm josh issue:scout`
|
|
192
|
-
|
|
193
|
-
**Every new Issue is filed with `pnpm josh issue:file`, which runs the `issue:scout` scan first — read
|
|
194
|
-
its duplicate and epic answers.** This applies inside every workflow, including observations and review
|
|
195
|
-
follow-ups. The guard refuses any other filing call. Read `issue-scout.md` at that point for the
|
|
196
|
-
duplicate, closed-Issue and epic decisions and for `--distinct`; `issue-fold-existing.md` handles a
|
|
197
|
-
compatible duplicate. `docs/josh-commands-automation.md` → "`josh issue:file`" defines the command.
|
|
198
|
-
|
|
199
|
-
## 2f. The working-tree hold — one run per tree
|
|
200
|
-
|
|
201
|
-
**Trigger:** the first call of `fullrun` and `halfrun` alike — before the title is normalized, before
|
|
202
|
-
`git switch main`, and before a `new` entry files its Issue. **Then:** a `#N` entry first runs
|
|
203
|
-
`pnpm josh run:entry <N> --to <command>` (§2k, the tree claim included); `new` runs bare
|
|
204
|
-
`pnpm josh run:hold`. `hold` continues; `busy` and `unknown` stop with a `confirmation` Telegram
|
|
205
|
-
carrying what stderr printed. **`kickoff` is exempt** (it edits nothing). A stop that leaves the tree
|
|
206
|
-
clean releases explicitly with `pnpm josh run:release [<N>]`; a `halfrun` or `needs-human-review` stop
|
|
207
|
-
keeps the hold; `pnpm josh followup` releases a merged run. The answer table, the per-child rule and
|
|
208
|
-
the `--force` spelling are `working-tree-hold.md`, its single source, read at that trigger.
|
|
209
|
-
|
|
210
|
-
## 2g. An Issue's comments are part of the Issue
|
|
211
|
-
|
|
212
|
-
**Trigger:** before implementing at every `#N` entry point (`fullrun`, `halfrun`, `kickoff`, and each
|
|
213
|
-
`backlogrun` child in its own unit). **Then:** `pnpm josh issue:read <N> [<N> ...]` reads the body and
|
|
214
|
-
the comments in one call — a decision recorded after the body was written lives only in a comment, and
|
|
215
|
-
of a body and a comment that disagree the later text wins. Two comment kinds are not the run's to act
|
|
216
|
-
on blindly — a scope reassigned to another Issue, and an Issue already merged (the `already-done`
|
|
217
|
-
exit) — and both, the long-thread delegation and why `pnpm josh rule:guard` refuses the body-only read,
|
|
218
|
-
are `issue-comments.md`, its single source, read at that trigger.
|
|
219
|
-
|
|
220
|
-
## 2h. A command that can take minutes is issued in the background
|
|
221
|
-
|
|
222
|
-
**Trigger:** before backgrounding the first long-running command (`pnpm josh gate`). **Then:** issue
|
|
223
|
-
`pnpm josh git -y`, `pnpm josh gate` and the CI wait detached while `pnpm josh followup` stays in the
|
|
224
|
-
foreground — the turn never ends at the push, bar a dispatched lane child's pre-gate cut
|
|
225
|
-
(`pre-gate-cut.md`). A parent waiting on its children is the same rule at the batch's scale: a
|
|
226
|
-
background command's completion re-invokes the session, so the `backlogrun` loop starts no sleep of
|
|
227
|
-
its own. The single source is `background-commands.md` → "Background the gate and push", with the
|
|
228
|
-
parent-wake half at `backlogrun-progress.md` → "The parent keeps no clock of its own".
|
|
229
|
-
|
|
230
|
-
## 2i. An observation worth filing is filed without asking
|
|
231
|
-
|
|
232
|
-
**When a first-party observation is worth filing, file it without asking and continue the run.**
|
|
233
|
-
Read `observation-filing.md` in full before filing: it decides the depth test, filing ceilings, labels,
|
|
234
|
-
second-filing fold, ledger fallback and delegated-child handoff. Use `pnpm josh repo:party` to decide
|
|
235
|
-
first-party status, then file with `pnpm josh issue:file` (§2e). A third-party target remains
|
|
236
|
-
Tier C (`CLAUDE.md`).
|
|
237
|
-
|
|
238
|
-
## 2j. The end-of-run retrospective — read when `run:step` prints it
|
|
239
|
-
|
|
240
|
-
**When `pnpm josh run:step` prints the retrospective step, read `retrospective.md` in full and run the
|
|
241
|
-
digest it names once.** File up to two worthwhile improvements through `issue:file` (scout and
|
|
242
|
-
`epic:bundle` included), stack the rest in the observation ledger, and close the step with the command described
|
|
243
|
-
there. A dispatched lane child never runs the retrospective.
|
|
244
|
-
|
|
245
|
-
## 2k. The stage ladder
|
|
246
|
-
|
|
247
|
-
`kickoff` → `halfrun` → `prrun` → `fullrun` (joshuafolkken/kit#3042): the command sets how far a run
|
|
248
|
-
goes, the Issue where it starts. `run:entry <N> --to <command>` prints `stage #<N> — at: … · start:
|
|
249
|
-
…`; **`start: reached` redoes nothing — stop** (at `merged`, the next line answers). A
|
|
250
|
-
stop's `Next:` line names the commands further up. Table: `docs/how-to/run-issues.md`.
|
|
251
|
-
|
|
252
107
|
## 3. What stays resident, and what is read from here
|
|
253
108
|
|
|
254
109
|
**The residency criterion is `prompts/collaboration-workflow/residency.md`, its single source — read
|
|
255
|
-
only when a rule is
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
retirement route; none is restated here.
|
|
110
|
+
only when a rule is placed, moved or retired, never during a run.** Its questions — question 0
|
|
111
|
+
(`pnpm josh oracle:list`), the ordering question (`pnpm josh run:step`), the first and the second —
|
|
112
|
+
are asked there in order; none is restated here.
|
|
@@ -88,4 +88,4 @@ backgrounded `josh gate` / `git` / `followup` / `ship` there, and the `Stop` hoo
|
|
|
88
88
|
task still running back to wait.
|
|
89
89
|
|
|
90
90
|
The operational section above is the single source of the rule. `followup.md`, `chain-rule.md` and
|
|
91
|
-
`
|
|
91
|
+
`progress-watcher.md` → "Progress while the run is quiet" route here for it rather than restating it.
|
|
@@ -24,7 +24,7 @@ bare Issue promotes itself under `backlogrun` but not under `fullrun`"):
|
|
|
24
24
|
2. **Stash the work in progress and remove `in-progress` from `#<N>`**, exactly as steps 2 and 4 of
|
|
25
25
|
"A prerequisite discovered mid-run" do — `git stash push -u -m "..."` with the `-u`, the
|
|
26
26
|
`gh api repos/{owner}/{repo}/issues/<N>/comments` post that records the stash, and
|
|
27
|
-
`
|
|
27
|
+
`pnpm josh run:release <N>`, which removes the label with the hold.
|
|
28
28
|
3. **Ask `pnpm josh epic:bundle <N>` whether an epic already tracks `#<N>` before creating one.**
|
|
29
29
|
|
|
30
30
|
| Answer | What to do |
|
|
@@ -115,7 +115,7 @@ summary is bounded the way it is".
|
|
|
115
115
|
3. **Observations that could bite later** — something noticed and not filed, a flaky check, a
|
|
116
116
|
surprising diff, work a later child will collide with. **This is the only route a child's
|
|
117
117
|
discretionary observation has**: a child files `route:tier-a` and `route:interrupt` only, and the
|
|
118
|
-
parent files what survives — `
|
|
118
|
+
parent files what survives — `observation-filing.md`, 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
120
|
becomes one line in the observation ledger, and a second line under the same key files it. **A
|
|
121
121
|
child appends only to its own issue's file, `docs/maintainers/observations/<N>.md`, in its own
|
|
@@ -148,92 +148,10 @@ asked at every merge; delegation is not an alternative to it.
|
|
|
148
148
|
|
|
149
149
|
## A delegated unit that stopped without reporting
|
|
150
150
|
|
|
151
|
-
**
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
the silent-unit window (`| Silent delegated unit | 30 min |` in `backlogrun-progress.md`).
|
|
156
|
-
|
|
157
|
-
**Note where the unit writes at hand-off; the modification time is read from the file, not carried.**
|
|
158
|
-
**Where the child runs in a lane, that note goes into the lane rather than the conversation** —
|
|
159
|
-
`pnpm josh lane:output <N> <path>`, in the same turn as the dispatch, so it comes back from
|
|
160
|
-
`pnpm josh lane:output <N>` in any session.
|
|
161
|
-
|
|
162
|
-
**Ask the command rather than combining the traces yourself.** Traces are read **in the checkout the
|
|
163
|
-
unit was given** — this session's own unless the unit was handed a separate work tree, and the stash in
|
|
164
|
-
the recovery below is taken there too.
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
pnpm josh run:liveness <N> --output <path> --process none
|
|
168
|
-
pnpm josh run:liveness <N> --output <path> --process alive
|
|
169
|
-
pnpm josh run:liveness <N> --output <path> --process none --window 45 --repo <owner/repo>
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
| Answer | What it found | What the parent does |
|
|
173
|
-
| --- | --- | --- |
|
|
174
|
-
| `alive` | The output moved, or a process of the child is running | Keep polling; touch nothing |
|
|
175
|
-
| `stopped` | The output has been frozen past the window and no process of the child is alive | The recovery below |
|
|
176
|
-
| `settled` | The child closed, or the unit parked it with `needs-decision` | Re-read it with `pnpm josh run:status <N>` — one read-only call whose state section says which branch and whose carry counters beside it feed the failure-streak decision — and take the branch its state section says |
|
|
177
|
-
| `undetermined` | A trace could not be read | Read the trace that failed and ask again — and see the two-in-a-row rule below |
|
|
178
|
-
|
|
179
|
-
**Two `undetermined` answers in a row is a fault in the check, not a slow unit.** The second
|
|
180
|
-
consecutive `undetermined` on the same child ends the polling: send a `confirmation` Telegram naming
|
|
181
|
-
the trace that failed, and stop. **It is never escalated to a `stopped`** — nothing was read.
|
|
182
|
-
|
|
183
|
-
**Silence and no process together — never either one alone.** **A trace that could not be read answers
|
|
184
|
-
`undetermined`, never `stopped`**, and a process trace nobody gave is an unasked question rather than
|
|
185
|
-
"no process". **Output that moved answers `alive` on its own; a live process is weighed only once every
|
|
186
|
-
trace has answered.** Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why liveness needs
|
|
187
|
-
silence and no process together".
|
|
188
|
-
|
|
189
|
-
**The path passed to `--output` is absolute** — the command refuses a relative one. **The process
|
|
190
|
-
trace is the one the command does not read for itself**: run it in the unit's checkout and read the
|
|
191
|
-
command lines rather than the names — `pgrep -laf 'josh gate'` etc. — looking for one naming **that
|
|
192
|
-
checkout's path**, since several kit projects may run at once. **Read the file the path points at, not
|
|
193
|
-
the link**: a transcript path is a symlink whose own modification time never changes, so a `stat` typed
|
|
194
|
-
by hand needs `-L` (`run:liveness` follows the link itself).
|
|
195
|
-
|
|
196
|
-
**A clean checkout is not evidence that the unit is alive** — a stop can come while the unit is still
|
|
197
|
-
reading the skill and the issue. The checkout is read only for whether there is work to stash before
|
|
198
|
-
the child is parked; **"nothing was ever opened for the child" is `pnpm josh run:hold`'s preflight check
|
|
199
|
-
at the start of the next child, not this one's.**
|
|
200
|
-
|
|
201
|
-
**What follows is what a failed child already gets.** Re-read the child first with
|
|
202
|
-
`pnpm josh run:status <N>` — its state section carries the same `state:` / `labels:` /
|
|
203
|
-
`human_review:` lines `issue:state` prints, and folds in the carry counters this recovery reads
|
|
204
|
-
anyway; then, while it is still `state: OPEN` and not carrying `needs-decision`.
|
|
205
|
-
**A re-read carrying `needs-decision`** means the unit parked the child and then stopped, so fall
|
|
206
|
-
through to the loop's park branch: leave the label on, count nothing against the consecutive-failure
|
|
207
|
-
guard, and go back to step 1.
|
|
208
|
-
|
|
209
|
-
1. **Stash the half-finished work** — `git stash push -u -m "backlogrun: stopped unit for #<N>"` — and
|
|
210
|
-
record it on the Issue. `-u` is not optional, and the comment is what gets the stash popped — by
|
|
211
|
-
message, `pnpm josh stash:pop "backlogrun: stopped unit for #<N>"`, never a positional
|
|
212
|
-
`git stash pop` that a shared stack lets another lane divert.
|
|
213
|
-
2. **Classify how the child ended and act, in one call** — `pnpm josh run:merge <N> --output <path>`
|
|
214
|
-
(add `--epic <E> --repo <owner/repo> --owner "$PPID"` for a named epic). **It is the same composite a
|
|
215
|
-
returned child takes** (`backlogrun-progress.md` → "Running a named epic's children"), reached here
|
|
216
|
-
from the poll rather than from a return — **one** decision, never a second copy of it. It **reads the
|
|
217
|
-
child's exit record without waiting for the unit to return**, telling an `outage` — a child that
|
|
218
|
-
could not reach the API — apart from an `abandoned` one that stopped mid-implementation, and it drops
|
|
219
|
-
the stale `in-progress` itself, so there is no separate label-removal step:
|
|
220
|
-
- **outage** — the child never reached the API, so it is counted into its own outage streak and
|
|
221
|
-
**re-dispatched in the same run** by being offered again, **not** parked with `needs-decision` and
|
|
222
|
-
**not** counted against the consecutive-failure guard. **The re-dispatch resumes the child's
|
|
223
|
-
session**: `lane:dispatch` reads the `session_id` off the exit record and relaunches with
|
|
224
|
-
`--resume`; with no session id it falls back to a fresh `fullrun`, and the report says which path
|
|
225
|
-
it took. **Outages inside a two-minute window count once** toward the streak. The re-dispatch is
|
|
226
|
-
bounded by `CONSECUTIVE_OUTAGE_LIMIT` in `scripts/run/run-merge.ts`: *distinct* outages trip the
|
|
227
|
-
separate outage guard, at which point the command prints `environment` and the run stops. It never
|
|
228
|
-
re-dispatches into a dead API forever.
|
|
229
|
-
- **abandoned** — counted against the consecutive-failure guard and parked with `needs-decision`,
|
|
230
|
-
exactly as a failed child. Never retried silently.
|
|
231
|
-
3. **Read the token it printed and take that branch** — a next child number to run (the re-dispatched
|
|
232
|
-
outage child among them), `environment` / `stop` to end the run, or `busy` / `retry` to re-read —
|
|
233
|
-
the same tokens the merge event reads (`backlogrun-progress.md` → "Running a named epic's children").
|
|
234
|
-
Then go back to step 1 of the loop.
|
|
235
|
-
|
|
236
|
-
Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why the poll routes through `run:merge`".
|
|
151
|
+
**Hand the child to the unit without blocking on its return, and poll** — a stopped unit leaves no
|
|
152
|
+
notification behind. Once its output has been unchanged for the silent-unit window, read
|
|
153
|
+
`backlogrun-recovery.md` → "A delegated unit that stopped without reporting" and ask
|
|
154
|
+
`pnpm josh run:liveness`.
|
|
237
155
|
|
|
238
156
|
## Audit before the first child
|
|
239
157
|
|
|
@@ -281,40 +199,11 @@ This is the same rule `latest-gate.md` is the single source of.
|
|
|
281
199
|
Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why `josh latest` is hoisted to the
|
|
282
200
|
session".
|
|
283
201
|
|
|
284
|
-
## Preflight —
|
|
285
|
-
|
|
286
|
-
**The child's claim is what asks it.** `pnpm josh run:hold <N>` — the first call of the child's
|
|
287
|
-
`fullrun` procedure — runs the preflight check before it takes the tree: it hands back a hold **only on
|
|
288
|
-
a clean tree**, and returns `reclaim` / `resume` / `park` without claiming otherwise. There is no
|
|
289
|
-
separate command to ask first. Rationale: `docs/maintainers/backlogrun-child-rationale.md` → "Why the
|
|
290
|
-
preflight is part of the claim".
|
|
202
|
+
## Preflight — the child's claim asks it
|
|
291
203
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
204
|
+
`pnpm josh run:hold <N>`, the first call of the child's `fullrun`, checks for an interrupted run's
|
|
205
|
+
leftovers before it claims the tree, and prints the step for each answer (`reclaim` / `resume` /
|
|
206
|
+
`park`) on stderr — follow it, and report a reclaim or resume with its stash reference. The answers are
|
|
207
|
+
`docs/josh-commands-automation.md` → "`josh run:hold`"; rationale:
|
|
208
|
+
`docs/maintainers/backlogrun-child-rationale.md` → "Why the preflight is part of the claim".
|
|
295
209
|
|
|
296
|
-
| Answer | What it found | What to do |
|
|
297
|
-
| --- | --- | --- |
|
|
298
|
-
| `hold` | Nothing left behind; the tree is claimed | Start the child. This is the ordinary answer. |
|
|
299
|
-
| `reclaim` | Uncommitted changes, or HEAD off the default branch | Run what stderr printed: `git stash push -u -m "run:hold reclaimed before #<N>"`, then `git switch <default> && git pull`. **`-u` is not optional** (a new `*.test.ts` is untracked). **Then record the stash on `#<N>` as a comment, and ask `run:hold` again** — the check is re-askable. |
|
|
300
|
-
| `resume` | An open PR, or a `#<N>` branch with commits or a dirty lane | **Reuse it and run the whole verification gate from the start** — never only the part the interrupted run had not reached. The tools are idempotent; what was missing was that **nobody had verified what the dead run already committed**. |
|
|
301
|
-
| `park` | The pull request for `#<N>` is **merged** or **closed** | **Park the child** — `needs-decision` plus a comment naming what was found — and continue. Carrying on over a merged PR duplicates work; over a closed one revives rejected work. Do not delete the branch, reopen the PR, or commit on top of it. |
|
|
302
|
-
| `busy` | Another **live** run holds this tree | Stop before filing anything — `run:hold`'s own answer, unchanged. |
|
|
303
|
-
| `unknown` | The tree could not be read | Stop the session and report. It is not "the tree is clean". |
|
|
304
|
-
|
|
305
|
-
**The rule answers, so the run does not judge.**
|
|
306
|
-
|
|
307
|
-
**The `git stash` above is one of the flows that authorizes automatic stashing**
|
|
308
|
-
(`prompts/collaboration-workflow/operating-rules.md` → the `git stash` bullet). **It is the one entry
|
|
309
|
-
there not followed by a pop**: what is stashed belongs to a run that is gone, so **the Issue comment is
|
|
310
|
-
the only thing that can bring it back** — recovered by message, `pnpm josh stash:pop "run:hold
|
|
311
|
-
reclaimed before #<N>"`, never a positional `git stash pop` a shared stash stack lets another lane
|
|
312
|
-
divert.
|
|
313
|
-
|
|
314
|
-
**Report what was reclaimed** — a child that started from a `reclaim` or a `resume` says so, with the
|
|
315
|
-
stash reference where there was one.
|
|
316
|
-
|
|
317
|
-
**It is not asked in a lane** — `run:hold` claimed inside a lane skips the check, and `lane:open`'s own
|
|
318
|
-
answer covers an interrupted lane instead. **Asked in the primary checkout while a lane for that child
|
|
319
|
-
is open, `run:hold` reads `resume` only if `<N>-lane` has a commit or a dirty tree** — a clean one
|
|
320
|
-
at the default branch reads `hold`. The loop never gets there, because `epic:next` does not offer a child already carrying `in-progress`.
|
|
@@ -84,8 +84,12 @@ it a defect (not an improvement, refactor, removal or feature)? Is it in kit's o
|
|
|
84
84
|
checks — not a consumer repository's CI or template? Does it, on `main` now, make unrelated PRs
|
|
85
85
|
answer wrongly (a false green or a false red)? All three, and the issue carries `run:solo`; any one
|
|
86
86
|
missing, and it carries `run:lane` and fills a lane like any other child. `backlog:next` and `epic:next --lanes` enforce both (joshuafolkken/kit#2776,
|
|
87
|
-
#2779)
|
|
88
|
-
`
|
|
87
|
+
#2779), and an issue a run files (an interrupt, a split child, a prerequisite) carries one of the
|
|
88
|
+
two from its filing, because an issue with neither answers `triage` and nothing starts. **It stops
|
|
89
|
+
the other lanes for one reason only: a batch run on broken verification leaves nobody's result
|
|
90
|
+
trustworthy** — that the issue's own verification sits under the defect is the issue's own concern,
|
|
91
|
+
checked by the verification after the fix. This paragraph is the rule's single source; rationale:
|
|
92
|
+
`docs/maintainers/wip-cap-rationale.md` → 「単独実行の理由と由来」.
|
|
89
93
|
|
|
90
94
|
**A lane's review does not inherit the lane, and `pnpm josh review:brief` is what closes that.**
|
|
91
95
|
`pnpm josh review:brief` prints the lane's absolute root, branch and HEAD, hands over targets written
|
|
@@ -103,7 +107,7 @@ isolation. So `epic:next` is asked **with** `--lanes`, and everything below runs
|
|
|
103
107
|
switched".
|
|
104
108
|
|
|
105
109
|
**Report the throughput gain only with its merge-race cost** — every overlap that becomes a conflict
|
|
106
|
-
costs a resolution, a re-run gate and a review ("Conflicts are not predicted"
|
|
110
|
+
costs a resolution, a re-run gate and a review (`backlogrun-recovery.md` → "Conflicts are not predicted"). Rationale:
|
|
107
111
|
`docs/maintainers/backlogrun-lanes-rationale.md` → "Why lanes cost as well as buy throughput".
|
|
108
112
|
|
|
109
113
|
### Once per repository, before the first lane opens
|
|
@@ -205,71 +209,18 @@ lane is cut from.
|
|
|
205
209
|
|
|
206
210
|
### Conflicts are not predicted
|
|
207
211
|
|
|
208
|
-
**
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
already on `main` is resolved before the gate reads the tree. What this section covers is an overlap
|
|
212
|
-
that lands on `main` *after* it, which `followup` still reports as a conflict.
|
|
213
|
-
|
|
214
|
-
**Nothing here forecasts which children will overlap.** The overlap surfaces where GitHub already
|
|
215
|
-
reports it: a pull request that conflicts with its base comes back `mergeStateStatus: DIRTY`, which
|
|
216
|
-
`git-pr-checks-eval.ts` reads as a **failure** rather than polling through it — so `pnpm josh followup`
|
|
217
|
-
ends that child with a named conflict in about ten seconds.
|
|
218
|
-
|
|
219
|
-
**That child does not stop: it resolves the conflict in its own lane.** It is **not** counted against
|
|
220
|
-
the consecutive-failure guard either way.
|
|
221
|
-
|
|
222
|
-
**The merge direction is `origin/main` into the lane's branch, never a rebase**, and no step below
|
|
223
|
-
rewrites a pushed commit. Rationale: `docs/maintainers/backlogrun-lanes-rationale.md` → "Why a conflict
|
|
224
|
-
is resolved in the lane rather than handed to a person".
|
|
225
|
-
|
|
226
|
-
1. **Resolve in the lane.** `git fetch origin main`, merge `origin/main` into the lane's branch, resolve
|
|
227
|
-
in place. Do not close the lane, open another, or switch its branch.
|
|
228
|
-
2. **Re-run the whole gate.** The tree changed, so the green recorded before the conflict is void:
|
|
229
|
-
`pnpm josh lint:related` and `pnpm josh test:related`, then `pnpm josh gate`.
|
|
230
|
-
3. **Review the resolution, one round.** Brief it with `pnpm josh review:brief` and run `/code-review`
|
|
231
|
-
over the resolution diff, then require `pnpm josh review:attest --check` to answer `ok`. That round
|
|
232
|
-
is a different subject and does not spend one of the two the cap allows — `prompts/review.md` →
|
|
233
|
-
"Review round cap" carries the exception.
|
|
234
|
-
4. **Conclude the merge and push it, with `pnpm josh git -y`** — the only sanctioned way; without it
|
|
235
|
-
nothing changes on `origin` and condition 3 parks the child for good. **Record the resolution on the
|
|
236
|
-
Issue in this same step** — a comment naming the conflicting paths — because condition 3 counts
|
|
237
|
-
resolutions off the Issue comments, not off memory.
|
|
238
|
-
5. **Merge**, by re-running `pnpm josh followup` exactly as before.
|
|
239
|
-
|
|
240
|
-
**The safeguard is the re-run verification, not who holds the pen** — a conflict the run can resolve is
|
|
241
|
-
not routed to a person.
|
|
242
|
-
|
|
243
|
-
**The run steps back under these four conditions, and under no others. The list is exhaustive and
|
|
244
|
-
carries no judgement.**
|
|
245
|
-
|
|
246
|
-
1. **The resolution requires deleting the other side's change.** That decides intended behavior, not
|
|
247
|
-
text. It goes to the user as a **specification** question — "behavior A or behavior B" — never as a
|
|
248
|
-
diff.
|
|
249
|
-
2. **Both sides rewrote the same lines** — overlapping, not adjacent. Read off the structure of the
|
|
250
|
-
conflict hunks, so it needs no interpretation.
|
|
251
|
-
3. **A second conflict on the same child.** One resolution per child; the count is read off the Issue
|
|
252
|
-
comments step 4 writes, so it survives an interrupt.
|
|
253
|
-
4. **The re-run gate did not come back green, or the resolution review returned a High.** Not only a
|
|
254
|
-
High: a lint error, a failing test or a spell-check hit that merging a moved `main` introduced is
|
|
255
|
-
this condition too.
|
|
256
|
-
|
|
257
|
-
Meeting any of the four, the child is parked — `needs-decision` plus a comment naming which of the four
|
|
258
|
-
it was — and its lane is **kept**, because the pushed branch is the resume path (the table below).
|
|
259
|
-
|
|
260
|
-
**Leave the tree clean before parking: `git merge --abort` precedes a park under conditions 1, 2 or 4.**
|
|
261
|
-
Conditions 1 and 2 are read mid-merge with conflict markers still in the tree, condition 4 after a merge
|
|
262
|
-
that is resolved but not committed; condition 3 fires before any merge is started, so there is nothing
|
|
263
|
-
to abort.
|
|
212
|
+
**A child whose pull request conflicts with `main` resolves it in its own lane rather than stopping** —
|
|
213
|
+
read `backlogrun-recovery.md` → "Conflicts are not predicted" when `pnpm josh followup` reports the
|
|
214
|
+
conflict.
|
|
264
215
|
|
|
265
216
|
### What happens to a lane
|
|
266
217
|
|
|
267
218
|
| When | The lane | Why |
|
|
268
219
|
| --- | --- | --- |
|
|
269
220
|
| The child **merged** | `pnpm josh lane:close <N>` | `followup` released the hold and the branch is on `main`; nothing in that tree is wanted |
|
|
270
|
-
| The child was **parked before its commit** |
|
|
271
|
-
| The child was **parked after its commit and push** | **Left open**, its directory and held seat recorded on the Issue | The
|
|
272
|
-
| The child hit a **merge conflict** | **Left open** — the resolution happens in it | The child resolves in place ("Conflicts are not predicted"). A park under that section's four conditions takes the row above |
|
|
221
|
+
| The child was **parked before its commit** | **Left open**, its uncommitted work in place, its directory and held seat recorded on the Issue | The stash stack is shared by every work tree, so a parallel lane can pop another's entry — the tree itself is the safe place for the work. `lane:close` is a **forced** removal that would take it. `pnpm josh lane:launch <N>` dispatches the released child into the kept lane rather than refusing it as `already-open` — only a lane a child was already dispatched into; a failed-install lane is still refused |
|
|
222
|
+
| The child was **parked after its commit and push** | **Left open**, its directory and held seat recorded on the Issue | The tree is clean because committed. What `lane:close` would take is the **local branch**, which is the resume path |
|
|
223
|
+
| The child hit a **merge conflict** | **Left open** — the resolution happens in it | The child resolves in place (`backlogrun-recovery.md` → "Conflicts are not predicted"). A park under that section's four conditions takes the row above |
|
|
273
224
|
| The child stopped on **`needs-human-review`** | **Left open and untouched** | The uncommitted work *is* the artifact a person has to look at. Name the lane directory in the stop report and in the Telegram |
|
|
274
225
|
| The child **failed** | Whichever of the two parked rows applies, plus the consecutive-failure count | Same reasoning; only the counter differs. **A merge conflict is not this row** — it takes the row above, and it is not counted |
|
|
275
226
|
| **`lane:open` failed on the install** | `pnpm josh lane:close <N>`, then park the child | A lane exists that no `pnpm josh …` runs in and the next `lane:open` answers `already-open`. Closing frees the seat; parking is right because the cause is one a person fixes. Carry pnpm's reason into the park note |
|
|
@@ -278,7 +229,7 @@ to abort.
|
|
|
278
229
|
**A lane closed after a push is reopened by `pnpm josh lane:open <N>`**, which attaches to a local
|
|
279
230
|
`<N>-lane` or creates one from `origin/<N>-lane`, saying on standard error which it reused. **The branch
|
|
280
231
|
still has to have reached the remote for that to hold** — a child parked before its commit has nothing
|
|
281
|
-
on `origin`, which is why that row
|
|
232
|
+
on `origin`, which is why that row keeps its lane open rather than closing it. Rationale:
|
|
282
233
|
`docs/maintainers/backlogrun-lanes-rationale.md` → "Why a committed child's lane is kept".
|
|
283
234
|
|
|
284
235
|
**Which row a child takes is decided by what `followup` printed, not by reading the situation.** **What
|