@joshuafolkken/kit 1.957.0 → 1.978.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/.claude/skills/workflow-commands/background-commands.md +3 -0
  2. package/.claude/skills/workflow-commands/backlogrun-child.md +75 -120
  3. package/.claude/skills/workflow-commands/backlogrun-lanes.md +78 -115
  4. package/.claude/skills/workflow-commands/backlogrun-progress.md +82 -146
  5. package/.claude/skills/workflow-commands/backlogrun-steps.md +173 -229
  6. package/.claude/skills/workflow-commands/backlogrun.md +3 -1
  7. package/.claude/skills/workflow-commands/followup.md +3 -0
  8. package/.claude/skills/workflow-commands/fullrun.md +4 -4
  9. package/.claude/skills/workflow-commands/halfrun.md +12 -7
  10. package/.claude/skills/workflow-commands/observation-filing.md +31 -25
  11. package/.claude/skills/workflow-commands/pre-gate-cut.md +96 -161
  12. package/.claude/skills/workflow-commands/working-tree-hold.md +16 -1
  13. package/.github/workflows/pr-classification.yml +12 -1
  14. package/CLAUDE.md +3 -3
  15. package/README.md +25 -21
  16. package/dist/CLAUDE.md +3 -3
  17. package/dist/hooks/batch-guard.js +4 -4
  18. package/dist/hooks/{chunk-XSL4SRMA.js → chunk-2K52BRWV.js} +2 -2
  19. package/dist/hooks/{chunk-M6K7EQDO.js → chunk-BNGGEY3Z.js} +38 -32
  20. package/dist/hooks/{chunk-KOCK5FXQ.js → chunk-BVMSPG3M.js} +3 -3
  21. package/dist/hooks/{chunk-3ON7HOYB.js → chunk-CRGJTD6E.js} +1 -1
  22. package/dist/hooks/{chunk-HJXQZ7V4.js → chunk-F6OM6SIG.js} +3 -3
  23. package/dist/hooks/{chunk-LDQDZYHX.js → chunk-KQG4776P.js} +1 -1
  24. package/dist/hooks/{chunk-244WYOEO.js → chunk-NXL3SBXY.js} +2 -2
  25. package/dist/hooks/{chunk-IJPBTDTB.js → chunk-Q7LE77CO.js} +88 -18
  26. package/dist/hooks/{chunk-BELI5XSS.js → chunk-ZPLXLJ7O.js} +15 -5
  27. package/dist/hooks/{chunk-GNOITLRR.js → chunk-ZYYSBNR6.js} +4 -4
  28. package/dist/hooks/codex-hook-adapter.js +10 -10
  29. package/dist/hooks/duplicate-read-guard.js +5 -5
  30. package/dist/hooks/format-edited.js +2 -2
  31. package/dist/hooks/investigation-guard.js +5 -5
  32. package/dist/hooks/pretool-guard.js +9 -9
  33. package/dist/hooks/stop-guard.js +206 -176
  34. package/dist/josh.js +8 -4
  35. package/package.json +4 -4
  36. package/prompts/collaboration-workflow/wip-cap.md +1 -1
  37. package/scripts/backlog/backlog-arrival.ts +11 -1
  38. package/scripts/backlog/backlog-budget.ts +25 -8
  39. package/scripts/backlog/backlog-next.ts +45 -2
  40. package/scripts/backlog/backlog-offer.ts +1 -0
  41. package/scripts/backlog/backlog-plan-cli.ts +66 -27
  42. package/scripts/backlog/backlog-plan.ts +30 -2
  43. package/scripts/backlog/backlog-stalled.ts +9 -0
  44. package/scripts/backlog/backlog-waves.ts +169 -0
  45. package/scripts/ci/pr-classification.ts +13 -12
  46. package/scripts/document/document-byte-budget.ts +1 -1
  47. package/scripts/document/entry-read-budget.ts +7 -5
  48. package/scripts/epic/epic-lane-offer.ts +69 -4
  49. package/scripts/epic/epic-next.ts +2 -2
  50. package/scripts/epic/epic-solo.ts +147 -0
  51. package/scripts/epic/epic-triage.ts +47 -0
  52. package/scripts/gate/hook-gate-reuse.ts +7 -8
  53. package/scripts/git/git-closes-keyword.ts +15 -0
  54. package/scripts/git/git-followup-flush.ts +5 -6
  55. package/scripts/git/git-followup-issue-close.ts +75 -0
  56. package/scripts/git/git-pr-followup-wrapup.ts +36 -6
  57. package/scripts/git/git-pr-followup.ts +9 -16
  58. package/scripts/git/git-staging.ts +33 -20
  59. package/scripts/git/issue-labels.ts +75 -5
  60. package/scripts/hooks/stop-guard.ts +1 -0
  61. package/scripts/init/init-bootstrap.ts +92 -0
  62. package/scripts/init/init-install.ts +67 -0
  63. package/scripts/init/init-logic-workspace.ts +1 -1
  64. package/scripts/init/init.ts +58 -13
  65. package/scripts/init/start-plan.ts +1 -1
  66. package/scripts/init/start-steps.ts +5 -28
  67. package/scripts/issue/issue-closing-pr.ts +93 -0
  68. package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +2 -1
  69. package/scripts/josh/josh-commands-project.ts +5 -1
  70. package/scripts/josh/josh-commands-workflow.ts +3 -3
  71. package/scripts/observations/observation-ledger-prepare.ts +31 -0
  72. package/scripts/observations/observation-ledger.ts +5 -5
  73. package/scripts/observations/observations-flush.ts +11 -30
  74. package/scripts/repo/repository-labels.ts +91 -0
  75. package/scripts/rules/implementation-cut.ts +49 -16
  76. package/scripts/rules/lane-background.ts +25 -5
  77. package/scripts/rules/stop-rules.ts +16 -4
  78. package/scripts/run/run-carry-cli.ts +21 -0
  79. package/scripts/run/run-cut-cli.ts +92 -110
  80. package/scripts/run/run-cut-report.ts +167 -0
  81. package/scripts/run/run-cut.ts +23 -7
  82. package/scripts/run/run-entry-cli.ts +70 -3
  83. package/scripts/run/run-halfrun-resume.ts +104 -0
  84. package/scripts/run/run-headless.ts +1 -0
  85. package/scripts/run/run-hold-cli.ts +57 -13
  86. package/scripts/run/run-hold.ts +26 -4
  87. package/scripts/run/run-merge-cli.ts +28 -14
  88. package/scripts/run/run-merge-steps.ts +38 -2
  89. package/scripts/run/run-merge.ts +41 -3
  90. package/scripts/run/run-prep-cli.ts +8 -2
  91. package/scripts/run/run-prep-locate.ts +165 -0
  92. package/scripts/run/run-prep.ts +12 -1
  93. package/scripts/run/run-step-cli.ts +16 -0
  94. package/scripts/run/run-step.ts +28 -4
  95. package/scripts/run/run-tail-cli.ts +4 -2
  96. package/scripts/run/run-wake-work.ts +4 -0
  97. package/scripts/safe-chain/ci-installer-pin.ts +8 -4
  98. package/scripts/security/security-audit.ts +12 -1
  99. package/scripts/sync/sync.ts +6 -0
  100. package/scripts/time-runtime/time-background.ts +11 -0
  101. package/scripts/time-runtime/time-transcript-line.ts +4 -0
  102. package/templates/pnpm-workspace.static.yaml +2 -0
@@ -15,6 +15,13 @@ on:
15
15
  # nothing here needs it: every run reads the pull request's labels as they stand when it runs, not as
16
16
  # its event carried them, so whichever suite GitHub counts as newest holds a current verdict.
17
17
 
18
+ # The same safe-chain installer pin as ci.yml — the release and its install-safe-chain.sh SHA-256.
19
+ # `pnpm dlx … setup-ci` left only shims, so the install below ran without a scan (joshuafolkken/kit#2765).
20
+ # `josh latest` moves both together, in this file and in ci.yml.
21
+ env:
22
+ SAFE_CHAIN_INSTALLER_VERSION: 1.5.20
23
+ SAFE_CHAIN_INSTALLER_SHA256: 0ad25efe15d1fa56105157a454d647223e78eb0c53d1f85e3d10afcd722e7bfd
24
+
18
25
  jobs:
19
26
  classification:
20
27
  name: Release classification
@@ -63,7 +70,11 @@ jobs:
63
70
  ${{ runner.os }}-pnpm-store-
64
71
 
65
72
  - name: Setup safe-chain
66
- run: pnpm dlx @aikidosec/safe-chain@1.5.20 setup-ci
73
+ run: |
74
+ installer="$RUNNER_TEMP/install-safe-chain.sh"
75
+ curl --proto '=https' -fsSL "https://github.com/AikidoSec/safe-chain/releases/download/$SAFE_CHAIN_INSTALLER_VERSION/install-safe-chain.sh" -o "$installer"
76
+ echo "$SAFE_CHAIN_INSTALLER_SHA256 $installer" | sha256sum -c -
77
+ sh "$installer" --ci
67
78
 
68
79
  - name: Install dependencies
69
80
  env:
package/CLAUDE.md CHANGED
@@ -89,7 +89,7 @@ Read from a `.env` file at the project root by the AI scripts, `josh port` and `
89
89
 
90
90
  ### Dependency overrides (`pnpm-workspace.yaml` / `package.json`)
91
91
 
92
- - **Effective overrides live in `pnpm-workspace.yaml`.** pnpm 11 and 12 ignore `pnpm.overrides` in `package.json` (verified with pnpm 12.6.0). Check both files for existing declarations, but never count the ignored package field as an effective override. **An absent or empty `pnpm.overrides` is not evidence that the project has no overrides.**
92
+ - **Effective overrides live in `pnpm-workspace.yaml`.** pnpm 11 and 12 ignore `pnpm.overrides` in `package.json`. Check both files for existing declarations, but never count the ignored package field as an effective override. **An absent or empty `pnpm.overrides` is not evidence that the project has no overrides.**
93
93
  - **NEVER** remove or modify entries in **either** location without explicit user approval.
94
94
  - **NEVER** modify the `devEngines` field in `package.json` without explicit user confirmation. It pins the development toolchain (e.g. pnpm version); silently changing it can break CI or other contributors' environments.
95
95
  - **The check is a command you run, not a conclusion you reach.** After `pnpm update`, `josh latest`, or any dependency-update command, **load the `dependency-update` skill** and follow its procedure before reporting anything about the pins.
@@ -144,7 +144,7 @@ Before every `git commit` (follow-up commits included), self-review against `pro
144
144
 
145
145
  ## Doc Sync Rules
146
146
 
147
- **`CLAUDE.md` is the single source for every agent rule.** `AGENTS.md` and `GEMINI.md` carry no rules — a rule addition, spec change or wording fix is written **once**, here (joshuafolkken/kit#963). The structural test [scripts/document/ai-document-pointers.test.ts](https://github.com/joshuafolkken/kit/blob/main/scripts/document/ai-document-pointers.test.ts) fails if a rule body reappears in either, or if a pointer loses the sentence that sends an agent here.
147
+ **`CLAUDE.md` is the single source for every agent rule.** `AGENTS.md` and `GEMINI.md` carry no rules — a rule addition, spec change or wording fix is written **once**, here (joshuafolkken/kit#963).
148
148
 
149
149
  **docs/ must stay in sync with the package.** When `josh bump` changes the version, review `docs/` and update any section describing changed behavior (new/renamed commands, `josh init` / `josh sync` behavior, new config files) before committing.
150
150
 
@@ -166,7 +166,7 @@ Before every `git commit` (follow-up commits included), self-review against `pro
166
166
 
167
167
  `kickoff`, `fullrun`, `halfrun` and `backlogrun` are the Issue-driven shorthand commands. **Their procedures are not resident** — they live in the `workflow-commands` skill. **What stays here is decided by one question: must the rule fire on a turn where no skill was loaded?** Explicit invocation, the mid-workflow stop notification, the `overrides` / `devEngines` prohibitions, the UI-verification gate and the three `epic:*` rules below all do; everything a run reaches only after reading the skill is routed to, never restated (`SKILL.md` → "What stays resident, and what is read from here").
168
168
 
169
- **Read the skill before running any part of a command — including the first `gh` call.** Acting from the table below alone is not enough: the table says which command was typed, not how to run it.
169
+ **Read the skill before running any part of a command — including the first `gh` call.**
170
170
 
171
171
  | Typed keyword | What it does | Read first |
172
172
  | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # @joshuafolkken/kit
2
2
 
3
- A development toolkit that sets up a repository for AI-assisted work with one command. `josh init` gives an AI assistant (Claude Code, Codex, Gemini, Cursor) the project's rules, and the `josh` CLI runs the checks and the Git / GitHub Issue workflow the same way in every project. You stop copying config between repositories and re-explaining conventions to the assistant. For the problems kit exists to solve, see [why.md](./docs/why.md) (Japanese).
3
+ A development toolkit for AI-assisted work. `josh init` gives an AI assistant (Claude Code, Codex, Gemini, Cursor) the project's rules, formatting and checks in one command. With `kickoff`, `fullrun` and `backlogrun`, the agent then takes a GitHub Issue through plan → implement → verify → PR → merge, the same way in every project. Why kit exists: [why.md](./docs/why.md) (Japanese).
4
4
 
5
5
  ## What your project gets
6
6
 
7
- kit does not branch by language. It asks one question — does the project use Node tooling? — and picks a [profile](./docs/init.md#project-profiles):
7
+ kit picks a [profile](./docs/init.md#project-profiles) from one question — does the project use Node tooling?
8
8
 
9
9
  | Your project | Profile | What you get |
10
10
  | ---------------------------------------- | -------- | ----------------------------------------------------------------- |
@@ -12,54 +12,58 @@ kit does not branch by language. It asks one question — does the project use N
12
12
  | HTML / CSS (browser JavaScript included) | `static` | Formatting (Prettier), AI assistant files, Git / VS Code settings |
13
13
  | Another language (Python, Rust, Go, …) | `static` | AI assistant files and Git / VS Code settings only |
14
14
 
15
- kit adds no linter or test runner for languages other than JavaScript and TypeScript; in a `static` project, `josh` skips each check that has nothing to run and says why.
15
+ In a `static` project, `josh` skips each check that has nothing to run and says why.
16
16
 
17
17
  ## Quick start
18
18
 
19
- In your project directory:
19
+ Requires [Node.js](https://nodejs.org/) 22.19.0+ and [pnpm](https://pnpm.io/) for every profile ([getting-started.md](./docs/getting-started.md)); the [gh CLI](https://cli.github.com/) for `josh version` and the Issue workflow is required by `josh start` and optional otherwise. Run in your project directory.
20
+
21
+ ### The project is already on GitHub, or will not use GitHub
20
22
 
21
23
  ```bash
22
- pnpm add -D --allow-build=esbuild @joshuafolkken/kit
23
- pnpm exec josh init
24
- pnpm install
25
- pnpm josh format
24
+ pnpm --allow-build=esbuild dlx @joshuafolkken/kit init
26
25
  pnpm josh gate
27
26
  ```
28
27
 
29
- `josh init` is the entry without GitHub. To start a new project on the GitHub Issue workflow (`kickoff`), run `pnpm exec josh start` instead of `josh init` — it also creates the Git repository, the GitHub repository and the labels ([init.md → `josh init` or `josh start`](./docs/init.md#josh-init-or-josh-start)).
28
+ ### The project has no GitHub repository yet, and will use the Issue workflow
29
+
30
+ ```bash
31
+ pnpm add -D --allow-build=esbuild --allow-build=unrs-resolver @joshuafolkken/kit
32
+ pnpm exec josh start
33
+ ```
30
34
 
31
- It needs [Node.js](https://nodejs.org/) 22.19.0 or later with [pnpm](https://pnpm.io/), even for a `static` project; [getting-started.md](./docs/getting-started.md) installs both. The global `josh` command ([cli.md](./docs/cli.md)) and the [gh CLI](https://cli.github.com/) for `josh version` and the GitHub Issue workflow are optional.
35
+ `josh start` also runs `git init` when needed and creates and pushes the GitHub repository. Details: [init.md → `josh init` or `josh start`](./docs/init.md#josh-init-or-josh-start).
32
36
 
33
37
  ## Documentation
34
38
 
35
39
  **Get started**
36
40
 
37
- - [getting-started.md](./docs/getting-started.md) — first install for an `index.html` site or a non-Node project (`static`)
38
- - [package.md](./docs/package.md) — add kit to a Node project (`node`)
41
+ - [getting-started.md](./docs/getting-started.md) — first install for a `static` project
42
+ - [package.md](./docs/package.md) — add kit to a Node project
39
43
  - [tutorial.md](./docs/tutorial.md) — your first change with an agent, from Issue to merge
40
- - [how-to.md](./docs/how-to.md) — step-by-step guides by task: update, release, run Issues, fix a failing gate
44
+ - [how-to.md](./docs/how-to.md) — guides by task
41
45
  - [overview.md](./docs/overview.md) — what kit sets up and how it works
42
46
 
43
47
  **Commands and configuration**
44
48
 
45
- - [cli.md](./docs/cli.md) — install the global `josh` command
49
+ - [cli.md](./docs/cli.md) — the global `josh` command
46
50
  - [josh-commands.md](./docs/josh-commands.md) — every `josh` command ([catalog](./docs/josh-command-catalog.md))
47
- - [init.md](./docs/init.md) — what `josh init` creates, per profile
48
- - [sync.md](./docs/sync.md) — what `josh sync` updates after an upgrade
49
- - [manual-config.md](./docs/manual-config.md) — use the presets without `josh init`
50
- - [package-api.md](./docs/package-api.md) — the config presets and libraries the package exports
51
+ - [init.md](./docs/init.md) — what `josh init` creates
52
+ - [sync.md](./docs/sync.md) — what `josh sync` updates
53
+ - [manual-config.md](./docs/manual-config.md) — the presets without `josh init`
54
+ - [package-api.md](./docs/package-api.md) — the package's exports
51
55
 
52
56
  **AI workflow and operations**
53
57
 
54
- - [scripts-ai.md](./docs/scripts-ai.md) — Telegram notifications and the Issue workflow commands
58
+ - [scripts-ai.md](./docs/scripts-ai.md) — Issue workflow commands and Telegram notifications
55
59
  - [cloud-session.md](./docs/cloud-session.md) — running in an agent container
56
- - [eval.md](./docs/eval.md) — measuring whether the agent rules are followed
60
+ - [eval.md](./docs/eval.md) — measuring rule adherence
57
61
  - [troubleshooting.md](./docs/troubleshooting.md) — install and auth errors
58
62
  - [authentication.md](./docs/authentication.md) — existing GitHub Packages installs only
59
63
 
60
64
  ## Contributing
61
65
 
62
- Community standards live in [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md); security reports go through [SECURITY.md](./SECURITY.md). Development conventions are in [CLAUDE.md](./CLAUDE.md); releases are in [publishing.md](./docs/publishing.md), and maintainer records in [docs/maintainers/](./docs/maintainers/).
66
+ Conventions are in [CLAUDE.md](./CLAUDE.md), releases in [publishing.md](./docs/publishing.md). See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) and [SECURITY.md](./SECURITY.md); maintainer records are in [docs/maintainers/](./docs/maintainers/).
63
67
 
64
68
  ## License
65
69
 
package/dist/CLAUDE.md CHANGED
@@ -89,7 +89,7 @@ Read from a `.env` file at the project root by the AI scripts, `josh port` and `
89
89
 
90
90
  ### Dependency overrides (`pnpm-workspace.yaml` / `package.json`)
91
91
 
92
- - **Effective overrides live in `pnpm-workspace.yaml`.** pnpm 11 and 12 ignore `pnpm.overrides` in `package.json` (verified with pnpm 12.6.0). Check both files for existing declarations, but never count the ignored package field as an effective override. **An absent or empty `pnpm.overrides` is not evidence that the project has no overrides.**
92
+ - **Effective overrides live in `pnpm-workspace.yaml`.** pnpm 11 and 12 ignore `pnpm.overrides` in `package.json`. Check both files for existing declarations, but never count the ignored package field as an effective override. **An absent or empty `pnpm.overrides` is not evidence that the project has no overrides.**
93
93
  - **NEVER** remove or modify entries in **either** location without explicit user approval.
94
94
  - **NEVER** modify the `devEngines` field in `package.json` without explicit user confirmation. It pins the development toolchain (e.g. pnpm version); silently changing it can break CI or other contributors' environments.
95
95
  - **The check is a command you run, not a conclusion you reach.** After `pnpm update`, `josh latest`, or any dependency-update command, **load the `dependency-update` skill** and follow its procedure before reporting anything about the pins.
@@ -144,7 +144,7 @@ Before every `git commit` (follow-up commits included), self-review against `nod
144
144
 
145
145
  ## Doc Sync Rules
146
146
 
147
- **`CLAUDE.md` is the single source for every agent rule.** `AGENTS.md` and `GEMINI.md` carry no rules — a rule addition, spec change or wording fix is written **once**, here (joshuafolkken/kit#963). The structural test [scripts/document/ai-document-pointers.test.ts](https://github.com/joshuafolkken/kit/blob/main/scripts/document/ai-document-pointers.test.ts) fails if a rule body reappears in either, or if a pointer loses the sentence that sends an agent here.
147
+ **`CLAUDE.md` is the single source for every agent rule.** `AGENTS.md` and `GEMINI.md` carry no rules — a rule addition, spec change or wording fix is written **once**, here (joshuafolkken/kit#963).
148
148
 
149
149
  **docs/ must stay in sync with the package.** When `josh bump` changes the version, review `https://github.com/joshuafolkken/kit/tree/main/docs/` and update any section describing changed behavior (new/renamed commands, `josh init` / `josh sync` behavior, new config files) before committing.
150
150
 
@@ -166,7 +166,7 @@ Before every `git commit` (follow-up commits included), self-review against `nod
166
166
 
167
167
  `kickoff`, `fullrun`, `halfrun` and `backlogrun` are the Issue-driven shorthand commands. **Their procedures are not resident** — they live in the `workflow-commands` skill. **What stays here is decided by one question: must the rule fire on a turn where no skill was loaded?** Explicit invocation, the mid-workflow stop notification, the `overrides` / `devEngines` prohibitions, the UI-verification gate and the three `epic:*` rules below all do; everything a run reaches only after reading the skill is routed to, never restated (`SKILL.md` → "What stays resident, and what is read from here").
168
168
 
169
- **Read the skill before running any part of a command — including the first `gh` call.** Acting from the table below alone is not enough: the table says which command was typed, not how to run it.
169
+ **Read the skill before running any part of a command — including the first `gh` call.**
170
170
 
171
171
  | Typed keyword | What it does | Read first |
172
172
  | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
@@ -9,10 +9,10 @@ import {
9
9
  load_environment_file,
10
10
  notice_refusal_path,
11
11
  refusal_path
12
- } from "./chunk-244WYOEO.js";
13
- import "./chunk-XSL4SRMA.js";
14
- import "./chunk-LDQDZYHX.js";
15
- import "./chunk-BELI5XSS.js";
12
+ } from "./chunk-NXL3SBXY.js";
13
+ import "./chunk-2K52BRWV.js";
14
+ import "./chunk-KQG4776P.js";
15
+ import "./chunk-ZPLXLJ7O.js";
16
16
  import "./chunk-WPALEIRX.js";
17
17
  import "./chunk-RKUAD3I6.js";
18
18
  export {
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  lane_child_marker
3
- } from "./chunk-LDQDZYHX.js";
3
+ } from "./chunk-KQG4776P.js";
4
4
  import {
5
5
  time_bundle_call,
6
6
  time_format,
7
7
  time_round_trips,
8
8
  time_spans,
9
9
  time_transcript_line
10
- } from "./chunk-BELI5XSS.js";
10
+ } from "./chunk-ZPLXLJ7O.js";
11
11
 
12
12
  // scripts/lane/lane-guard-policy.ts
13
13
  var DEFAULT_MODE = "refuse";
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  ALREADY_DONE_LABEL,
3
3
  BREAKING_CHANGE_LABEL,
4
+ BUGFIX_LABEL,
4
5
  BUG_LABEL,
5
6
  CONTEXT_CUT_THRESHOLD,
6
7
  ENHANCEMENT_LABEL,
@@ -9,6 +10,7 @@ import {
9
10
  NEEDS_DECISION_LABEL,
10
11
  NEEDS_HUMAN_REVIEW_LABEL,
11
12
  RECENT_REQUEST_WINDOW,
13
+ RELEASE_CLASSIFICATION_NAMES,
12
14
  agent_role_profile,
13
15
  agent_session_environment,
14
16
  bash_triggers,
@@ -35,31 +37,31 @@ import {
35
37
  run_watcher_guard,
36
38
  shell_segments,
37
39
  tail_commands
38
- } from "./chunk-IJPBTDTB.js";
40
+ } from "./chunk-Q7LE77CO.js";
39
41
  import {
40
42
  find_local_bin_upwards
41
43
  } from "./chunk-3V37IID6.js";
42
44
  import {
43
45
  batch_outcome
44
- } from "./chunk-244WYOEO.js";
46
+ } from "./chunk-NXL3SBXY.js";
45
47
  import {
46
48
  investigation_refusal
47
- } from "./chunk-KOCK5FXQ.js";
49
+ } from "./chunk-BVMSPG3M.js";
48
50
  import {
49
51
  duplicate_read_outcome
50
- } from "./chunk-GNOITLRR.js";
52
+ } from "./chunk-ZYYSBNR6.js";
51
53
  import {
52
54
  investigation_reads
53
- } from "./chunk-HJXQZ7V4.js";
55
+ } from "./chunk-F6OM6SIG.js";
54
56
  import {
55
57
  lane_guard_policy,
56
58
  time_batch_guard
57
- } from "./chunk-XSL4SRMA.js";
59
+ } from "./chunk-2K52BRWV.js";
58
60
  import {
59
61
  hook_decision,
60
62
  lane_child_marker,
61
63
  run_issue_number
62
- } from "./chunk-LDQDZYHX.js";
64
+ } from "./chunk-KQG4776P.js";
63
65
  import {
64
66
  PLATFORM_TEMP_ROOT,
65
67
  cost_attribute,
@@ -71,7 +73,7 @@ import {
71
73
  stamp_file,
72
74
  time_density_hook,
73
75
  time_shell
74
- } from "./chunk-BELI5XSS.js";
76
+ } from "./chunk-ZPLXLJ7O.js";
75
77
 
76
78
  // scripts/hooks/pretool-guard.ts
77
79
  import { text } from "node:stream/consumers";
@@ -1016,24 +1018,37 @@ function current_state() {
1016
1018
  directory: process.cwd(),
1017
1019
  source: process.env,
1018
1020
  carried: run_cut.carried_cut_sync,
1021
+ held_issue: run_cut.held_issue_sync,
1019
1022
  // **Read through the short reuse window** (joshuafolkken/kit#2385). The row now fires per
1020
1023
  // threshold crossing rather than once per run, so this predicate is a candidate on every edit;
1021
1024
  // the window collapses one turn's burst of edits to a single whole-transcript price.
1022
1025
  verdict: () => implementation_cut_verdict.reused_verdict(() => cost_cli.session_verdict())
1023
1026
  };
1024
1027
  }
1025
- function uncut_lane_child_issue(state) {
1028
+ function lane_child_issue(state) {
1026
1029
  if (!lane_child_marker.is_child_of(state.directory, state.source)) return void 0;
1027
- const issue = lane_paths.lane_issue_of(state.directory, { ...state.source });
1030
+ return lane_paths.lane_issue_of(state.directory, { ...state.source });
1031
+ }
1032
+ function held_run_issue(state) {
1033
+ if (lane_paths.lane_issue_of(state.directory, { ...state.source }) !== void 0) return void 0;
1034
+ return state.held_issue();
1035
+ }
1036
+ function uncut_run_issue(state) {
1037
+ const issue = lane_child_issue(state) ?? held_run_issue(state);
1028
1038
  if (issue === void 0) return void 0;
1029
1039
  return state.carried()?.issue === issue ? void 0 : issue;
1030
1040
  }
1041
+ function warrants_the_cut(state) {
1042
+ const verdict = state.verdict();
1043
+ if (lane_child_issue(state) === void 0) return verdict === cost_verdict.OVER_VERDICT;
1044
+ return verdict !== cost_verdict.UNDER_VERDICT;
1045
+ }
1031
1046
  function is_over_threshold_edit(call, state = current_state()) {
1032
- if (!is_edit_tool(call.name) || uncut_lane_child_issue(state) === void 0) return false;
1033
- return state.verdict() !== cost_verdict.UNDER_VERDICT;
1047
+ if (!is_edit_tool(call.name) || uncut_run_issue(state) === void 0) return false;
1048
+ return warrants_the_cut(state);
1034
1049
  }
1035
1050
  var THRESHOLD_TEXT = `${cost_format.format_tokens(CONTEXT_CUT_THRESHOLD)}-token`;
1036
- var IMPLEMENTATION_CUT_REASON = `\u26D4 implementation-phase cut: this checkout is a lane dispatched for this issue and its recent-context cost has crossed the shared ${THRESHOLD_TEXT} threshold mid-implementation, so the thinking accumulated so far is now re-read on every later request. Take the cut before this edit. First write a handoff file with the Write tool \u2014 the user\u2019s instruction verbatim, what you have completed, what remains, and what you deliberately did not touch \u2014 and pass it as \`--handoff <path>\`, so the fresh process resumes on the original instruction rather than the working tree alone (joshuafolkken/kit#2354); a resume that finds no instruction is refused \`incomplete\` rather than continuing blind. \`pnpm josh run:cut --impl <N> --handoff <path>\` ends this process and relaunches a fresh one that resumes back into implementation (\`resume-impl\`), dropping the accumulated context rather than carrying it \u2014 joshuafolkken/kit#1933 built the boundary and joshuafolkken/kit#2310 measured it firing 0 times because the verdict was only ever read at session entry, where the context has not yet grown. The verdict is \`pnpm josh cost --cut\`'s exactly \u2014 the same per-request billed-input statistic against the same threshold, never a second measurement. Issue \`pnpm josh run:cut --impl <N> --handoff <path>\` now and read the verdict: on \`cut\`, **end the turn immediately** \u2014 the fresh process owns the run and continues implementing, so it must not be waited for; on \`not-a-lane\`, \`unready\`, \`busy\`, \`failed\` or \`unknown\`, this process carries the run on and the edit is simply the next call. Never relaunch a second process after \`busy\`. This fired because the dispatch mark names this lane; a person working here carries no mark and sees no refusal, so there is no human-or-child judgement left to make. The procedure is \`.claude/skills/workflow-commands/pre-gate-cut.md\`. Reissue this edit once the cut has answered \u2014 an edit reissued right after this refusal passes, so \`busy\` / \`failed\` cannot wedge the run edit after edit; this fires again on the next threshold crossing rather than once per run.`;
1051
+ var IMPLEMENTATION_CUT_REASON = `\u26D4 implementation-phase cut: this checkout is a lane dispatched for this issue, or a run holds it for this issue (joshuafolkken/kit#2760), and its recent-context cost has crossed the shared ${THRESHOLD_TEXT} threshold mid-implementation, so the thinking accumulated so far is now re-read on every later request. Take the cut before this edit. First write a handoff file with the Write tool \u2014 the user\u2019s instruction verbatim, what you have completed, what remains, and what you deliberately did not touch \u2014 and pass it as \`--handoff <path>\`, so the fresh process resumes on the original instruction rather than the working tree alone (joshuafolkken/kit#2354); a resume that finds no instruction is refused \`incomplete\` rather than continuing blind. \`pnpm josh run:cut --impl <N> --handoff <path>\` ends this process and relaunches a fresh one that resumes back into implementation (\`resume-impl\`), dropping the accumulated context rather than carrying it \u2014 joshuafolkken/kit#1933 built the boundary and joshuafolkken/kit#2310 measured it firing 0 times because the verdict was only ever read at session entry, where the context has not yet grown. The verdict is \`pnpm josh cost --cut\`'s exactly \u2014 the same per-request billed-input statistic against the same threshold, never a second measurement. Issue \`pnpm josh run:cut --impl <N> --handoff <path>\` now and read the verdict: on \`cut\`, **end the turn immediately** \u2014 in a lane the fresh process owns the run and continues implementing, so it must not be waited for; outside a lane nothing is relaunched, so first send the \`confirmation\` Telegram naming the resume command \`fullrun #<N>\` and keep the hold; on \`not-a-lane\`, \`unready\`, \`busy\`, \`failed\` or \`unknown\`, this process carries the run on and the edit is simply the next call. Never relaunch a second process after \`busy\`. This fired because the dispatch mark names this lane or the run hold names this issue; a person working here carries no mark and holds no run, so sees no refusal, so there is no human-or-child judgement left to make. The procedure is \`.claude/skills/workflow-commands/pre-gate-cut.md\`. Reissue this edit once the cut has answered \u2014 an edit reissued right after this refusal passes, so \`busy\` / \`failed\` cannot wedge the run edit after edit; this fires again on the next threshold crossing rather than once per run.`;
1037
1052
  var REISSUE_WINDOW_MS = 9e4;
1038
1053
  function is_reissued_refusal(now_ms, delivered_at_ms) {
1039
1054
  return now_ms - delivered_at_ms < REISSUE_WINDOW_MS;
@@ -1057,7 +1072,7 @@ var implementation_cut = {
1057
1072
  is_over_threshold_edit,
1058
1073
  is_reissued_refusal,
1059
1074
  takes_the_impl_cut,
1060
- uncut_lane_child_issue
1075
+ uncut_run_issue
1061
1076
  };
1062
1077
 
1063
1078
  // scripts/rules/issue-bug-label.ts
@@ -1951,12 +1966,12 @@ function uncut_lane_issue(state) {
1951
1966
  if (state.marked_issue !== issue) return void 0;
1952
1967
  return state.carried()?.issue === issue ? void 0 : issue;
1953
1968
  }
1954
- function warrants_the_cut(verdict) {
1969
+ function warrants_the_cut2(verdict) {
1955
1970
  return verdict !== cost_verdict.UNDER_VERDICT;
1956
1971
  }
1957
1972
  function is_uncut_gate(command, state = current_state2()) {
1958
1973
  if (!runs_the_gate(command) || uncut_lane_issue(state) === void 0) return false;
1959
- return warrants_the_cut(state.context_verdict());
1974
+ return warrants_the_cut2(state.context_verdict());
1960
1975
  }
1961
1976
  var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at, so take the cut before running it. `pnpm josh run:cut <N>` ends this process and relaunches a fresh one that resumes from the gate, dropping the thinking built up while implementing rather than carrying it on every later request \u2014 joshuafolkken/kit#1839 measured 176K of 204K output riding across that boundary, and joshuafolkken/kit#1864 measured the step itself firing 0 times in 6 lane children while it was carried as prose. Issue `pnpm josh run:cut <N>` now, and read the verdict: on `cut`, **end the turn immediately** \u2014 the fresh process owns the run from there and must not be waited for; on `not-a-lane`, `unready`, `busy`, `failed` or `unknown`, this process carries the run on and the gate is simply the next call. Never relaunch a second process after `busy`. This fired because the dispatch mark names this lane; a person working here carries no mark and sees no refusal, so there is no human-or-child judgement left to make. The procedure is `.claude/skills/workflow-commands/pre-gate-cut.md`. Reissue the gate once the cut has answered \u2014 this fires once per run, so it cannot repeat on the call in hand.";
1962
1977
  function reaches_the_pre_gate_boundary(call, _turn, run2) {
@@ -3577,16 +3592,7 @@ import { readFileSync as readFileSync6 } from "node:fs";
3577
3592
  import { fileURLToPath as fileURLToPath2 } from "node:url";
3578
3593
  import { execaSync } from "execa";
3579
3594
  import { z as z8 } from "zod";
3580
- var BUGFIX = "bugfix";
3581
- var BREAKING = "breaking-change";
3582
- var CLASSIFICATION_LABELS2 = [
3583
- BREAKING,
3584
- "enhancement",
3585
- BUGFIX,
3586
- "other-change",
3587
- "ignore-for-release"
3588
- ];
3589
- var CLASSIFICATION_SET = new Set(CLASSIFICATION_LABELS2);
3595
+ var CLASSIFICATION_SET = new Set(RELEASE_CLASSIFICATION_NAMES);
3590
3596
  var ISSUE_BUG_LABEL = "bug";
3591
3597
  var DECLARATION = /^- リリース分類: (.+)$/gmu;
3592
3598
  var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
@@ -3605,14 +3611,14 @@ function classification_error(labels, author) {
3605
3611
  return `Choose exactly one release classification; found: ${selected.join(", ")}`;
3606
3612
  }
3607
3613
  if (selected.length === 1 || author.endsWith("[bot]")) return void 0;
3608
- return `Choose one release classification: ${CLASSIFICATION_LABELS2.join(", ")}`;
3614
+ return `Choose one release classification: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}`;
3609
3615
  }
3610
3616
  function is_classification(value) {
3611
3617
  return CLASSIFICATION_SET.has(value);
3612
3618
  }
3613
3619
  function release_candidates(candidates) {
3614
- if (!candidates.includes(BREAKING)) return candidates;
3615
- return candidates.filter((candidate) => candidate !== "enhancement");
3620
+ if (!candidates.includes(BREAKING_CHANGE_LABEL)) return candidates;
3621
+ return candidates.filter((candidate) => candidate !== ENHANCEMENT_LABEL);
3616
3622
  }
3617
3623
  function issue_candidates(issue_json) {
3618
3624
  const issue = z8.object({ labels: z8.array(LABEL), body: z8.string().nullable() }).parse(JSON.parse(issue_json));
@@ -3621,8 +3627,8 @@ function issue_candidates(issue_json) {
3621
3627
  const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
3622
3628
  const unknown = declared.filter((value) => !is_classification(value));
3623
3629
  if (unknown.length > 0) throw new Error(`Unknown release classification: ${unknown.join(", ")}`);
3624
- if (names.includes(ISSUE_BUG_LABEL) && !candidates.includes(BREAKING)) {
3625
- candidates.push(BUGFIX);
3630
+ if (names.includes(ISSUE_BUG_LABEL) && !candidates.includes(BREAKING_CHANGE_LABEL)) {
3631
+ candidates.push(BUGFIX_LABEL);
3626
3632
  }
3627
3633
  return candidates;
3628
3634
  }
@@ -3632,7 +3638,7 @@ function select_issue_classification(issue_json) {
3632
3638
  const [label] = selected;
3633
3639
  if (label === void 0 || selected.length > 1) {
3634
3640
  throw new Error(
3635
- `Choose one release classification before opening the PR: ${CLASSIFICATION_LABELS2.join(", ")}; found: ${selected.join(", ") || "none"}. Add "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: <label>" to the Issue body.`
3641
+ `Choose one release classification before opening the PR: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}; found: ${selected.join(", ") || "none"}. Add "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: <label>" to the Issue body.`
3636
3642
  );
3637
3643
  }
3638
3644
  return label;
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  investigation_reads
3
- } from "./chunk-HJXQZ7V4.js";
3
+ } from "./chunk-F6OM6SIG.js";
4
4
  import {
5
5
  lane_guard_policy
6
- } from "./chunk-XSL4SRMA.js";
6
+ } from "./chunk-2K52BRWV.js";
7
7
  import {
8
8
  hook_decision
9
- } from "./chunk-LDQDZYHX.js";
9
+ } from "./chunk-KQG4776P.js";
10
10
 
11
11
  // scripts/delegation/investigation-guard.ts
12
12
  import { text } from "node:stream/consumers";
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  ESLINT_EDIT_CACHE_FLAGS,
7
7
  time_density_hook
8
- } from "./chunk-BELI5XSS.js";
8
+ } from "./chunk-ZPLXLJ7O.js";
9
9
 
10
10
  // scripts/hooks/format-edited-file.ts
11
11
  import { existsSync as existsSync2 } from "node:fs";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  time_batch_guard
3
- } from "./chunk-XSL4SRMA.js";
3
+ } from "./chunk-2K52BRWV.js";
4
4
  import {
5
5
  hook_decision
6
- } from "./chunk-LDQDZYHX.js";
6
+ } from "./chunk-KQG4776P.js";
7
7
  import {
8
8
  cost_blocks,
9
9
  cost_transcript,
10
10
  time_bundle_call,
11
11
  time_shell,
12
12
  time_spans
13
- } from "./chunk-BELI5XSS.js";
13
+ } from "./chunk-ZPLXLJ7O.js";
14
14
 
15
15
  // scripts/delegation/investigation-reads.ts
16
16
  import path from "node:path";
@@ -3,7 +3,7 @@ import {
3
3
  stamp_file,
4
4
  time_density_hook,
5
5
  time_hook_transcript
6
- } from "./chunk-BELI5XSS.js";
6
+ } from "./chunk-ZPLXLJ7O.js";
7
7
  import {
8
8
  josh_environment_file
9
9
  } from "./chunk-WPALEIRX.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  lane_guard_policy,
3
3
  time_batch_guard
4
- } from "./chunk-XSL4SRMA.js";
4
+ } from "./chunk-2K52BRWV.js";
5
5
  import {
6
6
  hook_decision
7
- } from "./chunk-LDQDZYHX.js";
7
+ } from "./chunk-KQG4776P.js";
8
8
 
9
9
  // scripts/hooks/batch-guard.ts
10
10
  import { text } from "node:stream/consumers";