@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
|
@@ -65,15 +65,19 @@ function block_ceiling(size: number): number {
|
|
|
65
65
|
// unreached file, so the definition cannot rot as documents move on or off the execution path.
|
|
66
66
|
const DOCUMENT_BYTE_BUDGET: ReadonlyArray<DocumentBudget> = [
|
|
67
67
|
{ path: '.claude/skills/dependency-update/SKILL.md', bytes: 8192 },
|
|
68
|
-
|
|
68
|
+
// joshuafolkken/kit#3173 split the waves and the `epic:bundle` detail into lazily read references.
|
|
69
|
+
{ path: '.claude/skills/epic-commands/SKILL.md', bytes: 20_480 },
|
|
70
|
+
{ path: '.claude/skills/epic-commands/epic-bundle.md', bytes: 12_288 },
|
|
71
|
+
{ path: '.claude/skills/epic-commands/execution-waves.md', bytes: 12_288 },
|
|
69
72
|
{ path: '.claude/skills/verify-ui/SKILL.md', bytes: 8192 },
|
|
70
|
-
{ path: '.claude/skills/workflow-commands/followup-reference.md', bytes: 16_384 },
|
|
71
73
|
{ path: '.claude/skills/workflow-commands/fullrun-steps.md', bytes: 8192 },
|
|
72
74
|
{ path: '.claude/skills/workflow-commands/into-target.md', bytes: 4096 },
|
|
73
75
|
{ path: '.claude/skills/workflow-commands/issue-comments.md', bytes: 8192 },
|
|
74
76
|
{ path: '.claude/skills/workflow-commands/issue-fold-existing.md', bytes: 4096 },
|
|
75
77
|
{ path: '.claude/skills/workflow-commands/needs-human-review.md', bytes: 8192 },
|
|
76
|
-
{ path: '.claude/skills/workflow-commands/observation-filing.md', bytes:
|
|
78
|
+
{ path: '.claude/skills/workflow-commands/observation-filing.md', bytes: 12_288 },
|
|
79
|
+
// joshuafolkken/kit#3176 moved the ledger out of `observation-filing.md`, read only when it appends.
|
|
80
|
+
{ path: '.claude/skills/workflow-commands/observation-ledger.md', bytes: 12_288 },
|
|
77
81
|
// `pre-gate-cut.md` left this per-document budget in joshuafolkken/kit#2289: it became a point-of-use
|
|
78
82
|
// document, so its bytes are now held by every entry's total read (`entry-read-budget.ts`) and the
|
|
79
83
|
// two budgets must not hold it twice — the reachability line moved it from `unreached` to
|
|
@@ -82,34 +86,44 @@ const DOCUMENT_BYTE_BUDGET: ReadonlyArray<DocumentBudget> = [
|
|
|
82
86
|
{ path: '.claude/skills/workflow-commands/target-repository.md', bytes: 8192 },
|
|
83
87
|
{ path: '.claude/skills/workflow-commands/working-tree-hold.md', bytes: 8192 },
|
|
84
88
|
// joshuafolkken/kit#2998 split the reference: the developer commands stay, the rest moved out.
|
|
85
|
-
|
|
89
|
+
// joshuafolkken/kit#3175 raised it: the supervisor, provider-table and answer-to-budget prose moved
|
|
90
|
+
// here out of `backlogrun-steps.md`, so a run reads it only when it asks about those commands.
|
|
91
|
+
{ path: 'docs/josh-commands-automation.md', bytes: 159_744 },
|
|
86
92
|
{ path: 'docs/josh-commands.md', bytes: 36_864 },
|
|
87
93
|
{ path: 'prompts/coding-standards.md', bytes: 8192 },
|
|
88
94
|
{ path: 'prompts/collaboration-workflow.md', bytes: 8192 },
|
|
89
95
|
{ path: 'prompts/collaboration-workflow/file-edits.md', bytes: 12_288 },
|
|
90
96
|
{ path: 'prompts/collaboration-workflow/gh-rest.md', bytes: 8192 },
|
|
91
97
|
{ path: 'prompts/collaboration-workflow/glossary.md', bytes: 4096 },
|
|
92
|
-
{ path: 'prompts/collaboration-workflow/issue-citation.md', bytes:
|
|
93
|
-
// #
|
|
94
|
-
{ path: 'prompts/collaboration-workflow/issue-template.md', bytes:
|
|
95
|
-
{ path: 'prompts/collaboration-workflow/operating-rules.md', bytes:
|
|
96
|
-
|
|
97
|
-
{ path: 'prompts/collaboration-workflow/
|
|
98
|
-
{ path: 'prompts/collaboration-workflow/
|
|
98
|
+
{ path: 'prompts/collaboration-workflow/issue-citation.md', bytes: 4096 },
|
|
99
|
+
// #3178 left the template and the judgement tables; the epic commands moved to `epic-commands`, the by-hand fallback stayed.
|
|
100
|
+
{ path: 'prompts/collaboration-workflow/issue-template.md', bytes: 8192 },
|
|
101
|
+
{ path: 'prompts/collaboration-workflow/operating-rules.md', bytes: 12_288 },
|
|
102
|
+
// #3177 moved the rationale to `docs/maintainers/output-bounds-rationale.md`.
|
|
103
|
+
{ path: 'prompts/collaboration-workflow/output-bounds.md', bytes: 4096 },
|
|
104
|
+
{ path: 'prompts/collaboration-workflow/overview.md', bytes: 4096 },
|
|
105
|
+
// #3178 replaced the review-chain restatement with a pointer to `chain-rule.md`.
|
|
106
|
+
{ path: 'prompts/collaboration-workflow/plan-comment.md', bytes: 8192 },
|
|
99
107
|
{ path: 'prompts/collaboration-workflow/principles.md', bytes: 12_288 },
|
|
100
108
|
{ path: 'prompts/collaboration-workflow/proposal-request.md', bytes: 4096 },
|
|
101
|
-
|
|
102
|
-
{ path: 'prompts/collaboration-workflow/
|
|
103
|
-
|
|
104
|
-
{ path: 'prompts/collaboration-workflow/
|
|
105
|
-
|
|
109
|
+
// #3178 dropped the restatements `report:lint` and `chain-rule.md` already carry.
|
|
110
|
+
{ path: 'prompts/collaboration-workflow/report-format.md', bytes: 16_384 },
|
|
111
|
+
// #3177 cut it to the four questions; the history and lists moved to `docs/maintainers/residency-rationale.md`.
|
|
112
|
+
{ path: 'prompts/collaboration-workflow/residency.md', bytes: 8192 },
|
|
113
|
+
// #3186 moved the hook wiring and history to `docs/maintainers/rule-delivery-rationale.md`;
|
|
114
|
+
// #3179 adds the `index-mutation` / `destructive-command` / `protected-file` entries.
|
|
115
|
+
{ path: 'prompts/collaboration-workflow/rule-delivery.md', bytes: 20_480 },
|
|
116
|
+
{ path: 'prompts/collaboration-workflow/shell-body.md', bytes: 8192 },
|
|
117
|
+
// #3177 moved the measurements and rejected mechanisms to `docs/maintainers/turn-batching-rationale.md`.
|
|
118
|
+
{ path: 'prompts/collaboration-workflow/turn-batching.md', bytes: 8192 },
|
|
106
119
|
{ path: 'prompts/collaboration-workflow/upstream-interrupt.md', bytes: 12_288 },
|
|
107
|
-
{ path: 'prompts/collaboration-workflow/wip-cap.md', bytes:
|
|
120
|
+
{ path: 'prompts/collaboration-workflow/wip-cap.md', bytes: 12_288 },
|
|
108
121
|
{ path: 'prompts/refactoring.md', bytes: 8192 },
|
|
109
|
-
|
|
110
|
-
{ path: 'prompts/review.md', bytes:
|
|
122
|
+
// #3180 moved the history and the lint-settled proofs to `docs/maintainers/`.
|
|
123
|
+
{ path: 'prompts/review-rubric.md', bytes: 16_384 },
|
|
124
|
+
{ path: 'prompts/review.md', bytes: 16_384 },
|
|
111
125
|
{ path: 'prompts/sonar-hotspot-handling.md', bytes: 8192 },
|
|
112
|
-
{ path: 'prompts/testing-guide.md', bytes:
|
|
126
|
+
{ path: 'prompts/testing-guide.md', bytes: 20_480 },
|
|
113
127
|
]
|
|
114
128
|
|
|
115
129
|
// The recorded ceiling for one path, or undefined when it carries no budget entry.
|
|
@@ -57,7 +57,7 @@ const ENTRY_READ_BUDGET: ReadonlyArray<EntryBudget> = [
|
|
|
57
57
|
// block in joshuafolkken/kit#2317 when `backlogrun-child.md`'s outage section recorded the
|
|
58
58
|
// session-resume re-dispatch and the outage-fold window.
|
|
59
59
|
// Raised in joshuafolkken/kit#2328 when `retrospective.md` joined the point-of-use set and `SKILL.md`
|
|
60
|
-
// grew by
|
|
60
|
+
// grew by `retrospective.md`: every entry that reads `SKILL.md` discovers the retrospective document, so its ~5KB
|
|
61
61
|
// and the new section crossed a block for each. The lane child is exempt — it never runs the
|
|
62
62
|
// retrospective (`run:step` answers `stop` for a child at the stop position), so it skips both.
|
|
63
63
|
// joshuafolkken/kit#2335 recorded the drain-time firing with the operational detail in
|
|
@@ -70,8 +70,8 @@ const ENTRY_READ_BUDGET: ReadonlyArray<EntryBudget> = [
|
|
|
70
70
|
// list, so its ~48KB read crossed a block downward and the recorded ceiling drops to the block multiple
|
|
71
71
|
// the stale-ratchet message named. The other entries still read it, so their rows hold.
|
|
72
72
|
// joshuafolkken/kit#2345 added the `implementation-unit` delegation row (full fan-out procedure in
|
|
73
|
-
// `docs/josh-commands-automation.md` → "`josh fanout`"); `
|
|
74
|
-
// pointer, folded into the existing enumeration and offset by tightening
|
|
73
|
+
// `docs/josh-commands-automation.md` → "`josh fanout`"); `delegation.md` gained only a one-clause mention and a
|
|
74
|
+
// pointer, folded into the existing enumeration and offset by tightening `delegation.md` prose, so every entry
|
|
75
75
|
// stayed within its block (kickoff has no block of headroom — its pre-#2294 ceiling is the next
|
|
76
76
|
// multiple, which the downward ratchet holds shut).
|
|
77
77
|
// joshuafolkken/kit#2353 wired the watcher-guard note into `backlogrun-progress.md` (read by the three
|
|
@@ -92,12 +92,24 @@ const ENTRY_READ_BUDGET: ReadonlyArray<EntryBudget> = [
|
|
|
92
92
|
// `backlogrun-*` phase documents it never opens. Each total now counts only what its path reaches.
|
|
93
93
|
// joshuafolkken/kit#3077 trimmed non-resident rule bodies from `CLAUDE.md`, lowering fullrun, prrun
|
|
94
94
|
// and backlogrun one block each.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
// Lowered in joshuafolkken/kit#3172: the heartbeat left `backlogrun-progress.md` for its own
|
|
96
|
+
// `progress-watcher.md`, and `pre-gate-cut.md` became the lane child's alone, so fullrun, halfrun
|
|
97
|
+
// and prrun stop paying for ~50KB of batch and lane procedure; backlogrun lost the moved prose.
|
|
98
|
+
// Lowered in joshuafolkken/kit#3174: `SKILL.md` was cut to a manifest (~21KB → ~11KB) and the entry
|
|
99
|
+
// sequence `fullrun`, `halfrun` and `prrun` shared moved into one `entry-sequence.md`.
|
|
100
|
+
// Lowered in joshuafolkken/kit#3175: the loop became the driver's hand-backs, the supervisor and
|
|
101
|
+
// provider prose moved to `docs/josh-commands-automation.md`, and the failure-only sections moved to
|
|
102
|
+
// `backlogrun-recovery.md`, which the parent's reach still charges whole.
|
|
103
|
+
// joshuafolkken/kit#3171 cut `CLAUDE.md` to triggers and pointers (~12 KB), lowering every entry.
|
|
104
|
+
{ entry: 'kickoff', bytes: 45_056 },
|
|
105
|
+
// Raised in joshuafolkken/kit#3177: #3173, #3181 and #3183 merged in parallel and together tipped
|
|
106
|
+
// fullrun 12 bytes over its block; none of #3177's documents are in its read set.
|
|
107
|
+
// Lowered back in joshuafolkken/kit#3180: the history and lint-settled proofs left its read set.
|
|
108
|
+
{ entry: 'fullrun', bytes: 57_344 },
|
|
109
|
+
{ entry: 'halfrun', bytes: 57_344 },
|
|
110
|
+
{ entry: 'prrun', bytes: 61_440 },
|
|
111
|
+
{ entry: 'backlogrun', bytes: 176_128 },
|
|
112
|
+
{ entry: LANE_CHILD, bytes: 57_344 },
|
|
101
113
|
]
|
|
102
114
|
|
|
103
115
|
function byte_size(root: string, relative_path: string): number {
|
|
@@ -19,19 +19,12 @@ const LANE_CHILD = 'lane-child'
|
|
|
19
19
|
const FULLRUN = 'fullrun'
|
|
20
20
|
|
|
21
21
|
// **The `SKILL.md` sections a dispatched lane child never uses**, read at the section level rather
|
|
22
|
-
// than in full. A child
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
// invocation, so §0 cannot decide anything for it either. Review delegation remains in chain-rule.md.
|
|
22
|
+
// than in full. A child never edits these documents (§3), and its dispatch is already an explicit
|
|
23
|
+
// workflow invocation, so §0 cannot decide anything for it either. The other rules it never uses — the
|
|
24
|
+
// `into` target, delegation, the repository prefix, the scout, observation filing, the retrospective —
|
|
25
|
+
// are single rows of §2's table since joshuafolkken/kit#3174, so no section of them is left to trim.
|
|
27
26
|
const UNUSED_SKILL_SECTIONS: ReadonlyArray<string> = [
|
|
28
27
|
'0. The rule that fires before any of them — explicit invocation',
|
|
29
|
-
'2a. The `into <target>` suffix — where the new Issue lands',
|
|
30
|
-
'2b. Delegating a step to a cheaper tier',
|
|
31
|
-
'2c. The `owner/repo#` prefix — which repository the run acts on',
|
|
32
|
-
'2e. Before filing a new Issue — `pnpm josh issue:scout`',
|
|
33
|
-
'2i. An observation worth filing is filed without asking',
|
|
34
|
-
'2j. The end-of-run retrospective — read when `run:step` prints it',
|
|
35
28
|
'3. What stays resident, and what is read from here',
|
|
36
29
|
]
|
|
37
30
|
|
|
@@ -49,10 +42,12 @@ const UNUSED_SKILL_SECTIONS: ReadonlyArray<string> = [
|
|
|
49
42
|
// list — what one invocation approves, the named-issue order, the session-cut record, the loop and the
|
|
50
43
|
// once-per-session tail — none of which a leaf child performs. Every reference to it lives in a
|
|
51
44
|
// document the child never reads (`backlogrun.md`, `backlogrun-progress.md`, `retrospective.md`) or in a
|
|
52
|
-
// `SKILL.md` section the child trims (§0's session-cut note
|
|
45
|
+
// `SKILL.md` section the child trims (§0's session-cut note), so the child has no path
|
|
53
46
|
// that opens it. It was the child's single largest read — ~16,000 tokens read whole — charged for a
|
|
54
47
|
// document it never reaches, so dropping it is a correction of an over-count, not a loss of any rule the
|
|
55
48
|
// child needs. The parent still reads it in full.
|
|
49
|
+
// **`progress-watcher.md` is the parent's too** (joshuafolkken/kit#3172): a dispatched child is refused
|
|
50
|
+
// a watcher by its `JOSH_LANE_CHILD` mark, so it never opens the watcher's document.
|
|
56
51
|
const SKIPPED_POINT_OF_USE: ReadonlySet<string> = new Set([
|
|
57
52
|
'backlogrun-child.md',
|
|
58
53
|
'backlogrun-lanes.md',
|
|
@@ -61,13 +56,16 @@ const SKIPPED_POINT_OF_USE: ReadonlySet<string> = new Set([
|
|
|
61
56
|
'delegation.md',
|
|
62
57
|
'issue-scout.md',
|
|
63
58
|
'latest-gate.md',
|
|
59
|
+
'progress-watcher.md',
|
|
64
60
|
'retrospective.md',
|
|
65
61
|
])
|
|
66
62
|
|
|
67
63
|
// **A child that parks reads `backlogrun-park.md`** (`SKILL.md` §1, "A lane child that parks"), a
|
|
68
64
|
// document a standalone `fullrun`'s path never names — so the child's reach adds it to its base
|
|
69
|
-
// entry's (joshuafolkken/kit#3078).
|
|
70
|
-
|
|
65
|
+
// entry's (joshuafolkken/kit#3078). **`pre-gate-cut.md` is the child's alone** (joshuafolkken/kit#3172):
|
|
66
|
+
// only a lane child resumes or takes the pre-gate cut, so `fullrun.md` stopped naming it and the
|
|
67
|
+
// child's reach carries it instead.
|
|
68
|
+
const REACHED_POINT_OF_USE: ReadonlySet<string> = new Set(['backlogrun-park.md', 'pre-gate-cut.md'])
|
|
71
69
|
|
|
72
70
|
function costed(root: string): ReadSetCost {
|
|
73
71
|
return read_set_trim.costed(root, {
|
|
@@ -48,15 +48,15 @@ const POINT_OF_USE_LABEL = '-- read at the point of use, not at the entry --'
|
|
|
48
48
|
const LANE_CHILD_NOTE: ReadonlyArray<string> = [
|
|
49
49
|
' a dispatched lane child (`JOSH_LANE_CHILD`) reads this trimmed set:',
|
|
50
50
|
' - skips the point-of-use documents the parent owns — child dispatch, lane opening, the progress watcher and the hand-off',
|
|
51
|
-
' - omits SKILL.md §0/§
|
|
51
|
+
' - omits SKILL.md §0/§3 — dispatch already authorized the run and a leaf child edits no rule',
|
|
52
52
|
]
|
|
53
53
|
// **The `backlogrun` parent reads a trimmed set of its own** — a scheduler that never implements, so
|
|
54
54
|
// the implementer-only `SKILL.md` sections are read section by section rather than whole
|
|
55
|
-
// (joshuafolkken/kit#2256). A *different* trim from the lane child's: the parent keeps §0
|
|
56
|
-
//
|
|
55
|
+
// (joshuafolkken/kit#2256). A *different* trim from the lane child's: the parent keeps §0, which is the
|
|
56
|
+
// scheduler's own, and drops no point-of-use document.
|
|
57
57
|
const BACKLOGRUN_PARENT_NOTE: ReadonlyArray<string> = [
|
|
58
58
|
' the backlogrun parent (scheduler) reads this trimmed set:',
|
|
59
|
-
' - omits SKILL.md §
|
|
59
|
+
' - omits SKILL.md §3 — the parent edits no rule mid-run',
|
|
60
60
|
' - keeps every point-of-use document — the parent is the one dispatching children and running lanes',
|
|
61
61
|
]
|
|
62
62
|
const FETCH_RULE =
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// is joshuafolkken/kit#1856's addition**: it governs the `/code-review` → `followup` chain, which in
|
|
16
16
|
// `fullrun` / `queue` / `epicrun` / `backlogrun` runs *after* the first edit, so its 7,396 tokens
|
|
17
17
|
// were resident from the entry for no run that had yet reached a review.
|
|
18
|
-
// **`background-commands.md` is joshuafolkken/kit#1873's**: it was
|
|
18
|
+
// **`background-commands.md` is joshuafolkken/kit#1873's**: it was `background-commands.md`'s resident body, governing the
|
|
19
19
|
// background execution of the gate, the push and the merge tail — all after the first edit — so it
|
|
20
20
|
// left `SKILL.md` for the point-of-use list. `SKILL.md` → §1, "Four documents are read at the point
|
|
21
21
|
// of use", is the single source.
|
|
@@ -32,18 +32,26 @@
|
|
|
32
32
|
// cut, a step every implementing run — and every dispatched lane child — reaches after the entry, so
|
|
33
33
|
// its read is a point-of-use read the count was silently omitting. Measured on the backlogrun of
|
|
34
34
|
// 2026-09-21, the lane children read it 21 times across 13 runs — the largest single document read,
|
|
35
|
-
// and the one the point-of-use list had no row for.
|
|
35
|
+
// and the one the point-of-use list had no row for. Only a lane child reaches it (joshuafolkken/kit#3172):
|
|
36
|
+
// `fullrun.md` no longer names it, so it is charged to the lane child's role alone.
|
|
37
|
+
// **`progress-watcher.md` joins them** (joshuafolkken/kit#3172): the heartbeat every implementing run
|
|
38
|
+
// starts once its hold is claimed, split out of `backlogrun-progress.md` so a single-issue run stops
|
|
39
|
+
// paying for the batch's hand-off and waiting procedure to read it.
|
|
36
40
|
const POINT_OF_USE_FILES: ReadonlySet<string> = new Set([
|
|
37
41
|
'latest-gate.md',
|
|
38
42
|
'followup.md',
|
|
39
43
|
'chain-rule.md',
|
|
40
44
|
'background-commands.md',
|
|
41
45
|
'pre-gate-cut.md',
|
|
46
|
+
'progress-watcher.md',
|
|
42
47
|
'backlogrun-child.md',
|
|
43
48
|
'backlogrun-lanes.md',
|
|
44
49
|
'backlogrun-progress.md',
|
|
45
50
|
'backlogrun-park.md',
|
|
46
51
|
'backlogrun-steps.md',
|
|
52
|
+
// Read only when a delegated unit goes silent or a lane's pull request conflicts with `main` — a
|
|
53
|
+
// failure path, so a run in which nothing fails never reads it (joshuafolkken/kit#3175).
|
|
54
|
+
'backlogrun-recovery.md',
|
|
47
55
|
// Read only when `run:step` prints `pnpm josh retrospective` at a run's stop position — the very
|
|
48
56
|
// end of a run, never the entry (joshuafolkken/kit#2328). Kept out of every entry's read for the
|
|
49
57
|
// same reason the phase documents above are: no run that never drains its backlog reaches it.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { document_reachability } from './document-reachability'
|
|
2
|
+
|
|
3
|
+
// The byte budget of the always-resident document — `CLAUDE.md`, loaded on every request. It is held
|
|
4
|
+
// here rather than in `document-byte-budget.ts` because a resident document is covered by every entry
|
|
5
|
+
// total and must not carry a per-document block entry as well (joshuafolkken/kit#2257); it is held here
|
|
6
|
+
// rather than inside `workflow-skills.test.ts` so `josh bytes CLAUDE.md` counts against the same number
|
|
7
|
+
// the suite enforces (joshuafolkken/kit#3171). Loosening any of the three constants is Tier C —
|
|
8
|
+
// `prompts/collaboration-workflow/residency.md`.
|
|
9
|
+
|
|
10
|
+
// The documents sat at ~83 KB each before the joshuafolkken/kit#854 split, crept back to ~56 KB, and
|
|
11
|
+
// were cut below 30 KB by joshuafolkken/kit#1924. joshuafolkken/kit#3171 cut `CLAUDE.md` to ~14 KB —
|
|
12
|
+
// triggers and pointers only — and lowered this ceiling with it, so the document cannot creep back. It
|
|
13
|
+
// is a guard against re-inlining, not a budget to tune prose against.
|
|
14
|
+
const RESIDENT_CEILING_BYTES = 18_000
|
|
15
|
+
|
|
16
|
+
// joshuafolkken/kit#951: the ceiling alone stops the wrong thing. Reached, it does not block the
|
|
17
|
+
// next rule — it makes that rule pay for itself by deleting a neighboring sentence, and the
|
|
18
|
+
// sentence chosen is whichever one no marker pinned rather than whichever one matters least. A
|
|
19
|
+
// required margin turns "at the limit" into a failure while there is still room to write the fix,
|
|
20
|
+
// which is the only point at which moving a procedure into a skill is still a choice.
|
|
21
|
+
const RESIDENT_HEADROOM_BYTES = 2000
|
|
22
|
+
|
|
23
|
+
// joshuafolkken/kit#1275: a floor under the room left once the procedures are out, so a wholesale
|
|
24
|
+
// re-inlining fails by name instead of silently returning the document to a few bytes of headroom.
|
|
25
|
+
const RE_INLINE_GUARD_HEADROOM_BYTES = 1000
|
|
26
|
+
|
|
27
|
+
const EFFECTIVE_CEILING_BYTES = RESIDENT_CEILING_BYTES - RESIDENT_HEADROOM_BYTES
|
|
28
|
+
|
|
29
|
+
// The size a resident document must stay below — the effective ceiling minus the re-inline floor. The
|
|
30
|
+
// suite fails at it, and `josh bytes` counts the headroom against it.
|
|
31
|
+
const RESIDENT_LIMIT_BYTES = EFFECTIVE_CEILING_BYTES - RE_INLINE_GUARD_HEADROOM_BYTES
|
|
32
|
+
|
|
33
|
+
// The limit for a resident document, or undefined for any other path.
|
|
34
|
+
function limit_bytes_for(relative_path: string): number | undefined {
|
|
35
|
+
return document_reachability.RESIDENT_BASE.includes(relative_path)
|
|
36
|
+
? RESIDENT_LIMIT_BYTES
|
|
37
|
+
: undefined
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const resident_budget = {
|
|
41
|
+
EFFECTIVE_CEILING_BYTES,
|
|
42
|
+
RE_INLINE_GUARD_HEADROOM_BYTES,
|
|
43
|
+
RESIDENT_LIMIT_BYTES,
|
|
44
|
+
limit_bytes_for,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { resident_budget }
|
|
@@ -5,7 +5,7 @@ import { to_issue_reference } from './epic-reference'
|
|
|
5
5
|
// Whether an issue is an epic this repository's writers may edit, and why it is not when it is not.
|
|
6
6
|
//
|
|
7
7
|
// Both `josh epic --add` and `josh epic --remove` ask exactly this before they compute anything: the
|
|
8
|
-
// label,
|
|
8
|
+
// label, a task list to place rows in, and a declaration
|
|
9
9
|
// their edit can be relative to. It lives in one module rather than in each of them, because the two
|
|
10
10
|
// commands must refuse the same inputs for the same reasons — a second copy is where one comes to
|
|
11
11
|
// accept an epic the other refuses (joshuafolkken/kit#1712).
|
|
@@ -40,18 +40,15 @@ function promote_remedy(epic_number: number): string {
|
|
|
40
40
|
// The label and the task list are checked separately from the declaration because they fail
|
|
41
41
|
// differently: without rows there is nowhere to put a new one, and without a declaration there is
|
|
42
42
|
// nothing for an edit to be relative to.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (epic_parse.has_external_task_list_entry(body)) {
|
|
51
|
-
return `${reference} tracks a child in another repository; editing the declared order of a cross-repository epic is joshuafolkken/kit#864's scope, not this command's.`
|
|
52
|
-
}
|
|
43
|
+
//
|
|
44
|
+
// **A child in another repository is not a refusal** (joshuafolkken/kit#3161). The declaration names
|
|
45
|
+
// bare numbers only, so neither command can write an order across repositories — such an order lives
|
|
46
|
+
// in the native relations alone (`epic_graph.child_links`), which these edits never read or drop — and
|
|
47
|
+
// the rewrite leaves a row it does not recognize exactly where it stood.
|
|
48
|
+
function find_epic_shape_error(subject: EpicShapeSubject): string | undefined {
|
|
49
|
+
if (subject.labels.includes(EPIC_LABEL)) return undefined
|
|
53
50
|
|
|
54
|
-
return
|
|
51
|
+
return `${to_issue_reference(subject.epic_number)} does not carry the \`${EPIC_LABEL}\` label, so it is not an epic. ${promote_remedy(subject.epic_number)}`
|
|
55
52
|
}
|
|
56
53
|
|
|
57
54
|
function find_subject_error(
|
|
@@ -60,7 +57,7 @@ function find_subject_error(
|
|
|
60
57
|
): string | undefined {
|
|
61
58
|
const reference = to_issue_reference(subject.epic_number)
|
|
62
59
|
if (subject.body === undefined) return `Could not read the body of ${reference}.`
|
|
63
|
-
const shape_error = find_epic_shape_error(subject
|
|
60
|
+
const shape_error = find_epic_shape_error(subject)
|
|
64
61
|
if (shape_error !== undefined) return shape_error
|
|
65
62
|
|
|
66
63
|
if (tracked.length === 0) {
|
|
@@ -6,7 +6,7 @@ import { epic_report, type EpicNextResult } from './epic-report'
|
|
|
6
6
|
|
|
7
7
|
// The `run:solo` gate on what a run is offered (joshuafolkken/kit#2776).
|
|
8
8
|
//
|
|
9
|
-
// `
|
|
9
|
+
// `backlogrun-lanes.md`'s run-alone rule says an issue whose defect reaches the verification path runs
|
|
10
10
|
// alone, and until this gate that was a judgement made at dispatch — the offer handed such an issue
|
|
11
11
|
// out beside others and `backlog:drive` launched every number it was given. The label records the
|
|
12
12
|
// judgement once; this applies it to every ask, so it holds without an agent in the loop.
|
|
@@ -9,7 +9,11 @@ const CHECK = 'exports'
|
|
|
9
9
|
const FAIL_EXIT_CODE = 1
|
|
10
10
|
// A consumer's namespaces are read from `.svelte` files and routes a TypeScript program over its
|
|
11
11
|
// `tsconfig.json` does not see, so every member they use would read as unused. The check is kit's own.
|
|
12
|
-
|
|
12
|
+
//
|
|
13
|
+
// **Not a skip notice** (joshuafolkken/kit#3162). `SKIP_MARKER` means "a check passed without running",
|
|
14
|
+
// and the gate withholds its green record on it — so a consumer, where this notice prints on every
|
|
15
|
+
// run, never got a green record. Out of scope by design is not unverified, so the marker stays out.
|
|
16
|
+
const CONSUMER_NOTICE = `josh ${CHECK}: checks only the kit repository itself — nothing to check in a consumer project.`
|
|
13
17
|
|
|
14
18
|
function format_member(root: string, member: NamespaceMember): string {
|
|
15
19
|
return `${path.relative(root, member.file)}:${String(member.line)} ${member.namespace}.${member.member}`
|
|
@@ -26,7 +30,7 @@ function report(root: string, members: ReadonlyArray<NamespaceMember>): string {
|
|
|
26
30
|
|
|
27
31
|
async function run_unused_members(root: string): Promise<number> {
|
|
28
32
|
if (doctor_consumer.is_kit_consumer(root)) {
|
|
29
|
-
console.info(
|
|
33
|
+
console.info(CONSUMER_NOTICE)
|
|
30
34
|
|
|
31
35
|
return 0
|
|
32
36
|
}
|
|
@@ -48,6 +52,6 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
48
52
|
process.exitCode = await run_unused_members(project_checks.project_root(process.cwd()))
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
const unused_members_cli = { run_unused_members }
|
|
55
|
+
const unused_members_cli = { run_unused_members, CONSUMER_NOTICE }
|
|
52
56
|
|
|
53
57
|
export { unused_members_cli }
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PrConflictError } from '#scripts/gh/git-pr-checks-eval'
|
|
1
2
|
import { time_format } from '#scripts/time-runtime/time-format'
|
|
2
3
|
|
|
3
4
|
// Where `pnpm josh followup` spends its own wall clock (joshuafolkken/kit#1349).
|
|
@@ -73,8 +74,15 @@ const STAGE = {
|
|
|
73
74
|
// blocker and on a red check, and those are the runs whose wait is longest — reporting nothing for
|
|
74
75
|
// them would leave the measurement blind to exactly the invocations worth measuring.
|
|
75
76
|
interrupted: 'interrupted',
|
|
77
|
+
// The interrupted lap when the wait failed on a merge conflict (joshuafolkken/kit#3221), so the
|
|
78
|
+
// stage block names the cause a resumed session used to look up with `gh pr view`.
|
|
79
|
+
conflict: 'conflict',
|
|
76
80
|
} as const
|
|
77
81
|
|
|
82
|
+
function stopped_lap(error: unknown): string {
|
|
83
|
+
return error instanceof PrConflictError ? STAGE.conflict : STAGE.interrupted
|
|
84
|
+
}
|
|
85
|
+
|
|
78
86
|
interface FollowupStage {
|
|
79
87
|
name: string
|
|
80
88
|
duration_ms: number
|
|
@@ -143,6 +151,7 @@ const git_followup_stages = {
|
|
|
143
151
|
total_ms,
|
|
144
152
|
format_stages,
|
|
145
153
|
print_stages,
|
|
154
|
+
stopped_lap,
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
export type { FollowupStage, StageLog }
|
|
@@ -437,7 +437,7 @@ async function run(input: FollowupInput): Promise<string | undefined> {
|
|
|
437
437
|
try {
|
|
438
438
|
return await run_stages(input, log)
|
|
439
439
|
} catch (error) {
|
|
440
|
-
lap(log,
|
|
440
|
+
lap(log, git_followup_stages.stopped_lap(error))
|
|
441
441
|
|
|
442
442
|
throw error
|
|
443
443
|
} finally {
|
|
@@ -97,10 +97,17 @@ function tag_reference_api_path(tag: string, repo?: string): string {
|
|
|
97
97
|
return `${repo_api_path(repo)}/git/ref/tags/${tag}`
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// The GitHub Release published for one tag. REST answers 404 until `publish.yml`'s `create-release`
|
|
101
|
+
// job has run, which is what the release command's progress watch asks (joshuafolkken/kit#3193).
|
|
102
|
+
function release_by_tag_api_path(tag: string, repo?: string): string {
|
|
103
|
+
return `${repo_api_path(repo)}/releases/tags/${tag}`
|
|
104
|
+
}
|
|
105
|
+
|
|
100
106
|
const git_gh_api_path = {
|
|
101
107
|
FULL_PAGE_QUERY,
|
|
102
108
|
repo_api_path,
|
|
103
109
|
tag_ref_api_path: tag_reference_api_path,
|
|
110
|
+
release_by_tag_api_path,
|
|
104
111
|
issues_api_path,
|
|
105
112
|
issue_api_path,
|
|
106
113
|
blocked_by_api_path,
|
|
@@ -26,8 +26,10 @@ const SUMMARY_FIELDS = 'number,title,labels,createdAt'
|
|
|
26
26
|
// `SUMMARY_FIELDS` on purpose: a listing carries no `blockedBy`, so the field is answered from each
|
|
27
27
|
// row's own dependencies endpoint, and asking for it on the shared list would put that request
|
|
28
28
|
// behind the next-issues display too — where a refused one becomes a failure with no message at all,
|
|
29
|
-
// since the listing swallows the error (joshuafolkken/kit#996, joshuafolkken/kit#1025).
|
|
30
|
-
|
|
29
|
+
// since the listing swallows the error (joshuafolkken/kit#996, joshuafolkken/kit#1025). `body` costs
|
|
30
|
+
// no request — the REST listing row already carries it — and is what the backlog offer reads for
|
|
31
|
+
// the restructures each issue declares (joshuafolkken/kit#3221).
|
|
32
|
+
const PICKUP_FIELDS = `${SUMMARY_FIELDS},blockedBy,body`
|
|
31
33
|
|
|
32
34
|
// Every listing below goes through the one REST invocation in `git-gh-issue-list.ts`. It kept the
|
|
33
35
|
// `json_fields` / `limit` contract it had as a `gh issue list` wrapper, so these callers changed
|
|
@@ -111,7 +113,7 @@ async function issue_list_by_label(label: string, limit: number): Promise<IssueL
|
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
// The same filter with the fields the `auto-ok` pickup needs (joshuafolkken/kit#906): it orders by
|
|
114
|
-
// `createdAt
|
|
116
|
+
// `createdAt`, re-checks `labels` client-side and reads each body for its declared restructures. A
|
|
115
117
|
// label that does not exist in the repository is not an error — the listing comes back empty, which
|
|
116
118
|
// is exactly "nobody has opted anything in".
|
|
117
119
|
// `json_fields` overrides the pickup's list. Its only caller is the probe that runs *after* a failed
|
|
@@ -2,6 +2,7 @@ import { FULL_PAGE_QUERY, git_gh_api_path } from './git-gh-api-path'
|
|
|
2
2
|
import { git_gh_exec } from './git-gh-exec'
|
|
3
3
|
import { git_gh_helpers } from './git-gh-helpers'
|
|
4
4
|
import { git_gh_pr_rest, type RestPull } from './git-gh-pr-rest'
|
|
5
|
+
import { to_gh_state } from './git-gh-rest-state'
|
|
5
6
|
|
|
6
7
|
// Reading pull requests through REST, in the answers `gh pr view` used to give.
|
|
7
8
|
//
|
|
@@ -81,6 +82,8 @@ interface PullMergeState {
|
|
|
81
82
|
is_merged: boolean
|
|
82
83
|
merged_at: string | undefined
|
|
83
84
|
head_sha: string | undefined
|
|
85
|
+
// `josh ship` reads `DIRTY` here to re-merge a conflicting pull request (joshuafolkken/kit#3221).
|
|
86
|
+
merge_state_status: string | undefined
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
type PullNumberRead =
|
|
@@ -234,6 +237,7 @@ async function pr_get_merge_state(branch_name: string): Promise<PullMergeState |
|
|
|
234
237
|
is_merged: git_gh_pr_rest.is_merged(pull),
|
|
235
238
|
merged_at: pull.merged_at ?? undefined,
|
|
236
239
|
head_sha: pull.head?.sha,
|
|
240
|
+
merge_state_status: to_gh_state(pull.mergeable_state),
|
|
237
241
|
}
|
|
238
242
|
}
|
|
239
243
|
|
|
@@ -240,7 +240,14 @@ function is_auto_merge_blocked(snapshot: PrStateSnapshot): boolean {
|
|
|
240
240
|
)
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
// A failed wait whose cause is a merge conflict (joshuafolkken/kit#3221), so `followup` names its last
|
|
244
|
+
// lap `conflict` rather than `interrupted` and the cause is read from the stage block, not looked up.
|
|
245
|
+
class PrConflictError extends Error {
|
|
246
|
+
override name = 'PrConflictError'
|
|
247
|
+
}
|
|
248
|
+
|
|
243
249
|
export {
|
|
250
|
+
PrConflictError,
|
|
244
251
|
evaluate_pr_state,
|
|
245
252
|
is_auto_merge_blocked,
|
|
246
253
|
is_review_decision_decisive,
|
|
@@ -251,5 +258,6 @@ export {
|
|
|
251
258
|
REQUIRED_CHECKS,
|
|
252
259
|
CODERABBIT_CHECK_NAME,
|
|
253
260
|
is_required_check,
|
|
261
|
+
is_merge_conflict,
|
|
254
262
|
}
|
|
255
263
|
export type { PrEvaluation }
|
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
describe_pr_failure,
|
|
7
7
|
evaluate_pr_state,
|
|
8
8
|
is_auto_merge_blocked,
|
|
9
|
+
is_merge_conflict,
|
|
9
10
|
is_review_decision_decisive,
|
|
11
|
+
PrConflictError,
|
|
10
12
|
type PrEvaluation,
|
|
11
13
|
} from './git-pr-checks-eval'
|
|
12
14
|
import { parse_pr_state_snapshot, read_string, type PrStateSnapshot } from './git-pr-checks-parse'
|
|
@@ -142,6 +144,12 @@ function advance_stable_count(previous: number, state: PrEvaluation): number {
|
|
|
142
144
|
return state === 'success' ? previous + 1 : 0
|
|
143
145
|
}
|
|
144
146
|
|
|
147
|
+
function failure_error(message: string, snapshot: PrStateSnapshot): Error {
|
|
148
|
+
return is_merge_conflict(snapshot.merge_state_status)
|
|
149
|
+
? new PrConflictError(message)
|
|
150
|
+
: new Error(message)
|
|
151
|
+
}
|
|
152
|
+
|
|
145
153
|
function classify_poll_result(input: {
|
|
146
154
|
snapshot: PrStateSnapshot
|
|
147
155
|
stable_count: number
|
|
@@ -150,7 +158,9 @@ function classify_poll_result(input: {
|
|
|
150
158
|
}): { is_done: boolean; next_stable_count: number } {
|
|
151
159
|
const state = input.evaluator.evaluate(input.snapshot)
|
|
152
160
|
|
|
153
|
-
if (state === 'failure')
|
|
161
|
+
if (state === 'failure') {
|
|
162
|
+
throw failure_error(input.evaluator.describe(input.snapshot), input.snapshot)
|
|
163
|
+
}
|
|
154
164
|
|
|
155
165
|
const next_stable_count = advance_stable_count(input.stable_count, state)
|
|
156
166
|
|
package/scripts/git/constants.ts
CHANGED
|
@@ -12,6 +12,11 @@ const PORCELAIN_FLAG = '--porcelain'
|
|
|
12
12
|
// The untracked-files mode every porcelain status reading passes (`git-command.ts` carries why it is
|
|
13
13
|
// passed and why it is `all`), shared so another module's own reading cannot drift from it.
|
|
14
14
|
const UNTRACKED_FILES_FLAG = '--untracked-files=all'
|
|
15
|
+
// The git binary a spawn runs in place of the platform's own (joshuafolkken/kit#3234). The spawn path
|
|
16
|
+
// is absolute, so a `git` placed in front on `PATH` never stands in for it: the unit suite's network
|
|
17
|
+
// guard shimmed `git` that way, and `josh ship`'s tests fetched and merged the default branch into the
|
|
18
|
+
// checkout they ran in without the guard ever seeing the call. The guard names its shim here instead.
|
|
19
|
+
const GIT_BINARY_KEY = 'JOSH_GIT_BINARY'
|
|
15
20
|
|
|
16
21
|
function get_git_command(): string {
|
|
17
22
|
if (platform() === 'win32') {
|
|
@@ -22,6 +27,10 @@ function get_git_command(): string {
|
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
function get_git_command_for_spawn(): string {
|
|
30
|
+
const binary = process.env[GIT_BINARY_KEY]
|
|
31
|
+
|
|
32
|
+
if (binary !== undefined && binary !== '') return binary
|
|
33
|
+
|
|
25
34
|
if (platform() === 'win32') {
|
|
26
35
|
return String.raw`C:\Program Files\Git\cmd\git.exe`
|
|
27
36
|
}
|
|
@@ -35,6 +44,7 @@ const git_utilities = {
|
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
export {
|
|
47
|
+
GIT_BINARY_KEY,
|
|
38
48
|
REQUIRED_STATUS_LENGTH,
|
|
39
49
|
STAGED_STATUS_INDEX,
|
|
40
50
|
UNTRACKED_FILE_PREFIX,
|