@joshuafolkken/kit 1.1471.0 → 1.1514.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 +6 -6
- package/.claude/skills/epic-commands/SKILL.md +2 -14
- package/.claude/skills/epic-commands/epic-bundle.md +9 -5
- package/.claude/skills/epic-commands/execution-waves.md +1 -2
- package/.claude/skills/verify-ui/SKILL.md +1 -2
- package/.claude/skills/workflow-commands/SKILL.md +7 -9
- package/.claude/skills/workflow-commands/background-commands.md +3 -7
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -10
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +6 -15
- package/.claude/skills/workflow-commands/backlogrun-park.md +2 -8
- package/.claude/skills/workflow-commands/backlogrun-progress.md +10 -19
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +8 -8
- package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -10
- package/.claude/skills/workflow-commands/backlogrun.md +31 -50
- package/.claude/skills/workflow-commands/chain-rule.md +7 -6
- package/.claude/skills/workflow-commands/delegation.md +12 -8
- package/.claude/skills/workflow-commands/entry-sequence.md +1 -3
- package/.claude/skills/workflow-commands/followup.md +3 -6
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -5
- package/.claude/skills/workflow-commands/fullrun.md +4 -6
- package/.claude/skills/workflow-commands/halfrun.md +3 -7
- package/.claude/skills/workflow-commands/into-target.md +1 -2
- package/.claude/skills/workflow-commands/issue-comments.md +3 -3
- package/.claude/skills/workflow-commands/issue-scout.md +3 -2
- package/.claude/skills/workflow-commands/latest-gate.md +2 -6
- package/.claude/skills/workflow-commands/needs-human-review.md +2 -5
- package/.claude/skills/workflow-commands/observation-filing.md +0 -14
- package/.claude/skills/workflow-commands/observation-ledger.md +4 -9
- package/.claude/skills/workflow-commands/pre-gate-cut.md +11 -16
- package/.claude/skills/workflow-commands/prerequisite.md +1 -2
- package/.claude/skills/workflow-commands/progress-watcher.md +2 -7
- package/.claude/skills/workflow-commands/prrun.md +3 -5
- package/.claude/skills/workflow-commands/retrospective.md +4 -4
- package/.claude/skills/workflow-commands/split-assessment.md +1 -3
- package/.claude/skills/workflow-commands/target-repository.md +1 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +2 -4
- package/.codex/hooks.json +6 -6
- package/.github/actions/setup-node/action.yml +1 -1
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/publish.yml +2 -2
- package/CLAUDE.md +1 -1
- package/cspell/index.yaml +7 -0
- package/dist/CLAUDE.md +1 -1
- package/dist/commands/document-section-cli.js +67 -34
- package/dist/hooks/batch-guard.js +6 -6
- package/dist/hooks/chunk-4KKD2UTK.js +66 -0
- package/dist/hooks/{chunk-J47HU5H5.js → chunk-6TS2JD6D.js} +3 -3
- package/dist/hooks/chunk-7DSBJVFH.js +50 -0
- package/dist/hooks/{chunk-YHBZAJSV.js → chunk-A65Y4YOR.js} +3 -3
- package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-APUO6U4J.js} +85 -7
- package/dist/hooks/{chunk-IX6TTTI6.js → chunk-EFXE6C37.js} +8 -22
- package/dist/hooks/chunk-GP4IEC4O.js +20 -0
- package/dist/hooks/{chunk-SHGPANFB.js → chunk-JP45SOCJ.js} +3 -3
- package/dist/hooks/{chunk-K4EOONYM.js → chunk-LAOV7NLM.js} +1 -1
- package/dist/hooks/chunk-M4HGZV7U.js +83 -0
- package/dist/hooks/{chunk-KC5AK2GF.js → chunk-O6GDRNJB.js} +3 -3
- package/dist/hooks/{chunk-YYPI7SJZ.js → chunk-PF2NZL2A.js} +5 -5
- package/dist/hooks/{chunk-H5HVWYXK.js → chunk-PTICX4OL.js} +3 -4
- package/dist/hooks/{chunk-IIGFYXKC.js → chunk-RT27QRJW.js} +581 -1438
- package/dist/hooks/{chunk-43ZHT22P.js → chunk-SYOTDYCI.js} +1127 -1089
- package/dist/hooks/{chunk-AS74OU3D.js → chunk-TNUMY6NL.js} +1507 -1336
- package/dist/hooks/chunk-UPUZF3AN.js +279 -0
- package/dist/hooks/{chunk-EUMACUK2.js → chunk-WK6SMBIC.js} +1948 -806
- package/dist/hooks/codex-hook-adapter.js +17 -14
- package/dist/hooks/duplicate-read-guard.js +7 -7
- package/dist/hooks/format-edited.js +5 -4
- package/dist/hooks/inputs.json +317 -264
- package/dist/hooks/investigation-guard.js +8 -11
- package/dist/hooks/pretool-guard.js +16 -13
- package/dist/hooks/session-lang.js +370 -25
- package/dist/hooks/stop-guard.js +2576 -176
- package/dist/josh.js +2124 -277
- package/lefthook/base.yml +5 -3
- package/package.json +12 -10
- package/prompts/collaboration-workflow/file-edits.md +1 -3
- package/prompts/collaboration-workflow/gh-rest.md +1 -2
- package/prompts/collaboration-workflow/issue-citation.md +2 -4
- package/prompts/collaboration-workflow/issue-template.md +10 -2
- package/prompts/collaboration-workflow/lane-instructions.md +35 -0
- package/prompts/collaboration-workflow/operating-rules.md +2 -6
- package/prompts/collaboration-workflow/output-bounds.md +3 -3
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/principles.md +14 -8
- package/prompts/collaboration-workflow/report-format.md +9 -0
- package/prompts/collaboration-workflow/residency.md +12 -8
- package/prompts/collaboration-workflow/rule-delivery.md +3 -11
- package/prompts/collaboration-workflow/shell-body.md +6 -6
- package/prompts/collaboration-workflow/turn-batching.md +5 -5
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +6 -6
- package/prompts/collaboration-workflow.md +1 -0
- package/prompts/review.md +4 -5
- package/prompts/testing-guide.md +2 -2
- package/scripts/agent/agent-argv.ts +20 -4
- package/scripts/agent/agent-role-profile.ts +101 -45
- package/scripts/agent/agent-safe-text.ts +60 -0
- package/scripts/agent/claude-agent-argv.ts +14 -0
- package/scripts/agent/codex-agent-argv.ts +2 -0
- package/scripts/agent/lane-instructions.ts +144 -0
- package/scripts/backlog/backlog-budget.ts +4 -4
- package/scripts/backlog/backlog-drive-named.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +9 -1
- package/scripts/backlog/backlog-occupied.ts +56 -0
- package/scripts/backlog/backlog-ready.ts +47 -10
- package/scripts/delegation/duplicate-read-guard.ts +2 -2
- package/scripts/delegation/investigation-guard.ts +15 -65
- package/scripts/delegation/investigation-reads.ts +0 -1
- package/scripts/document/document-byte-budget.ts +6 -5
- package/scripts/document/document-section-cli.ts +17 -5
- package/scripts/document/entry-read-budget.ts +2 -2
- package/scripts/document/read-set-cli.ts +4 -1
- package/scripts/epic/epic-audit-orphans.ts +5 -8
- package/scripts/epic/epic-audit.ts +52 -1
- package/scripts/epic/epic-bundle-evidence.ts +49 -26
- package/scripts/epic/epic-bundle-referenced.ts +14 -3
- package/scripts/epic/epic-bundle.ts +17 -9
- package/scripts/followup/git-followup-workflow.ts +19 -1
- package/scripts/gate/check-inputs.ts +129 -0
- package/scripts/gate/check-reuse.ts +162 -0
- package/scripts/gate/core-budget.ts +93 -44
- package/scripts/gate/core-wait.ts +130 -0
- package/scripts/gate/free-cores.ts +49 -0
- package/scripts/gate/gate-ledger.ts +17 -3
- package/scripts/gate/gate-plan.ts +23 -1
- package/scripts/gate/gate-report.ts +15 -2
- package/scripts/gate/gate-run-steps.ts +150 -0
- package/scripts/gate/held-mark.ts +55 -0
- package/scripts/gate/machine-capacity.ts +70 -11
- package/scripts/gate/pre-commit-type-check.ts +14 -1
- package/scripts/gate/verification-gate.ts +58 -125
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +24 -2
- package/scripts/gh/git-pr.ts +13 -1
- package/scripts/git/main-merge-regenerate.ts +78 -0
- package/scripts/git/main-merge.ts +14 -5
- package/scripts/hooks/batch-guard.ts +5 -8
- package/scripts/hooks/pre-commit-lint.ts +91 -0
- package/scripts/hooks/pre-push-unit.ts +1 -1
- package/scripts/hooks/pretool-guard.ts +27 -52
- package/scripts/hooks/reserved-run.ts +1 -0
- package/scripts/hooks/run-hook.sh +10 -12
- package/scripts/hooks/stop-actions.ts +204 -0
- package/scripts/hooks/stop-guard.ts +62 -21
- package/scripts/init/hook-launch.ts +12 -7
- package/scripts/issue/expected-effect-lint.ts +59 -0
- package/scripts/issue/issue-cite-cli.ts +35 -15
- package/scripts/issue/issue-classification.ts +1 -1
- package/scripts/issue/issue-lint-cli.ts +5 -3
- package/scripts/issue/issue-scout-cli.ts +19 -14
- package/scripts/issue/markdown-section.ts +19 -5
- package/scripts/josh/command-usage.ts +110 -0
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-command-types.ts +55 -9
- package/scripts/josh/josh-commands-ai.ts +13 -0
- package/scripts/josh/josh-commands-development.ts +1 -1
- package/scripts/josh/josh-commands-hooks.ts +6 -0
- package/scripts/josh/josh-commands-lane.ts +10 -1
- package/scripts/josh/josh-commands-workflow.ts +5 -0
- package/scripts/josh/josh-logic.ts +6 -15
- package/scripts/josh/josh-usage-automation.ts +121 -0
- package/scripts/josh/josh-usage-backlog.ts +180 -0
- package/scripts/josh/josh-usage-developer.ts +230 -0
- package/scripts/josh/josh-usage-hooks.ts +38 -0
- package/scripts/josh/josh-usage-issue.ts +205 -0
- package/scripts/josh/josh-usage-review.ts +101 -0
- package/scripts/josh/josh-usage-run.ts +252 -0
- package/scripts/josh/josh-usage-session.ts +238 -0
- package/scripts/josh/josh-usage-workflow.ts +212 -0
- package/scripts/josh/josh.ts +14 -5
- package/scripts/josh/package-directory.ts +20 -0
- package/scripts/lane/lane-capacity.ts +8 -2
- package/scripts/lane/lane-check-stats.ts +56 -0
- package/scripts/lane/lane-child-invocation.ts +35 -4
- package/scripts/lane/lane-dispatch.ts +3 -3
- package/scripts/lane/lane-guard-policy.ts +2 -2
- package/scripts/lane/lane-handoff.ts +8 -1
- package/scripts/lane/lane-install.ts +12 -4
- package/scripts/lane/lane-ledger.ts +43 -1
- package/scripts/lane/lane-limit-cli.ts +8 -9
- package/scripts/lane/lane-measure-cli.ts +2 -0
- package/scripts/lane/lane-preserve.ts +29 -1
- package/scripts/lane/lane-registry.ts +9 -7
- package/scripts/lane/lane-restart.ts +5 -26
- package/scripts/lane/lane-session-action.ts +146 -0
- package/scripts/lane/lane-session-broker.ts +57 -138
- package/scripts/lane/lane-withdraw-cli.ts +71 -0
- package/scripts/lane/lane-withdraw.ts +182 -0
- package/scripts/lint/format.ts +4 -4
- package/scripts/lint/lint-parallel.ts +10 -3
- package/scripts/lint/lint-related-scope.ts +4 -1
- package/scripts/notify/telegram-test.ts +10 -5
- package/scripts/report/report-format-reference.ts +2 -0
- package/scripts/review/acceptance-map-check.ts +61 -0
- package/scripts/review/acceptance-map.ts +205 -0
- package/scripts/review/review-brief-cli.ts +1 -1
- package/scripts/rules/agent-model.ts +59 -0
- package/scripts/rules/delivered-rules.ts +11 -2
- package/scripts/rules/filing-cap.ts +1 -0
- package/scripts/rules/firing-point.ts +6 -5
- package/scripts/rules/guard-remedy.ts +117 -0
- package/scripts/rules/issue-comments.ts +67 -6
- package/scripts/rules/last-prompt.ts +50 -5
- package/scripts/rules/oracle-list-cli.ts +7 -0
- package/scripts/rules/piped-verification.ts +3 -1
- package/scripts/rules/rule-list.ts +4 -1
- package/scripts/rules/rule-registry-rows.ts +10 -0
- package/scripts/rules/rule-registry.ts +7 -4
- package/scripts/rules/rule-rewrite.ts +114 -0
- package/scripts/rules/rule-value.ts +7 -1
- package/scripts/rules/shell-segments.ts +15 -0
- package/scripts/rules/stop-decision.ts +77 -0
- package/scripts/rules/stop-rules.ts +147 -47
- package/scripts/rules/tail-commands.ts +15 -1
- package/scripts/run/board/run-board-cli.ts +2 -0
- package/scripts/run/board/run-board-closed.ts +8 -2
- package/scripts/run/board/run-board-github.ts +9 -1
- package/scripts/run/board/run-board-header.ts +4 -1
- package/scripts/run/board/run-board-labels.ts +2 -0
- package/scripts/run/board/run-board-layout.ts +1 -1
- package/scripts/run/board/run-board-read.ts +16 -0
- package/scripts/run/board/run-board-reason.ts +10 -1
- package/scripts/run/board/run-board-render-legend.ts +1 -0
- package/scripts/run/board/run-board-render-slot.ts +1 -1
- package/scripts/run/board/run-board-render-waits.ts +41 -0
- package/scripts/run/board/run-board-render.ts +6 -1
- package/scripts/run/board/run-board-row-yield.ts +1 -0
- package/scripts/run/board/run-board-state.ts +5 -0
- package/scripts/run/board/run-board-status.ts +72 -21
- package/scripts/run/board/run-board-tick.ts +5 -1
- package/scripts/run/cut/run-cut-cli.ts +3 -2
- package/scripts/run/cut/run-cut-report.ts +16 -0
- package/scripts/run/detached-launch.ts +23 -4
- package/scripts/run/entry/run-entry-cli.ts +8 -1
- package/scripts/run/event/run-event-render.ts +1 -0
- package/scripts/run/event/run-event-scope.ts +19 -1
- package/scripts/run/event/run-event-stream-emit.ts +13 -6
- package/scripts/run/event/run-event-stream.ts +4 -0
- package/scripts/run/hold/run-hold-session.ts +46 -0
- package/scripts/run/hold/run-hold.ts +7 -1
- package/scripts/run/launch-priority.ts +32 -0
- package/scripts/run/merge/run-merge-cli.ts +16 -65
- package/scripts/run/merge/run-merge-signals.ts +99 -0
- package/scripts/run/merge/run-merge-steps.ts +11 -1
- package/scripts/run/merge/run-merge.ts +21 -9
- package/scripts/run/run-liveness.ts +1 -1
- package/scripts/run/run-poll-hook.ts +157 -0
- package/scripts/run/run-step-cli.ts +22 -15
- package/scripts/run/run-step-section.ts +85 -0
- package/scripts/run/ship/run-ship-cli.ts +5 -12
- package/scripts/run/ship/run-ship-detach.ts +9 -0
- package/scripts/run/ship/run-ship-next.ts +10 -2
- package/scripts/run/ship/run-ship-overlap.ts +195 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +33 -15
- package/scripts/run/ship/run-ship-preflight.ts +28 -2
- package/scripts/run/ship/run-ship-return.ts +31 -7
- package/scripts/run/ship/run-ship-review-steps.ts +12 -10
- package/scripts/run/ship/run-ship-steps.ts +1 -1
- package/scripts/run/ship/run-ship-stop-context.ts +206 -0
- package/scripts/run/ship/run-ship-sync.ts +14 -6
- package/scripts/test/test-e2e-guard.ts +30 -5
- package/scripts/test/test-unit-guard.ts +16 -1
- package/scripts/test/unit-worker-share.ts +26 -4
- package/scripts/time-runtime/time-shell.ts +29 -4
- package/scripts/time-runtime/time-spans.ts +1 -0
- package/scripts/time-runtime/time-tool-call.ts +7 -0
- package/templates/gitignore +6 -2
- package/dist/hooks/chunk-K4LMBQC2.js +0 -68
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import type { CommandUsage } from './josh-command-types'
|
|
2
|
+
|
|
3
|
+
// The usage of the commands `docs/josh-commands-run.md` documents from `run:progress` on — the run's
|
|
4
|
+
// watchers, the lanes, and the session-budget and document-reading commands — keyed by command name.
|
|
5
|
+
// The page's usage blocks are generated from this table and `josh help <command>` prints it, so an
|
|
6
|
+
// example or a flag is written once, here (#3937). The run lifecycle before it is `josh-usage-run.ts`.
|
|
7
|
+
const BARE = { arguments: '' }
|
|
8
|
+
const PATH_DIR = '--path <dir>'
|
|
9
|
+
|
|
10
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
11
|
+
const SESSION_USAGE: Readonly<Record<string, CommandUsage>> = {
|
|
12
|
+
'run:progress': {
|
|
13
|
+
examples: [
|
|
14
|
+
{ arguments: '--output <path>' },
|
|
15
|
+
{ arguments: '--once', note: 'five labelled lines now, whatever the clock says' },
|
|
16
|
+
{ arguments: '--interval 20 --repo joshuafolkken/app-kit --hours 4' },
|
|
17
|
+
],
|
|
18
|
+
flags: [
|
|
19
|
+
{
|
|
20
|
+
names: ['--mark'],
|
|
21
|
+
description:
|
|
22
|
+
'record that a real report happened without printing a line (keeps the last line for `run:wake --list`).',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
names: ['--path'],
|
|
26
|
+
description:
|
|
27
|
+
'print the ambient heartbeat log\'s path and exit. Every heartbeat line is mirrored there, so `tail -F "$(pnpm josh run:progress --path)"` follows the run across a `backlogrun` session cut. Reads no run state, so it answers in a lane child too.',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
names: ['--interval <min>'],
|
|
31
|
+
description:
|
|
32
|
+
'silence interval (default 20; also `JOSH_PROGRESS_INTERVAL_MINUTES`, then `josh.progress_interval_minutes`).',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
names: ['--wait'],
|
|
36
|
+
description:
|
|
37
|
+
'start once in the background: each report goes to the event stream and ambient log, never stdout; exits only on an arrival, `josh followup` ending the run, or `--hours`.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
names: ['--hours <n>'],
|
|
41
|
+
description: 'how long the watcher lives (default 8 with `--wait`, 1 otherwise).',
|
|
42
|
+
},
|
|
43
|
+
{ names: ['--repo <owner/name>'], description: 'scopes the read.' },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
'run:board': {
|
|
47
|
+
examples: [
|
|
48
|
+
{ arguments: '', note: 'redraw until interrupted' },
|
|
49
|
+
{ arguments: '--once', note: 'one frame, then exit' },
|
|
50
|
+
{ arguments: '--chat', note: 'one frame for a chat, recorded as a progress report' },
|
|
51
|
+
{
|
|
52
|
+
arguments: '--every 5',
|
|
53
|
+
note: 'the --chat frame as a 📊 Progress Telegram every 5 minutes, until the run ends',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
flags: [
|
|
57
|
+
{
|
|
58
|
+
names: ['--chat'],
|
|
59
|
+
description:
|
|
60
|
+
'answers a `backlogrun` progress question: the frame `--once` draws, with only `🧠` on the machine line and no escapes; it records the report as `run:progress --mark` does.',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
names: ['--every <minutes>'],
|
|
64
|
+
description:
|
|
65
|
+
'sends the `--chat` frame as a `📊 Progress` Telegram now and every `<minutes>` until the run ends — only when a person asks for it.',
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
'run:watcher:guard': { examples: [BARE] },
|
|
70
|
+
'run:stranded': { examples: [BARE] },
|
|
71
|
+
'lane:open': { examples: [{ arguments: '1490', note: 'prints the lane directory on stdout' }] },
|
|
72
|
+
'lane:close': {
|
|
73
|
+
examples: [{ arguments: '1490' }, { arguments: '--all' }],
|
|
74
|
+
flags: [{ names: ['--all'], description: 'closes every lane.' }],
|
|
75
|
+
},
|
|
76
|
+
'lane:list': { examples: [BARE] },
|
|
77
|
+
'lane:prune': { examples: [BARE] },
|
|
78
|
+
'lane:output': {
|
|
79
|
+
examples: [
|
|
80
|
+
{ arguments: '1713 /abs/path/to/agent-7.jsonl', note: 'record it; prints the path back' },
|
|
81
|
+
{ arguments: '1713', note: 'read it; prints the path, or `none`' },
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
'lane:dispatch': {
|
|
85
|
+
examples: [
|
|
86
|
+
{
|
|
87
|
+
arguments: '1749',
|
|
88
|
+
note: "prints the child's pid; a refusal is an empty capture and exit 1",
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
flags: [
|
|
92
|
+
{
|
|
93
|
+
names: ['JOSH_{SCHEDULER,WORKER,REVIEWER}_MODEL'],
|
|
94
|
+
description:
|
|
95
|
+
'Claude Code role overrides; Anthropic defaults are respectively `claude-opus-5-5`, `claude-opus-5-5`, and `claude-opus-5-5`. Codex keeps its provider-specific model.',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
names: ['JOSH_{SCHEDULER,WORKER,REVIEWER}_EFFORT'],
|
|
99
|
+
description:
|
|
100
|
+
'role effort overrides for either provider; defaults are `medium`, `medium`, and `high`.',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
names: ['JOSH_REVIEWER_VERIFICATION_{MODEL,EFFORT}'],
|
|
104
|
+
description:
|
|
105
|
+
'review round 2 and later (the verification pass); Anthropic defaults are `claude-sonnet-5-5` / `high`, falling back to `JOSH_REVIEWER_*`.',
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
'lane:await': {
|
|
110
|
+
examples: [
|
|
111
|
+
{ arguments: '1749 1750', note: 'block until either lane completes' },
|
|
112
|
+
{
|
|
113
|
+
arguments: '1749 1750 --owner "$PPID"',
|
|
114
|
+
note: 'reclaim the carry record for a resumed conversation first',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
'lane:launch': {
|
|
119
|
+
examples: [
|
|
120
|
+
{ arguments: '1749', note: 'every lane after the first' },
|
|
121
|
+
{
|
|
122
|
+
arguments: '1749 --stash "backlogrun: josh latest before lanes"',
|
|
123
|
+
note: 'the first lane only',
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
'lane:sample': { examples: [{ arguments: '', note: 'one machine-load reading' }] },
|
|
128
|
+
'lane:stats': {
|
|
129
|
+
examples: [{ arguments: '--period 7', note: "a 7-day period's stage medians and maxima" }],
|
|
130
|
+
},
|
|
131
|
+
cost: {
|
|
132
|
+
examples: [
|
|
133
|
+
{
|
|
134
|
+
arguments: '--cut',
|
|
135
|
+
note: 'compare billed input per request with the shared 135,000 context-cut threshold',
|
|
136
|
+
},
|
|
137
|
+
{ arguments: '--over <tokens>', note: 'compare with an explicit limit' },
|
|
138
|
+
{ arguments: `--cut ${PATH_DIR}`, note: 'Anthropic project or current OpenAI worktree' },
|
|
139
|
+
],
|
|
140
|
+
flags: [
|
|
141
|
+
{
|
|
142
|
+
names: [PATH_DIR],
|
|
143
|
+
description:
|
|
144
|
+
'selects another Anthropic project; OpenAI accepts only linked checkouts of the current project.',
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
'doc:section': {
|
|
149
|
+
examples: [
|
|
150
|
+
{ arguments: '<file.md> "<heading>"' },
|
|
151
|
+
{ arguments: 'backlogrun.md "The hand-off"' },
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
'read:set': {
|
|
155
|
+
examples: [
|
|
156
|
+
{ arguments: '', note: 'every entry point' },
|
|
157
|
+
{ arguments: 'backlogrun', note: 'one of them' },
|
|
158
|
+
{ arguments: 'backlogrun --json' },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
'doc:read': {
|
|
162
|
+
examples: [
|
|
163
|
+
{ arguments: 'CLAUDE.md', note: 'under the cap: prints the document' },
|
|
164
|
+
{ arguments: 'backlogrun.md', note: 'over the cap: prints a directive, no content' },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
'read:files': {
|
|
168
|
+
examples: [
|
|
169
|
+
{ arguments: 'a.ts b.ts c.ts', note: 'under the cap: prints each file under its own header' },
|
|
170
|
+
{
|
|
171
|
+
arguments: 'a.ts big.ts',
|
|
172
|
+
note: 'over the cap: prints a directive to Read them in one turn, no content',
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
'edit:files': {
|
|
177
|
+
examples: [
|
|
178
|
+
{
|
|
179
|
+
arguments: 'plan.txt',
|
|
180
|
+
note: 'applies every block in the plan, one line per edit reporting the outcome',
|
|
181
|
+
},
|
|
182
|
+
{ arguments: "- <<'EDITS'", note: 'plan from stdin, then EDITS' },
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
time: {
|
|
186
|
+
examples: [
|
|
187
|
+
{ arguments: '', note: 'the last run tree, wall clock and cost by role' },
|
|
188
|
+
{ arguments: '--run', note: 'the same run-tree scope, named explicitly' },
|
|
189
|
+
{ arguments: '--json', note: 'the same figures, machine-readable' },
|
|
190
|
+
{ arguments: PATH_DIR, note: "read another project's transcripts from this checkout" },
|
|
191
|
+
],
|
|
192
|
+
flags: [
|
|
193
|
+
{
|
|
194
|
+
names: ['--run'],
|
|
195
|
+
description:
|
|
196
|
+
'(default) the whole run tree, wall clock led beside dollars. It is the only scope; any other flag is a usage error (exit 1). History: `docs/maintainers/josh-commands-run-rationale.md` → "`josh cost` and `josh time` lost their report scopes".',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
names: [PATH_DIR],
|
|
200
|
+
description:
|
|
201
|
+
'aim the read at another project (absolute path); keeps the `cwd` behavior when absent.',
|
|
202
|
+
},
|
|
203
|
+
{ names: ['--json'], description: 'the run tree, machine-readable.' },
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
'cost:audit': {
|
|
207
|
+
examples: [
|
|
208
|
+
{ arguments: '', note: 'the last 7 days against the 7 before' },
|
|
209
|
+
{ arguments: '--period 30', note: 'the last 30 days against the 30 before' },
|
|
210
|
+
],
|
|
211
|
+
flags: [
|
|
212
|
+
{
|
|
213
|
+
names: ['--period <days>'],
|
|
214
|
+
description: 'the length of each period, a positive whole number of days (default 7).',
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
},
|
|
218
|
+
retrospective: {
|
|
219
|
+
examples: [{ arguments: '', note: 'the digest for the run this checkout carries' }],
|
|
220
|
+
},
|
|
221
|
+
eval: {
|
|
222
|
+
examples: [
|
|
223
|
+
{ arguments: '', note: 'every scenario' },
|
|
224
|
+
{ arguments: 'consult-not-execute', note: 'one scenario by name' },
|
|
225
|
+
],
|
|
226
|
+
flags: [
|
|
227
|
+
{ names: ['JOSH_EVAL_MODEL'], description: 'the model to run against (default `sonnet`).' },
|
|
228
|
+
{
|
|
229
|
+
names: ['JOSH_EVAL_CONCURRENCY'],
|
|
230
|
+
description:
|
|
231
|
+
'how many sessions run at once (default `5`); a non-positive-integer value is refused.',
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
}
|
|
236
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
237
|
+
|
|
238
|
+
export { SESSION_USAGE }
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import type { CommandUsage } from './josh-command-types'
|
|
2
|
+
|
|
3
|
+
// The usage of the commands `docs/josh-commands-automation.md` documents under "Workflow",
|
|
4
|
+
// "Versioning", "Maintenance" and "Git hooks", keyed by command name. The page's usage blocks are
|
|
5
|
+
// generated from this table and `josh help <command>` prints it, so an example or a flag is written
|
|
6
|
+
// once, here (#3939).
|
|
7
|
+
const PR_TITLE = '"PR title #N"'
|
|
8
|
+
const ISSUE_URL = '--issue-url "https://..."'
|
|
9
|
+
const REVIEW_ISSUE = '--issue 2325'
|
|
10
|
+
const CHECK = '--check'
|
|
11
|
+
const JSON_FLAG = '--json'
|
|
12
|
+
const BODY_FILE_NOTE =
|
|
13
|
+
'(`-` reads stdin); use this whenever the body carries a backtick or `$`. Passing both forms is refused.'
|
|
14
|
+
|
|
15
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
16
|
+
const WORKFLOW_USAGE: Readonly<Record<string, CommandUsage>> = {
|
|
17
|
+
followup: {
|
|
18
|
+
examples: [
|
|
19
|
+
{ arguments: PR_TITLE, note: 'merges (default)' },
|
|
20
|
+
{ arguments: String.raw`${PR_TITLE} --notify-message "Implemented X:\n- change 1"` },
|
|
21
|
+
{ arguments: `${PR_TITLE} --notify-message-file completion.md` },
|
|
22
|
+
{ arguments: `${PR_TITLE} --ai-review-ignore-reason "false positive"` },
|
|
23
|
+
{ arguments: `${PR_TITLE} --no-merge`, note: 'do the work, leave the PR open' },
|
|
24
|
+
],
|
|
25
|
+
flags: [
|
|
26
|
+
{
|
|
27
|
+
names: ['--no-merge'],
|
|
28
|
+
description:
|
|
29
|
+
'do the follow-up work but do not merge; leaves the PR open (the only flag that stops the merge). `--merge` is a deprecated no-op. A PR already merged by hand skips the CI wait, the AI-review scan and the merge and runs only the post-merge tail; a completion report already on the Issue is not posted again.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
names: ['--notify-message'],
|
|
33
|
+
description: 'inline completion body; `\\n` expands to newlines.',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
names: ['--notify-message-file'],
|
|
37
|
+
description: `read the completion body from a file ${BODY_FILE_NOTE}`,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
names: ['--ai-review-ignore-reason'],
|
|
41
|
+
description: 'reason to dismiss an AI-review finding.',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
notify: {
|
|
46
|
+
examples: [
|
|
47
|
+
{ arguments: String.raw`--task-type planning ${ISSUE_URL} --body="- bullet 1\n- bullet 2"` },
|
|
48
|
+
{
|
|
49
|
+
arguments: `--task-type confirmation ${ISSUE_URL} --body-file r.md --recommended "Go" --alternative "Wait"`,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
flags: [
|
|
53
|
+
{
|
|
54
|
+
names: ['--task-type'],
|
|
55
|
+
description:
|
|
56
|
+
'one of `planning` 📋, `completion` ✅, `failure` ❌, `warning` ⚠️, `kickoff_retry` 🔄, `confirmation` ⏸️. Do not send `completion` or `warning` by hand — `josh followup` sends them.',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
names: ['--body', "--body=$'…'"],
|
|
60
|
+
description: "inline body; use `--body=$'…'` when it starts with `-`.",
|
|
61
|
+
},
|
|
62
|
+
{ names: ['--body-file'], description: `read the body from a file ${BODY_FILE_NOTE}` },
|
|
63
|
+
{
|
|
64
|
+
names: ['--repo-name', '--issue-url', '--pr-url'],
|
|
65
|
+
description:
|
|
66
|
+
'header repository, resolved in that order, then the working directory. The issue title is read from `--issue-url`.',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
names: ['--recommended', '--alternative'],
|
|
70
|
+
description:
|
|
71
|
+
'the choices appended under `JOSH_SESSION_LANG` headings; `--recommended` is required for `confirmation`, `--alternative` is repeatable.',
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
'observations:flush': { examples: [{ arguments: '' }] },
|
|
76
|
+
'measure:rerun': { examples: [{ arguments: '2212' }] },
|
|
77
|
+
'review:record': {
|
|
78
|
+
examples: [
|
|
79
|
+
{ arguments: `${REVIEW_ISSUE} bug-risks:medium:src/foo.ts:42 tests:low:a.test.ts` },
|
|
80
|
+
{ arguments: REVIEW_ISSUE, note: 'a zero-finding round — records one `none` line' },
|
|
81
|
+
{
|
|
82
|
+
arguments: `${REVIEW_ISSUE} --comment`,
|
|
83
|
+
note: 'a round that passed after the PR opened — an Issue comment, no append',
|
|
84
|
+
},
|
|
85
|
+
{ arguments: `${CHECK} ${REVIEW_ISSUE}`, note: 'the merge gate: was it recorded?' },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
bump: { examples: [{ arguments: 'major' }, { arguments: 'minor' }, { arguments: 'patch' }] },
|
|
89
|
+
release: {
|
|
90
|
+
examples: [
|
|
91
|
+
{ arguments: '' },
|
|
92
|
+
{ arguments: '--dry-run', note: 'count and report, write nothing' },
|
|
93
|
+
],
|
|
94
|
+
flags: [
|
|
95
|
+
{
|
|
96
|
+
names: ['--dry-run'],
|
|
97
|
+
description:
|
|
98
|
+
'count and report only; writes nothing, fetches nothing, and creates no work tree.',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
names: ['--help', '-h'],
|
|
102
|
+
description:
|
|
103
|
+
'print the usage line and exit 0 without fetching or releasing. Any other argument is refused with the usage line and a non-zero exit, before anything is fetched.',
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
'release:scope': {
|
|
108
|
+
examples: [
|
|
109
|
+
{ arguments: '', note: '→ required | skip | unknown' },
|
|
110
|
+
{ arguments: '--json', note: '{"scope":"…","reason":"…"} on one line' },
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
'ruleset:check': {
|
|
114
|
+
examples: [
|
|
115
|
+
{ arguments: '', note: 'report only' },
|
|
116
|
+
{ arguments: '--apply', note: 'add the missing checks to the existing rule' },
|
|
117
|
+
],
|
|
118
|
+
flags: [
|
|
119
|
+
{
|
|
120
|
+
names: ['--apply'],
|
|
121
|
+
description:
|
|
122
|
+
"append the missing checks to the ruleset's required-checks rule (or to the branch protection's contexts). It never creates a ruleset: with none, create one under Settings → Rules → Rulesets, then rerun. Writing a repository setting needs admin access, so only this flag writes — `josh sync` and `josh doctor` never do.",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
'audit:provision': {
|
|
127
|
+
examples: [
|
|
128
|
+
{ arguments: '', note: 'no-op if a scanner is already present' },
|
|
129
|
+
{ arguments: '--force', note: 'ignore backoff, allow a longer download' },
|
|
130
|
+
],
|
|
131
|
+
flags: [
|
|
132
|
+
{
|
|
133
|
+
names: ['--force'],
|
|
134
|
+
description:
|
|
135
|
+
'ignore the 6-hour failure backoff and allow a longer download window; the command to run after fixing a network problem.',
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
'reconcile-templates': {
|
|
140
|
+
examples: [
|
|
141
|
+
{ arguments: '', note: 'regenerate copy templates + record tripwire hashes' },
|
|
142
|
+
{ arguments: CHECK, note: 'verify templates are in sync; non-zero on drift' },
|
|
143
|
+
],
|
|
144
|
+
flags: [
|
|
145
|
+
{
|
|
146
|
+
names: [CHECK],
|
|
147
|
+
description:
|
|
148
|
+
'verify only; exits non-zero on drift. A pre-commit hook runs this when a tracked source or copy template is staged.',
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
'pre-push-unit': { examples: [{ arguments: '' }] },
|
|
153
|
+
'reserved-run': {
|
|
154
|
+
examples: [
|
|
155
|
+
{ arguments: '2 -- pnpm install', note: 'hold 2 cores while installing' },
|
|
156
|
+
{ arguments: '1 -- pnpm josh audit', note: 'hold 1 core while scanning' },
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
'pre-commit-type-check': { examples: [{ arguments: '' }] },
|
|
160
|
+
'pr:classification': {
|
|
161
|
+
examples: [{ arguments: '', note: 'run by CI on a pull request; fails without one label' }],
|
|
162
|
+
},
|
|
163
|
+
'observation:record': {
|
|
164
|
+
examples: [
|
|
165
|
+
{ arguments: "flaky-e2e d1 'tests/e2e/login.test.ts' 'times out on CI only'" },
|
|
166
|
+
{
|
|
167
|
+
arguments: "flaky-e2e d1 'src/app.ts' 'fails there too' --checkout ~/Development/app",
|
|
168
|
+
note: "another repository's ledger",
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
flags: [
|
|
172
|
+
{
|
|
173
|
+
names: ['--checkout <path>'],
|
|
174
|
+
description: "count and append in that repository's `.josh/observations/` instead.",
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
'release:github': {
|
|
179
|
+
examples: [
|
|
180
|
+
{ arguments: '', note: 'run by CI with GH_TOKEN, RELEASE_TAG and GITHUB_REPOSITORY set' },
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
'latest:scope': {
|
|
184
|
+
examples: [
|
|
185
|
+
{ arguments: '', note: 'required or skip, the reason on stderr' },
|
|
186
|
+
{ arguments: '--record', note: 'note a finished josh latest run' },
|
|
187
|
+
{ arguments: JSON_FLAG, note: 'the verdict and the reason as JSON' },
|
|
188
|
+
],
|
|
189
|
+
flags: [
|
|
190
|
+
{ names: ['--record'], description: 'write the completion record `josh latest` ends with.' },
|
|
191
|
+
{ names: [JSON_FLAG], description: 'emit the verdict and its reason as JSON.' },
|
|
192
|
+
],
|
|
193
|
+
},
|
|
194
|
+
'latest:guard': { examples: [{ arguments: '', note: 'refuses inside a lane' }] },
|
|
195
|
+
'prevent-main-commit': { examples: [{ arguments: '', note: 'run by the pre-commit hook' }] },
|
|
196
|
+
'check-commit-message': {
|
|
197
|
+
examples: [{ arguments: '.git/COMMIT_EDITMSG', note: 'run by the commit-msg hook' }],
|
|
198
|
+
},
|
|
199
|
+
'secretlint-scan': {
|
|
200
|
+
examples: [{ arguments: 'src/app.ts .env.example', note: 'the staged paths' }],
|
|
201
|
+
},
|
|
202
|
+
'pre-commit-lint': {
|
|
203
|
+
examples: [
|
|
204
|
+
{ arguments: 'cspell src/app.ts' },
|
|
205
|
+
{ arguments: 'prettier src/app.ts' },
|
|
206
|
+
{ arguments: 'eslint src/app.ts' },
|
|
207
|
+
],
|
|
208
|
+
},
|
|
209
|
+
}
|
|
210
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
211
|
+
|
|
212
|
+
export { WORKFLOW_USAGE }
|
package/scripts/josh/josh.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { doctor_consumer } from '#scripts/doctor/doctor-consumer'
|
|
2
|
+
import { command_usage } from './command-usage'
|
|
2
3
|
import { find_package_directory, josh_logic, UNKNOWN_COMMAND_EXIT_CODE } from './josh-logic'
|
|
3
4
|
|
|
4
5
|
const ARGV_OFFSET = 2
|
|
@@ -12,10 +13,6 @@ const HELP_COMMANDS: ReadonlySet<string> = new Set(['help', '--help', '-h'])
|
|
|
12
13
|
// A bare `--all` in the command slot is a help request, not a command.
|
|
13
14
|
const ALL_FLAG = '--all'
|
|
14
15
|
|
|
15
|
-
function print_help(is_all: boolean, is_consumer: boolean): void {
|
|
16
|
-
console.info(josh_logic.format_help(is_all, is_consumer))
|
|
17
|
-
}
|
|
18
|
-
|
|
19
16
|
// Both halves go to stderr. The help listing is a diagnosis here, not the answer, and a shell
|
|
20
17
|
// wiring `--port $(josh port dev)` reads stdout alone, so a command name this kit cannot resolve
|
|
21
18
|
// has to leave that stream empty rather than substitute the whole toolkit index (#825).
|
|
@@ -24,6 +21,18 @@ function handle_unknown(cmd: string): never {
|
|
|
24
21
|
process.exit(1)
|
|
25
22
|
}
|
|
26
23
|
|
|
24
|
+
// `josh help <command>` prints that one command's usage — the text its reference page renders
|
|
25
|
+
// (#3932); a flag in the topic slot is still a listing request (`josh --help --all`).
|
|
26
|
+
function print_help(is_all: boolean, is_consumer: boolean, topic: string | undefined): void {
|
|
27
|
+
if (topic === undefined || topic.startsWith('-')) {
|
|
28
|
+
console.info(josh_logic.format_help(is_all, is_consumer))
|
|
29
|
+
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.info(command_usage.format_command_help(topic) ?? handle_unknown(topic))
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
// `process.exit` truncates a piped stdout at its buffer size, and the output at risk is the script's
|
|
28
37
|
// own — `scripts/gate/verification-gate.ts` writes its per-check blocks
|
|
29
38
|
// and its failure summary through this process, and sets `process.exitCode` rather than exiting for
|
|
@@ -44,7 +53,7 @@ async function main(): Promise<void> {
|
|
|
44
53
|
const is_consumer = doctor_consumer.is_kit_consumer(find_package_directory(process.cwd()))
|
|
45
54
|
|
|
46
55
|
if (!cmd || cmd === ALL_FLAG || HELP_COMMANDS.has(cmd)) {
|
|
47
|
-
print_help(is_all, is_consumer)
|
|
56
|
+
print_help(is_all, is_consumer, process.argv[ARGV_OFFSET + 1])
|
|
48
57
|
|
|
49
58
|
return
|
|
50
59
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { ancestor_directories } from '#scripts/lib/ancestor-directories'
|
|
4
|
+
|
|
5
|
+
const PACKAGE_JSON = 'package.json'
|
|
6
|
+
|
|
7
|
+
// Resolve the kit package root by ascending to the nearest package.json. This works both
|
|
8
|
+
// from the bundled dist/josh.js (one level under the root) and from the tsx source at
|
|
9
|
+
// scripts/josh/ (two levels), so this file's depth no longer has to be hard-coded.
|
|
10
|
+
// A leaf apart from `josh-logic`, so a bundled command can import it without pulling the
|
|
11
|
+
// dispatcher's main-guarded closure into its single-file bundle.
|
|
12
|
+
function find_package_directory(start_directory: string): string {
|
|
13
|
+
return (
|
|
14
|
+
ancestor_directories.nearest(start_directory, (directory) =>
|
|
15
|
+
existsSync(path.join(directory, PACKAGE_JSON)),
|
|
16
|
+
) ?? start_directory
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { find_package_directory }
|
|
@@ -73,8 +73,14 @@ function seated_limit(limit: number): number {
|
|
|
73
73
|
// Never negative: a repository holding more `in-progress` issues than the limit allows — the limit
|
|
74
74
|
// was lowered, or a stale label outlived its run — has no free lane, and a negative count read as
|
|
75
75
|
// "how many to offer" would be a slice nobody meant.
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
//
|
|
77
|
+
// **A lane that holds no place under the limit still holds its port seat** (joshuafolkken/kit#3967):
|
|
78
|
+
// `seated` counts every open lane, so the free count never offers more launches than seats are left.
|
|
79
|
+
function free_lanes(limit: number, occupied: number, seated = occupied): number {
|
|
80
|
+
const by_limit = seated_limit(limit) - occupied
|
|
81
|
+
const by_seats = lane_seed_policy.LAST_LANE_SEAT - seated
|
|
82
|
+
|
|
83
|
+
return Math.max(NO_LANES, Math.min(by_limit, by_seats))
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
const lane_capacity = {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { lane_ledger, type GateCheckRecord, type GateEntry, type LedgerEntry } from './lane-ledger'
|
|
2
|
+
import { lane_stage_stats } from './lane-stage-stats'
|
|
3
|
+
import { lane_stats, type StatsWindow } from './lane-stats'
|
|
4
|
+
|
|
5
|
+
// Which check a gate waited on: the ledger's per-check rows of one period reduced to one row per check
|
|
6
|
+
// — median, maximum, how many runs and how many were reused — printed last by `josh lane:stats`. The
|
|
7
|
+
// rows are in the order the checks first appear.
|
|
8
|
+
//
|
|
9
|
+
// **A reused check is counted, never timed.** It started no process, so its zero would pull the median
|
|
10
|
+
// toward a check that never ran; a check with only reused rows prints `not measured`.
|
|
11
|
+
|
|
12
|
+
const MS_PER_SECOND = 1000
|
|
13
|
+
const DECIMALS = 1
|
|
14
|
+
const COLUMNS = ['check', 'median (s)', 'max (s)', 'runs', 'reused'] as const
|
|
15
|
+
|
|
16
|
+
function is_gate(entry: LedgerEntry): entry is GateEntry {
|
|
17
|
+
return entry.kind === lane_ledger.KIND.GATE
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function cell(milliseconds: number | undefined): string {
|
|
21
|
+
return milliseconds === undefined
|
|
22
|
+
? lane_stage_stats.NOT_MEASURED
|
|
23
|
+
: (milliseconds / MS_PER_SECOND).toFixed(DECIMALS)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function check_row(label: string, checks: ReadonlyArray<GateCheckRecord>): string {
|
|
27
|
+
const runs = checks.filter((check) => check.label === label)
|
|
28
|
+
const timed = runs.filter((check) => check.is_reused !== true).map((check) => check.elapsed_ms)
|
|
29
|
+
|
|
30
|
+
return lane_stats.to_row([
|
|
31
|
+
label,
|
|
32
|
+
cell(lane_stats.median(timed)),
|
|
33
|
+
cell(lane_stats.peak(timed)),
|
|
34
|
+
String(runs.length),
|
|
35
|
+
String(runs.length - timed.length),
|
|
36
|
+
])
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// The period's table: `entries` is the whole ledger, filtered here to `window`.
|
|
40
|
+
function table(entries: ReadonlyArray<LedgerEntry>, window: StatsWindow): string {
|
|
41
|
+
const checks = lane_stats
|
|
42
|
+
.in_window(entries, window)
|
|
43
|
+
.filter(is_gate)
|
|
44
|
+
.flatMap((gate) => gate.checks ?? [])
|
|
45
|
+
const labels = [...new Set(checks.map((check) => check.label))]
|
|
46
|
+
|
|
47
|
+
return [
|
|
48
|
+
lane_stats.to_row(COLUMNS),
|
|
49
|
+
lane_stats.to_row(COLUMNS.map(() => '---')),
|
|
50
|
+
...labels.map((label) => check_row(label, checks)),
|
|
51
|
+
].join('\n')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const lane_check_stats = { table }
|
|
55
|
+
|
|
56
|
+
export { lane_check_stats }
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import { agent_role_profile } from '#scripts/agent/agent-role-profile'
|
|
1
2
|
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
2
3
|
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
3
4
|
import { run_ship_next, type ShipResume } from '#scripts/run/ship/run-ship-next'
|
|
4
5
|
import type { Stage } from '#scripts/run/ship/run-ship-stage'
|
|
6
|
+
import { run_ship_stop_context, type StopContext } from '#scripts/run/ship/run-ship-stop-context'
|
|
5
7
|
|
|
6
8
|
interface ShipStop extends ShipResume {
|
|
7
9
|
stage: Stage
|
|
10
|
+
context?: StopContext
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
const CHILD_INVOCATION = 'fullrun'
|
|
14
|
+
const LINE_BREAK = '\n'
|
|
11
15
|
// What a brokered reviewer's prompt ends with, so the one pattern below finds it too.
|
|
12
16
|
const REVIEW_INVOCATION = 'the reviewer of lane'
|
|
13
17
|
const RESUME_GUIDE = '.claude/skills/workflow-commands/pre-gate-cut.md'
|
|
@@ -79,14 +83,41 @@ function outage_resume_invocation(issue: string): string {
|
|
|
79
83
|
// **A known stage puts the next command in the prompt**, so the relaunched
|
|
80
84
|
// session runs it rather than re-deriving it from `chain-rule.md`. An OpenAI lane's supervisor sees only
|
|
81
85
|
// that the ship failed, not where, so without a stage the prompt points at `run:step` as before.
|
|
86
|
+
//
|
|
87
|
+
// **A stop that carries its context puts it in the prompt too** — the failed output's
|
|
88
|
+
// tail and the changed files (`run-ship-stop-context.ts`), so the session starts at the fix rather than
|
|
89
|
+
// at `josh ship --log` and `git diff` (joshuafolkken/kit#3923).
|
|
90
|
+
//
|
|
91
|
+
// The context gets what the rest of the prompt leaves of the one argv element's cap, so the whole
|
|
92
|
+
// prompt still launches (joshuafolkken/kit#3964).
|
|
93
|
+
function known_stop_lines(
|
|
94
|
+
issue: string,
|
|
95
|
+
stop: ShipStop,
|
|
96
|
+
frame: ReadonlyArray<string>,
|
|
97
|
+
): ReadonlyArray<string> {
|
|
98
|
+
const { context } = stop
|
|
99
|
+
const is_excerpted = run_ship_stop_context.has_excerpt(context)
|
|
100
|
+
const next = run_ship_next.next_step(issue, stop.stage, stop, is_excerpted)
|
|
101
|
+
|
|
102
|
+
if (context === undefined) return [next]
|
|
103
|
+
|
|
104
|
+
const fixed = [...frame, next].join(LINE_BREAK).length + LINE_BREAK.length
|
|
105
|
+
const budget = agent_role_profile.MAX_VALUE_LENGTH - fixed
|
|
106
|
+
|
|
107
|
+
return [next, run_ship_stop_context.describe(issue, context, budget)]
|
|
108
|
+
}
|
|
109
|
+
|
|
82
110
|
function ship_stop_invocation(issue: string, stop?: ShipStop): string {
|
|
83
111
|
const opening = `Resuming the lane child for issue ${issue_cite.plain(issue)} after its detached ship supervisor stopped at a failed stage — do not re-read the workflow-commands entry documents (SKILL.md, fullrun.md).`
|
|
84
|
-
const
|
|
112
|
+
const closing = `Do not re-plan or re-implement what is already on the branch. ${child_invocation(issue)}`
|
|
113
|
+
const middle =
|
|
85
114
|
stop === undefined
|
|
86
|
-
?
|
|
87
|
-
|
|
115
|
+
? [
|
|
116
|
+
`Run \`pnpm josh run:step ${issue}\` and read the stopped report it names, fix what stopped the ship, then hand the region back per chain-rule.md.`,
|
|
117
|
+
]
|
|
118
|
+
: known_stop_lines(issue, stop, [opening, closing])
|
|
88
119
|
|
|
89
|
-
return
|
|
120
|
+
return [opening, ...middle, closing].join(LINE_BREAK)
|
|
90
121
|
}
|
|
91
122
|
|
|
92
123
|
const lane_child_invocation = {
|
|
@@ -7,7 +7,7 @@ import { IN_PROGRESS_LABEL } from '#scripts/issue/issue-labels'
|
|
|
7
7
|
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
8
8
|
import { session_cite } from '#scripts/issue/session-cite'
|
|
9
9
|
import { telegram_notify } from '#scripts/notify/telegram-notify'
|
|
10
|
-
import { detached_launch } from '#scripts/run/detached-launch'
|
|
10
|
+
import { detached_launch, type LaunchArgv } from '#scripts/run/detached-launch'
|
|
11
11
|
import { run_event_stream } from '#scripts/run/event/run-event-stream'
|
|
12
12
|
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
13
13
|
import { run_ending } from '#scripts/run/run-ending'
|
|
@@ -197,7 +197,7 @@ function existing_dispatch(request: StartRequest): DispatchOutcome | undefined {
|
|
|
197
197
|
return dispatched_of(request, active.pid, [])
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
function launch_argv(request: StartRequest, nonce: string | undefined):
|
|
200
|
+
function launch_argv(request: StartRequest, nonce: string | undefined): LaunchArgv {
|
|
201
201
|
if (request.profile.provider !== 'openai') return request.argv
|
|
202
202
|
if (nonce === undefined) throw new Error('OpenAI supervisor nonce is missing')
|
|
203
203
|
|
|
@@ -404,7 +404,7 @@ function log_sentence(outcome: Dispatched, issue: string): string {
|
|
|
404
404
|
return ` Its output is NOT being kept — ${outcome.notes.join(NOTE_SEPARATOR)} — so ${outcome.log_path} will not grow and the process trace is the only answer: ${poll}.`
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
-
return ` It writes to ${outcome.log_path}.
|
|
407
|
+
return ` It writes to ${outcome.log_path}. Wait on it with \`pnpm josh lane:await ${issue} --owner "$PPID"\` in the background and end the turn; once that output falls silent, ${poll}.`
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
// Whether this dispatch resumed the disconnected child's session or started fresh — the report the
|