@joshuafolkken/kit 1.1383.0 → 1.1435.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/skills/epic-commands/SKILL.md +1 -1
- package/.claude/skills/epic-commands/epic-bundle.md +5 -0
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +5 -3
- package/.claude/skills/workflow-commands/backlogrun-steps.md +4 -3
- package/.claude/skills/workflow-commands/backlogrun.md +1 -0
- package/.claude/skills/workflow-commands/chain-rule.md +4 -2
- package/.claude/skills/workflow-commands/issue-comments.md +6 -0
- package/.claude/skills/workflow-commands/observation-ledger.md +3 -2
- package/.claude/skills/workflow-commands/pre-gate-cut.md +5 -3
- package/README.md +25 -0
- package/dist/hooks/audit-provision.js +2 -2
- package/dist/hooks/batch-guard.js +7 -7
- package/dist/hooks/{chunk-LOJTBU5V.js → chunk-2G5F2YCD.js} +3 -3
- package/dist/hooks/{chunk-4MGHBTOM.js → chunk-3LE6VLSR.js} +25 -8
- package/dist/hooks/{chunk-Y5R47QHU.js → chunk-4BHUPFKF.js} +1 -1
- package/dist/hooks/{chunk-KC6LUZZ2.js → chunk-5SJSSCJG.js} +1 -1
- package/dist/hooks/{chunk-FZ6FUSBM.js → chunk-723HKZO5.js} +1 -1
- package/dist/hooks/{chunk-RYP3TSUJ.js → chunk-7KMN5QB5.js} +3 -3
- package/dist/hooks/{chunk-NEC4AT4Z.js → chunk-DGT54IH5.js} +4 -0
- package/dist/hooks/{chunk-YKUITFT7.js → chunk-EMB55BDF.js} +4 -4
- package/dist/hooks/{chunk-JBBMAPC4.js → chunk-IX6TTTI6.js} +4 -0
- package/dist/hooks/{chunk-6MAW7BCM.js → chunk-JXQBK323.js} +2677 -190
- package/dist/hooks/{chunk-KCF2YE7O.js → chunk-MSYSUSY6.js} +5 -5
- package/dist/hooks/{chunk-LC56R53A.js → chunk-MU4LJFIV.js} +4 -4
- package/dist/hooks/{chunk-7VSZ2N4B.js → chunk-QL6QTPWN.js} +3 -3
- package/dist/hooks/{chunk-TT742SIO.js → chunk-XER6SSIB.js} +92 -19
- package/dist/hooks/{chunk-2X2ART5G.js → chunk-YW452ZAX.js} +500 -29
- package/dist/hooks/{chunk-6AC4C2IO.js → chunk-YZXYOAZ3.js} +187 -443
- package/dist/hooks/codex-hook-adapter.js +15 -15
- package/dist/hooks/duplicate-read-guard.js +8 -8
- package/dist/hooks/format-edited.js +5 -5
- package/dist/hooks/inputs.json +262 -201
- package/dist/hooks/investigation-guard.js +8 -8
- package/dist/hooks/pretool-guard.js +14 -14
- package/dist/hooks/session-lang.js +124 -15
- package/dist/hooks/stop-guard.js +98 -55
- package/dist/josh.js +63 -10
- package/package.json +4 -3
- package/prompts/review.md +22 -0
- package/scripts/agent/claude-agent-argv.ts +13 -1
- package/scripts/auth/auth-setup-cli.ts +101 -0
- package/scripts/auth/claude-token-output.ts +78 -0
- package/scripts/auth/claude-token.ts +68 -0
- package/scripts/backlog/backlog-drive-cli.ts +2 -4
- package/scripts/backlog/backlog-drive-epic.ts +24 -8
- package/scripts/backlog/backlog-drive-launch.ts +5 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +7 -2
- package/scripts/backlog/backlog-drive-named.ts +4 -2
- package/scripts/backlog/backlog-drive-owner.ts +72 -5
- package/scripts/backlog/backlog-drive-unread.ts +56 -0
- package/scripts/backlog/backlog-drive.ts +16 -8
- package/scripts/backlog/backlog-overlap.ts +22 -5
- package/scripts/backlog/backlog-ready.ts +1 -3
- package/scripts/backlog/backlogrun-args.ts +13 -2
- package/scripts/backlog/backlogrun-cli.ts +91 -19
- package/scripts/backlog/backlogrun-launch.ts +80 -5
- package/scripts/backlog/backlogrun-replace.ts +166 -0
- package/scripts/backlog/backlogrun-stop.ts +178 -0
- package/scripts/behavior/behavior-cli.ts +6 -1
- package/scripts/doctor/doctor-io.ts +60 -9
- package/scripts/doctor/doctor.ts +20 -1
- package/scripts/document/document-byte-budget.ts +3 -3
- package/scripts/epic/epic-bundle-cli.ts +8 -8
- package/scripts/epic/epic-bundle-referenced.ts +2 -5
- package/scripts/epic/epic-bundle.ts +39 -4
- package/scripts/exports/unused-members-cli.ts +2 -1
- package/scripts/followup/followup-checks-event.ts +82 -0
- package/scripts/followup/git-followup-finish.ts +16 -2
- package/scripts/followup/git-followup-workflow.ts +5 -2
- package/scripts/followup/git-pr-followup-checks.ts +18 -4
- package/scripts/followup/git-pr-followup-wrapup.ts +5 -0
- package/scripts/followup/git-pr-followup.ts +4 -1
- package/scripts/fresh-machine/fresh-machine-cli.ts +204 -0
- package/scripts/fresh-machine/fresh-machine-docker.ts +65 -0
- package/scripts/fresh-machine/fresh-machine-image.ts +62 -0
- package/scripts/fresh-machine/fresh-machine-log.ts +61 -0
- package/scripts/fresh-machine/fresh-machine-patterns.ts +130 -0
- package/scripts/fresh-machine/fresh-machine-run.ts +215 -0
- package/scripts/fresh-machine/fresh-machine-script.ts +45 -0
- package/scripts/fresh-machine/fresh-machine-spec.ts +57 -0
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +34 -0
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +31 -0
- package/scripts/gate/gate-report.ts +70 -15
- package/scripts/gate/project-checks.ts +13 -2
- package/scripts/gate/scoped-green.ts +2 -1
- package/scripts/gate/verification-gate.ts +4 -3
- package/scripts/gh/gh-author-association.ts +14 -0
- package/scripts/gh/git-gh-conditional.ts +66 -0
- package/scripts/gh/git-gh-exec.ts +1 -1
- package/scripts/gh/git-gh-issue-read.ts +6 -3
- package/scripts/gh/git-gh-issue-write.ts +5 -1
- package/scripts/gh/git-gh-issue.ts +4 -1
- package/scripts/gh/git-pr-checks-eval.ts +13 -0
- package/scripts/gh/git-pr-checks-parse.ts +8 -1
- package/scripts/gh/git-pr-checks-watch.ts +11 -4
- package/scripts/gh/git-pr-checks.ts +36 -2
- package/scripts/git/git-command.ts +16 -4
- package/scripts/git/git-schemas.ts +1 -0
- package/scripts/git/git-spawn-sync.ts +1 -1
- package/scripts/hooks/pretool-guard.ts +3 -1
- package/scripts/init/hook-command-rewrite.ts +31 -0
- package/scripts/init/init-actions.ts +4 -1
- package/scripts/init/init-ai-copy.ts +33 -10
- package/scripts/init/init-basic.ts +8 -3
- package/scripts/init/init-logic-toolchain.ts +76 -0
- package/scripts/init/init-logic.ts +2 -0
- package/scripts/init/init.ts +5 -23
- package/scripts/init/project-profile.ts +36 -7
- package/scripts/init/start-exec.ts +27 -1
- package/scripts/init/start-plan.ts +30 -4
- package/scripts/init/start-steps.ts +77 -3
- package/scripts/init/start.ts +21 -13
- package/scripts/init/workflow-mark.ts +35 -0
- package/scripts/issue/issue-ack-cli.ts +84 -0
- package/scripts/issue/issue-labels.ts +40 -8
- package/scripts/issue/issue-state-cli.ts +14 -4
- package/scripts/issue/issue-watch-diff.ts +152 -0
- package/scripts/issue/issue-watch-gate.ts +81 -0
- package/scripts/issue/issue-watch-hook.ts +54 -0
- package/scripts/issue/issue-watch.ts +240 -0
- package/scripts/issue/measure-rerun-cli.ts +3 -4
- package/scripts/josh/josh-command-map.ts +4 -0
- package/scripts/josh/josh-commands-backlog.ts +2 -2
- package/scripts/josh/josh-commands-development.ts +1 -1
- package/scripts/josh/josh-commands-issue.ts +7 -0
- package/scripts/josh/josh-commands-lane.ts +11 -2
- package/scripts/josh/josh-commands-project.ts +25 -1
- package/scripts/josh/josh-verdict.ts +33 -4
- package/scripts/lane/claude-lane-broker.ts +142 -0
- package/scripts/lane/lane-await.ts +6 -2
- package/scripts/lane/lane-cache.ts +37 -7
- package/scripts/lane/lane-capacity.ts +8 -6
- package/scripts/lane/lane-child-invocation.ts +1 -0
- package/scripts/lane/lane-cli.ts +15 -1
- package/scripts/lane/lane-close.ts +15 -6
- package/scripts/lane/lane-dispatch.ts +36 -10
- package/scripts/lane/lane-environment.ts +1 -1
- package/scripts/lane/lane-launch-cli.ts +13 -4
- package/scripts/lane/lane-ledger.ts +21 -3
- package/scripts/lane/lane-measure-cli.ts +10 -2
- package/scripts/lane/lane-open.ts +9 -1
- package/scripts/lane/lane-preserve.ts +49 -0
- package/scripts/lane/lane-reap.ts +20 -5
- package/scripts/lane/lane-registry.ts +6 -0
- package/scripts/lane/lane-restart-cli.ts +51 -0
- package/scripts/lane/lane-restart.ts +175 -0
- package/scripts/lane/{openai-review-broker.ts → lane-session-broker.ts} +106 -28
- package/scripts/lane/lane-spent.ts +195 -0
- package/scripts/lane/lane-stage-stats.ts +27 -3
- package/scripts/lane/lane-stop-stats.ts +96 -0
- package/scripts/lane/openai-lane-supervisor.ts +2 -2
- package/scripts/lane/process-tools.ts +31 -0
- package/scripts/lib/buffered-process.ts +36 -2
- package/scripts/lib/pnpm-reach.ts +27 -0
- package/scripts/lib/status-icons.ts +5 -1
- package/scripts/lint/lint-parallel.ts +19 -2
- package/scripts/observations/observation-ledger-home.ts +1 -0
- package/scripts/review/review-attest-cli.ts +21 -6
- package/scripts/review/review-brief-cli.ts +2 -2
- package/scripts/review/review-comment-round.ts +114 -0
- package/scripts/review/review-record-cli.ts +39 -17
- package/scripts/rules/implementation-cut.ts +3 -3
- package/scripts/rules/pre-gate-cut.ts +1 -1
- package/scripts/run/board/run-board-checks.ts +42 -0
- package/scripts/run/board/run-board-cli.ts +2 -0
- package/scripts/run/board/run-board-every.ts +3 -1
- package/scripts/run/board/run-board-fit.ts +16 -5
- package/scripts/run/board/run-board-fresh.ts +64 -0
- package/scripts/run/board/run-board-header.ts +139 -37
- package/scripts/run/board/run-board-labels.ts +47 -4
- package/scripts/run/board/run-board-lane-event.ts +66 -0
- package/scripts/run/board/run-board-layout.ts +57 -9
- package/scripts/run/board/run-board-now.ts +234 -0
- package/scripts/run/board/run-board-operation-read.ts +75 -0
- package/scripts/run/board/run-board-operation.ts +150 -0
- package/scripts/run/board/run-board-phase.ts +26 -1
- package/scripts/run/board/run-board-plan.ts +4 -6
- package/scripts/run/board/run-board-read.ts +58 -5
- package/scripts/run/board/run-board-reason.ts +124 -0
- package/scripts/run/board/run-board-render-checks.ts +55 -0
- package/scripts/run/board/run-board-render-legend.ts +12 -3
- package/scripts/run/board/run-board-render-slot.ts +2 -2
- package/scripts/run/board/run-board-render-tail.ts +128 -0
- package/scripts/run/board/run-board-render-thanks.ts +50 -0
- package/scripts/run/board/run-board-render-title.ts +58 -0
- package/scripts/run/board/run-board-render.ts +96 -80
- package/scripts/run/board/run-board-row-yield.ts +32 -0
- package/scripts/run/board/run-board-setup.ts +121 -0
- package/scripts/run/board/run-board-span.ts +49 -7
- package/scripts/run/board/run-board-state.ts +10 -0
- package/scripts/run/board/run-board-status.ts +76 -13
- package/scripts/run/board/run-board-thanks-csv.ts +71 -0
- package/scripts/run/board/run-board-thanks-read.ts +112 -0
- package/scripts/run/board/run-board-thanks.ts +53 -0
- package/scripts/run/board/run-board-tick.ts +53 -16
- package/scripts/run/board/run-board-usual.ts +44 -0
- package/scripts/run/carry/run-carry-added.ts +1 -1
- package/scripts/run/carry/run-carry-args.ts +9 -1
- package/scripts/run/carry/run-carry-change.ts +1 -1
- package/scripts/run/carry/run-carry-cli.ts +39 -52
- package/scripts/run/carry/run-carry-end.ts +73 -0
- package/scripts/run/carry/run-carry-ended.ts +9 -1
- package/scripts/run/carry/run-carry.ts +24 -1
- package/scripts/run/entry/run-entry-cli.ts +5 -0
- package/scripts/run/event/run-event-checks.ts +54 -0
- package/scripts/run/event/run-event-render.ts +3 -0
- package/scripts/run/event/run-event-scope.ts +1 -0
- package/scripts/run/event/run-event-setup.ts +91 -0
- package/scripts/run/event/run-event-stream.ts +46 -9
- package/scripts/run/merge/run-merge-cli.ts +7 -4
- package/scripts/run/merge/run-merge-ship.ts +61 -0
- package/scripts/run/merge/run-merge-steps.ts +7 -14
- package/scripts/run/merge/run-merge-token.ts +16 -2
- package/scripts/run/run-headless.ts +1 -0
- package/scripts/run/run-step.ts +2 -0
- package/scripts/run/run-stranded-detect.ts +58 -12
- package/scripts/run/ship/run-ship-cli.ts +22 -2
- package/scripts/run/ship/run-ship-return.ts +31 -13
- package/scripts/run/ship/run-ship-review-steps.ts +17 -4
- package/scripts/run/ship/run-ship-stage.ts +1 -0
- package/scripts/run/wake/run-wake-await.ts +130 -0
- package/scripts/run/wake/run-wake-cli.ts +108 -74
- package/scripts/run/wake/run-wake-describe.ts +36 -2
- package/scripts/run/wake/run-wake-driver.ts +21 -5
- package/scripts/run/wake/run-wake-handoff.ts +1 -1
- package/scripts/run/wake/run-wake-session.ts +20 -3
- package/scripts/run/wake/run-wake-stop.ts +37 -0
- package/scripts/run/wake/run-wake-supervise.ts +44 -0
- package/scripts/sync/claude-settings-merge.ts +144 -0
- package/scripts/sync/sync-ai-files.ts +28 -3
- package/scripts/sync/sync.ts +15 -0
- package/scripts/test/project-test-script.ts +73 -0
- package/scripts/test/skip-marker.ts +14 -1
- package/scripts/test/test-related.ts +3 -2
- package/scripts/test/test-unit-guard.ts +78 -14
- package/scripts/time-runtime/time-reported-failure.ts +11 -3
- package/scripts/uninstall/distributed-files.ts +92 -0
- package/scripts/uninstall/uninstall-plan.ts +119 -0
- package/scripts/uninstall/uninstall-report.ts +61 -0
- package/scripts/uninstall/uninstall.ts +206 -0
- package/templates/AGENTS.basic.md +4 -0
- package/templates/GEMINI.basic.md +6 -0
- package/dist/hooks/chunk-6V5OPIUU.js +0 -13
- package/scripts/run/board/run-board-track.ts +0 -22
|
@@ -150,7 +150,7 @@ worked form.
|
|
|
150
150
|
|
|
151
151
|
**An `in-progress` issue occupies a lane rather than the whole repository.** The occupancy is counted
|
|
152
152
|
from that repository's own `in-progress` listing — never from anything the session remembers — and
|
|
153
|
-
what is left of `JOSH_LANE_LIMIT` (**default
|
|
153
|
+
what is left of `JOSH_LANE_LIMIT` (**default 4**) is what gets offered. At zero the answer is `wait`
|
|
154
154
|
and the holders are named on standard error. A parked child releases its lane; one stopped by
|
|
155
155
|
`needs-human-review` goes on holding one, because its uncommitted work is still in that checkout.
|
|
156
156
|
|
|
@@ -9,6 +9,11 @@ settle. `Nothing to bundle.` needs neither.
|
|
|
9
9
|
already recorded between them. **A similar title never counts on its own** — "related" expands
|
|
10
10
|
without limit, and the threshold is what keeps an unrelated issue out.
|
|
11
11
|
|
|
12
|
+
**The release issue is neither a candidate nor a subject**, like an epic. `issue:file --release` records
|
|
13
|
+
every change awaiting publication as its blocker, so that relation is mechanical, not a sign of shared
|
|
14
|
+
work. Counted as a signal, it would put the release and an unrelated change in one epic. A
|
|
15
|
+
`blocked-by` or a prose reference between any other two issues still counts.
|
|
16
|
+
|
|
12
17
|
**The search is not limited to the open backlog.** Every issue number the subject's body names is read
|
|
13
18
|
on its own, whatever its state. A **closed** reference counts only when an open epic already tracks
|
|
14
19
|
it, since the answer worth recovering is `add_to_epic`; an epic created over a closed issue has
|
|
@@ -113,9 +113,10 @@ The bullets below describe that dispatch:
|
|
|
113
113
|
trace alone**, because its log will never grow.
|
|
114
114
|
- **The child is started as `fullrun #<N>` with the lane as its working directory.** The batch a
|
|
115
115
|
person approved by typing `backlogrun` covers the child.
|
|
116
|
-
- **It
|
|
117
|
-
`.claude/settings.json`
|
|
118
|
-
|
|
116
|
+
- **It passes `--permission-mode bypassPermissions`, never `--dangerously-skip-permissions`.** A
|
|
117
|
+
current Claude Code ignores the mode `.claude/settings.json` declares, and a new lane worktree is
|
|
118
|
+
never a trusted workspace; that file's `deny` list still refuses what it names, so the run reports
|
|
119
|
+
what stopped rather than loosening it.
|
|
119
120
|
|
|
120
121
|
**Start each child without blocking on it, and poll them all** — a silent one is
|
|
121
122
|
`backlogrun-recovery.md` → "A delegated unit that stopped without reporting", read in that child's
|
|
@@ -142,6 +143,7 @@ conflict.
|
|
|
142
143
|
| 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 |
|
|
143
144
|
| 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 |
|
|
144
145
|
| **`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 |
|
|
146
|
+
| The lane is **spent** — no child working in it, its Issue closed, not one this run launched and has not collected with `run:merge`, a clean tree, no commit that is on no remote | Nothing to do — `pnpm josh lane:prune` closes it | Nothing in it is wanted, so no one has to type the close. Any other lane is kept and `lane:prune` says why on standard error |
|
|
145
147
|
| The run was **interrupted** | Nothing to do — the work tree survives on disk | The next session's `pnpm josh lane:prune` closes what git no longer has a tree for. **Park that child**, naming the lane and `pnpm josh lane:close <N>` as the way out |
|
|
146
148
|
|
|
147
149
|
**A lane closed after a push is reopened by `pnpm josh lane:open <N>`**, which attaches to a local
|
|
@@ -61,7 +61,7 @@ resumed session runs `remaining` from `--json`. The contract is `docs/josh-comma
|
|
|
61
61
|
```bash
|
|
62
62
|
pnpm josh run:carry --begin "backlogrun --max 5 --idle 30" --owner "$PPID"
|
|
63
63
|
pnpm josh run:carry --json # read it back in a resumed session
|
|
64
|
-
pnpm josh run:wake --start # same turn as --begin
|
|
64
|
+
pnpm josh run:wake --start # same turn as --begin; `running` under `josh backlogrun`
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
**Always pass `--owner "$PPID"`**, and ask it before the plan, in the same turn as the first `pnpm josh
|
|
@@ -85,7 +85,8 @@ named epic's children", never the root as a standalone `fullrun`, then ask `pnpm
|
|
|
85
85
|
a child number or `complete` continues; only `stop` or a failure records `pnpm josh run:carry --done <E>
|
|
86
86
|
--owner "$PPID"`.
|
|
87
87
|
|
|
88
|
-
**A person keeps control of the
|
|
88
|
+
**A person keeps control of the run** — `pnpm josh run:wake --list` reads it, `pnpm josh backlogrun
|
|
89
|
+
--stop` stops it (`docs/josh-commands.md` → "`josh backlogrun`").
|
|
89
90
|
|
|
90
91
|
Rationale: `docs/maintainers/backlogrun-steps-rationale.md` → "Why a session cut does not end the run"
|
|
91
92
|
|
|
@@ -129,7 +130,7 @@ section the row names:
|
|
|
129
130
|
| Handed back | What the session does | Read |
|
|
130
131
|
| --- | --- | --- |
|
|
131
132
|
| `triage` | Label each issue stderr names `run:solo` or `run:lane` (`blocked-by` where one must land first) | "Resolve what the plan can resolve, before starting" above |
|
|
132
|
-
| `offer` | Report what stderr printed; **never pick an issue by hand** | — |
|
|
133
|
+
| `offer` | Report what stderr printed — a failed offer, or a named issue whose state stayed unreadable; **never pick an issue by hand** | — |
|
|
133
134
|
| `launch #N` | Read the lane's log and park `#N` | `backlogrun-park.md` → "park and continue" |
|
|
134
135
|
| `merge [<token>] #N` | `environment` ends the run; the others re-read the child | `backlogrun-progress.md` → "Running a named epic's children" |
|
|
135
136
|
| `epic #N` | A named epic's turn | "The session cut is inside the invocation" above |
|
|
@@ -46,6 +46,7 @@ is still that one invocation (`backlogrun-steps.md` → "The session cut is insi
|
|
|
46
46
|
session only when it needs judgment.
|
|
47
47
|
7. **End the record when the run ends** — `run:report`, then `run:carry --end` (or `--end --stopped
|
|
48
48
|
"<reason>"`) and `run:wake --stop`. An empty plan is not that end; the driver's idle watch decides it.
|
|
49
|
+
A person stops a run from the terminal with `pnpm josh backlogrun --stop`, which makes both calls.
|
|
49
50
|
|
|
50
51
|
## The route table
|
|
51
52
|
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
This is the execution contract for `fullrun` and `backlogrun`, and for `prrun` up to the pull request: a `prrun` never issues `pnpm josh ship` or a merging `pnpm josh followup` — it opens the pull request with `pnpm josh git -y` and ends by `prrun.md` → "The difference — the end of the run". The record below is reference only.
|
|
6
6
|
Review results and successful pushes are never turn boundaries.
|
|
7
7
|
|
|
8
|
-
0. **A lane child**: `pnpm josh main:merge`, the
|
|
8
|
+
0. **A lane child**: `pnpm josh main:merge`, the self-check (`prompts/review.md` → "Before round 1 —
|
|
9
|
+
the implementer's self-check"), the scoped pair, `pnpm josh ship --detach --review
|
|
9
10
|
"<title> #<N>"` (`--cite <N>`), then **end the turn** on `launched`/`busy`. A stop relaunches a child
|
|
10
11
|
whose prompt names `pnpm josh ship --log <N>` and (Anthropic lane) the re-detach to run after
|
|
11
12
|
the fix — `pnpm josh ship --detach`, `--review` only if the stopped ship carried it and stopped before
|
|
@@ -13,7 +14,8 @@ Review results and successful pushes are never turn boundaries.
|
|
|
13
14
|
`failed` → step 1. A backgrounded `ship` issued alone is moved to the foreground by the hook
|
|
14
15
|
rather than refused.
|
|
15
16
|
1. Run `pnpm josh main:merge`. **Then issue `pnpm josh run:cut <N>` alone, before the scoped pair and
|
|
16
|
-
the gate** — the pre-gate cut (a no-op outside a lane). Then
|
|
17
|
+
the gate** — the pre-gate cut (a no-op outside a lane). Then answer the self-check
|
|
18
|
+
(`prompts/review.md` → "Before round 1 — the implementer's self-check"), run the final scoped lint/test pair and
|
|
17
19
|
`pnpm josh run:review`: it starts `pnpm josh gate` in the background and prints the `/code-review`
|
|
18
20
|
brief in one call, so the two overlap. Launch the `/code-review` subagent as the `general-purpose`
|
|
19
21
|
agent type with that brief (every tool, so `--fix` applies; never a guessed type name).
|
|
@@ -91,3 +91,9 @@ never the comment text.
|
|
|
91
91
|
**`pnpm josh rule:guard` refuses the body-only read** and hands over the reissue and the conflict rule
|
|
92
92
|
at the moment they bind (`prompts/collaboration-workflow/rule-delivery.md`). **This file is the rule,
|
|
93
93
|
not the hook** — a session that runs no hooks still owes the read.
|
|
94
|
+
|
|
95
|
+
## A person's update mid-run
|
|
96
|
+
|
|
97
|
+
When the hook, `review:attest --check` or `followup` shows an Issue update, read it as above — the
|
|
98
|
+
later text is in force — fix what it changes, then `pnpm josh issue:ack <N>`. The watch and what it
|
|
99
|
+
does not catch: `docs/josh-commands-backlog.md` → "`josh issue:ack`".
|
|
@@ -106,8 +106,9 @@ could not.
|
|
|
106
106
|
and appends nothing. That round reads only, so no commit of the run's follows it; a line in the tree
|
|
107
107
|
would be pushed onto the open pull request and its CI would start over. `pnpm josh ship --review`
|
|
108
108
|
does this for a passing round 2. **A round 2 that blocks records in the tree as before** — the fix it
|
|
109
|
-
stops for is pushed anyway and carries the lines.
|
|
110
|
-
|
|
109
|
+
stops for is pushed anyway and carries the lines. Once the Issue is closed, the next round recorded
|
|
110
|
+
to the ledger carries the comment's lines into `<N>-comment-rounds.md` with its own commit, so
|
|
111
|
+
`pnpm josh review:findings` and the retrospective count them (`review-comment-round.ts`).
|
|
111
112
|
- **`pnpm josh followup` commits any other line appended after the run's commit onto the pull request,
|
|
112
113
|
before the merge** — the residual path, for an observation recorded between the commit and the
|
|
113
114
|
merge. After the merge gates and before the CI wait, `followup` reads the tree and, **only when the
|
|
@@ -169,9 +169,11 @@ built for the lane child.
|
|
|
169
169
|
**The trigger**: `pnpm josh rule:guard` refuses an `Edit` / `Write` in a dispatched lane child whose
|
|
170
170
|
recent-context cost is over threshold, handing back `pnpm josh run:cut --impl <N> --handoff <path>`.
|
|
171
171
|
`cut` ends the turn; a fresh process's `run:cut --resume <N>` answers `resume-impl` and continues
|
|
172
|
-
implementation — **the implementation resume clears the record**, so the cut may fire again.
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
implementation — **the implementation resume clears the record**, so the cut may fire again. **A cut
|
|
173
|
+
that relaunches its successor owes no Telegram**, the pre-gate cut as much as this one: nobody has
|
|
174
|
+
anything to act on, and a resume answering `stale` / `busy` sends its own. Outside a lane nothing is
|
|
175
|
+
relaunched, so `run:cut --impl` prints the held run's instruction — on a measured `over` that run
|
|
176
|
+
keeps the hold, sends a `confirmation` Telegram naming `fullrun #<N>` and ends the turn. The refusal states the rest — **It fires on every threshold crossing,
|
|
175
177
|
not once per run**; **An edit reissued right after a refusal passes**; **An unmeasurable session
|
|
176
178
|
warrants the cut**; **It is silent between a cut and its resume**. Rationale:
|
|
177
179
|
`docs/maintainers/pre-gate-cut-rationale.md` → "Why the rules are guards, not prose";
|
package/README.md
CHANGED
|
@@ -35,6 +35,16 @@ pnpm exec josh start
|
|
|
35
35
|
|
|
36
36
|
Next: [tutorial](./docs/tutorial.md)
|
|
37
37
|
|
|
38
|
+
### Your first backlogrun
|
|
39
|
+
|
|
40
|
+
Tell the agent the change you want, then type `kickoff new auto ok` to it (or add the `auto-ok` label to an existing Issue).
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm josh backlogrun
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Details: [Run the backlog unattended](./docs/how-to/run-backlog.md)
|
|
47
|
+
|
|
38
48
|
### AI assistant only — no GitHub account needed
|
|
39
49
|
|
|
40
50
|
Requires [Node.js and pnpm](./docs/setup/prerequisites.md).
|
|
@@ -45,6 +55,21 @@ pnpm --allow-build=esbuild dlx @joshuafolkken/kit init
|
|
|
45
55
|
|
|
46
56
|
Next: [tutorial](./docs/tutorial.md#without-github-one-change-checked-locally)
|
|
47
57
|
|
|
58
|
+
## Claude Code in a fresh-machine run
|
|
59
|
+
|
|
60
|
+
A [`josh fresh:run`](./docs/maintainers/fresh-machine.md) scenario that runs Claude Code needs a sign-in, saved once:
|
|
61
|
+
|
|
62
|
+
1. In a terminal at the kit repository, run:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm josh auth:setup
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
2. A browser opens: sign in with your Claude account and press "Authorize".
|
|
69
|
+
3. Done when the terminal prints `saved: CLAUDE_CODE_OAUTH_TOKEN (macOS keychain)`. There is no token to copy or write into a file.
|
|
70
|
+
4. To check, run `pnpm josh auth:setup --check`: it prints `ok` and the day it was saved.
|
|
71
|
+
5. When the token expires, Claude Code in the container fails to sign in — start again from step 1.
|
|
72
|
+
|
|
48
73
|
## Docs
|
|
49
74
|
|
|
50
75
|
[How-to](./docs/how-to.md) · [All docs](./docs/overview.md)
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import {
|
|
3
3
|
timed_fetch
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-723HKZO5.js";
|
|
5
5
|
import {
|
|
6
6
|
error_text
|
|
7
7
|
} from "./chunk-CDY4NFQG.js";
|
|
8
8
|
import {
|
|
9
9
|
PROJECT_ROOT,
|
|
10
10
|
stamp_file
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-DGT54IH5.js";
|
|
12
12
|
|
|
13
13
|
// scripts/security/security-audit-provision.ts
|
|
14
14
|
import { chmodSync, mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
load_environment_file,
|
|
10
10
|
notice_refusal_path,
|
|
11
11
|
refusal_path
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-7KMN5QB5.js";
|
|
13
|
+
import "./chunk-5SJSSCJG.js";
|
|
14
|
+
import "./chunk-MU4LJFIV.js";
|
|
15
|
+
import "./chunk-XER6SSIB.js";
|
|
16
|
+
import "./chunk-4BHUPFKF.js";
|
|
17
|
+
import "./chunk-3LE6VLSR.js";
|
|
18
|
+
import "./chunk-DGT54IH5.js";
|
|
19
19
|
export {
|
|
20
20
|
DISABLED_VALUES,
|
|
21
21
|
SWITCH_ENV_KEY,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
investigation_reads
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QL6QTPWN.js";
|
|
4
4
|
import {
|
|
5
5
|
lane_guard_policy
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-5SJSSCJG.js";
|
|
7
7
|
import {
|
|
8
8
|
hook_decision
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MU4LJFIV.js";
|
|
10
10
|
|
|
11
11
|
// scripts/delegation/investigation-guard.ts
|
|
12
12
|
import { text } from "node:stream/consumers";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
PROBE_TIMEOUT_MS,
|
|
5
5
|
SUITE_TIMEOUT_MS,
|
|
6
6
|
stamp_file
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DGT54IH5.js";
|
|
8
8
|
|
|
9
9
|
// scripts/lib/json-value.ts
|
|
10
10
|
function parse_or_undefined(text) {
|
|
@@ -511,12 +511,19 @@ async function commit(message) {
|
|
|
511
511
|
async function delete_branch(branch_name) {
|
|
512
512
|
await git_spawn.read(["branch", "-d", branch_name]);
|
|
513
513
|
}
|
|
514
|
-
async function
|
|
515
|
-
const
|
|
516
|
-
const output = await git_spawn.read(["rev-list", "--count", range]);
|
|
514
|
+
async function read_commit_count(revisions) {
|
|
515
|
+
const output = await git_spawn.read(["rev-list", "--count", ...revisions]);
|
|
517
516
|
const parsed = Number(output);
|
|
518
517
|
if (output.length > 0 && Number.isFinite(parsed)) return parsed;
|
|
519
|
-
throw new Error(
|
|
518
|
+
throw new Error(
|
|
519
|
+
`\`git rev-list --count ${revisions.join(" ")}\` printed \`${output}\` rather than a count`
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
async function commit_count_beyond(base, tip) {
|
|
523
|
+
return await read_commit_count([`${base}..${tip}`]);
|
|
524
|
+
}
|
|
525
|
+
async function commit_count_unpushed(branch_name) {
|
|
526
|
+
return await read_commit_count([branch_name, "--not", "--remotes"]);
|
|
520
527
|
}
|
|
521
528
|
function is_exit_code_128(cause) {
|
|
522
529
|
return typeof cause === "object" && cause !== null && "exit_code" in cause && cause.exit_code === "128";
|
|
@@ -633,6 +640,7 @@ var git_command = {
|
|
|
633
640
|
checkout,
|
|
634
641
|
commit,
|
|
635
642
|
commit_count_beyond,
|
|
643
|
+
commit_count_unpushed,
|
|
636
644
|
delete_branch,
|
|
637
645
|
push: push2,
|
|
638
646
|
pull_fast_forward,
|
|
@@ -1341,7 +1349,7 @@ function next_added(carry, additions) {
|
|
|
1341
1349
|
}
|
|
1342
1350
|
function add_issues(target, carry, additions) {
|
|
1343
1351
|
const next = { ...carry, added: next_added(carry, additions) };
|
|
1344
|
-
stamp_file.
|
|
1352
|
+
stamp_file.replace_stamp(target, next);
|
|
1345
1353
|
return next;
|
|
1346
1354
|
}
|
|
1347
1355
|
var run_carry_added = { add_issues, ordered };
|
|
@@ -1434,7 +1442,7 @@ function apply_change(target, carry, change, now = /* @__PURE__ */ new Date()) {
|
|
|
1434
1442
|
done: next_done(carry, effective.done),
|
|
1435
1443
|
retrospective: effective.retrospective === true || carry.retrospective
|
|
1436
1444
|
};
|
|
1437
|
-
stamp_file.
|
|
1445
|
+
stamp_file.replace_stamp(target, next);
|
|
1438
1446
|
return next;
|
|
1439
1447
|
}
|
|
1440
1448
|
var run_carry_change = { apply_change };
|
|
@@ -2049,6 +2057,7 @@ var run_carry_schema = z2.object({
|
|
|
2049
2057
|
owner_pid: z2.number().optional(),
|
|
2050
2058
|
owner_start: z2.string().optional(),
|
|
2051
2059
|
owner_transcript: z2.string().optional(),
|
|
2060
|
+
is_owner_headless: z2.boolean().optional(),
|
|
2052
2061
|
is_handed_off: z2.boolean().optional(),
|
|
2053
2062
|
done: z2.array(z2.number()).optional(),
|
|
2054
2063
|
retrospective: z2.boolean().optional(),
|
|
@@ -2090,7 +2099,8 @@ function fresh_carry(invocation, owner, now) {
|
|
|
2090
2099
|
outages: NO_INCREMENT3,
|
|
2091
2100
|
owner_pid: owner.pid,
|
|
2092
2101
|
owner_start: owner.start,
|
|
2093
|
-
owner_transcript: owner.transcript
|
|
2102
|
+
owner_transcript: owner.transcript,
|
|
2103
|
+
is_owner_headless: owner.is_headless
|
|
2094
2104
|
};
|
|
2095
2105
|
}
|
|
2096
2106
|
function begin_carry(target, invocation, owner = NO_OWNER, now = /* @__PURE__ */ new Date()) {
|
|
@@ -2103,6 +2113,7 @@ function adopt_carry(target, carry, owner = NO_OWNER) {
|
|
|
2103
2113
|
owner_pid: owner.pid,
|
|
2104
2114
|
owner_start: owner.start,
|
|
2105
2115
|
owner_transcript: owner.transcript,
|
|
2116
|
+
is_owner_headless: owner.is_headless,
|
|
2106
2117
|
is_handed_off: false
|
|
2107
2118
|
};
|
|
2108
2119
|
stamp_file.remove_stamp(target);
|
|
@@ -2119,6 +2130,11 @@ function is_owned_by(carry, owner) {
|
|
|
2119
2130
|
function is_foreign_live_owner(carry, owner) {
|
|
2120
2131
|
return is_owner_live(carry) && !is_owned_by(carry, owner);
|
|
2121
2132
|
}
|
|
2133
|
+
function is_held_by_another(carry, is_live = is_owner_live) {
|
|
2134
|
+
const caller = owner_of(process.pid);
|
|
2135
|
+
const is_own = carry.owner_pid === caller.pid && carry.owner_start === caller.start;
|
|
2136
|
+
return !is_own && is_live(carry);
|
|
2137
|
+
}
|
|
2122
2138
|
function is_handed_off_to(carry, invocation) {
|
|
2123
2139
|
return carry.is_handed_off === true && carry.invocation === invocation;
|
|
2124
2140
|
}
|
|
@@ -2205,6 +2221,7 @@ var run_carry = {
|
|
|
2205
2221
|
fresh_carry,
|
|
2206
2222
|
is_count_refused,
|
|
2207
2223
|
is_foreign_live_owner,
|
|
2224
|
+
is_held_by_another,
|
|
2208
2225
|
is_owner_live,
|
|
2209
2226
|
lost_message,
|
|
2210
2227
|
nothing_to_resume_message,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_guard_policy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5SJSSCJG.js";
|
|
4
4
|
import {
|
|
5
5
|
hook_decision
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MU4LJFIV.js";
|
|
7
7
|
import {
|
|
8
8
|
time_batch_guard
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XER6SSIB.js";
|
|
10
10
|
|
|
11
11
|
// scripts/hooks/batch-guard.ts
|
|
12
12
|
import { text } from "node:stream/consumers";
|
|
@@ -3,6 +3,9 @@ import path from "node:path";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
var PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
5
5
|
var PROJECT_ROOT = process.cwd();
|
|
6
|
+
function package_path(relative_path) {
|
|
7
|
+
return path.join(PACKAGE_DIR, relative_path);
|
|
8
|
+
}
|
|
6
9
|
|
|
7
10
|
// scripts/josh/stamp-file.ts
|
|
8
11
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -144,6 +147,7 @@ var SUITE_TIMEOUT_MS = 18e5;
|
|
|
144
147
|
|
|
145
148
|
export {
|
|
146
149
|
PROJECT_ROOT,
|
|
150
|
+
package_path,
|
|
147
151
|
PLATFORM_TEMP_ROOT,
|
|
148
152
|
platform_temporary,
|
|
149
153
|
stamp_file,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolve_local_bin,
|
|
3
3
|
resolve_package_bin
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IX6TTTI6.js";
|
|
5
5
|
import {
|
|
6
6
|
ESLINT_EDIT_CACHE_FLAGS,
|
|
7
7
|
time_density_hook
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-XER6SSIB.js";
|
|
9
9
|
import {
|
|
10
10
|
file_reader,
|
|
11
11
|
json_value
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3LE6VLSR.js";
|
|
13
13
|
import {
|
|
14
14
|
HOOK_PROCESS_TIMEOUT_MS
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-DGT54IH5.js";
|
|
16
16
|
|
|
17
17
|
// scripts/hooks/format-edited-file.ts
|
|
18
18
|
import { existsSync as existsSync2 } from "node:fs";
|
|
@@ -85,6 +85,10 @@ function resolve_package_bin(base_directory, package_name, bin_name) {
|
|
|
85
85
|
|
|
86
86
|
export {
|
|
87
87
|
ancestor_directories,
|
|
88
|
+
vscode_settings_schema,
|
|
89
|
+
json_object_schema,
|
|
90
|
+
string_array_schema,
|
|
91
|
+
string_record_schema,
|
|
88
92
|
resolve_local_bin,
|
|
89
93
|
find_local_bin_upwards,
|
|
90
94
|
resolve_package_bin
|