@joshuafolkken/kit 1.1784.0 → 1.2114.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/agents/reviewer-verification.md +19 -0
- package/.claude/agents/reviewer.md +19 -0
- package/.claude/settings.json +5 -6
- package/.claude/skills/dependency-update/SKILL.md +9 -10
- package/.claude/skills/workflow-commands/SKILL.md +6 -6
- package/.claude/skills/workflow-commands/background-commands.md +8 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +41 -32
- package/.claude/skills/workflow-commands/delegation.md +6 -6
- package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +7 -5
- package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +9 -4
- package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -2
- package/.claude/skills/workflow-commands/observation-filing.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
- package/.claude/skills/workflow-commands/prerequisite.md +3 -2
- package/.claude/skills/workflow-commands/retrospective.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +7 -5
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-pnpm/action.yml +9 -16
- package/.github/dependabot.yml +16 -0
- package/.github/workflows/auto-tag.yml +45 -0
- package/.github/workflows/ci.yml +155 -15
- package/.github/workflows/dependabot-auto-merge.yml +63 -4
- package/.github/workflows/production.yml +8 -0
- package/.github/workflows/publish.yml +59 -45
- package/.vscode/settings.json +19 -0
- package/CLAUDE.md +5 -12
- package/SECURITY.md +2 -2
- package/dist/CLAUDE.md +5 -12
- package/dist/commands/document-read-cli.js +2 -1
- package/dist/commands/document-section-main.js +2 -1
- package/dist/commands/read-set-cli.js +194 -134
- package/dist/commands/run-prep-main.js +9694 -10173
- package/dist/commands/run-step-cli.js +22138 -18285
- package/dist/hooks/audit-provision.js +23 -5
- package/dist/hooks/chunk-3GKE653K.js +6204 -0
- package/dist/hooks/chunk-45CJJOO7.js +1243 -0
- package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
- package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
- package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
- package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
- package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
- package/dist/hooks/chunk-VVNYJWEI.js +30 -0
- package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
- package/dist/hooks/codex-hook-adapter.js +8 -8
- package/dist/hooks/format-edited.js +4 -5
- package/dist/hooks/inputs.json +415 -389
- package/dist/hooks/pretool-guard.js +7 -6
- package/dist/hooks/session-lang.js +101 -258
- package/dist/hooks/stop-guard.js +1744 -2576
- package/dist/josh.js +7133 -6368
- package/dist/version/index.js +161 -1
- package/eslint/rules/comment-why-only.js +108 -0
- package/package.json +15 -8
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +14 -11
- package/prompts/collaboration-workflow/issue-citation.md +0 -4
- package/prompts/collaboration-workflow/issue-template.md +40 -21
- package/prompts/collaboration-workflow/lane-instructions.md +3 -1
- package/prompts/collaboration-workflow/measurement.md +8 -1
- package/prompts/collaboration-workflow/operating-rules.md +11 -2
- package/prompts/collaboration-workflow/output-bounds.md +6 -2
- package/prompts/collaboration-workflow/plan-comment.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/residency.md +3 -2
- package/prompts/collaboration-workflow/rule-delivery.md +13 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +3 -1
- package/prompts/review-rubric.md +8 -0
- package/prompts/review.md +31 -22
- package/prompts/testing-guide.md +1 -0
- package/scripts/agent/agent-argv.ts +14 -16
- package/scripts/agent/agent-provider.ts +138 -0
- package/scripts/agent/agent-role-profile.ts +108 -156
- package/scripts/agent/agent-safe-text.ts +20 -5
- package/scripts/agent/api-usage-limit.ts +65 -0
- package/scripts/agent/claude-agent-argv.ts +19 -9
- package/scripts/agent/codex-agent-argv.ts +118 -22
- package/scripts/agent/usage-limit-reset.ts +179 -0
- package/scripts/auth/claude-token-output.ts +2 -2
- package/scripts/auto-ok/auto-ok-author.ts +53 -0
- package/scripts/auto-ok/auto-ok-cli.ts +20 -9
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +6 -1
- package/scripts/backlog/backlog-drive-hold.ts +3 -3
- package/scripts/backlog/backlog-drive-idle.ts +10 -0
- package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
- package/scripts/backlog/backlog-drive-launch.ts +8 -2
- package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
- package/scripts/backlog/backlog-drive-named.ts +28 -7
- package/scripts/backlog/backlog-drive-paused.ts +5 -4
- package/scripts/backlog/backlog-drive-restore.ts +11 -3
- package/scripts/backlog/backlog-drive.ts +21 -60
- package/scripts/backlog/backlog-gate-scope.ts +61 -0
- package/scripts/backlog/backlog-measure-close.ts +112 -0
- package/scripts/backlog/backlog-next.ts +39 -49
- package/scripts/backlog/backlog-occupied.ts +2 -2
- package/scripts/backlog/backlog-overlap.ts +42 -8
- package/scripts/backlog/backlog-plan-cli.ts +4 -1
- package/scripts/backlog/backlog-plan-comment.ts +81 -0
- package/scripts/backlog/backlog-plan-read.ts +19 -6
- package/scripts/backlog/backlog-pool.ts +50 -12
- package/scripts/backlog/backlog-rank.ts +60 -13
- package/scripts/backlog/backlog-stalled-detect.ts +2 -1
- package/scripts/backlog/backlog-waves.ts +17 -2
- package/scripts/backlog/backlogrun-launch.ts +7 -4
- package/scripts/cost-runtime/context-cut-payback.ts +27 -25
- package/scripts/cost-runtime/cost-cli.ts +37 -16
- package/scripts/cost-runtime/cost-pricing.ts +9 -0
- package/scripts/cost-runtime/cost-verdict.ts +4 -1
- package/scripts/delegation/delegation-policy.ts +2 -2
- package/scripts/delegation/duplicate-read-guard.ts +1 -0
- package/scripts/delegation/investigation-guard.ts +14 -2
- package/scripts/delegation/investigation-reads.ts +45 -23
- package/scripts/dependabot/dependabot-cooldown.ts +3 -2
- package/scripts/discovery/repo-party.ts +80 -20
- package/scripts/discovery/session-owner-pin.ts +51 -0
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/command-reference-line-budget.ts +42 -0
- package/scripts/document/document-byte-budget.ts +17 -7
- package/scripts/document/document-checks.ts +20 -0
- package/scripts/document/document-ratchet-check.ts +101 -0
- package/scripts/document/document-section.ts +1 -0
- package/scripts/document/entry-read-budget.ts +7 -3
- package/scripts/document/issue-citation-budget.ts +94 -0
- package/scripts/epic/epic-cli-argv.ts +2 -2
- package/scripts/epic/epic-fetch.ts +4 -2
- package/scripts/epic/epic-graph.ts +7 -2
- package/scripts/epic/epic-issue.ts +3 -1
- package/scripts/epic/epic-rank.ts +5 -0
- package/scripts/exports/unused-members-check.ts +62 -0
- package/scripts/exports/unused-members-cli.ts +6 -51
- package/scripts/followup/followup-ci-path.ts +67 -0
- package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
- package/scripts/followup/followup-coderabbit-wait.ts +13 -10
- package/scripts/followup/followup-failed-tests.ts +160 -0
- package/scripts/followup/followup-job-needs.ts +100 -0
- package/scripts/followup/followup-job-rerun.ts +303 -0
- package/scripts/followup/followup-main-move.ts +113 -0
- package/scripts/followup/git-followup-finish.ts +43 -11
- package/scripts/followup/git-followup-pending.ts +3 -3
- package/scripts/followup/git-followup-stages.ts +41 -11
- package/scripts/followup/git-pr-followup-checks.ts +55 -16
- package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
- package/scripts/followup/git-pr-followup.ts +62 -27
- package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
- package/scripts/gate/busy-average.ts +34 -2
- package/scripts/gate/check-related-pinned.ts +43 -0
- package/scripts/gate/check-related-reuse.ts +64 -0
- package/scripts/gate/check-related-section.ts +57 -0
- package/scripts/gate/check-related-unplanned.ts +34 -0
- package/scripts/gate/check-related.ts +265 -0
- package/scripts/gate/command-memory.ts +1 -1
- package/scripts/gate/core-admission.ts +24 -6
- package/scripts/gate/core-budget-timing.ts +20 -6
- package/scripts/gate/core-budget.ts +40 -11
- package/scripts/gate/core-wait-record.ts +3 -2
- package/scripts/gate/core-wait.ts +25 -2
- package/scripts/gate/core-weights.ts +15 -7
- package/scripts/gate/gate-labels.ts +46 -0
- package/scripts/gate/gate-ledger.ts +14 -6
- package/scripts/gate/gate-plan.ts +103 -58
- package/scripts/gate/gate-report.ts +9 -7
- package/scripts/gate/gate-run-steps.ts +26 -3
- package/scripts/gate/gate-skip.ts +45 -6
- package/scripts/gate/gate-static-group.ts +60 -0
- package/scripts/gate/gate-steps.ts +2 -1
- package/scripts/gate/gate-tree.ts +4 -2
- package/scripts/gate/hook-gate-reuse.ts +19 -2
- package/scripts/gate/metrics-totals.ts +59 -0
- package/scripts/gate/scoped-green.ts +68 -15
- package/scripts/gate/since-green.ts +14 -6
- package/scripts/gate/structural-checks.ts +96 -0
- package/scripts/gate/verification-gate.ts +51 -16
- package/scripts/gate/verification-inputs.ts +21 -6
- package/scripts/gate/verification-tail.ts +52 -0
- package/scripts/gh/gh-author-association.ts +23 -2
- package/scripts/gh/git-ai-review-scan.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +12 -3
- package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
- package/scripts/gh/git-gh-exec.ts +32 -2
- package/scripts/gh/git-gh-issue-read.ts +4 -2
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +8 -2
- package/scripts/gh/git-gh-issue.ts +12 -5
- package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
- package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
- package/scripts/gh/git-gh-pr-read.ts +74 -13
- package/scripts/gh/git-gh-pr-rest.ts +3 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
- package/scripts/gh/git-gh-pr-too-large.ts +20 -0
- package/scripts/gh/git-gh-pr.ts +21 -7
- package/scripts/gh/git-gh-retry.ts +141 -0
- package/scripts/gh/git-pr-ai-review.ts +15 -6
- package/scripts/gh/git-pr-checks-eval.ts +3 -0
- package/scripts/gh/git-pr-checks.ts +5 -5
- package/scripts/git/base-tree.ts +30 -0
- package/scripts/git/change-base.ts +4 -10
- package/scripts/git/changed-paths-sync.ts +63 -0
- package/scripts/git/changed-paths.ts +16 -1
- package/scripts/git/git-common-directory.ts +11 -1
- package/scripts/git/git-diff-reads.ts +66 -20
- package/scripts/git/git-error.ts +9 -2
- package/scripts/git/git-schemas.ts +13 -0
- package/scripts/git/git-worktree.ts +13 -0
- package/scripts/git/gone-branch.ts +4 -1
- package/scripts/git/main-merge-budget-conflict.ts +89 -0
- package/scripts/git/main-merge-guard.ts +55 -18
- package/scripts/git/main-merge-regenerate.ts +59 -25
- package/scripts/git/main-merge.ts +53 -5
- package/scripts/git/no-base-checkout.ts +127 -0
- package/scripts/git/stash/git-stash.ts +11 -2
- package/scripts/git/stash/stash-push-cli.ts +10 -0
- package/scripts/hooks/batch-guard.ts +40 -21
- package/scripts/hooks/edited-cspell.ts +37 -11
- package/scripts/hooks/format-edited-file.ts +22 -2
- package/scripts/hooks/lane-plan-guard.ts +50 -0
- package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
- package/scripts/hooks/pre-commit-lint.ts +14 -1
- package/scripts/hooks/pre-push-related-switch.ts +10 -0
- package/scripts/hooks/pre-push-unit.ts +76 -10
- package/scripts/hooks/pretool-guard.ts +2 -0
- package/scripts/hooks/reserved-run.ts +14 -1
- package/scripts/hooks/run-hook.sh +23 -8
- package/scripts/hooks/step-zero-notice.ts +6 -1
- package/scripts/hooks/stop-actions.ts +3 -15
- package/scripts/hooks/stop-guard.ts +7 -6
- package/scripts/init/distributed-paths.ts +1 -0
- package/scripts/init/hook-command-rewrite.ts +5 -1
- package/scripts/init/hook-launch.ts +4 -2
- package/scripts/issue/aggregation-split.ts +52 -0
- package/scripts/issue/defect-origin-line.ts +19 -1
- package/scripts/issue/defect-rate-cli.ts +5 -102
- package/scripts/issue/defect-report.ts +4 -4
- package/scripts/issue/effect-audit-cli.ts +178 -0
- package/scripts/issue/effect-audit.ts +185 -0
- package/scripts/issue/expected-effect-lint.ts +64 -9
- package/scripts/issue/git-next-issues.ts +5 -0
- package/scripts/issue/issue-body-or-comment.ts +38 -4
- package/scripts/issue/issue-cite-cli.ts +1 -3
- package/scripts/issue/issue-classification.ts +1 -0
- package/scripts/issue/issue-closing-pr.ts +8 -1
- package/scripts/issue/issue-evidence-exit.ts +4 -2
- package/scripts/issue/issue-file-cap.ts +58 -0
- package/scripts/issue/issue-file-cli.ts +111 -38
- package/scripts/issue/issue-file-deferral.ts +52 -0
- package/scripts/issue/issue-file-fold.ts +29 -10
- package/scripts/issue/issue-file-interrupt.ts +85 -0
- package/scripts/issue/issue-file-lane-hint.ts +30 -0
- package/scripts/issue/issue-file.ts +43 -6
- package/scripts/issue/issue-labels.ts +19 -2
- package/scripts/issue/issue-lint-cli.ts +27 -2
- package/scripts/issue/issue-measured-cli.ts +13 -35
- package/scripts/issue/issue-measured-close.ts +58 -0
- package/scripts/issue/issue-not-before-label.ts +2 -2
- package/scripts/issue/issue-not-before.ts +4 -1
- package/scripts/issue/issue-priority-cli.ts +60 -0
- package/scripts/issue/issue-priority-raise.ts +55 -0
- package/scripts/issue/issue-priority.ts +174 -43
- package/scripts/issue/issue-rank.ts +21 -4
- package/scripts/issue/issue-read-cli.ts +32 -6
- package/scripts/issue/issue-read.ts +37 -12
- package/scripts/issue/issue-sample-gate.ts +95 -74
- package/scripts/issue/issue-sample-prime.ts +127 -0
- package/scripts/issue/issue-sample-required.ts +57 -0
- package/scripts/issue/issue-sample-source.ts +12 -11
- package/scripts/issue/issue-search.ts +124 -0
- package/scripts/issue/issue-state.ts +13 -1
- package/scripts/issue/issue-template-section.ts +43 -0
- package/scripts/issue/issue-watch-diff.ts +31 -1
- package/scripts/issue/issue-watch-hook.ts +11 -2
- package/scripts/issue/issue-watch.ts +55 -12
- package/scripts/issue/markdown-section.ts +1 -0
- package/scripts/issue/measure-declaration.ts +121 -0
- package/scripts/issue/measure-rerun-cli.ts +7 -70
- package/scripts/issue/plan-consumers-section.ts +22 -1
- package/scripts/issue/reproduction-measure.ts +3 -1
- package/scripts/issue/size-estimate.ts +90 -0
- package/scripts/issue/trusted-measure.ts +84 -0
- package/scripts/josh/command-usage.ts +3 -2
- package/scripts/josh/durable-state-migrate.ts +105 -0
- package/scripts/josh/durable-state.ts +112 -0
- package/scripts/josh/josh-aliases.ts +95 -0
- package/scripts/josh/josh-command-map.ts +1 -82
- package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
- package/scripts/josh/josh-commands-ai.ts +5 -5
- package/scripts/josh/josh-commands-development.ts +59 -58
- package/scripts/josh/josh-commands-issue-write.ts +23 -4
- package/scripts/josh/josh-commands-issue.ts +32 -0
- package/scripts/josh/josh-commands-lane.ts +87 -4
- package/scripts/josh/josh-commands-lint.ts +16 -3
- package/scripts/josh/josh-commands-maintenance.ts +15 -0
- package/scripts/josh/josh-commands-review.ts +41 -6
- package/scripts/josh/josh-commands-ship.ts +56 -8
- package/scripts/josh/josh-commands-test-check.ts +80 -0
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/josh-environment-file.ts +43 -3
- package/scripts/josh/josh-in-process.ts +2 -2
- package/scripts/josh/josh-logic.ts +5 -3
- package/scripts/josh/josh-run.ts +19 -1
- package/scripts/josh/run-record-path.ts +15 -0
- package/scripts/josh/stamp-file.ts +11 -2
- package/scripts/lane/lane-adopt-cli.ts +98 -0
- package/scripts/lane/lane-adopt.ts +208 -0
- package/scripts/lane/lane-await.ts +5 -8
- package/scripts/lane/lane-baseline.ts +123 -0
- package/scripts/lane/lane-breakdown-cli.ts +64 -0
- package/scripts/lane/lane-breakdown-implement.ts +170 -0
- package/scripts/lane/lane-breakdown-laps.ts +107 -0
- package/scripts/lane/lane-breakdown-pinned.ts +76 -0
- package/scripts/lane/lane-breakdown-text.ts +145 -0
- package/scripts/lane/lane-breakdown.ts +239 -0
- package/scripts/lane/lane-check-stats.ts +29 -8
- package/scripts/lane/lane-child-invocation.ts +9 -2
- package/scripts/lane/lane-child-mark-keys.ts +12 -0
- package/scripts/lane/lane-child-marker.ts +20 -1
- package/scripts/lane/lane-ci-path-stats.ts +73 -0
- package/scripts/lane/lane-claim-stats.ts +84 -0
- package/scripts/lane/lane-close.ts +8 -3
- package/scripts/lane/lane-dispatch-log.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +2 -2
- package/scripts/lane/lane-gap-stats.ts +7 -6
- package/scripts/lane/lane-guard-policy.ts +7 -1
- package/scripts/lane/lane-implement-stats.ts +207 -0
- package/scripts/lane/lane-implement-subagents.ts +90 -0
- package/scripts/lane/lane-investigation-switch.ts +16 -0
- package/scripts/lane/lane-ledger-kind.ts +31 -0
- package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
- package/scripts/lane/lane-ledger-schema.ts +119 -36
- package/scripts/lane/lane-ledger-write.ts +257 -0
- package/scripts/lane/lane-ledger.ts +31 -177
- package/scripts/lane/lane-load.ts +1 -1
- package/scripts/lane/lane-measure-cli.ts +176 -59
- package/scripts/lane/lane-net-read.ts +44 -0
- package/scripts/lane/lane-net-time.ts +212 -0
- package/scripts/lane/lane-open.ts +16 -7
- package/scripts/lane/lane-output.ts +2 -4
- package/scripts/lane/lane-overrun-prompt.ts +147 -0
- package/scripts/lane/lane-overrun.ts +274 -0
- package/scripts/lane/lane-paths.ts +24 -1
- package/scripts/lane/lane-pause-cli.ts +4 -1
- package/scripts/lane/lane-paused-spans.ts +97 -0
- package/scripts/lane/lane-plan-check.ts +207 -0
- package/scripts/lane/lane-plan-cli.ts +41 -0
- package/scripts/lane/lane-plan.ts +144 -0
- package/scripts/lane/lane-registry.ts +14 -1
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-round-one-stats.ts +51 -0
- package/scripts/lane/lane-sampler.ts +23 -4
- package/scripts/lane/lane-session-action.ts +93 -18
- package/scripts/lane/lane-session-broker.ts +49 -21
- package/scripts/lane/lane-session-reread-main.ts +14 -0
- package/scripts/lane/lane-session-reread.ts +51 -0
- package/scripts/lane/lane-ship-lap-stats.ts +74 -0
- package/scripts/lane/lane-sleep.ts +58 -0
- package/scripts/lane/lane-spent.ts +1 -1
- package/scripts/lane/lane-split-stats.ts +28 -0
- package/scripts/lane/lane-stage-stats.ts +13 -1
- package/scripts/lane/lane-state.ts +41 -9
- package/scripts/lane/lane-stats-tables.ts +58 -0
- package/scripts/lane/lane-stats.ts +21 -5
- package/scripts/lane/lane-stop-stats.ts +51 -19
- package/scripts/lane/lane-tail-stats.ts +32 -0
- package/scripts/lane/lane-transcript-calls.ts +67 -10
- package/scripts/lane/lane-transcript-stats.ts +44 -12
- package/scripts/lane/lane-value-cell.ts +72 -0
- package/scripts/lane/lane-value.ts +118 -0
- package/scripts/lane/lane-withdraw-closed.ts +124 -0
- package/scripts/lane/lane-withdraw.ts +108 -31
- package/scripts/lane/lane-yield.ts +85 -0
- package/scripts/lane/openai-lane-ship.ts +12 -11
- package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
- package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
- package/scripts/lane/openai-lane-supervisor.ts +5 -4
- package/scripts/lib/poll.ts +38 -9
- package/scripts/lib/settled-together.ts +10 -0
- package/scripts/lib/shell-quote.ts +21 -0
- package/scripts/lib/token-shape.ts +111 -0
- package/scripts/lint/eslint-daemon-sources.ts +79 -0
- package/scripts/lint/eslint-daemon.ts +45 -6
- package/scripts/lint/eslint-warm-cli.ts +7 -0
- package/scripts/lint/eslint-warm.ts +66 -0
- package/scripts/lint/import-graph.ts +141 -11
- package/scripts/lint/lint-gate-scope.ts +2 -2
- package/scripts/lint/lint-parallel.ts +54 -6
- package/scripts/lint/lint-related.ts +154 -33
- package/scripts/lint/rename-cli.ts +179 -0
- package/scripts/lint/rename-identifier.ts +192 -0
- package/scripts/lint/type-only-imports.ts +58 -0
- package/scripts/notify/telegram-notify.ts +12 -3
- package/scripts/observations/observation-record.ts +42 -16
- package/scripts/observations/observations-flush.ts +32 -9
- package/scripts/overrides/overrides-check.ts +9 -1
- package/scripts/release/release-approval-prune.ts +7 -1
- package/scripts/repo/required-checks-logic.ts +4 -1
- package/scripts/repo/ruleset-check.ts +4 -3
- package/scripts/report/markdown-shape.ts +28 -0
- package/scripts/report/report-format-reference.ts +15 -1
- package/scripts/report/report-labels.ts +12 -1
- package/scripts/report/report-lint-child-summary.ts +94 -0
- package/scripts/report/report-lint-cli.ts +26 -7
- package/scripts/report/report-lint.ts +2 -20
- package/scripts/review/prose-stale-cli.ts +88 -0
- package/scripts/review/prose-stale-scan.ts +152 -0
- package/scripts/review/review-attest.ts +73 -23
- package/scripts/review/review-brief-cli.ts +68 -19
- package/scripts/review/review-brief-paths.ts +22 -0
- package/scripts/review/review-brief.ts +14 -7
- package/scripts/review/review-comment-carry.ts +47 -0
- package/scripts/review/review-comment-round.ts +85 -22
- package/scripts/review/review-finding-ledger.ts +109 -7
- package/scripts/review/review-finding-text.ts +43 -0
- package/scripts/review/review-interaction.ts +11 -0
- package/scripts/review/review-lane-handover.ts +68 -0
- package/scripts/review/review-lint-cli.ts +57 -0
- package/scripts/review/review-lint-findings.ts +92 -0
- package/scripts/review/review-lint-sections.ts +80 -0
- package/scripts/review/review-lint.ts +221 -0
- package/scripts/review/review-prior-findings.ts +102 -0
- package/scripts/review/review-readers-scan.ts +4 -2
- package/scripts/review/review-record-cli.ts +177 -54
- package/scripts/review/review-record-code-round.ts +55 -0
- package/scripts/review/review-record-comment.ts +60 -0
- package/scripts/review/review-record-interaction.ts +35 -0
- package/scripts/review/review-record-pinned.ts +108 -0
- package/scripts/review/review-record.ts +25 -1
- package/scripts/review/review-reviewed-tree.ts +307 -0
- package/scripts/review/review-round-one-closure.ts +62 -0
- package/scripts/review/review-round-reuse.ts +106 -0
- package/scripts/review/review-round2-cli.ts +91 -29
- package/scripts/review/review-round2-skip-comment.ts +55 -0
- package/scripts/review/review-round2.ts +24 -8
- package/scripts/review/review-stamps.ts +7 -3
- package/scripts/review/review-stop-log.ts +20 -6
- package/scripts/review/review-stops-cli.ts +2 -1
- package/scripts/review/review-submit-cli.ts +101 -0
- package/scripts/rules/agent-model.ts +1 -1
- package/scripts/rules/bash-triggers.ts +3 -3
- package/scripts/rules/concise-reply.ts +88 -0
- package/scripts/rules/credential-body.ts +77 -0
- package/scripts/rules/decision-oracle.ts +1 -1
- package/scripts/rules/delivered-rules.ts +36 -17
- package/scripts/rules/destructive-command.ts +3 -11
- package/scripts/rules/direct-issue-comment.ts +34 -12
- package/scripts/rules/direct-issue-read.ts +191 -0
- package/scripts/rules/direct-pr-create.ts +4 -24
- package/scripts/rules/early-heartbeat.ts +2 -0
- package/scripts/rules/edit-tool.ts +27 -0
- package/scripts/rules/file-edit-rows.ts +17 -0
- package/scripts/rules/file-rewrite.ts +146 -0
- package/scripts/rules/firing-point.ts +3 -2
- package/scripts/rules/gh-api.ts +128 -7
- package/scripts/rules/gh-repo-selector.ts +84 -0
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/guard-remedy.ts +14 -5
- package/scripts/rules/implementation-cut.ts +61 -28
- package/scripts/rules/investigator-foreground.ts +231 -0
- package/scripts/rules/issue-citation.ts +15 -60
- package/scripts/rules/issue-comments.ts +9 -4
- package/scripts/rules/josh-git-bare.ts +1 -1
- package/scripts/rules/lane-background.ts +41 -13
- package/scripts/rules/lane-direct-tool.ts +107 -9
- package/scripts/rules/lane-interactive-ask.ts +4 -1
- package/scripts/rules/lane-park.ts +4 -2
- package/scripts/rules/lane-spilled-read.ts +90 -0
- package/scripts/rules/lane-split-park.ts +1 -1
- package/scripts/rules/lane-switch-main.ts +4 -4
- package/scripts/rules/last-prompt.ts +20 -47
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/permission-guards.ts +5 -1
- package/scripts/rules/piped-verification-shapes.ts +110 -0
- package/scripts/rules/piped-verification.ts +67 -17
- package/scripts/rules/poll-loop.ts +72 -9
- package/scripts/rules/pr-merge.ts +5 -5
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +88 -24
- package/scripts/rules/reply-language.ts +3 -17
- package/scripts/rules/reply-prose.ts +34 -0
- package/scripts/rules/repo-admin.ts +132 -0
- package/scripts/rules/reviewer-foreground.ts +88 -0
- package/scripts/rules/round-one-check-related.ts +120 -0
- package/scripts/rules/rule-body-guard.ts +5 -15
- package/scripts/rules/rule-value-cache.ts +53 -5
- package/scripts/rules/rule-value-candidates.ts +84 -0
- package/scripts/rules/rule-value-cli.ts +59 -11
- package/scripts/rules/rule-value.ts +17 -4
- package/scripts/rules/run-tail-rule.ts +1 -1
- package/scripts/rules/sed-in-place.ts +196 -0
- package/scripts/rules/shell-segments.ts +10 -2
- package/scripts/rules/stop-rule-rows.ts +1 -13
- package/scripts/rules/stop-rules.ts +33 -58
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +110 -23
- package/scripts/rules/timed-rerun.ts +1 -1
- package/scripts/rules/turn-filings.ts +90 -0
- package/scripts/rules/worktree-guard.ts +22 -7
- package/scripts/run/board/run-board-ending-reason.ts +6 -2
- package/scripts/run/board/run-board-fit.ts +24 -1
- package/scripts/run/board/run-board-found.ts +134 -0
- package/scripts/run/board/run-board-header.ts +8 -0
- package/scripts/run/board/run-board-labels.ts +11 -1
- package/scripts/run/board/run-board-lane-time.ts +1 -0
- package/scripts/run/board/run-board-link.ts +15 -2
- package/scripts/run/board/run-board-notes.ts +7 -1
- package/scripts/run/board/run-board-operation.ts +4 -2
- package/scripts/run/board/run-board-phase.ts +2 -5
- package/scripts/run/board/run-board-plan.ts +1 -1
- package/scripts/run/board/run-board-read.ts +46 -1
- package/scripts/run/board/run-board-reason.ts +20 -8
- package/scripts/run/board/run-board-render-checks.ts +3 -2
- package/scripts/run/board/run-board-render-drawn.ts +11 -0
- package/scripts/run/board/run-board-render-found.ts +157 -0
- package/scripts/run/board/run-board-render-lead.ts +9 -0
- package/scripts/run/board/run-board-render-legend.ts +19 -0
- package/scripts/run/board/run-board-render-tail.ts +1 -1
- package/scripts/run/board/run-board-render.ts +82 -18
- package/scripts/run/board/run-board-spin.ts +1 -3
- package/scripts/run/board/run-board-status.ts +2 -0
- package/scripts/run/board/run-board-tick.ts +39 -10
- package/scripts/run/carry/run-carry-ended.ts +3 -2
- package/scripts/run/carry/run-carry.ts +3 -2
- package/scripts/run/cut/run-cut-cli.ts +33 -133
- package/scripts/run/cut/run-cut-digest.ts +152 -0
- package/scripts/run/cut/run-cut-handoff.ts +52 -8
- package/scripts/run/cut/run-cut-report.ts +24 -3
- package/scripts/run/cut/run-cut-resume.ts +129 -0
- package/scripts/run/cut/run-cut-review.ts +105 -0
- package/scripts/run/cut/run-cut.ts +18 -7
- package/scripts/run/detached-launch.ts +1 -1
- package/scripts/run/entry/run-entry-cli.ts +88 -19
- package/scripts/run/entry/run-entry-spill.ts +83 -0
- package/scripts/run/entry/run-entry-stop.ts +5 -1
- package/scripts/run/entry/run-entry-trust.ts +91 -0
- package/scripts/run/event/run-event-baseline.ts +56 -0
- package/scripts/run/event/run-event-filed.ts +9 -3
- package/scripts/run/event/run-event-overrun.ts +197 -0
- package/scripts/run/event/run-event-render.ts +4 -0
- package/scripts/run/event/run-event-stream.ts +25 -3
- package/scripts/run/hold/run-stop-notify.ts +3 -8
- package/scripts/run/merge/run-merge-cap.ts +57 -0
- package/scripts/run/merge/run-merge-cli.ts +66 -23
- package/scripts/run/merge/run-merge-outcome.ts +2 -0
- package/scripts/run/merge/run-merge-ship.ts +13 -3
- package/scripts/run/merge/run-merge-signals.ts +40 -23
- package/scripts/run/merge/run-merge-steps.ts +56 -36
- package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
- package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
- package/scripts/run/merge/run-merge.ts +41 -14
- package/scripts/run/review/run-review-cli.ts +306 -20
- package/scripts/run/review/run-review-early-push.ts +121 -0
- package/scripts/run/review/run-review-join-read.ts +94 -0
- package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
- package/scripts/run/review/run-review-pinned-join.ts +216 -0
- package/scripts/run/review/run-review-pinned-steps.ts +383 -0
- package/scripts/run/review/run-review-pinned-tree.ts +37 -0
- package/scripts/run/review/run-review-pinned.ts +53 -0
- package/scripts/run/review/run-review-steps.ts +70 -34
- package/scripts/run/review/run-review.ts +26 -6
- package/scripts/run/run-parent-cut-hook.ts +3 -4
- package/scripts/run/run-prep.ts +1 -0
- package/scripts/run/run-stage-read.ts +2 -6
- package/scripts/run/run-step-cli.ts +17 -5
- package/scripts/run/run-step-lane-plan.ts +27 -0
- package/scripts/run/run-step-section.ts +26 -7
- package/scripts/run/run-step.ts +5 -2
- package/scripts/run/ship/run-ship-args.ts +19 -0
- package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
- package/scripts/run/ship/run-ship-cli.ts +131 -39
- package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
- package/scripts/run/ship/run-ship-detach.ts +10 -4
- package/scripts/run/ship/run-ship-handover.ts +106 -0
- package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
- package/scripts/run/ship/run-ship-lap.ts +63 -0
- package/scripts/run/ship/run-ship-next.ts +27 -26
- package/scripts/run/ship/run-ship-overlap.ts +8 -3
- package/scripts/run/ship/run-ship-place.ts +9 -2
- package/scripts/run/ship/run-ship-planned.ts +92 -0
- package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
- package/scripts/run/ship/run-ship-preflight.ts +16 -4
- package/scripts/run/ship/run-ship-probe.ts +23 -9
- package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
- package/scripts/run/ship/run-ship-relaunch.ts +51 -0
- package/scripts/run/ship/run-ship-return.ts +103 -29
- package/scripts/run/ship/run-ship-review-reason.ts +24 -0
- package/scripts/run/ship/run-ship-review-steps.ts +230 -59
- package/scripts/run/ship/run-ship-review.ts +171 -51
- package/scripts/run/ship/run-ship-reviewer.ts +138 -42
- package/scripts/run/ship/run-ship-scoped.ts +39 -10
- package/scripts/run/ship/run-ship-stage.ts +49 -13
- package/scripts/run/ship/run-ship-steps.ts +24 -4
- package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
- package/scripts/run/ship/run-ship-stop-context.ts +50 -13
- package/scripts/run/ship/run-ship-sync.ts +171 -30
- package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
- package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
- package/scripts/run/ship/run-ship-waiter.ts +114 -0
- package/scripts/run/ship/run-ship.ts +16 -2
- package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
- package/scripts/run/wake/run-wake-cli.ts +6 -113
- package/scripts/run/wake/run-wake-code.ts +53 -11
- package/scripts/run/wake/run-wake-driver.ts +5 -3
- package/scripts/run/wake/run-wake-finish.ts +137 -0
- package/scripts/run/wake/run-wake-loop.ts +5 -3
- package/scripts/run/wake/run-wake-ports.ts +11 -3
- package/scripts/run/wake/run-wake-session.ts +2 -0
- package/scripts/run/wake/run-wake.ts +3 -2
- package/scripts/safe-chain/ci-installer-pin.ts +49 -8
- package/scripts/safe-chain/project-config.ts +3 -2
- package/scripts/security/secretlint-scan.ts +42 -9
- package/scripts/security/security-audit-provision-main.ts +9 -1
- package/scripts/security/security-audit-provision.ts +1 -1
- package/scripts/security/security-audit.ts +21 -1
- package/scripts/security/sonar-file.ts +10 -5
- package/scripts/split/split-assess.ts +12 -3
- package/scripts/split/split-early-notice.ts +116 -0
- package/scripts/split/split-measure.ts +20 -2
- package/scripts/split/split-resolution.ts +107 -0
- package/scripts/test/direct-importers.ts +185 -0
- package/scripts/test/pure-files-entries.ts +83 -0
- package/scripts/test/related-heavy-tests.ts +81 -0
- package/scripts/test/test-no-base.ts +88 -0
- package/scripts/test/test-pinned-cache-logic.ts +363 -0
- package/scripts/test/test-pinned-cache.ts +337 -0
- package/scripts/test/test-pinned-emit.ts +49 -0
- package/scripts/test/test-pinned-functions.ts +116 -0
- package/scripts/test/test-pinned-ledger.ts +80 -0
- package/scripts/test/test-pinned-logic.ts +208 -20
- package/scripts/test/test-pinned-main.ts +84 -18
- package/scripts/test/test-pinned-pool.ts +73 -0
- package/scripts/test/test-pinned-probe.ts +254 -0
- package/scripts/test/test-pinned-prune-logic.ts +118 -0
- package/scripts/test/test-pinned-reach.ts +194 -0
- package/scripts/test/test-pinned-record.ts +196 -0
- package/scripts/test/test-pinned-rewire.ts +148 -0
- package/scripts/test/test-pinned-spawn.ts +81 -0
- package/scripts/test/test-pinned-stage.ts +70 -0
- package/scripts/test/test-pinned.ts +258 -47
- package/scripts/test/test-reach-cli.ts +61 -0
- package/scripts/test/test-read-map.ts +35 -11
- package/scripts/test/test-read-recording.ts +17 -5
- package/scripts/test/test-read-trace.ts +26 -8
- package/scripts/test/test-red-logic.ts +46 -7
- package/scripts/test/test-red.ts +34 -14
- package/scripts/test/test-related-claim.ts +37 -0
- package/scripts/test/test-related-main.ts +4 -1
- package/scripts/test/test-related-moved.ts +91 -0
- package/scripts/test/test-related-record.ts +43 -23
- package/scripts/test/test-related-scope.ts +99 -34
- package/scripts/test/test-related-synced.ts +135 -0
- package/scripts/test/test-related-touched.ts +84 -0
- package/scripts/test/test-related.ts +167 -83
- package/scripts/test/test-unit-guard.ts +28 -5
- package/scripts/test/unit-durations.ts +41 -0
- package/scripts/test/unit-worker-share.ts +5 -4
- package/scripts/test/vitest-cache-directory.ts +19 -0
- package/scripts/test/vitest-cli-excludes.ts +14 -0
- package/scripts/test/vitest-failure-summary.ts +111 -0
- package/scripts/test/whole-suite-files.ts +12 -1
- package/scripts/time-runtime/time-batch-guard.ts +42 -4
- package/scripts/time-runtime/time-bundle-call.ts +1 -1
- package/scripts/time-runtime/time-bundles.ts +36 -5
- package/scripts/time-runtime/time-markers.ts +2 -2
- package/scripts/time-runtime/time-search-call.ts +38 -0
- package/scripts/time-runtime/time-shell.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +17 -5
- package/scripts/version/development-engines-verdict.ts +124 -0
- package/scripts/version/latest-corepack.ts +2 -0
- package/templates/gitignore +2 -0
- package/templates/workflows/ci.yml +41 -0
- package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
- package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
- package/dist/hooks/chunk-TUIFS5E7.js +0 -72
- package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
- package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
- package/scripts/rules/filing-cap.ts +0 -139
|
@@ -16,22 +16,30 @@ import {
|
|
|
16
16
|
read_string,
|
|
17
17
|
string_array_schema,
|
|
18
18
|
string_record_schema,
|
|
19
|
+
time_batch_guard,
|
|
20
|
+
time_bundle_call,
|
|
19
21
|
time_density_hook,
|
|
20
22
|
time_hook_transcript,
|
|
23
|
+
time_search_call,
|
|
21
24
|
time_shell,
|
|
25
|
+
time_spans,
|
|
22
26
|
time_transcript_line,
|
|
23
27
|
transcript_record,
|
|
24
28
|
vscode_settings_schema
|
|
25
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-Z6DQJKH3.js";
|
|
26
30
|
import {
|
|
27
31
|
BLOCKED_BY_COUNT_FIELD,
|
|
28
32
|
BLOCKED_BY_FIELD,
|
|
29
33
|
FULL_PAGE_QUERY,
|
|
30
34
|
agent_role_profile,
|
|
31
35
|
agent_session_role,
|
|
36
|
+
changed_paths,
|
|
32
37
|
detached_launch,
|
|
33
38
|
distributed_paths,
|
|
39
|
+
document_section,
|
|
40
|
+
find_package_directory,
|
|
34
41
|
forget_pr_numbers,
|
|
42
|
+
gh_author_association,
|
|
35
43
|
gh_failure,
|
|
36
44
|
git_gh_api_path,
|
|
37
45
|
git_gh_conditional,
|
|
@@ -49,24 +57,24 @@ import {
|
|
|
49
57
|
parse_json_object_or_undefined,
|
|
50
58
|
read_blocked_by,
|
|
51
59
|
read_json_listing,
|
|
60
|
+
read_listed_pull,
|
|
52
61
|
read_pull,
|
|
62
|
+
read_pull_or_listed,
|
|
53
63
|
require_pr_number,
|
|
54
64
|
run_hold,
|
|
55
65
|
session_language,
|
|
56
66
|
stamp_record,
|
|
57
67
|
to_gh_state
|
|
58
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-3GKE653K.js";
|
|
59
69
|
import {
|
|
60
|
-
GIT_LOCATION_VARIABLES,
|
|
61
70
|
PACKAGE_JSON,
|
|
62
71
|
ancestor_directories,
|
|
63
72
|
cli_flags,
|
|
64
73
|
cost_transcript,
|
|
65
74
|
cost_usage,
|
|
75
|
+
durable_state,
|
|
66
76
|
file_reader,
|
|
67
|
-
|
|
68
|
-
git_common_directory,
|
|
69
|
-
git_spawn_sync,
|
|
77
|
+
issue_citation,
|
|
70
78
|
issue_cite,
|
|
71
79
|
issue_number_shape,
|
|
72
80
|
json_value,
|
|
@@ -76,15 +84,17 @@ import {
|
|
|
76
84
|
own_session,
|
|
77
85
|
package_manifest,
|
|
78
86
|
process_identity,
|
|
79
|
-
repo_discovery,
|
|
80
|
-
repo_origin,
|
|
81
87
|
run_carry,
|
|
82
88
|
run_event_stream,
|
|
83
89
|
run_event_stream_emit,
|
|
84
90
|
run_ship_stage,
|
|
85
91
|
session_cite
|
|
86
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-7SIUNQXK.js";
|
|
87
93
|
import {
|
|
94
|
+
session_owner_pin
|
|
95
|
+
} from "./chunk-VVNYJWEI.js";
|
|
96
|
+
import {
|
|
97
|
+
GIT_LOCATION_VARIABLES,
|
|
88
98
|
MS_PER_MINUTE,
|
|
89
99
|
MS_PER_SECOND,
|
|
90
100
|
PACKAGE_DIR,
|
|
@@ -92,9 +102,16 @@ import {
|
|
|
92
102
|
PROBE_TIMEOUT_MS,
|
|
93
103
|
PROJECT_ROOT,
|
|
94
104
|
error_text,
|
|
105
|
+
git_command,
|
|
106
|
+
git_common_directory,
|
|
107
|
+
git_diff_reads,
|
|
108
|
+
git_location_environment,
|
|
109
|
+
git_spawn_sync,
|
|
95
110
|
package_path,
|
|
111
|
+
repo_discovery,
|
|
112
|
+
repo_origin,
|
|
96
113
|
stamp_file
|
|
97
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-45CJJOO7.js";
|
|
98
115
|
|
|
99
116
|
// scripts/josh/hook-decision.ts
|
|
100
117
|
import { text } from "node:stream/consumers";
|
|
@@ -186,10 +203,10 @@ function record_refusal(target, now_ms) {
|
|
|
186
203
|
}
|
|
187
204
|
}
|
|
188
205
|
function create_refusal_stamp(prefix) {
|
|
189
|
-
function
|
|
206
|
+
function path19(transcript_path) {
|
|
190
207
|
return stamp_file.stamp_path(prefix, transcript_path);
|
|
191
208
|
}
|
|
192
|
-
return { path:
|
|
209
|
+
return { path: path19, last_ms: last_refusal_ms, record: record_refusal };
|
|
193
210
|
}
|
|
194
211
|
var { load_environment_file } = josh_environment_file;
|
|
195
212
|
var NO_OUTCOME = { reason: void 0, notice: void 0, fault: void 0 };
|
|
@@ -245,10 +262,10 @@ function create_transcript_guard(spec) {
|
|
|
245
262
|
const stamp = create_refusal_stamp(spec.prefix);
|
|
246
263
|
const notify_stamp = spec.notify ? create_refusal_stamp(spec.notify.prefix) : void 0;
|
|
247
264
|
const parts = { spec, stamp, notify_stamp };
|
|
248
|
-
function
|
|
265
|
+
function is_enabled3() {
|
|
249
266
|
return is_switch_enabled(spec.switch_key);
|
|
250
267
|
}
|
|
251
|
-
function
|
|
268
|
+
function refusal_path2(transcript_path) {
|
|
252
269
|
return stamp.path(transcript_path);
|
|
253
270
|
}
|
|
254
271
|
function outcome(raw_payload, now_ms = Date.now()) {
|
|
@@ -261,7 +278,7 @@ function create_transcript_guard(spec) {
|
|
|
261
278
|
function refusal(raw_payload, now_ms = Date.now()) {
|
|
262
279
|
return outcome(raw_payload, now_ms).reason;
|
|
263
280
|
}
|
|
264
|
-
return { is_enabled, outcome, refusal, refusal_path };
|
|
281
|
+
return { is_enabled: is_enabled3, outcome, refusal, refusal_path: refusal_path2 };
|
|
265
282
|
}
|
|
266
283
|
function emit_outcome(outcome) {
|
|
267
284
|
const { reason, notice, fault } = outcome;
|
|
@@ -356,273 +373,119 @@ async function bounded_map(items, limit, worker) {
|
|
|
356
373
|
}
|
|
357
374
|
var bounded_pool = { bounded_map, pool_width };
|
|
358
375
|
|
|
359
|
-
// scripts/rules/
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
// scripts/rules/stop-decision.ts
|
|
377
|
+
var RECOMMENDED_LABEL = /^recommended[*_]*:/iu;
|
|
378
|
+
var ALTERNATIVE_LABEL = /^alternative[*_]*:/iu;
|
|
379
|
+
var LEADING_EMPHASIS = /^[*_]+/u;
|
|
380
|
+
var TRAILING_EMPHASIS = /(?<![*_])[*_]+$/u;
|
|
381
|
+
var BULLET = /^[-*]\s+/u;
|
|
382
|
+
var QUESTION_ENDING = /(?:[??]|か|かな|かね)[\s。.]*$/u;
|
|
383
|
+
function unwrapped(text2) {
|
|
384
|
+
return text2.trim().replace(LEADING_EMPHASIS, "").replace(TRAILING_EMPHASIS, "").trim();
|
|
385
|
+
}
|
|
386
|
+
function bare_line(line) {
|
|
387
|
+
return unwrapped(line.trim().replace(BULLET, ""));
|
|
388
|
+
}
|
|
389
|
+
function choice_of(message, label) {
|
|
390
|
+
const line = message.split("\n").map((one) => bare_line(one)).find((one) => label.test(one));
|
|
391
|
+
const choice = line === void 0 ? void 0 : unwrapped(line.replace(label, ""));
|
|
392
|
+
return choice === "" ? void 0 : choice;
|
|
393
|
+
}
|
|
394
|
+
function decision_of(message) {
|
|
395
|
+
const recommended = choice_of(message, RECOMMENDED_LABEL);
|
|
396
|
+
if (recommended === void 0) return void 0;
|
|
397
|
+
return { recommended, alternative: choice_of(message, ALTERNATIVE_LABEL) };
|
|
398
|
+
}
|
|
399
|
+
function is_question(prompt) {
|
|
400
|
+
return QUESTION_ENDING.test(prompt.trim());
|
|
401
|
+
}
|
|
402
|
+
var DECISION_REASON = "\u26D4 stop decision: this working tree is held by your run and your reply names no decision. If the run waits on a person, end the reply with a `Recommended: <choice>` line and, where there is one, an `Alternative: <choice>` line \u2014 the hook sends the `confirmation` Telegram from them. If it waits on nobody, continue the run, or say in one line that nothing is awaited. Do not repeat your previous reply.";
|
|
403
|
+
var stop_decision = { DECISION_REASON, decision_of, is_question };
|
|
379
404
|
|
|
380
|
-
// scripts/
|
|
381
|
-
var
|
|
382
|
-
var
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
"env",
|
|
390
|
-
"time"
|
|
391
|
-
]);
|
|
392
|
-
var FLAGGED_WRAPPERS = /* @__PURE__ */ new Set(["time"]);
|
|
393
|
-
var WRAPPER_VALUE_FLAGS = /* @__PURE__ */ new Set(["-o", "-f", "--output", "--format"]);
|
|
394
|
-
var SUBSHELL_OPEN = "(";
|
|
395
|
-
var VALUE_TAKING_GLOBALS = /* @__PURE__ */ new Set([
|
|
396
|
-
"-C",
|
|
397
|
-
"-c",
|
|
398
|
-
"--git-dir",
|
|
399
|
-
"--work-tree",
|
|
400
|
-
"--namespace",
|
|
401
|
-
"--exec-path",
|
|
402
|
-
"--super-prefix"
|
|
403
|
-
]);
|
|
404
|
-
var FLAG_PREFIX = "-";
|
|
405
|
-
var GIT_COMMAND = "git";
|
|
406
|
-
var NEXT = 1;
|
|
407
|
-
var AFTER_VALUE = 2;
|
|
408
|
-
var WORD = /(?:\\.|'[^']*'|"(?:\\.|[^"\\])*"|\S)+/gsu;
|
|
409
|
-
function words_of(segment) {
|
|
410
|
-
return segment.match(WORD) ?? [];
|
|
411
|
-
}
|
|
412
|
-
var PATH_SEPARATOR = "/";
|
|
413
|
-
function program_name(word) {
|
|
414
|
-
return word.slice(word.lastIndexOf(PATH_SEPARATOR) + NEXT);
|
|
415
|
-
}
|
|
416
|
-
function is_wrapper_token(word) {
|
|
417
|
-
return word === SUBSHELL_OPEN || ENV_ASSIGNMENT.test(word) || WRAPPER_WORDS.has(program_name(word));
|
|
418
|
-
}
|
|
419
|
-
function wrapper_flag_width(word = "") {
|
|
420
|
-
if (!word.startsWith(FLAG_PREFIX)) return 0;
|
|
421
|
-
return WRAPPER_VALUE_FLAGS.has(word) ? AFTER_VALUE : NEXT;
|
|
422
|
-
}
|
|
423
|
-
function after_wrapper_word(words, index) {
|
|
424
|
-
let next = index + NEXT;
|
|
425
|
-
if (!FLAGGED_WRAPPERS.has(program_name(words[index] ?? ""))) return next;
|
|
426
|
-
let width = wrapper_flag_width(words[next]);
|
|
427
|
-
while (width > 0) {
|
|
428
|
-
next += width;
|
|
429
|
-
width = wrapper_flag_width(words[next]);
|
|
430
|
-
}
|
|
431
|
-
return next;
|
|
432
|
-
}
|
|
433
|
-
function after_wrapper(words) {
|
|
434
|
-
let index = 0;
|
|
435
|
-
while (index < words.length && is_wrapper_token(words[index] ?? "")) {
|
|
436
|
-
index = after_wrapper_word(words, index);
|
|
437
|
-
}
|
|
438
|
-
return index;
|
|
405
|
+
// scripts/discovery/repo-party.ts
|
|
406
|
+
var FIRST_PARTY = "first-party";
|
|
407
|
+
var THIRD_PARTY = "third-party";
|
|
408
|
+
var UNKNOWN = "unknown";
|
|
409
|
+
var GH_REPO_ENV_KEY = "GH_REPO";
|
|
410
|
+
var GH_REPO_PATH_SEGMENTS = 2;
|
|
411
|
+
function classify(session_owner, target) {
|
|
412
|
+
if (session_owner === void 0 || target === void 0) return UNKNOWN;
|
|
413
|
+
return session_owner.toLowerCase() === target.toLowerCase() ? FIRST_PARTY : THIRD_PARTY;
|
|
439
414
|
}
|
|
440
|
-
function
|
|
441
|
-
return
|
|
415
|
+
function parse_owner_repo(owner_repo) {
|
|
416
|
+
return repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${owner_repo}`);
|
|
442
417
|
}
|
|
443
|
-
function
|
|
444
|
-
|
|
445
|
-
while (index < words.length) {
|
|
446
|
-
const flag = words[index] ?? "";
|
|
447
|
-
if (!flag.startsWith(FLAG_PREFIX)) return index;
|
|
448
|
-
index += global_step(flag);
|
|
449
|
-
}
|
|
450
|
-
return index;
|
|
418
|
+
function target_owner(owner_repo) {
|
|
419
|
+
return parse_owner_repo(owner_repo)?.owner;
|
|
451
420
|
}
|
|
452
|
-
function
|
|
453
|
-
|
|
454
|
-
const command_index = after_wrapper(words);
|
|
455
|
-
const word = words[command_index];
|
|
456
|
-
if (word === void 0) return void 0;
|
|
457
|
-
return { name: program_name(word), args: words.slice(command_index + NEXT) };
|
|
421
|
+
function current_owner(repository_path = process.cwd()) {
|
|
422
|
+
return session_owner_pin.pinned(repository_path) ?? repo_discovery.resolve_current_owner(repository_path);
|
|
458
423
|
}
|
|
459
|
-
function
|
|
460
|
-
|
|
461
|
-
return call?.name === command ? call.args : void 0;
|
|
424
|
+
function selector_repository(selector) {
|
|
425
|
+
return parse_owner_repo(selector.split("/").slice(-GH_REPO_PATH_SEGMENTS).join("/"));
|
|
462
426
|
}
|
|
463
|
-
function
|
|
464
|
-
|
|
465
|
-
if (words === void 0) return void 0;
|
|
466
|
-
const subcommand_index = after_globals(words, 0);
|
|
467
|
-
return { subcommand: words[subcommand_index], args: words.slice(subcommand_index + NEXT) };
|
|
427
|
+
function selector_owner(selector) {
|
|
428
|
+
return selector_repository(selector)?.owner;
|
|
468
429
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if (!SHORT_CLUSTER.test(token)) return false;
|
|
472
|
-
const cluster = token.slice(FLAG_PREFIX.length);
|
|
473
|
-
for (let index = 0; index < letters.length; index += 1) {
|
|
474
|
-
if (cluster.includes(letters.charAt(index))) return true;
|
|
475
|
-
}
|
|
476
|
-
return false;
|
|
430
|
+
function remote_repositories(repository_path) {
|
|
431
|
+
return repo_discovery.read_remote_urls(repository_path).map((url) => repo_origin.parse_origin_url(url));
|
|
477
432
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
var SEGMENT_SEPARATOR = /&&|\|\||;|\n/u;
|
|
482
|
-
var SEGMENT_PARTS = new RegExp(`(${SEGMENT_SEPARATOR.source})`, "u");
|
|
483
|
-
var COMMAND_SEPARATOR = /&&|\|\||;|\n|\|&?|(?<![<>])&(?!>)/u;
|
|
484
|
-
function segments_of(command) {
|
|
485
|
-
return command.split(SEGMENT_SEPARATOR).map((segment) => segment.trim());
|
|
433
|
+
function placeholder_repositories(repository_path, environment) {
|
|
434
|
+
const gh_repo = environment[GH_REPO_ENV_KEY];
|
|
435
|
+
return gh_repo === void 0 || gh_repo === "" ? remote_repositories(repository_path) : [selector_repository(gh_repo)];
|
|
486
436
|
}
|
|
487
|
-
function
|
|
488
|
-
return
|
|
437
|
+
function placeholder_owners(repository_path = process.cwd(), environment = process.env) {
|
|
438
|
+
return placeholder_repositories(repository_path, environment).map((identity) => identity?.owner);
|
|
489
439
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
if (plain === void 0) return commands_of(command);
|
|
494
|
-
const cuts = [...plain.matchAll(COMMAND_SEPARATORS)].map((match) => ({
|
|
495
|
-
begin: match.index,
|
|
496
|
-
end: match.index + match[0].length
|
|
497
|
-
}));
|
|
498
|
-
const starts = [0, ...cuts.map((cut) => cut.end)];
|
|
499
|
-
const stops = cuts.map((cut) => cut.begin);
|
|
500
|
-
return starts.map((start, index) => command.slice(start, stops[index] ?? command.length).trim());
|
|
440
|
+
function is_same_repository(left, right) {
|
|
441
|
+
if (left === void 0 || classify(left.owner, right.owner) !== FIRST_PARTY) return false;
|
|
442
|
+
return left.repo.toLowerCase() === right.repo.toLowerCase();
|
|
501
443
|
}
|
|
502
|
-
function
|
|
503
|
-
|
|
444
|
+
function sole_repository(candidates) {
|
|
445
|
+
const [first, ...rest] = candidates;
|
|
446
|
+
if (first === void 0) return void 0;
|
|
447
|
+
return rest.every((candidate) => is_same_repository(candidate, first)) ? first : void 0;
|
|
504
448
|
}
|
|
505
|
-
function
|
|
506
|
-
|
|
507
|
-
if (plain === void 0) return void 0;
|
|
508
|
-
const cut = plain.search(SEGMENT_SEPARATOR);
|
|
509
|
-
return (cut === -1 ? command : command.slice(0, cut)).trim();
|
|
449
|
+
function current_repository(repository_path = process.cwd(), environment = process.env) {
|
|
450
|
+
return sole_repository(placeholder_repositories(repository_path, environment));
|
|
510
451
|
}
|
|
511
|
-
function
|
|
512
|
-
|
|
513
|
-
if (!named.startsWith(time_shell.JOSH_PREFIX)) return false;
|
|
514
|
-
return names.has(named.slice(time_shell.JOSH_PREFIX.length));
|
|
452
|
+
function is_own_repository(target, own) {
|
|
453
|
+
return is_same_repository(own, target);
|
|
515
454
|
}
|
|
516
|
-
var
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
455
|
+
var repo_party = {
|
|
456
|
+
FIRST_PARTY,
|
|
457
|
+
THIRD_PARTY,
|
|
458
|
+
UNKNOWN,
|
|
459
|
+
classify,
|
|
460
|
+
current_owner,
|
|
461
|
+
current_repository,
|
|
462
|
+
is_own_repository,
|
|
463
|
+
placeholder_owners,
|
|
464
|
+
selector_owner,
|
|
465
|
+
sole_repository,
|
|
466
|
+
target_owner
|
|
523
467
|
};
|
|
524
468
|
|
|
525
|
-
// scripts/rules/
|
|
526
|
-
function
|
|
527
|
-
return
|
|
528
|
-
if (call.name !== cost_blocks.BASH_TOOL) return false;
|
|
529
|
-
return is_match(time_shell.bash_command(call.input));
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
var ISSUE_CREATE_COMMAND = /\bgh\s+(?:\S+\s+)*?issue\s+create\b/u;
|
|
533
|
-
var ISSUES_ENDPOINT = /repos\/[^\s'"]*\/issues(?=$|["'\s])/u;
|
|
534
|
-
var TITLE_FIELD = /(?:-f|-F|--field|--raw-field)\s*'?title=/u;
|
|
535
|
-
var GH_API_COMMAND = /\bgh\s+api\b/u;
|
|
536
|
-
var SHELL_SCRIPT_RUNNER = /\b(?:(?:ba|z|da|k)?sh\s+(?:-\w+\s+)*-\w*c\b|eval\b)/u;
|
|
537
|
-
function spoken_line(command) {
|
|
538
|
-
if (time_shell.has_heredoc(command)) return command;
|
|
539
|
-
const plain = time_shell.unquoted(command);
|
|
540
|
-
return SHELL_SCRIPT_RUNNER.test(plain) ? command : plain;
|
|
541
|
-
}
|
|
542
|
-
var LEADING_SHELL_SCRIPT_RUNNER = new RegExp(`^${SHELL_SCRIPT_RUNNER.source}`, "u");
|
|
543
|
-
var QUOTE_MARK = /["']/gu;
|
|
544
|
-
function shell_script_of(segment) {
|
|
545
|
-
const call = git_argv.program_of(segment);
|
|
546
|
-
if (call === void 0) return void 0;
|
|
547
|
-
const spoken = [call.name, ...call.args].join(" ");
|
|
548
|
-
const runner = LEADING_SHELL_SCRIPT_RUNNER.exec(spoken);
|
|
549
|
-
if (runner === null) return void 0;
|
|
550
|
-
return spoken.slice(runner[0].length).replaceAll(QUOTE_MARK, "").trim();
|
|
551
|
-
}
|
|
552
|
-
function is_direct_filing(command) {
|
|
553
|
-
const spoken = spoken_line(command);
|
|
554
|
-
if (ISSUE_CREATE_COMMAND.test(spoken)) return true;
|
|
555
|
-
return GH_API_COMMAND.test(spoken) && ISSUES_ENDPOINT.test(command) && TITLE_FIELD.test(command);
|
|
556
|
-
}
|
|
557
|
-
var FILING_NAMES = /* @__PURE__ */ new Set(["issue:file"]);
|
|
558
|
-
function is_issue_filing(command) {
|
|
559
|
-
return shell_segments.segments_of(command).some((segment) => shell_segments.is_josh_command(segment, FILING_NAMES));
|
|
560
|
-
}
|
|
561
|
-
var bash_triggers = { is_direct_filing, is_issue_filing, on_bash_command, shell_script_of };
|
|
562
|
-
|
|
563
|
-
// scripts/rules/filing-cap.ts
|
|
564
|
-
var FILING_CAP = 10;
|
|
565
|
-
var CAP_REACHED = FILING_CAP;
|
|
566
|
-
function is_filing_use(block) {
|
|
567
|
-
if (!tail_commands.is_bash_use(block)) return false;
|
|
568
|
-
return bash_triggers.is_issue_filing(time_shell.bash_command(block.input));
|
|
569
|
-
}
|
|
570
|
-
function collect_block(block, found) {
|
|
571
|
-
if (block.result_id !== "" && block.is_error === true) found.failures.add(block.result_id);
|
|
572
|
-
if (is_filing_use(block)) found.filing_ids.push(block.id);
|
|
573
|
-
}
|
|
574
|
-
function collect_line(line, found) {
|
|
575
|
-
const parsed = time_transcript_line.parse_line(line);
|
|
576
|
-
if (parsed === void 0) return;
|
|
577
|
-
for (const block of parsed.blocks) collect_block(block, found);
|
|
578
|
-
}
|
|
579
|
-
function scan_tail(tail) {
|
|
580
|
-
const found = { filing_ids: [], failures: /* @__PURE__ */ new Set() };
|
|
581
|
-
for (const line of tail.split("\n")) collect_line(line, found);
|
|
582
|
-
return found;
|
|
583
|
-
}
|
|
584
|
-
function prior_filing_count(tail) {
|
|
585
|
-
const { filing_ids, failures } = scan_tail(tail);
|
|
586
|
-
return filing_ids.filter((id) => !failures.has(id)).length;
|
|
469
|
+
// scripts/rules/tail-commands.ts
|
|
470
|
+
function is_bash_use(block) {
|
|
471
|
+
return block.type === cost_blocks.TOOL_USE_TYPE && block.name === cost_blocks.BASH_TOOL;
|
|
587
472
|
}
|
|
588
|
-
function
|
|
473
|
+
function bash_commands_of(line) {
|
|
589
474
|
const parsed = time_transcript_line.parse_line(line);
|
|
590
|
-
if (parsed
|
|
591
|
-
return parsed.blocks.
|
|
592
|
-
}
|
|
593
|
-
function current_turn(tail) {
|
|
594
|
-
const lines = tail.split("\n");
|
|
595
|
-
const start = lines.findLastIndex((line) => is_prompt_line(line));
|
|
596
|
-
return lines.slice(Math.max(start, 0)).join("\n");
|
|
475
|
+
if (parsed === void 0) return [];
|
|
476
|
+
return parsed.blocks.filter((block) => is_bash_use(block)).map((block) => time_shell.bash_command(block.input));
|
|
597
477
|
}
|
|
598
|
-
function
|
|
599
|
-
return
|
|
478
|
+
function prior_bash_commands(tail) {
|
|
479
|
+
return tail.split("\n").flatMap((line) => bash_commands_of(line));
|
|
600
480
|
}
|
|
601
|
-
function
|
|
602
|
-
|
|
481
|
+
function answered(text2, is_call, token) {
|
|
482
|
+
const blocks = time_transcript_line.parse_text(text2).flatMap((line) => line.blocks);
|
|
483
|
+
const call_ids = new Set(
|
|
484
|
+
blocks.filter((block) => is_call(time_shell.bash_command(block.input))).map((block) => block.id)
|
|
485
|
+
);
|
|
486
|
+
return blocks.some((block) => call_ids.has(block.result_id) && block.token_lines.includes(token));
|
|
603
487
|
}
|
|
604
|
-
var
|
|
605
|
-
var ROW = {
|
|
606
|
-
id: "filing-cap",
|
|
607
|
-
is_trigger: bash_triggers.on_bash_command(bash_triggers.is_issue_filing),
|
|
608
|
-
reason: FILING_CAP_REASON,
|
|
609
|
-
decide,
|
|
610
|
-
about: {
|
|
611
|
-
title: "The 10-Issue filing cap per run",
|
|
612
|
-
topic: "`.claude/skills/workflow-commands/prerequisite.md`, `observation-filing.md`",
|
|
613
|
-
fires: "the 11th `pnpm josh issue:file` in a run that already has 10 filings not refused; failed calls do not count. Every occurrence",
|
|
614
|
-
quiet: "fewer than 10 filings not refused"
|
|
615
|
-
}
|
|
616
|
-
};
|
|
617
|
-
var filing_cap = {
|
|
618
|
-
FILING_CAP,
|
|
619
|
-
FILING_CAP_REASON,
|
|
620
|
-
ROW,
|
|
621
|
-
current_turn,
|
|
622
|
-
is_prompt_line,
|
|
623
|
-
prior_filing_count,
|
|
624
|
-
turn_filing_count
|
|
625
|
-
};
|
|
488
|
+
var tail_commands = { answered, is_bash_use, prior_bash_commands };
|
|
626
489
|
|
|
627
490
|
// scripts/backlog/backlog-budget.ts
|
|
628
491
|
var MINUTES_PER_HOUR = 60;
|
|
@@ -707,7 +570,7 @@ function answer_decision(input) {
|
|
|
707
570
|
if (input.answer === "candidates") return { verdict: RUN_VERDICT, reason: run_reason(input) };
|
|
708
571
|
return FIXED_DECISIONS[input.answer] ?? idle_decision(input);
|
|
709
572
|
}
|
|
710
|
-
function
|
|
573
|
+
function decide(input) {
|
|
711
574
|
return max_decision(input) ?? answer_decision(input);
|
|
712
575
|
}
|
|
713
576
|
var backlog_budget = {
|
|
@@ -723,7 +586,7 @@ var backlog_budget = {
|
|
|
723
586
|
TRIAGE_VERDICT,
|
|
724
587
|
WAITING_ON,
|
|
725
588
|
WATCH_VERDICT,
|
|
726
|
-
decide
|
|
589
|
+
decide,
|
|
727
590
|
draining_reason,
|
|
728
591
|
idle_expired_reason,
|
|
729
592
|
idle_watch_reason,
|
|
@@ -735,171 +598,660 @@ var backlog_budget = {
|
|
|
735
598
|
taken_by
|
|
736
599
|
};
|
|
737
600
|
|
|
738
|
-
// scripts/
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
601
|
+
// scripts/run/cut/run-cut.ts
|
|
602
|
+
import { z as z4 } from "zod";
|
|
603
|
+
|
|
604
|
+
// scripts/run/cut/run-cut-digest.ts
|
|
605
|
+
import path3 from "node:path";
|
|
606
|
+
|
|
607
|
+
// scripts/delegation/duplicate-read-guard.ts
|
|
608
|
+
import { statSync } from "node:fs";
|
|
609
|
+
|
|
610
|
+
// scripts/lane/lane-guard-policy.ts
|
|
611
|
+
var DEFAULT_MODE = "refuse";
|
|
612
|
+
var OFF_MODE = "off";
|
|
613
|
+
var LANE_GUARD_POLICY = [
|
|
614
|
+
{
|
|
615
|
+
id: "investigation",
|
|
616
|
+
mode_in_lane_child: "refuse",
|
|
617
|
+
because: "the notice was measured not to move the reading \u2014 52% of lane cost stayed in main-line exploration \u2014 and the refusal fires once per accumulation, a round trip the child survives as it survives the rule row, so the child is refused like the main line"
|
|
752
618
|
},
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
619
|
+
{
|
|
620
|
+
id: "batching",
|
|
621
|
+
mode_in_lane_child: "off",
|
|
622
|
+
because: "a refusal ends a child turn and every advisory notice was measured not to move the call density, so the guard is off and the density stays readable through `josh time:density`"
|
|
757
623
|
},
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
"claude-opus-4-8": { input: 5, output: 25 },
|
|
763
|
-
"claude-opus-4-7": { input: 5, output: 25 },
|
|
764
|
-
"claude-opus-4-6": { input: 5, output: 25 },
|
|
765
|
-
"claude-sonnet-5-5": {
|
|
766
|
-
input: 2,
|
|
767
|
-
output: 10,
|
|
768
|
-
cache_read_multiplier: HALVED_CACHE_READ_MULTIPLIER
|
|
624
|
+
{
|
|
625
|
+
id: "search-batching",
|
|
626
|
+
mode_in_lane_child: "refuse",
|
|
627
|
+
because: "the largest share of single-call pairs in lane children is a search chain (`grep` / `sed` issued one per turn, about 10,600 pairs in 14 days), and a refusal re-fires only every third single-call search turn, so one refused round trip (about $0.036) is repaid once it folds two later searches into one turn"
|
|
769
628
|
},
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
629
|
+
{
|
|
630
|
+
id: "duplicate-read",
|
|
631
|
+
mode_in_lane_child: "notice",
|
|
632
|
+
because: "a refusal ends a child turn, yet unchanged re-reads are measured in lane children above all, so the child is nudged to scroll up to the earlier read by a notice rather than killed"
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
id: "rule",
|
|
636
|
+
mode_in_lane_child: "refuse",
|
|
637
|
+
because: "it carries the lane-only rules a child depends on (`pre-gate-cut`, `implementation-cut`, `lane-park`) and the safety rules it must still obey, and a notice was rejected despite the collateral a refusal costs a batched sibling, because a cut carried as prose was measured never to fire"
|
|
638
|
+
}
|
|
639
|
+
];
|
|
640
|
+
var KNOWN_GUARD_IDS = LANE_GUARD_POLICY.map((entry) => entry.id);
|
|
641
|
+
function entry_for(id) {
|
|
642
|
+
return LANE_GUARD_POLICY.find((entry) => entry.id === id.trim());
|
|
643
|
+
}
|
|
644
|
+
function mode_in_lane_child(id) {
|
|
645
|
+
return entry_for(id)?.mode_in_lane_child ?? DEFAULT_MODE;
|
|
646
|
+
}
|
|
647
|
+
function mode_here(id, directory = process.cwd(), source = process.env) {
|
|
648
|
+
const lane_mode = mode_in_lane_child(id);
|
|
649
|
+
if (lane_mode === DEFAULT_MODE) return DEFAULT_MODE;
|
|
650
|
+
return lane_child_marker.is_child_of(directory, source) ? lane_mode : DEFAULT_MODE;
|
|
651
|
+
}
|
|
652
|
+
function is_suppressed_here(id, directory = process.cwd(), source = process.env) {
|
|
653
|
+
return mode_here(id, directory, source) === OFF_MODE;
|
|
654
|
+
}
|
|
655
|
+
var lane_guard_policy = {
|
|
656
|
+
LANE_GUARD_POLICY,
|
|
657
|
+
KNOWN_GUARD_IDS,
|
|
658
|
+
entry_for,
|
|
659
|
+
mode_in_lane_child,
|
|
660
|
+
mode_here,
|
|
661
|
+
is_suppressed_here
|
|
775
662
|
};
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
function
|
|
787
|
-
return
|
|
663
|
+
|
|
664
|
+
// scripts/delegation/investigation-reads.ts
|
|
665
|
+
import path2 from "node:path";
|
|
666
|
+
|
|
667
|
+
// scripts/document/capped-print-part.ts
|
|
668
|
+
import path from "node:path";
|
|
669
|
+
var DIRECTORY_PREFIX = "josh-capped-print-";
|
|
670
|
+
var PART_PREFIX = "part-";
|
|
671
|
+
var PART_SUFFIX = ".md";
|
|
672
|
+
var PART_PATTERN = /^part-[1-9]\d*\.md$/u;
|
|
673
|
+
function part_name(index) {
|
|
674
|
+
return `${PART_PREFIX}${String(index + 1)}${PART_SUFFIX}`;
|
|
675
|
+
}
|
|
676
|
+
function is_part_file(absolute) {
|
|
677
|
+
const parent = path.basename(path.dirname(absolute));
|
|
678
|
+
return parent.startsWith(DIRECTORY_PREFIX) && PART_PATTERN.test(path.basename(absolute));
|
|
679
|
+
}
|
|
680
|
+
var capped_print_part = { DIRECTORY_PREFIX, part_name, is_part_file };
|
|
681
|
+
|
|
682
|
+
// scripts/git/changed-paths-sync.ts
|
|
683
|
+
function options_of(cwd) {
|
|
684
|
+
if (cwd === void 0) return {};
|
|
685
|
+
return { cwd, env: git_location_environment.location_free_environment() };
|
|
686
|
+
}
|
|
687
|
+
function default_branch_reference(options) {
|
|
688
|
+
const output = git_spawn_sync.read([...git_diff_reads.DEFAULT_BRANCH_ARGUMENTS], options);
|
|
689
|
+
const default_branch = git_diff_reads.default_branch_of(output);
|
|
690
|
+
const remote_reference = git_diff_reads.remote_reference_of(default_branch);
|
|
691
|
+
const check2 = git_diff_reads.reference_check_arguments(remote_reference);
|
|
692
|
+
return git_spawn_sync.read(check2, options) === void 0 ? default_branch : remote_reference;
|
|
693
|
+
}
|
|
694
|
+
function through_merge(base, reference, options) {
|
|
695
|
+
const incoming = git_spawn_sync.read(git_diff_reads.incoming_base_arguments(reference), options);
|
|
696
|
+
if (incoming === void 0) return base;
|
|
697
|
+
const kept = git_spawn_sync.read(git_diff_reads.later_base_arguments(base, incoming), options);
|
|
698
|
+
return git_diff_reads.later_base_of(kept, base);
|
|
699
|
+
}
|
|
700
|
+
function change_base(options) {
|
|
701
|
+
const reference = default_branch_reference(options);
|
|
702
|
+
const base = git_spawn_sync.read(git_diff_reads.merge_base_arguments(reference), options);
|
|
703
|
+
if (base === void 0) return reference;
|
|
704
|
+
return through_merge(base, reference, options);
|
|
705
|
+
}
|
|
706
|
+
function read_changed_paths(cwd) {
|
|
707
|
+
const options = options_of(cwd);
|
|
708
|
+
const tracked = git_spawn_sync.read(
|
|
709
|
+
git_diff_reads.names_since_arguments(change_base(options)),
|
|
710
|
+
options
|
|
711
|
+
);
|
|
712
|
+
const untracked = git_spawn_sync.read(git_diff_reads.UNTRACKED_ARGUMENTS, options);
|
|
713
|
+
return [tracked, untracked].flatMap((raw = "") => changed_paths.to_paths(raw));
|
|
788
714
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
715
|
+
var changed_paths_sync = { read_changed_paths };
|
|
716
|
+
|
|
717
|
+
// scripts/delegation/delegation-policy.ts
|
|
718
|
+
var DELEGATE_VERDICT = "delegate";
|
|
719
|
+
var KEEP_VERDICT = "keep";
|
|
720
|
+
var INVESTIGATION_FILE_THRESHOLD = 3;
|
|
721
|
+
var INVESTIGATION_SEARCH_TURN_THRESHOLD = 3;
|
|
722
|
+
var INVESTIGATOR_AGENT = "investigator";
|
|
723
|
+
var INVESTIGATION_LIMIT = `${String(INVESTIGATION_FILE_THRESHOLD)} files read and not edited, or ${String(INVESTIGATION_SEARCH_TURN_THRESHOLD)} search turns, since the last delegated unit`;
|
|
724
|
+
var INVESTIGATION_STEP = `Dispatch the \`${INVESTIGATOR_AGENT}\` agent (\`kit:${INVESTIGATOR_AGENT}\` in a consumer) with \`run_in_background: false\`; it returns \`file:line\` citations, never the file text.`;
|
|
725
|
+
var DELEGATABLE_STEPS = [
|
|
726
|
+
{
|
|
727
|
+
name: "gate-fix",
|
|
728
|
+
does: "apply the fixes the verification gate already named \u2014 a lint rule, a type error, a spelling the dictionary rejects",
|
|
729
|
+
verifier: "`pnpm josh gate` is re-run; a wrong fix fails it again, and the failure names the file"
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
name: "epic-child",
|
|
733
|
+
// One row, two entry points: an epic's child and one named issue of a `backlogrun` are the same
|
|
734
|
+
// unit — same brief, same summary, same verifier. A second row for the batch would be the clone
|
|
735
|
+
// `CLAUDE.md` prohibits.
|
|
736
|
+
does: "run one child of a batch end to end in an isolated unit \u2014 an epic's child or one named issue of a `backlogrun` alike \u2014 plan, verification gate, PR, merge \u2014 and return only its summary to the parent loop",
|
|
737
|
+
verifier: "the parent reads the child's state from GitHub with `pnpm josh issue:state`, not from the summary; a child reported done but not merged is still open, which is the failure showing rather than a run continuing, and its own gate, `/code-review` and CI ran inside the unit before `followup` would touch the PR"
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
name: "followup-filing",
|
|
741
|
+
// The late-run follow-up filing chain — `issue:file` (which scouts, lints, labels and runs
|
|
742
|
+
// epic:bundle itself) → epic --add — is a dependency chain the batching guard
|
|
743
|
+
// correctly keeps one call per step, and what makes it expensive is the ~340k context it runs in
|
|
744
|
+
// at the tail of a run, not the step count. A fresh unit runs the same
|
|
745
|
+
// chain at a small context, and the review round cap already composed the finding text, so what
|
|
746
|
+
// the unit is handed is mechanical: run the commands and act on their deterministic answers. This
|
|
747
|
+
// is not the batching guard's business — delegation only moves the chain to a cheaper context.
|
|
748
|
+
does: "run the late-run follow-up filing chain in an isolated unit \u2014 issue:file (lint, labels, scout, epic:bundle), then epic --add \u2014 given the finding text the parent already composed, and return the new Issue number and the epic:bundle answer",
|
|
749
|
+
verifier: "the parent reads the filed Issue from GitHub with `pnpm josh issue:state <new>`, not the unit's summary; a follow-up reported filed but not created is still absent, the way `epic-child`'s reported-done-but-not-merged child is still open. The finding text came from the parent and `issue:file`'s steps are deterministic, so the unit's work is the mechanical execution `issue:state` confirms"
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
name: "implementation-unit",
|
|
753
|
+
// The Step 0 change list already decided *what* to change — that design stays in the main line,
|
|
754
|
+
// which is why `design` is rejected below. What is delegated is the *writing* of one unit of that
|
|
755
|
+
// list, and only a unit whose files are disjoint from every other dispatched unit: two subagents
|
|
756
|
+
// editing one file in parallel race on it. `pnpm josh fanout` confirms that disjointness
|
|
757
|
+
// mechanically, so the split is read off the file sets rather than judged.
|
|
758
|
+
does: "implement one file-disjoint unit of the Step 0 change list in an isolated subagent \u2014 the files it edits shared with no other dispatched unit, confirmed by `pnpm josh fanout` \u2014 and return the edited files, never a summary standing in for the diff; the main line keeps integration and the verification gate. Units that share a file, or an Issue that will not split, stay serial",
|
|
759
|
+
verifier: "the parent runs the whole integrated change through `pnpm josh gate` and a `/code-review` subagent it would run anyway \u2014 a unit's mistake fails the same gate and review a serial edit passes through, so delegating writes nothing the backstop does not already catch, and the `pnpm josh fanout` disjointness removes the one failure parallelism adds, two units colliding on a file"
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
name: "survey",
|
|
763
|
+
does: "read across many files and report where something appears \u2014 every reference to a symbol, which documents carry a marker",
|
|
764
|
+
verifier: "the reported locations are checked directly; a fabricated or missed location does not survive one `grep` of what it claimed"
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
name: "investigation",
|
|
768
|
+
// Not `survey`: that row reports *where* something appears and is checked by one `grep`, while
|
|
769
|
+
// this one reports *how the subject works* and is checked by opening the lines it cited. The two
|
|
770
|
+
// verifiers differ, so widening `survey` would put both in one field and lose the boundary below.
|
|
771
|
+
// **No ordinal.** `${N}rd` would print `1rd` for any other threshold, past a test that only looks
|
|
772
|
+
// for the numeral, so the count is phrased as a plain "N or more".
|
|
773
|
+
does: `read the Issue's subject to find out how it currently works \u2014 once ${String(INVESTIGATION_FILE_THRESHOLD)} or more files the run will not edit have to be read, or ${String(INVESTIGATION_SEARCH_TURN_THRESHOLD)} or more search turns run without an edit \u2014 and return the conclusion plus the \`file:line\` citations that support it, never the file text, which would put the cost back where it was. A throwaway probe script is written, run and deleted inside the unit, which returns its output alone`,
|
|
774
|
+
verifier: "the parent opens the cited lines; a conclusion those lines do not support fails there, and reading a handful of cited regions costs far less than redoing the reading. The unit reports what the code does and never what to change \u2014 deciding that is `diagnosis`, which stays kept, so a unit returning a root cause would be delegating the rejected row under this name"
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
name: "lane-failure-investigation",
|
|
778
|
+
// The `backlogrun` parent's counterpart of `investigation`. The parent
|
|
779
|
+
// orchestrates and never implements, yet it read a failed lane's logs, records and sources in its
|
|
780
|
+
// own context — about 150 grep / cat / sed calls on 2026-10-02 — and every later request of the
|
|
781
|
+
// batch re-read them. The verifier is `investigation`'s, and so is the boundary: the unit reports
|
|
782
|
+
// what happened, and what the parent does about it (park, re-dispatch, file) stays its own call.
|
|
783
|
+
does: "find out why a lane's child stopped, failed or conflicted \u2014 its output log, run records, PR checks and the files they name \u2014 and return the conclusion plus the `file:line` or log-line citations that support it, never the text read, so the batch parent's context stays the size its orchestration needs",
|
|
784
|
+
verifier: "the parent opens the cited lines and re-reads the child with `pnpm josh issue:state`; a conclusion those do not support fails there. The unit reports what happened and never what to do \u2014 parking, re-dispatching or filing stays with the parent, so a wrong account is caught before it is acted on"
|
|
785
|
+
}
|
|
786
|
+
];
|
|
787
|
+
var REJECTED_STEPS = [
|
|
788
|
+
{
|
|
789
|
+
name: "notify-body",
|
|
790
|
+
because: "no verifier. A notification with a wrong body is sent and read as though it were right; nothing in the run disagrees with it afterwards"
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
name: "issue-comment",
|
|
794
|
+
because: "no verifier. A decision log or completion comment that says the wrong thing is the record, so there is nothing left to check it against"
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
name: "status-read",
|
|
798
|
+
because: "a misread routes the run to the wrong child, and no later step disagrees. Running the status command is already cheap; what is expensive is acting on it, which is not this step"
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
name: "diagnosis",
|
|
802
|
+
because: "a wrong root cause produces a fix that passes the gate and leaves the defect"
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
name: "design",
|
|
806
|
+
because: "the cost of a wrong design is paid by every step after it"
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
name: "split-assessment",
|
|
810
|
+
because: "a missed split widens one Issue into a batch nobody authorized"
|
|
811
|
+
},
|
|
812
|
+
{
|
|
813
|
+
name: "review",
|
|
814
|
+
because: "the review is the last thing between a defect and a merge; a cheaper one finds less"
|
|
815
|
+
}
|
|
816
|
+
];
|
|
817
|
+
function find_step(name) {
|
|
818
|
+
return DELEGATABLE_STEPS.find((step) => step.name === name.trim());
|
|
819
|
+
}
|
|
820
|
+
function verdict_for(name) {
|
|
821
|
+
return find_step(name) === void 0 ? KEEP_VERDICT : DELEGATE_VERDICT;
|
|
822
|
+
}
|
|
823
|
+
function rejection_for(name) {
|
|
824
|
+
return REJECTED_STEPS.find((step) => step.name === name.trim());
|
|
825
|
+
}
|
|
826
|
+
function reason_for(name) {
|
|
827
|
+
const step = find_step(name);
|
|
828
|
+
if (step !== void 0) return `delegatable: ${step.verifier}`;
|
|
829
|
+
const rejected = rejection_for(name);
|
|
830
|
+
if (rejected !== void 0) return `kept deliberately: ${rejected.because}`;
|
|
831
|
+
return "kept by default: not on the delegatable list, and the list is the whole of it";
|
|
832
|
+
}
|
|
833
|
+
var delegation_policy = {
|
|
834
|
+
DELEGATE_VERDICT,
|
|
835
|
+
INVESTIGATION_FILE_THRESHOLD,
|
|
836
|
+
INVESTIGATION_LIMIT,
|
|
837
|
+
INVESTIGATION_SEARCH_TURN_THRESHOLD,
|
|
838
|
+
INVESTIGATION_STEP,
|
|
839
|
+
INVESTIGATOR_AGENT,
|
|
840
|
+
KEEP_VERDICT,
|
|
841
|
+
DELEGATABLE_STEPS,
|
|
842
|
+
REJECTED_STEPS,
|
|
843
|
+
find_step,
|
|
844
|
+
verdict_for,
|
|
845
|
+
reason_for
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
// scripts/delegation/investigation-reads.ts
|
|
849
|
+
var READ_TOOLS = /* @__PURE__ */ new Set(["Read"]);
|
|
850
|
+
var DELEGATION_TOOLS = /* @__PURE__ */ new Set(["Agent", "Task"]);
|
|
851
|
+
var CONTENT_READ_COMMANDS = [
|
|
852
|
+
"bat",
|
|
853
|
+
"cat",
|
|
854
|
+
"head",
|
|
855
|
+
"less",
|
|
856
|
+
"more",
|
|
857
|
+
"nl",
|
|
858
|
+
"sed",
|
|
859
|
+
"tail"
|
|
860
|
+
];
|
|
861
|
+
var CONTENT_READ_LABELS = new Set(
|
|
862
|
+
CONTENT_READ_COMMANDS.map((command) => time_shell.bash_label(command))
|
|
863
|
+
);
|
|
864
|
+
var { INVESTIGATOR_AGENT: INVESTIGATOR_AGENT2 } = delegation_policy;
|
|
865
|
+
var REASON = `\u26D4 investigation: ${delegation_policy.INVESTIGATION_LIMIT}. ${delegation_policy.INVESTIGATION_STEP} Keep main-line reads to files you will edit; every read-only search turn counts. \`.claude/skills/workflow-commands/delegation.md\``;
|
|
866
|
+
var INSTRUCTION_PATHS = ["prompts", ".claude/skills"];
|
|
867
|
+
var INSTRUCTION_FILES = /* @__PURE__ */ new Set(["CLAUDE.md", "AGENTS.md", "GEMINI.md"]);
|
|
868
|
+
var REPOSITORY_ROOT = process.cwd();
|
|
869
|
+
function resolved(target) {
|
|
870
|
+
return path2.resolve(REPOSITORY_ROOT, target);
|
|
871
|
+
}
|
|
872
|
+
function repository_relative(absolute) {
|
|
873
|
+
return path2.relative(REPOSITORY_ROOT, absolute);
|
|
874
|
+
}
|
|
875
|
+
function is_instruction_document(target) {
|
|
876
|
+
const relative = repository_relative(resolved(target));
|
|
877
|
+
const segments = relative.split(path2.sep);
|
|
878
|
+
return INSTRUCTION_FILES.has(segments.at(-1) ?? "") || INSTRUCTION_PATHS.some((prefix) => relative.startsWith(`${prefix}${path2.sep}`));
|
|
879
|
+
}
|
|
880
|
+
var SESSION_TEMP_SEGMENT = /^claude-\d+$/u;
|
|
881
|
+
var SESSION_STATE_SEGMENTS = cost_transcript.TRANSCRIPT_ROOT.split(path2.sep);
|
|
882
|
+
var HARNESS_OUTPUT_DIRECTORY = "tasks";
|
|
883
|
+
var HARNESS_OUTPUT_EXTENSION = ".output";
|
|
884
|
+
var FILE_SEGMENT_INDEX = -1;
|
|
885
|
+
var PARENT_SEGMENT_INDEX = -2;
|
|
886
|
+
function has_state_root(segments, index) {
|
|
887
|
+
return SESSION_STATE_SEGMENTS.every((segment, offset) => segments[index + offset] === segment);
|
|
888
|
+
}
|
|
889
|
+
function is_harness_output(segments) {
|
|
890
|
+
return segments.some((segment) => SESSION_TEMP_SEGMENT.test(segment)) && segments.at(PARENT_SEGMENT_INDEX) === HARNESS_OUTPUT_DIRECTORY && (segments.at(FILE_SEGMENT_INDEX) ?? "").endsWith(HARNESS_OUTPUT_EXTENSION);
|
|
891
|
+
}
|
|
892
|
+
function is_outside_repository(absolute) {
|
|
893
|
+
return repository_relative(absolute).startsWith("..");
|
|
894
|
+
}
|
|
895
|
+
function is_session_artifact(target) {
|
|
896
|
+
const absolute = resolved(target);
|
|
897
|
+
const segments = absolute.split(path2.sep);
|
|
898
|
+
if (!is_outside_repository(absolute)) return false;
|
|
899
|
+
return segments.some((_segment, index) => has_state_root(segments, index)) || is_harness_output(segments) || capped_print_part.is_part_file(absolute);
|
|
900
|
+
}
|
|
901
|
+
function is_subject_file(target) {
|
|
902
|
+
return !is_instruction_document(target) && !is_session_artifact(target);
|
|
903
|
+
}
|
|
904
|
+
function is_nameable_file(target) {
|
|
905
|
+
return !target.includes("*") && !target.includes("?");
|
|
906
|
+
}
|
|
907
|
+
function is_content_read(label) {
|
|
908
|
+
return READ_TOOLS.has(label) || CONTENT_READ_LABELS.has(label);
|
|
909
|
+
}
|
|
910
|
+
function subject_targets(targets) {
|
|
911
|
+
return targets.filter((target) => is_nameable_file(target) && is_subject_file(target)).map((target) => resolved(target));
|
|
912
|
+
}
|
|
913
|
+
function call_targets(call) {
|
|
914
|
+
return subject_targets(time_bundle_call.call_facts(call.name, call.input).targets);
|
|
915
|
+
}
|
|
916
|
+
function delegation_instant(span) {
|
|
917
|
+
return span === void 0 ? hook_decision.NEVER_MS : span.ended_ms;
|
|
918
|
+
}
|
|
919
|
+
function is_failed_outcome(span) {
|
|
920
|
+
return span.outcome === time_spans.FAILED_OUTCOME;
|
|
921
|
+
}
|
|
922
|
+
function edited_files(spans) {
|
|
923
|
+
const written = spans.filter((span) => !is_failed_outcome(span)).flatMap((span) => subject_targets(span.writes));
|
|
924
|
+
return new Set(written);
|
|
925
|
+
}
|
|
926
|
+
function add_all(pending, targets, at_ms) {
|
|
927
|
+
for (const target of targets) if (!pending.has(target)) pending.set(target, at_ms);
|
|
928
|
+
}
|
|
929
|
+
function search_turn_key(searches, span) {
|
|
930
|
+
if (span.message_id !== time_spans.NO_MESSAGE_ID) return span.message_id;
|
|
931
|
+
return `${time_spans.NO_MESSAGE_ID}#${String(searches.size)}`;
|
|
932
|
+
}
|
|
933
|
+
function apply_search(searches, span) {
|
|
934
|
+
if (span.is_writing) {
|
|
935
|
+
searches.clear();
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
const turn = search_turn_key(searches, span);
|
|
939
|
+
if (time_search_call.is_read_only_search(span) && !searches.has(turn)) {
|
|
940
|
+
searches.set(turn, span.ended_ms);
|
|
941
|
+
}
|
|
792
942
|
}
|
|
793
|
-
function
|
|
794
|
-
return
|
|
943
|
+
function is_delegation(span) {
|
|
944
|
+
return DELEGATION_TOOLS.has(span.label) && !is_failed_outcome(span);
|
|
795
945
|
}
|
|
796
|
-
function
|
|
946
|
+
function apply_span(accumulation, span, edited) {
|
|
947
|
+
if (is_failed_outcome(span)) return;
|
|
948
|
+
if (is_delegation(span)) {
|
|
949
|
+
accumulation.pending.clear();
|
|
950
|
+
accumulation.searches.clear();
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
apply_search(accumulation.searches, span);
|
|
954
|
+
if (!is_content_read(span.label)) return;
|
|
955
|
+
const fresh = subject_targets(span.targets).filter((target) => !edited.has(target));
|
|
956
|
+
add_all(accumulation.pending, fresh, span.ended_ms);
|
|
957
|
+
}
|
|
958
|
+
function last_delegation_ms(spans) {
|
|
959
|
+
return delegation_instant(spans.findLast((span) => is_delegation(span)));
|
|
960
|
+
}
|
|
961
|
+
function pending_after(pending, since_ms) {
|
|
962
|
+
return [...pending.values()].filter((at_ms) => at_ms > since_ms).length;
|
|
963
|
+
}
|
|
964
|
+
function tally_of(text2, since_ms = hook_decision.NEVER_MS, branch_files = []) {
|
|
965
|
+
const { spans, started_ms } = time_spans.parse_timeline(text2);
|
|
966
|
+
const edited = /* @__PURE__ */ new Set([...edited_files(spans), ...subject_targets(branch_files)]);
|
|
967
|
+
const accumulation = { pending: /* @__PURE__ */ new Map(), searches: /* @__PURE__ */ new Map() };
|
|
968
|
+
for (const span of spans) apply_span(accumulation, span, edited);
|
|
797
969
|
return {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
price.input
|
|
806
|
-
),
|
|
807
|
-
cache_read_usd: priced(totals.cache_read_tokens * cache_read_multiplier(price), price.input),
|
|
808
|
-
output_usd: priced(totals.output_tokens, price.output)
|
|
970
|
+
pending: [...accumulation.pending.keys()],
|
|
971
|
+
pending_since: pending_after(accumulation.pending, since_ms),
|
|
972
|
+
reset_ms: last_delegation_ms(spans),
|
|
973
|
+
window_start_ms: started_ms,
|
|
974
|
+
searches: accumulation.searches.size,
|
|
975
|
+
searches_since: pending_after(accumulation.searches, since_ms),
|
|
976
|
+
edited
|
|
809
977
|
};
|
|
810
978
|
}
|
|
811
|
-
function
|
|
812
|
-
|
|
813
|
-
if (price === void 0) return { model, totals };
|
|
814
|
-
return { model, totals, cost_usd: estimate_cost(totals, price) };
|
|
979
|
+
function projected_count(pending, call, edited = /* @__PURE__ */ new Set()) {
|
|
980
|
+
return (/* @__PURE__ */ new Set([...pending, ...call_targets(call).filter((target) => !edited.has(target))])).size;
|
|
815
981
|
}
|
|
816
|
-
function
|
|
817
|
-
|
|
818
|
-
const is_long = cost_usage.billed_input(usage.totals) > LONG_PROMPT_THRESHOLD;
|
|
819
|
-
return is_long && Object.hasOwn(MODEL_PRICES, long_id) ? long_id : usage.model;
|
|
982
|
+
function is_at_threshold(pending_count) {
|
|
983
|
+
return pending_count + 1 >= delegation_policy.INVESTIGATION_FILE_THRESHOLD;
|
|
820
984
|
}
|
|
821
|
-
function
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
985
|
+
function is_at_search_threshold(search_count) {
|
|
986
|
+
return search_count + 1 >= delegation_policy.INVESTIGATION_SEARCH_TURN_THRESHOLD;
|
|
987
|
+
}
|
|
988
|
+
function has_cleared_the_disarm(tally, refused_at_ms) {
|
|
989
|
+
return tally.reset_ms > refused_at_ms || refused_at_ms < tally.window_start_ms;
|
|
990
|
+
}
|
|
991
|
+
function is_rearmed(tally, refused_at_ms) {
|
|
992
|
+
if (refused_at_ms === hook_decision.NEVER_MS || has_cleared_the_disarm(tally, refused_at_ms)) {
|
|
993
|
+
return true;
|
|
827
994
|
}
|
|
828
|
-
return
|
|
995
|
+
return is_at_threshold(tally.pending_since) || is_at_search_threshold(tally.searches_since);
|
|
829
996
|
}
|
|
830
|
-
function
|
|
831
|
-
return
|
|
832
|
-
usd: costs.reduce((sum, entry) => sum + (entry.cost_usd ?? 0), 0),
|
|
833
|
-
unpriced: costs.filter((entry) => entry.cost_usd === void 0).map((entry) => entry.model)
|
|
834
|
-
};
|
|
997
|
+
function is_unit_transcript(transcript) {
|
|
998
|
+
return transcript.split(path2.sep).includes(cost_transcript.UNIT_DIRECTORY);
|
|
835
999
|
}
|
|
836
|
-
function
|
|
837
|
-
return
|
|
1000
|
+
function is_unit_run(run2) {
|
|
1001
|
+
return run2 !== void 0 && is_unit_transcript(run2.transcript);
|
|
838
1002
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
1003
|
+
function is_read_only_command(call, labels) {
|
|
1004
|
+
if (call.name !== cost_blocks.BASH_TOOL) return false;
|
|
1005
|
+
const label = time_shell.bash_label(time_shell.bash_command(call.input));
|
|
1006
|
+
return labels.has(label) && time_batch_guard.is_read_only_call(call);
|
|
1007
|
+
}
|
|
1008
|
+
function is_search_call(call) {
|
|
1009
|
+
return time_search_call.is_read_only_search(
|
|
1010
|
+
time_spans.to_tool_call(call.name, call.input, time_spans.NO_MESSAGE_ID)
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
function is_refusable_call(call) {
|
|
1014
|
+
if (is_search_call(call)) return true;
|
|
1015
|
+
if (call_targets(call).length === 0) return false;
|
|
1016
|
+
if (READ_TOOLS.has(call.name)) return true;
|
|
1017
|
+
return is_read_only_command(call, CONTENT_READ_LABELS);
|
|
1018
|
+
}
|
|
1019
|
+
function is_growing_past_threshold(tally, call) {
|
|
1020
|
+
if (is_search_call(call)) return is_at_search_threshold(tally.searches);
|
|
1021
|
+
if (!is_at_threshold(tally.pending.length)) return false;
|
|
1022
|
+
return projected_count(tally.pending, call, tally.edited) > tally.pending.length;
|
|
1023
|
+
}
|
|
1024
|
+
function is_blocking(tally, call, refused_at_ms) {
|
|
1025
|
+
return is_growing_past_threshold(tally, call) && is_rearmed(tally, refused_at_ms);
|
|
1026
|
+
}
|
|
1027
|
+
function is_blocking_past_branch(text2, call, refused_at_ms) {
|
|
1028
|
+
if (!is_blocking(tally_of(text2, refused_at_ms), call, refused_at_ms)) return false;
|
|
1029
|
+
const branch_files = changed_paths_sync.read_changed_paths();
|
|
1030
|
+
return is_blocking(tally_of(text2, refused_at_ms, branch_files), call, refused_at_ms);
|
|
1031
|
+
}
|
|
1032
|
+
function should_block(text2, call, refused_at_ms, run2) {
|
|
1033
|
+
if (!is_refusable_call(call) || is_unit_run(run2)) return false;
|
|
1034
|
+
return is_blocking_past_branch(text2, call, refused_at_ms);
|
|
1035
|
+
}
|
|
1036
|
+
var investigation_reads = {
|
|
1037
|
+
DELEGATION_TOOLS,
|
|
1038
|
+
INVESTIGATOR_AGENT: INVESTIGATOR_AGENT2,
|
|
1039
|
+
READ_TOOLS,
|
|
1040
|
+
REASON,
|
|
1041
|
+
is_at_threshold,
|
|
1042
|
+
is_instruction_document,
|
|
1043
|
+
is_rearmed,
|
|
1044
|
+
is_refusable_call,
|
|
1045
|
+
is_session_artifact,
|
|
1046
|
+
is_subject_file,
|
|
1047
|
+
projected_count,
|
|
1048
|
+
resolved,
|
|
1049
|
+
should_block,
|
|
1050
|
+
tally_of
|
|
850
1051
|
};
|
|
851
1052
|
|
|
852
|
-
// scripts/
|
|
853
|
-
var
|
|
854
|
-
var
|
|
855
|
-
|
|
856
|
-
|
|
1053
|
+
// scripts/delegation/duplicate-read-guard.ts
|
|
1054
|
+
var SWITCH_ENV_KEY = "JOSH_DUPLICATE_READ_GUARD";
|
|
1055
|
+
var LANE_GUARD_ID = "duplicate-read";
|
|
1056
|
+
var STAMP_PREFIX = "josh-duplicate-read-guard-";
|
|
1057
|
+
var NOTICE_STAMP_PREFIX = "josh-duplicate-read-notice-";
|
|
1058
|
+
var READ_TOOL = "Read";
|
|
1059
|
+
var GLOB_CHARACTERS = /[*?]/u;
|
|
1060
|
+
var REASON2 = `\u26D4 duplicate read: this file was already read in this session and has not changed since (its mtime predates that read), so reading it again returns nothing new. Scroll up to the earlier result instead of re-reading it. A read with a new offset/limit, or of a file that has since changed, is allowed; set \`JOSH_DUPLICATE_READ_GUARD=off\` to disable this guard.`;
|
|
1061
|
+
var NOTICE = `\u26A0 duplicate read: this file was already read in this session and has not changed since, so re-reading it returns nothing new \u2014 scroll up to the earlier result instead of re-reading it. Set \`JOSH_DUPLICATE_READ_GUARD=off\` to silence this.`;
|
|
1062
|
+
function is_paginated(input) {
|
|
1063
|
+
return input["offset"] !== void 0 || input["limit"] !== void 0;
|
|
1064
|
+
}
|
|
1065
|
+
function names_one_file(file_path) {
|
|
1066
|
+
return typeof file_path === "string" && file_path !== "" && !GLOB_CHARACTERS.test(file_path);
|
|
1067
|
+
}
|
|
1068
|
+
function read_target(call) {
|
|
1069
|
+
if (call.name !== READ_TOOL || !json_value.is_record(call.input)) return void 0;
|
|
1070
|
+
const { input } = call;
|
|
1071
|
+
if (is_paginated(input) || !names_one_file(input["file_path"])) return void 0;
|
|
1072
|
+
return investigation_reads.resolved(input["file_path"]);
|
|
1073
|
+
}
|
|
1074
|
+
function is_refusable_call2(call) {
|
|
1075
|
+
return read_target(call) !== void 0;
|
|
1076
|
+
}
|
|
1077
|
+
function is_successful_read(span) {
|
|
1078
|
+
const is_read = investigation_reads.READ_TOOLS.has(span.label);
|
|
1079
|
+
return is_read && span.outcome !== time_spans.FAILED_OUTCOME;
|
|
1080
|
+
}
|
|
1081
|
+
function reads_target(span, target) {
|
|
1082
|
+
return span.targets.some((one) => investigation_reads.resolved(one) === target);
|
|
1083
|
+
}
|
|
1084
|
+
function last_read_ms(spans, target) {
|
|
1085
|
+
const times = spans.filter((span) => is_successful_read(span) && reads_target(span, target)).map((span) => span.ended_ms);
|
|
1086
|
+
return times.length === 0 ? hook_decision.NEVER_MS : Math.max(...times);
|
|
1087
|
+
}
|
|
1088
|
+
function file_mtime_ms(target) {
|
|
1089
|
+
try {
|
|
1090
|
+
return statSync(target).mtimeMs;
|
|
1091
|
+
} catch {
|
|
1092
|
+
return void 0;
|
|
1093
|
+
}
|
|
857
1094
|
}
|
|
858
|
-
function
|
|
859
|
-
|
|
860
|
-
return
|
|
1095
|
+
function read_window(tail, target) {
|
|
1096
|
+
const { spans, started_ms } = time_spans.parse_timeline(tail);
|
|
1097
|
+
return { last_ms: last_read_ms(spans, target), window_start_ms: started_ms };
|
|
861
1098
|
}
|
|
862
|
-
function
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
return POST_CUT_CONTEXT * write_over_read() / saved_per_request;
|
|
1099
|
+
function is_unchanged_reread(last_ms, mtime) {
|
|
1100
|
+
if (mtime === void 0 || last_ms === hook_decision.NEVER_MS) return false;
|
|
1101
|
+
return mtime < last_ms;
|
|
866
1102
|
}
|
|
867
|
-
function
|
|
868
|
-
|
|
1103
|
+
function is_rearmed2(window, fired_at_ms) {
|
|
1104
|
+
if (fired_at_ms === hook_decision.NEVER_MS || fired_at_ms < window.window_start_ms) return true;
|
|
1105
|
+
return window.last_ms > fired_at_ms;
|
|
869
1106
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1107
|
+
function is_redundant_reread(tail, call, fired_at_ms) {
|
|
1108
|
+
const target = read_target(call);
|
|
1109
|
+
if (target === void 0) return false;
|
|
1110
|
+
const window = read_window(tail, target);
|
|
1111
|
+
if (!is_unchanged_reread(window.last_ms, file_mtime_ms(target))) return false;
|
|
1112
|
+
return is_rearmed2(window, fired_at_ms);
|
|
1113
|
+
}
|
|
1114
|
+
function duplicate_mode() {
|
|
1115
|
+
return lane_guard_policy.mode_here(LANE_GUARD_ID);
|
|
1116
|
+
}
|
|
1117
|
+
function is_candidate(call) {
|
|
1118
|
+
return is_refusable_call2(call) && duplicate_mode() !== "off";
|
|
1119
|
+
}
|
|
1120
|
+
function should_block_here(tail, call, refused_at_ms) {
|
|
1121
|
+
if (duplicate_mode() !== "refuse") return false;
|
|
1122
|
+
return is_redundant_reread(tail, call, refused_at_ms);
|
|
1123
|
+
}
|
|
1124
|
+
function should_notify_here(tail, call, notified_at_ms) {
|
|
1125
|
+
if (duplicate_mode() !== "notice") return false;
|
|
1126
|
+
return is_redundant_reread(tail, call, notified_at_ms);
|
|
1127
|
+
}
|
|
1128
|
+
var GUARD = hook_decision.create_transcript_guard({
|
|
1129
|
+
prefix: STAMP_PREFIX,
|
|
1130
|
+
switch_key: SWITCH_ENV_KEY,
|
|
1131
|
+
is_candidate,
|
|
1132
|
+
should_block: should_block_here,
|
|
1133
|
+
reason: REASON2,
|
|
1134
|
+
notify: {
|
|
1135
|
+
prefix: NOTICE_STAMP_PREFIX,
|
|
1136
|
+
should_notify: should_notify_here,
|
|
1137
|
+
text: () => NOTICE
|
|
1138
|
+
}
|
|
1139
|
+
});
|
|
1140
|
+
var duplicate_read_refusal = GUARD.refusal;
|
|
1141
|
+
var duplicate_read_outcome = GUARD.outcome;
|
|
1142
|
+
var { is_enabled, refusal_path } = GUARD;
|
|
1143
|
+
var notice_refusal_path = hook_decision.create_refusal_stamp(NOTICE_STAMP_PREFIX).path;
|
|
1144
|
+
var { deny_envelope: deny_envelope2, DISABLED_VALUES: DISABLED_VALUES2 } = hook_decision;
|
|
1145
|
+
var duplicate_reads = {
|
|
1146
|
+
is_successful_read,
|
|
1147
|
+
REASON: REASON2,
|
|
1148
|
+
NOTICE
|
|
876
1149
|
};
|
|
877
1150
|
|
|
878
|
-
// scripts/
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
1151
|
+
// scripts/run/cut/run-cut-digest.ts
|
|
1152
|
+
import { z as z2 } from "zod";
|
|
1153
|
+
var session_digest_schema = z2.object({
|
|
1154
|
+
read: z2.array(z2.string()),
|
|
1155
|
+
decisions: z2.array(z2.string())
|
|
1156
|
+
});
|
|
1157
|
+
var MAX_READ_ENTRIES = 40;
|
|
1158
|
+
var MAX_DECISIONS = 12;
|
|
1159
|
+
var MAX_DECISION_CHARS = 240;
|
|
1160
|
+
var DECISION_PREFIX = "Auto-decided:";
|
|
1161
|
+
var DECISION_LINE = /(?:^|[\s'"=])(Auto-decided: [^\n]+)/gu;
|
|
1162
|
+
var TRAILING_QUOTES = /['"]$/u;
|
|
1163
|
+
var ASSISTANT = "assistant";
|
|
1164
|
+
var READ_LABEL = "Already read before the cut \u2014 re-read only the lines you need";
|
|
1165
|
+
var DECISIONS_LABEL = "Decided before the cut \u2014 do not reopen";
|
|
1166
|
+
function shown_path(target, cwd) {
|
|
1167
|
+
const relative = path3.relative(cwd, path3.resolve(cwd, target));
|
|
1168
|
+
return relative.startsWith("..") ? target : relative;
|
|
1169
|
+
}
|
|
1170
|
+
function newest_unique(entries, limit) {
|
|
1171
|
+
const unique = [...new Set(entries.toReversed())].toReversed();
|
|
1172
|
+
return unique.slice(-limit);
|
|
1173
|
+
}
|
|
1174
|
+
function read_files_of(text2, cwd) {
|
|
1175
|
+
const reads = time_spans.parse_timeline(text2).spans.filter((span) => duplicate_reads.is_successful_read(span)).flatMap((span) => span.targets.map((target) => shown_path(target, cwd)));
|
|
1176
|
+
return newest_unique(reads, MAX_READ_ENTRIES);
|
|
1177
|
+
}
|
|
1178
|
+
var COMMENT_INPUT_KEYS = ["command", "content"];
|
|
1179
|
+
function input_strings(input) {
|
|
1180
|
+
if (!json_value.is_record(input)) return [];
|
|
1181
|
+
return COMMENT_INPUT_KEYS.map((key2) => input[key2]).filter((value) => typeof value === "string");
|
|
1182
|
+
}
|
|
1183
|
+
function assistant_texts(record3) {
|
|
1184
|
+
if (record3?.type !== ASSISTANT) return [];
|
|
1185
|
+
return transcript_record.blocks_of(record3).flatMap((block) => [block.text ?? "", ...input_strings(block.input)]);
|
|
1186
|
+
}
|
|
1187
|
+
function decisions_of(text2) {
|
|
1188
|
+
const decisions = text2.split("\n").flatMap((line) => assistant_texts(transcript_record.parse(line))).flatMap((written) => [...written.matchAll(DECISION_LINE)].map((match) => match[1] ?? "")).map((line) => line.replace(TRAILING_QUOTES, "").slice(0, MAX_DECISION_CHARS));
|
|
1189
|
+
return newest_unique(decisions, MAX_DECISIONS);
|
|
1190
|
+
}
|
|
1191
|
+
function digest_of(text2, cwd) {
|
|
1192
|
+
return { read: read_files_of(text2, cwd), decisions: decisions_of(text2) };
|
|
1193
|
+
}
|
|
1194
|
+
function own_transcript(cwd, environment) {
|
|
1195
|
+
if (own_session.session_id_of(environment) === void 0) return void 0;
|
|
1196
|
+
const files = cost_transcript.list_sessions_across(cost_transcript.transcript_directories(cwd));
|
|
1197
|
+
const selection = own_session.select_own_session(files, environment);
|
|
1198
|
+
if (selection.kind === "absent") return void 0;
|
|
1199
|
+
const file = files[selection.index];
|
|
1200
|
+
return file === void 0 ? void 0 : cost_transcript.read_optional(file);
|
|
1201
|
+
}
|
|
1202
|
+
function own_digest(cwd = process.cwd(), environment = process.env) {
|
|
1203
|
+
const text2 = own_transcript(cwd, environment);
|
|
1204
|
+
return text2 === void 0 ? void 0 : digest_of(text2, cwd);
|
|
1205
|
+
}
|
|
1206
|
+
function describe_list(label, entries) {
|
|
1207
|
+
if (entries.length === 0) return [];
|
|
1208
|
+
const bullets = entries.map((entry) => ` - ${entry}`).join("\n");
|
|
1209
|
+
return [`${label}:
|
|
1210
|
+
${bullets}`];
|
|
1211
|
+
}
|
|
1212
|
+
function describe_digest(digest) {
|
|
1213
|
+
if (digest === void 0) return void 0;
|
|
1214
|
+
const blocks = [
|
|
1215
|
+
...describe_list(READ_LABEL, digest.read),
|
|
1216
|
+
...describe_list(DECISIONS_LABEL, digest.decisions)
|
|
1217
|
+
];
|
|
1218
|
+
return blocks.length === 0 ? void 0 : blocks.join("\n\n");
|
|
1219
|
+
}
|
|
1220
|
+
var run_cut_digest = {
|
|
1221
|
+
DECISION_PREFIX,
|
|
1222
|
+
describe_digest,
|
|
1223
|
+
digest_of,
|
|
1224
|
+
own_digest,
|
|
1225
|
+
session_digest_schema
|
|
1226
|
+
};
|
|
883
1227
|
|
|
884
1228
|
// scripts/run/cut/run-cut-handoff.ts
|
|
885
1229
|
import { readFileSync } from "node:fs";
|
|
886
|
-
import { z as
|
|
887
|
-
var handoff_schema =
|
|
888
|
-
instruction:
|
|
889
|
-
completed:
|
|
890
|
-
remaining:
|
|
891
|
-
untouched:
|
|
1230
|
+
import { z as z3 } from "zod";
|
|
1231
|
+
var handoff_schema = z3.object({
|
|
1232
|
+
instruction: z3.string(),
|
|
1233
|
+
completed: z3.array(z3.string()),
|
|
1234
|
+
remaining: z3.array(z3.string()),
|
|
1235
|
+
untouched: z3.array(z3.string()),
|
|
1236
|
+
findings: z3.array(z3.string()).optional()
|
|
892
1237
|
});
|
|
893
1238
|
var COMPLETED_LABEL = "Completed";
|
|
894
1239
|
var REMAINING_LABEL = "Remaining";
|
|
895
1240
|
var UNTOUCHED_LABEL = "Deliberately untouched";
|
|
896
1241
|
var INSTRUCTION_LABEL = "Instruction (verbatim)";
|
|
1242
|
+
var FINDINGS_LABEL = "Round-1 findings, attested but not recorded \u2014 do not rerun round 1: fix them, then record them with `pnpm josh review:record --issue <N>`";
|
|
897
1243
|
var EMPTY_LIST_NOTE = "(none)";
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1244
|
+
var PLACEHOLDER = "\u2026";
|
|
1245
|
+
var FINDINGS_PLACEHOLDER = "unrecorded";
|
|
1246
|
+
var EXAMPLE_LIST = `["${PLACEHOLDER}"]`;
|
|
1247
|
+
var EXAMPLE_VALUES = {
|
|
1248
|
+
instruction: `"${PLACEHOLDER}"`,
|
|
1249
|
+
completed: EXAMPLE_LIST,
|
|
1250
|
+
remaining: EXAMPLE_LIST,
|
|
1251
|
+
untouched: EXAMPLE_LIST,
|
|
1252
|
+
findings: `["${FINDINGS_PLACEHOLDER}"]`
|
|
1253
|
+
};
|
|
1254
|
+
var HANDOFF_FORMAT = `{${handoff_schema.keyof().options.map((key2) => `"${key2}":${EXAMPLE_VALUES[key2]}`).join(",")}}`;
|
|
903
1255
|
function parse_handoff(raw) {
|
|
904
1256
|
return json_value.parse_with(raw, handoff_schema);
|
|
905
1257
|
}
|
|
@@ -930,25 +1282,43 @@ function load_handoff(handoff_path, max_bytes) {
|
|
|
930
1282
|
}
|
|
931
1283
|
return { kind: "ok", handoff };
|
|
932
1284
|
}
|
|
933
|
-
function
|
|
1285
|
+
function describe_list2(label, items) {
|
|
934
1286
|
if (items.length === 0) return `${label}: ${EMPTY_LIST_NOTE}`;
|
|
935
1287
|
const bullets = items.map((item) => ` - ${item}`).join("\n");
|
|
936
1288
|
return `${label}:
|
|
937
1289
|
${bullets}`;
|
|
938
1290
|
}
|
|
1291
|
+
function carried_findings(handoff) {
|
|
1292
|
+
const findings = handoff?.findings ?? [];
|
|
1293
|
+
return findings.filter(
|
|
1294
|
+
(finding) => ![PLACEHOLDER, FINDINGS_PLACEHOLDER, ""].includes(finding.trim())
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
function describe_findings(handoff) {
|
|
1298
|
+
const findings = carried_findings(handoff);
|
|
1299
|
+
if (findings.length === 0) return [];
|
|
1300
|
+
return [describe_list2(FINDINGS_LABEL, findings)];
|
|
1301
|
+
}
|
|
939
1302
|
function describe_handoff(handoff) {
|
|
940
1303
|
return [
|
|
941
1304
|
`${INSTRUCTION_LABEL}:
|
|
942
1305
|
${handoff.instruction}`,
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
1306
|
+
describe_list2(COMPLETED_LABEL, handoff.completed),
|
|
1307
|
+
describe_list2(REMAINING_LABEL, handoff.remaining),
|
|
1308
|
+
describe_list2(UNTOUCHED_LABEL, handoff.untouched),
|
|
1309
|
+
...describe_findings(handoff)
|
|
946
1310
|
].join("\n\n");
|
|
947
1311
|
}
|
|
948
1312
|
var HANDOFF_PATH = ".josh/tmp/handoff-<N>.json";
|
|
1313
|
+
var ISSUE_PLACEHOLDER = "<N>";
|
|
1314
|
+
function handoff_path_of(issue) {
|
|
1315
|
+
return HANDOFF_PATH.replace(ISSUE_PLACEHOLDER, () => issue);
|
|
1316
|
+
}
|
|
949
1317
|
var run_cut_handoff = {
|
|
950
1318
|
HANDOFF_FORMAT,
|
|
951
1319
|
HANDOFF_PATH,
|
|
1320
|
+
handoff_path_of,
|
|
1321
|
+
carried_findings,
|
|
952
1322
|
describe_handoff,
|
|
953
1323
|
handoff_schema,
|
|
954
1324
|
is_complete_handoff,
|
|
@@ -960,21 +1330,21 @@ var run_cut_handoff = {
|
|
|
960
1330
|
// scripts/run/cut/run-cut.ts
|
|
961
1331
|
var CUT_PREFIX = "josh-run-cut-";
|
|
962
1332
|
var { PRE_GATE_PHASE, IMPLEMENTATION_PHASE } = agent_role_profile;
|
|
963
|
-
var IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD;
|
|
964
1333
|
var CUT_MAX_AGE_MS = backlog_budget.DEFAULT_IDLE_MS;
|
|
965
1334
|
var CUT_MAX_AGE_HOURS = backlog_budget.IDLE_WAIT_HOURS;
|
|
966
1335
|
var END_COMMAND = "pnpm josh run:cut --end";
|
|
967
1336
|
var READ_COMMAND = "pnpm josh run:cut --json";
|
|
968
1337
|
var MAX_HANDOFF_BYTES = 8192;
|
|
969
|
-
var run_cut_schema =
|
|
970
|
-
invocation:
|
|
971
|
-
issue:
|
|
972
|
-
branch:
|
|
973
|
-
phase:
|
|
974
|
-
cut_at:
|
|
975
|
-
is_handed_off:
|
|
1338
|
+
var run_cut_schema = z4.object({
|
|
1339
|
+
invocation: z4.string(),
|
|
1340
|
+
issue: z4.string(),
|
|
1341
|
+
branch: z4.string(),
|
|
1342
|
+
phase: z4.string(),
|
|
1343
|
+
cut_at: z4.string(),
|
|
1344
|
+
is_handed_off: z4.boolean().optional(),
|
|
976
1345
|
handoff: run_cut_handoff.handoff_schema.optional(),
|
|
977
|
-
|
|
1346
|
+
digest: run_cut_digest.session_digest_schema.optional(),
|
|
1347
|
+
is_merge_relaunched: z4.boolean().optional()
|
|
978
1348
|
});
|
|
979
1349
|
function cut_path(git_directory) {
|
|
980
1350
|
return stamp_file.stamp_path(CUT_PREFIX, git_directory);
|
|
@@ -997,21 +1367,21 @@ var CUT_SPEC = {
|
|
|
997
1367
|
function is_expired(cut, now) {
|
|
998
1368
|
return stamp_record.is_older_than(cut_at_of(cut), CUT_MAX_AGE_MS, now);
|
|
999
1369
|
}
|
|
1000
|
-
function
|
|
1001
|
-
const
|
|
1002
|
-
if (!("record" in
|
|
1003
|
-
return { kind:
|
|
1370
|
+
function classify2(raw, now) {
|
|
1371
|
+
const read4 = stamp_record.classify(raw, CUT_SPEC, now);
|
|
1372
|
+
if (!("record" in read4)) return read4;
|
|
1373
|
+
return { kind: read4.kind, cut: read4.record };
|
|
1004
1374
|
}
|
|
1005
1375
|
function read_cut(target, now = /* @__PURE__ */ new Date()) {
|
|
1006
|
-
return
|
|
1376
|
+
return classify2(stamp_file.read_stamp_text(target), now);
|
|
1007
1377
|
}
|
|
1008
1378
|
function worktree_git_directory_sync() {
|
|
1009
1379
|
return git_common_directory.own();
|
|
1010
1380
|
}
|
|
1011
1381
|
function carried_cut_sync(now = /* @__PURE__ */ new Date(), directory = worktree_git_directory_sync()) {
|
|
1012
1382
|
if (directory === void 0) return void 0;
|
|
1013
|
-
const
|
|
1014
|
-
return
|
|
1383
|
+
const read4 = read_cut(cut_path(directory), now);
|
|
1384
|
+
return read4.kind === "carried" ? read4.cut : void 0;
|
|
1015
1385
|
}
|
|
1016
1386
|
function lane_cut_sync(lane_directory) {
|
|
1017
1387
|
const directory = git_common_directory.own(lane_directory);
|
|
@@ -1027,7 +1397,8 @@ function fresh_cut(spec, now) {
|
|
|
1027
1397
|
phase: spec.phase,
|
|
1028
1398
|
cut_at: now.toISOString(),
|
|
1029
1399
|
is_handed_off: true,
|
|
1030
|
-
handoff: spec.handoff
|
|
1400
|
+
handoff: spec.handoff,
|
|
1401
|
+
digest: spec.digest
|
|
1031
1402
|
};
|
|
1032
1403
|
}
|
|
1033
1404
|
function resumes_into_implementation(phase) {
|
|
@@ -1039,6 +1410,11 @@ function within_handoff_bound(cut) {
|
|
|
1039
1410
|
function record_within_bound(spec, now = /* @__PURE__ */ new Date()) {
|
|
1040
1411
|
return within_handoff_bound(fresh_cut(spec, now));
|
|
1041
1412
|
}
|
|
1413
|
+
function with_digest(spec, digest_of2) {
|
|
1414
|
+
if (spec.handoff === void 0) return spec;
|
|
1415
|
+
const digested = { ...spec, digest: digest_of2() };
|
|
1416
|
+
return record_within_bound(digested) ? digested : spec;
|
|
1417
|
+
}
|
|
1042
1418
|
function begin_cut(target, spec, now = /* @__PURE__ */ new Date()) {
|
|
1043
1419
|
const cut = fresh_cut(spec, now);
|
|
1044
1420
|
if (!within_handoff_bound(cut)) return void 0;
|
|
@@ -1078,8 +1454,8 @@ function end_cut(target) {
|
|
|
1078
1454
|
}
|
|
1079
1455
|
function hold_of(directory) {
|
|
1080
1456
|
if (directory === void 0) return void 0;
|
|
1081
|
-
const
|
|
1082
|
-
return
|
|
1457
|
+
const read4 = run_hold.read_hold(run_hold.hold_path(directory));
|
|
1458
|
+
return read4.kind === "held" || read4.kind === "stale" ? read4.hold : void 0;
|
|
1083
1459
|
}
|
|
1084
1460
|
function fullrun_issue(hold) {
|
|
1085
1461
|
return hold?.is_fullrun === true ? hold.issue : void 0;
|
|
@@ -1124,7 +1500,6 @@ var run_cut = {
|
|
|
1124
1500
|
CUT_MAX_AGE_HOURS,
|
|
1125
1501
|
CUT_MAX_AGE_MS,
|
|
1126
1502
|
END_COMMAND,
|
|
1127
|
-
IMPLEMENTATION_CONTEXT_THRESHOLD,
|
|
1128
1503
|
IMPLEMENTATION_PHASE,
|
|
1129
1504
|
MAX_HANDOFF_BYTES,
|
|
1130
1505
|
PRE_GATE_PHASE,
|
|
@@ -1132,9 +1507,10 @@ var run_cut = {
|
|
|
1132
1507
|
begin_cut,
|
|
1133
1508
|
busy_message,
|
|
1134
1509
|
carried_cut_sync,
|
|
1135
|
-
classify,
|
|
1510
|
+
classify: classify2,
|
|
1136
1511
|
classify_resume,
|
|
1137
1512
|
current_state,
|
|
1513
|
+
with_digest,
|
|
1138
1514
|
cut_path,
|
|
1139
1515
|
describe_cut,
|
|
1140
1516
|
end_cut,
|
|
@@ -1161,6 +1537,56 @@ var run_cut = {
|
|
|
1161
1537
|
worktree_git_directory_sync
|
|
1162
1538
|
};
|
|
1163
1539
|
|
|
1540
|
+
// scripts/rules/shell-segments.ts
|
|
1541
|
+
var SEGMENT_SEPARATOR = /&&|\|\||;|\n/u;
|
|
1542
|
+
var SEGMENT_PARTS = new RegExp(`(${SEGMENT_SEPARATOR.source})`, "u");
|
|
1543
|
+
var COMMAND_SEPARATOR = /&&|\|\||;|\n|(?<!>)\|&?|(?<![<>])&(?!>)/u;
|
|
1544
|
+
function segments_of(command) {
|
|
1545
|
+
return command.split(SEGMENT_SEPARATOR).map((segment) => segment.trim());
|
|
1546
|
+
}
|
|
1547
|
+
function commands_of(command) {
|
|
1548
|
+
return command.split(COMMAND_SEPARATOR).map((segment) => segment.trim());
|
|
1549
|
+
}
|
|
1550
|
+
var COMMAND_SEPARATORS = new RegExp(COMMAND_SEPARATOR.source, "gu");
|
|
1551
|
+
function quote_aware_commands_of(command) {
|
|
1552
|
+
const plain = time_shell.blanked(command);
|
|
1553
|
+
if (plain === void 0) return commands_of(command);
|
|
1554
|
+
const cuts = [...plain.matchAll(COMMAND_SEPARATORS)].map((match) => ({
|
|
1555
|
+
begin: match.index,
|
|
1556
|
+
end: match.index + match[0].length
|
|
1557
|
+
}));
|
|
1558
|
+
const starts = [0, ...cuts.map((cut) => cut.end)];
|
|
1559
|
+
const stops = cuts.map((cut) => cut.begin);
|
|
1560
|
+
return starts.map((start, index) => command.slice(start, stops[index] ?? command.length).trim());
|
|
1561
|
+
}
|
|
1562
|
+
var LINE_CONTINUATION = /\\\n/gu;
|
|
1563
|
+
function joined_continuations(command) {
|
|
1564
|
+
return command.replaceAll(LINE_CONTINUATION, " ");
|
|
1565
|
+
}
|
|
1566
|
+
function parts_of(command) {
|
|
1567
|
+
return command.split(SEGMENT_PARTS);
|
|
1568
|
+
}
|
|
1569
|
+
function first_of(command) {
|
|
1570
|
+
const plain = time_shell.blanked(command);
|
|
1571
|
+
if (plain === void 0) return void 0;
|
|
1572
|
+
const cut = plain.search(SEGMENT_SEPARATOR);
|
|
1573
|
+
return (cut === -1 ? command : command.slice(0, cut)).trim();
|
|
1574
|
+
}
|
|
1575
|
+
function is_josh_command(segment, names) {
|
|
1576
|
+
const named = time_shell.josh_command_of(segment);
|
|
1577
|
+
if (!named.startsWith(time_shell.JOSH_PREFIX)) return false;
|
|
1578
|
+
return names.has(named.slice(time_shell.JOSH_PREFIX.length));
|
|
1579
|
+
}
|
|
1580
|
+
var shell_segments = {
|
|
1581
|
+
commands_of,
|
|
1582
|
+
first_of,
|
|
1583
|
+
is_josh_command,
|
|
1584
|
+
joined_continuations,
|
|
1585
|
+
parts_of,
|
|
1586
|
+
quote_aware_commands_of,
|
|
1587
|
+
segments_of
|
|
1588
|
+
};
|
|
1589
|
+
|
|
1164
1590
|
// scripts/rules/run-tail-rule.ts
|
|
1165
1591
|
var SEGMENT_PREFIX = String.raw`(?:\(\s*)?(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)*(?:npx\s+|pnpm\s+(?:exec\s+|run\s+)?)?`;
|
|
1166
1592
|
var WORD_END = String.raw`(?=\s|$|\))`;
|
|
@@ -1197,13 +1623,13 @@ function is_foreground_push_step(call) {
|
|
|
1197
1623
|
if (is_backgrounded(call.input)) return false;
|
|
1198
1624
|
return is_push_step_call(call);
|
|
1199
1625
|
}
|
|
1200
|
-
function
|
|
1626
|
+
function decide2() {
|
|
1201
1627
|
return true;
|
|
1202
1628
|
}
|
|
1203
1629
|
var RUN_TAIL_REASON = "\u26D4 run tail: this issues the commit-push-PR step in the foreground, where the harness decides when to stop waiting. Reissue it with `run_in_background` set; when it exits, go straight on to `pnpm josh followup` in the foreground \u2014 the turn never ends at the push (`.claude/skills/workflow-commands/background-commands.md`). It fires on every foreground push, not once per run.";
|
|
1204
1630
|
var run_tail_rule = {
|
|
1205
1631
|
RUN_TAIL_REASON,
|
|
1206
|
-
decide:
|
|
1632
|
+
decide: decide2,
|
|
1207
1633
|
is_backgrounded_push_step,
|
|
1208
1634
|
is_foreground_push_step,
|
|
1209
1635
|
is_push_step,
|
|
@@ -1211,10 +1637,12 @@ var run_tail_rule = {
|
|
|
1211
1637
|
};
|
|
1212
1638
|
|
|
1213
1639
|
// scripts/rules/lane-background.ts
|
|
1214
|
-
var
|
|
1640
|
+
var FOREGROUND_COMMANDS = new Set(
|
|
1641
|
+
["ship", "ship:wait", "lane:plan"].map((name) => `${time_shell.JOSH_PREFIX}${name}`)
|
|
1642
|
+
);
|
|
1215
1643
|
var LONG_RUNNING_COMMANDS = /* @__PURE__ */ new Set([
|
|
1216
1644
|
...["gate", "git", "followup"].map((name) => `${time_shell.JOSH_PREFIX}${name}`),
|
|
1217
|
-
|
|
1645
|
+
...FOREGROUND_COMMANDS
|
|
1218
1646
|
]);
|
|
1219
1647
|
var BACKGROUND_KEY2 = "run_in_background";
|
|
1220
1648
|
var TIMEOUT_KEY = "timeout";
|
|
@@ -1227,7 +1655,7 @@ function long_commands_of(command) {
|
|
|
1227
1655
|
}
|
|
1228
1656
|
function ships_alone(command) {
|
|
1229
1657
|
const names = long_commands_of(command);
|
|
1230
|
-
return names.length > 0 && names.every((name) => name
|
|
1658
|
+
return names.length > 0 && names.every((name) => FOREGROUND_COMMANDS.has(name));
|
|
1231
1659
|
}
|
|
1232
1660
|
function backgrounded_bash_command(call) {
|
|
1233
1661
|
if (call.name !== cost_blocks.BASH_TOOL || !is_backgrounded2(call.input)) return void 0;
|
|
@@ -1237,14 +1665,14 @@ function is_backgrounded_ship(call) {
|
|
|
1237
1665
|
const command = backgrounded_bash_command(call);
|
|
1238
1666
|
return command !== void 0 && ships_alone(command);
|
|
1239
1667
|
}
|
|
1240
|
-
function
|
|
1668
|
+
function is_candidate2(call) {
|
|
1241
1669
|
if (run_tail_rule.is_push_step_call(call)) return true;
|
|
1242
1670
|
const command = backgrounded_bash_command(call);
|
|
1243
1671
|
if (command === void 0 || is_backgrounded_ship(call)) return false;
|
|
1244
1672
|
return long_commands_of(command).length > 0;
|
|
1245
1673
|
}
|
|
1246
1674
|
function is_background_long_run(call, is_lane_child = () => lane_child_marker.is_child_of(process.cwd())) {
|
|
1247
|
-
return
|
|
1675
|
+
return is_candidate2(call) && is_lane_child();
|
|
1248
1676
|
}
|
|
1249
1677
|
function ship_alone_input(call) {
|
|
1250
1678
|
if (call.name !== cost_blocks.BASH_TOOL || !json_value.is_record(call.input)) return void 0;
|
|
@@ -1259,7 +1687,7 @@ function foreground_input(call, is_lane_child = () => lane_child_marker.is_child
|
|
|
1259
1687
|
if (input === void 0 || is_capped_foreground(input) || !is_lane_child()) return void 0;
|
|
1260
1688
|
return { ...input, [BACKGROUND_KEY2]: false, [TIMEOUT_KEY]: FOREGROUND_TIMEOUT_MS };
|
|
1261
1689
|
}
|
|
1262
|
-
var FOREGROUND_NOTE = "lane background: a lane child's `josh ship` backgrounded, by its flag or by outrunning the Bash timeout, dies with the headless turn
|
|
1690
|
+
var FOREGROUND_NOTE = "lane background: a lane child's `josh ship`, `josh ship:wait` or `josh lane:plan` backgrounded, by its flag or by outrunning the Bash timeout, dies with the headless turn \u2014 so it was run in the foreground at the 600000 ms cap, where `ship` detaches itself after the preflight. Then follow `chain-rule.md` step 0 (`josh ship:wait` on `launched`).";
|
|
1263
1691
|
function apply_line(open, line, launched_ids) {
|
|
1264
1692
|
const parsed = time_transcript_line.parse_line(line);
|
|
1265
1693
|
if (parsed === void 0) return;
|
|
@@ -1279,36 +1707,376 @@ function pending_background_ids(tail) {
|
|
|
1279
1707
|
function pending_agent_ids(tail) {
|
|
1280
1708
|
return unfinished_ids(tail, (block) => [block.agent_id]);
|
|
1281
1709
|
}
|
|
1282
|
-
|
|
1710
|
+
function pending_command_ids(tail) {
|
|
1711
|
+
return unfinished_ids(tail, (block) => [block.background_id]);
|
|
1712
|
+
}
|
|
1713
|
+
var LANE_BACKGROUND_REASON = '\u26D4 lane background: this session is a dispatched lane child (`JOSH_LANE_CHILD`), a headless process whose background tasks die when the turn ends. Hand over to `pnpm josh ship --detach --review "<title> #<N>"`, issued in the foreground, then `josh ship:wait <N>` on `launched` or end the turn. It fires on every occurrence (`.claude/skills/workflow-commands/chain-rule.md` step 0).';
|
|
1283
1714
|
var LANE_BACKGROUND_STOP_REASON = "\u26D4 lane background stop: this is a dispatched lane child (`JOSH_LANE_CHILD`) and a background task it launched has not finished, and ending this turn kills it. Wait for it in the foreground, or re-issue the work through `pnpm josh ship --detach` \u2014 do not notify, stop or repeat your reply.";
|
|
1284
|
-
var
|
|
1715
|
+
var LANE_AGENT_STOP_REASON = "\u26D4 lane agent stop: this is a dispatched lane child (`JOSH_LANE_CHILD`) and a subagent it launched has not finished; ending this turn kills it. Its completion notice arrives only when a tool call ends: wait with one short foreground call at a time (`sleep 20`) until it arrives \u2014 never a loop over its `.output`. Do not notify, stop or repeat your reply.";
|
|
1716
|
+
var ROW = {
|
|
1285
1717
|
id: "lane-background",
|
|
1286
1718
|
is_trigger: (call) => is_background_long_run(call),
|
|
1287
1719
|
reason: LANE_BACKGROUND_REASON,
|
|
1288
1720
|
decide: () => true,
|
|
1721
|
+
// `pretool-guard.ts` rewrites a lone `josh ship` to the foreground rather than refusing it; this is
|
|
1722
|
+
// the note it attaches, so `rule-value.ts` counts that rewrite as this row's delivery.
|
|
1723
|
+
rewrite_note: FOREGROUND_NOTE,
|
|
1724
|
+
// The Stop hook delivers the same rule at the turn's end, for the background task or subagent the
|
|
1725
|
+
// turn would kill.
|
|
1726
|
+
stop_reasons: [LANE_BACKGROUND_STOP_REASON, LANE_AGENT_STOP_REASON],
|
|
1289
1727
|
about: {
|
|
1290
1728
|
title: "Lane child background push",
|
|
1291
1729
|
topic: "`.claude/skills/workflow-commands/background-commands.md`",
|
|
1292
|
-
fires: "a dispatched lane child backgrounding `josh gate` / `git` / `followup` / `ship`; it hands over `pnpm josh ship --detach
|
|
1730
|
+
fires: "a dispatched lane child backgrounding `josh gate` / `git` / `followup` / `ship`; it hands over `pnpm josh ship --detach`; the Stop hook also blocks ending a turn with its background task or subagent unfinished. Every occurrence",
|
|
1293
1731
|
quiet: "not a lane child, or the foreground `ship --detach`"
|
|
1294
1732
|
}
|
|
1295
1733
|
};
|
|
1296
1734
|
var lane_background = {
|
|
1297
1735
|
FOREGROUND_NOTE,
|
|
1736
|
+
LANE_AGENT_STOP_REASON,
|
|
1298
1737
|
LANE_BACKGROUND_REASON,
|
|
1299
1738
|
LANE_BACKGROUND_STOP_REASON,
|
|
1300
|
-
ROW
|
|
1739
|
+
ROW,
|
|
1301
1740
|
foreground_input,
|
|
1302
1741
|
is_background_long_run,
|
|
1303
1742
|
pending_agent_ids,
|
|
1304
|
-
pending_background_ids
|
|
1743
|
+
pending_background_ids,
|
|
1744
|
+
pending_command_ids
|
|
1745
|
+
};
|
|
1746
|
+
|
|
1747
|
+
// scripts/rules/stop-rules.ts
|
|
1748
|
+
import { z as z5 } from "zod";
|
|
1749
|
+
|
|
1750
|
+
// scripts/rules/concise-reply.ts
|
|
1751
|
+
import path4 from "node:path";
|
|
1752
|
+
import { fileURLToPath } from "node:url";
|
|
1753
|
+
|
|
1754
|
+
// scripts/rules/reply-prose.ts
|
|
1755
|
+
var CODE_PATTERNS = [
|
|
1756
|
+
/```[\s\S]*?(?:```|$)/gu,
|
|
1757
|
+
/`[^`\n]*`/gu,
|
|
1758
|
+
/\]\([^)\s]*\)/gu,
|
|
1759
|
+
/https?:\/\/\S+/gu
|
|
1760
|
+
];
|
|
1761
|
+
var ASCII_RUN_PATTERN = /[!-~]+/gu;
|
|
1762
|
+
var STRUCTURE_LINE_PATTERN = /^\s*(?:\||[-*+] |[・•] ?|\d+\. )/u;
|
|
1763
|
+
function prose_of(message) {
|
|
1764
|
+
let text2 = message;
|
|
1765
|
+
for (const pattern of CODE_PATTERNS) text2 = text2.replaceAll(pattern, " ");
|
|
1766
|
+
return text2.replaceAll(ASCII_RUN_PATTERN, (run2) => run2.includes("/") ? " " : run2);
|
|
1767
|
+
}
|
|
1768
|
+
function narrative_of(message) {
|
|
1769
|
+
return prose_of(message).split("\n").filter((line) => !STRUCTURE_LINE_PATTERN.test(line)).join("\n");
|
|
1770
|
+
}
|
|
1771
|
+
var reply_prose = { narrative_of, prose_of };
|
|
1772
|
+
|
|
1773
|
+
// scripts/rules/concise-reply.ts
|
|
1774
|
+
var PROSE_LIMIT = 400;
|
|
1775
|
+
var EXEMPT_WORDS = ["\u8A73\u3057\u304F", "\u5177\u4F53\u7684\u306B", "\u8A73\u7D30"];
|
|
1776
|
+
var COUNTED_PATTERN = /[\p{L}\p{N}]/gu;
|
|
1777
|
+
var PRINCIPLES_FILE = "prompts/collaboration-workflow/principles.md";
|
|
1778
|
+
var SECTION = "concise-reply";
|
|
1779
|
+
var PACKAGE_DIRECTORY = find_package_directory(path4.dirname(fileURLToPath(import.meta.url)));
|
|
1780
|
+
var REASON_OPENING = `\u26D4 concise reply: your reply's prose outside code, tables and lists is over the limit of \`${PRINCIPLES_FILE}\` \u2192 "${SECTION}"`;
|
|
1781
|
+
var KEEP_DECISION = " Keep its `Recommended:` / `Alternative:` lines as they are.";
|
|
1782
|
+
function prose_length(message) {
|
|
1783
|
+
return reply_prose.narrative_of(message).match(COUNTED_PATTERN)?.length ?? 0;
|
|
1784
|
+
}
|
|
1785
|
+
function is_exempt(prompt) {
|
|
1786
|
+
return EXEMPT_WORDS.some((word) => prompt.includes(word));
|
|
1787
|
+
}
|
|
1788
|
+
function is_over(message, prompt) {
|
|
1789
|
+
if (prompt === void 0 || is_exempt(prompt)) return false;
|
|
1790
|
+
return prose_length(message) > PROSE_LIMIT;
|
|
1791
|
+
}
|
|
1792
|
+
function section_text(root) {
|
|
1793
|
+
const markdown = document_section.read_optional(path4.join(root, PRINCIPLES_FILE));
|
|
1794
|
+
return markdown === void 0 ? void 0 : document_section.section(markdown, SECTION)?.text;
|
|
1795
|
+
}
|
|
1796
|
+
function decision_note(message) {
|
|
1797
|
+
return stop_decision.decision_of(message) === void 0 ? "" : KEEP_DECISION;
|
|
1798
|
+
}
|
|
1799
|
+
function build_reason(message, root = PACKAGE_DIRECTORY) {
|
|
1800
|
+
const head = `${REASON_OPENING} (${String(prose_length(message))} of ${String(PROSE_LIMIT)}). Rewrite it shorter as that section says \u2014 do not repeat your previous reply.${decision_note(message)}`;
|
|
1801
|
+
const body = section_text(root);
|
|
1802
|
+
return body === void 0 ? head : `${head}
|
|
1803
|
+
|
|
1804
|
+
${body}`;
|
|
1805
|
+
}
|
|
1806
|
+
var ROW2 = {
|
|
1807
|
+
id: SECTION,
|
|
1808
|
+
reason: REASON_OPENING,
|
|
1809
|
+
about: {
|
|
1810
|
+
title: "Concise reply",
|
|
1811
|
+
topic: `\`principles.md\` \u2192 "${SECTION}"`,
|
|
1812
|
+
entry: "pnpm josh stop:guard",
|
|
1813
|
+
fires: `a reply whose narrative outside code, tables and lists is over ${String(PROSE_LIMIT)} letters. Blocks the stop`,
|
|
1814
|
+
quiet: "a reply under the limit, a prompt asking for the detail (`\u8A73\u3057\u304F` / `\u5177\u4F53\u7684\u306B` / `\u8A73\u7D30`), a fixed output in a code block, no prompt of the person\u2019s on the transcript tail, or a headless session"
|
|
1815
|
+
}
|
|
1816
|
+
};
|
|
1817
|
+
var concise_reply = {
|
|
1818
|
+
EXEMPT_WORDS,
|
|
1819
|
+
PROSE_LIMIT,
|
|
1820
|
+
REASON_OPENING,
|
|
1821
|
+
ROW: ROW2,
|
|
1822
|
+
build_reason,
|
|
1823
|
+
is_over,
|
|
1824
|
+
prose_length
|
|
1825
|
+
};
|
|
1826
|
+
|
|
1827
|
+
// scripts/rules/filing-offer.ts
|
|
1828
|
+
var OFFER_PATTERNS = [
|
|
1829
|
+
/起票(?:して)?(?:も)?(?:よければ|よろしければ|よいですか|良いですか|よろしいですか|いいですか)/u,
|
|
1830
|
+
/起票(?:しましょうか|しますか|するのが妥当|すべきだと|すべきと|を提案|をご提案)/u,
|
|
1831
|
+
/Issue\s*[化に](?:しましょうか|しますか|してよければ)/iu,
|
|
1832
|
+
/\b(?:shall|should)\s+I\s+(?:file|open|raise)\b/iu,
|
|
1833
|
+
/\b(?:want|like)\s+me\s+to\s+(?:file|open|raise)\b/iu,
|
|
1834
|
+
/\blet\s+me\s+know\s+if\s+you\s+(?:want|would\s+like)\s+(?:me\s+to\s+file|it\s+filed)\b/iu
|
|
1835
|
+
];
|
|
1836
|
+
var GITHUB_URL_OWNER = /github\.com\/([\w.-]+)\//gu;
|
|
1837
|
+
var OWNER_SEPARATOR = "/";
|
|
1838
|
+
function is_offer_line(line) {
|
|
1839
|
+
return OFFER_PATTERNS.some((pattern) => pattern.test(line));
|
|
1840
|
+
}
|
|
1841
|
+
function offers_filing(message) {
|
|
1842
|
+
return issue_citation.prose_lines(message).some((line) => is_offer_line(line));
|
|
1843
|
+
}
|
|
1844
|
+
function url_owners(message) {
|
|
1845
|
+
return [...message.matchAll(GITHUB_URL_OWNER)].map((match) => match[1] ?? "");
|
|
1846
|
+
}
|
|
1847
|
+
function qualified_owners(message) {
|
|
1848
|
+
return issue_citation.bare_references(message).filter((reference) => reference.includes(OWNER_SEPARATOR)).map((reference) => reference.split(OWNER_SEPARATOR)[0] ?? "");
|
|
1849
|
+
}
|
|
1850
|
+
function mentioned_owners(message) {
|
|
1851
|
+
return [...url_owners(message), ...qualified_owners(message)];
|
|
1852
|
+
}
|
|
1853
|
+
function is_first_party_target(message, session_owner) {
|
|
1854
|
+
if (session_owner === void 0) return false;
|
|
1855
|
+
return mentioned_owners(message).every(
|
|
1856
|
+
(owner) => repo_party.classify(session_owner, owner) === repo_party.FIRST_PARTY
|
|
1857
|
+
);
|
|
1858
|
+
}
|
|
1859
|
+
var filing_offer = { is_first_party_target, mentioned_owners, offers_filing };
|
|
1860
|
+
|
|
1861
|
+
// scripts/rules/reply-language.ts
|
|
1862
|
+
var LATIN_SCRIPT = "Latn";
|
|
1863
|
+
var COMPOUND_SCRIPTS = {
|
|
1864
|
+
Jpan: ["Hira", "Kana", "Hani"],
|
|
1865
|
+
Kore: ["Hang", "Hani"],
|
|
1866
|
+
Hans: ["Hani"],
|
|
1867
|
+
Hant: ["Hani"]
|
|
1868
|
+
};
|
|
1869
|
+
var MIN_PROSE_LETTERS = 20;
|
|
1870
|
+
var MATCH_SHARE_FLOOR = 0.5;
|
|
1871
|
+
var MIN_VOTING_LETTERS = 8;
|
|
1872
|
+
var LETTER_PATTERN = new RegExp("\\p{L}", "gu");
|
|
1873
|
+
var NON_LATIN_LETTER_PATTERN = new RegExp("(?![\\p{Script=Latn}\\p{Script=Common}\\p{Script=Inherited}])\\p{L}", "u");
|
|
1874
|
+
function script_of(lang) {
|
|
1875
|
+
try {
|
|
1876
|
+
return new Intl.Locale(lang).maximize().script;
|
|
1877
|
+
} catch {
|
|
1878
|
+
return void 0;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
function letter_pattern(script) {
|
|
1882
|
+
const scripts = COMPOUND_SCRIPTS[script] ?? [script];
|
|
1883
|
+
const classes = scripts.map((name) => String.raw`\p{Script=${name}}`).join("");
|
|
1884
|
+
try {
|
|
1885
|
+
return new RegExp(`[${classes}]`, "u");
|
|
1886
|
+
} catch {
|
|
1887
|
+
return void 0;
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
function letter_count(text2) {
|
|
1891
|
+
return text2.match(LETTER_PATTERN)?.length ?? 0;
|
|
1892
|
+
}
|
|
1893
|
+
function is_line_in_script(line, script, pattern) {
|
|
1894
|
+
if (script === LATIN_SCRIPT) return !NON_LATIN_LETTER_PATTERN.test(line);
|
|
1895
|
+
return pattern.test(line);
|
|
1896
|
+
}
|
|
1897
|
+
function voting_lines(prose) {
|
|
1898
|
+
const lines = prose.split("\n").filter((line) => letter_count(line) > 0);
|
|
1899
|
+
const voting = lines.filter((line) => letter_count(line) >= MIN_VOTING_LETTERS);
|
|
1900
|
+
return voting.length > 0 ? voting : lines;
|
|
1901
|
+
}
|
|
1902
|
+
function matches_share(prose, script, pattern) {
|
|
1903
|
+
const lines = voting_lines(prose);
|
|
1904
|
+
const matched = lines.filter((line) => is_line_in_script(line, script, pattern));
|
|
1905
|
+
return matched.length / lines.length;
|
|
1906
|
+
}
|
|
1907
|
+
function is_mismatch(message, lang) {
|
|
1908
|
+
const script = script_of(lang);
|
|
1909
|
+
if (script === void 0) return false;
|
|
1910
|
+
const pattern = letter_pattern(script);
|
|
1911
|
+
if (pattern === void 0) return false;
|
|
1912
|
+
const prose = reply_prose.prose_of(message);
|
|
1913
|
+
if (letter_count(prose) < MIN_PROSE_LETTERS) return false;
|
|
1914
|
+
return matches_share(prose, script, pattern) < MATCH_SHARE_FLOOR;
|
|
1915
|
+
}
|
|
1916
|
+
var reply_language = { is_mismatch, script_of };
|
|
1917
|
+
|
|
1918
|
+
// scripts/rules/stop-rules.ts
|
|
1919
|
+
var SWITCH_ENV_KEY2 = "JOSH_STOP_GUARD";
|
|
1920
|
+
var BLOCK_DECISION = "block";
|
|
1921
|
+
var stop_payload_schema = z5.object({
|
|
1922
|
+
transcript_path: z5.string().min(1),
|
|
1923
|
+
stop_hook_active: z5.boolean().nullish(),
|
|
1924
|
+
last_assistant_message: z5.string().nullish()
|
|
1925
|
+
});
|
|
1926
|
+
var NO_OUTCOME2 = { reason: void 0, actions: [], blocks_on_failure: false };
|
|
1927
|
+
var STOP_NOTIFY_REASON = '\u26D4 mid-workflow stop notification: this working tree is still held by a run and no `confirmation` Telegram was sent this turn. Send `pnpm josh notify --task-type confirmation --issue-url "<url>" --body=$\'<reason>\' --recommended "<choice>" --alternative "<choice>"` (`rule-delivery.md` \u2192 "stop-notify"), then confirm in one line that it was sent \u2014 do not repeat your previous reply.';
|
|
1928
|
+
var HOLD_RELEASE_REASON = "\u26D4 working-tree hold not released: this working tree is clean but its `run:hold` record is still in place. Release it with `pnpm josh run:release <N>` (bare for a `new` entry; `working-tree-hold.md`), then confirm in one line that it was released \u2014 do not repeat your previous reply.";
|
|
1929
|
+
var FILING_OFFER_REASON = '\u26D4 filing offer: your reply offers to file an Issue instead of filing it, and this run is unattended \u2014 nobody is there to answer. Run `pnpm josh issue:file "<title>" --body-file <path>` (Tier A, `observation-filing.md`), then end with the one-line citation of what was filed; do not repeat your previous reply. If it is not worth filing after all, say so in one line instead.';
|
|
1930
|
+
var HEADLESS_WAIT_MARKER = "\u26D4 headless parent:";
|
|
1931
|
+
var HEADLESS_REFUSAL_CAP = 3;
|
|
1932
|
+
var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await'];
|
|
1933
|
+
var HEADLESS_WAIT_BODY = ' this is a `claude -p` `backlogrun` parent with lanes in flight, and ending this turn kills the process and its background waits. Hand the loop back with `pnpm josh run:carry --cut --owner "$PPID"` (or `--end` when the run is over), then end the turn (`backlogrun-progress.md`).';
|
|
1934
|
+
var HEADLESS_WAIT_REASON = `${HEADLESS_WAIT_MARKER}${HEADLESS_WAIT_BODY}`;
|
|
1935
|
+
var INDEX_COMMAND_PATTERN = /git (?:add|stage|rm --cached|restore --staged|restore -S)\b/u;
|
|
1936
|
+
var PERMISSION_PATTERN = /許可|承認|permission|approve|approval|authorization/iu;
|
|
1937
|
+
var LANE_INDEX_REASON = "\u26D4 lane index permission: this is a dispatched lane child (`JOSH_LANE_CHILD`) and your reply asks a person for permission to change the git index. That is Tier A here (`chain-rule.md`): remove any conflict markers, run `pnpm josh git -y` (it stages and commits, a conflicted merge included) and continue the run \u2014 do not repeat your previous reply.";
|
|
1938
|
+
function asks_index_permission(message) {
|
|
1939
|
+
return INDEX_COMMAND_PATTERN.test(message) && PERMISSION_PATTERN.test(message);
|
|
1940
|
+
}
|
|
1941
|
+
function needs_index_route(context) {
|
|
1942
|
+
return context.lane_child && asks_index_permission(context.message);
|
|
1943
|
+
}
|
|
1944
|
+
function language_note(lang) {
|
|
1945
|
+
return `Write your reply in the session language (JOSH_SESSION_LANG: ${lang}); code, commands and identifiers stay as they are.`;
|
|
1946
|
+
}
|
|
1947
|
+
function build_language_reason(lang) {
|
|
1948
|
+
return `\u26D4 session language: your reply is not written in the session language (JOSH_SESSION_LANG: ${lang}). Rewrite it in that language and keep writing in it on the turns that follow, whatever language a notification, tool output or hook message was in (\`CLAUDE.md\` \u2192 "Output language").`;
|
|
1949
|
+
}
|
|
1950
|
+
function language_reason(context) {
|
|
1951
|
+
if (!reply_language.is_mismatch(context.message, context.session_lang)) return void 0;
|
|
1952
|
+
return build_language_reason(context.session_lang);
|
|
1953
|
+
}
|
|
1954
|
+
function concise_reason(context) {
|
|
1955
|
+
if (!concise_reply.is_over(context.message, context.prompt)) return void 0;
|
|
1956
|
+
return concise_reply.build_reason(context.message);
|
|
1957
|
+
}
|
|
1958
|
+
function is_unattended(context) {
|
|
1959
|
+
return context.headless_agent || context.lane_child || context.backlog_parent;
|
|
1960
|
+
}
|
|
1961
|
+
function needs_filing(context) {
|
|
1962
|
+
if (!is_unattended(context) || context.filed) return false;
|
|
1963
|
+
return filing_offer.offers_filing(context.message) && filing_offer.is_first_party_target(context.message, context.session_owner);
|
|
1964
|
+
}
|
|
1965
|
+
function is_held_idle(context) {
|
|
1966
|
+
if (context.hold_issue === void 0 || !context.hold_owned) return false;
|
|
1967
|
+
return !context.agent_pending && !context.handed_off;
|
|
1968
|
+
}
|
|
1969
|
+
function needs_notify(context) {
|
|
1970
|
+
return is_held_idle(context) && !context.notified && !context.answers_question;
|
|
1971
|
+
}
|
|
1972
|
+
function needs_decision(context) {
|
|
1973
|
+
return needs_notify(context) && stop_decision.decision_of(context.message) === void 0;
|
|
1974
|
+
}
|
|
1975
|
+
function needs_release(context) {
|
|
1976
|
+
return is_held_idle(context) && context.tree_clean && !context.prrun_stopped;
|
|
1977
|
+
}
|
|
1978
|
+
function reply_reason(context) {
|
|
1979
|
+
if (needs_filing(context)) return FILING_OFFER_REASON;
|
|
1980
|
+
if (context.headless_agent) return void 0;
|
|
1981
|
+
return language_reason(context) ?? concise_reason(context);
|
|
1982
|
+
}
|
|
1983
|
+
function decision_reason(context) {
|
|
1984
|
+
return needs_decision(context) ? stop_decision.DECISION_REASON : void 0;
|
|
1985
|
+
}
|
|
1986
|
+
function is_headless_held(context) {
|
|
1987
|
+
if (!context.headless_waiting) return false;
|
|
1988
|
+
return !context.stop_hook_active || context.headless_refusals < HEADLESS_REFUSAL_CAP;
|
|
1989
|
+
}
|
|
1990
|
+
function count_headless_refusals(tail) {
|
|
1991
|
+
const last_wait = Math.max(...HEADLESS_WAIT_CALLS.map((call) => tail.lastIndexOf(call)));
|
|
1992
|
+
return tail.slice(Math.max(last_wait, 0)).split(HEADLESS_WAIT_MARKER).length - 1;
|
|
1993
|
+
}
|
|
1994
|
+
function needs_background_wait(context) {
|
|
1995
|
+
return context.lane_child && context.background_pending;
|
|
1996
|
+
}
|
|
1997
|
+
function background_wait_reason(context) {
|
|
1998
|
+
if (context.command_pending) return lane_background.LANE_BACKGROUND_STOP_REASON;
|
|
1999
|
+
return lane_background.LANE_AGENT_STOP_REASON;
|
|
2000
|
+
}
|
|
2001
|
+
function lane_reason(context) {
|
|
2002
|
+
if (needs_index_route(context)) return LANE_INDEX_REASON;
|
|
2003
|
+
if (needs_background_wait(context)) return background_wait_reason(context);
|
|
2004
|
+
return void 0;
|
|
2005
|
+
}
|
|
2006
|
+
function model_reason(context) {
|
|
2007
|
+
const lane = lane_reason(context);
|
|
2008
|
+
if (lane !== void 0) return lane;
|
|
2009
|
+
const reasons = [reply_reason(context), decision_reason(context)].filter(
|
|
2010
|
+
(reason) => reason !== void 0
|
|
2011
|
+
);
|
|
2012
|
+
return reasons.length === 0 ? void 0 : reasons.join("\n\n");
|
|
2013
|
+
}
|
|
2014
|
+
function notify_actions(context, issue) {
|
|
2015
|
+
const decision = stop_decision.decision_of(context.message);
|
|
2016
|
+
if (decision === void 0 || !needs_notify(context)) return [];
|
|
2017
|
+
return [{ kind: "notify", issue, message: context.message, decision }];
|
|
2018
|
+
}
|
|
2019
|
+
function hold_actions(context) {
|
|
2020
|
+
const issue = context.hold_issue;
|
|
2021
|
+
if (issue === void 0) return [];
|
|
2022
|
+
const notify = notify_actions(context, issue);
|
|
2023
|
+
return needs_release(context) ? [...notify, { kind: "release", issue }] : notify;
|
|
2024
|
+
}
|
|
2025
|
+
function block_reason(context) {
|
|
2026
|
+
if (is_headless_held(context)) return HEADLESS_WAIT_REASON;
|
|
2027
|
+
if (context.stop_hook_active || context.cut_pending) return void 0;
|
|
2028
|
+
return model_reason(context);
|
|
2029
|
+
}
|
|
2030
|
+
function runs_actions(context, reason) {
|
|
2031
|
+
return reason === void 0 && !context.cut_pending && lane_reason(context) === void 0;
|
|
2032
|
+
}
|
|
2033
|
+
function stop_outcome(context) {
|
|
2034
|
+
const reason = block_reason(context);
|
|
2035
|
+
if (!runs_actions(context, reason)) return { ...NO_OUTCOME2, reason };
|
|
2036
|
+
const actions = hold_actions(context);
|
|
2037
|
+
if (actions.length === 0) return NO_OUTCOME2;
|
|
2038
|
+
return { reason, actions, blocks_on_failure: !context.stop_hook_active };
|
|
2039
|
+
}
|
|
2040
|
+
function fallback_reason(action) {
|
|
2041
|
+
return action.kind === "notify" ? STOP_NOTIFY_REASON : HOLD_RELEASE_REASON;
|
|
2042
|
+
}
|
|
2043
|
+
function block_envelope(reason, lang, notice) {
|
|
2044
|
+
const refusal = { decision: BLOCK_DECISION, reason: `${reason} ${language_note(lang)}` };
|
|
2045
|
+
return JSON.stringify(notice === void 0 ? refusal : { ...refusal, systemMessage: notice });
|
|
2046
|
+
}
|
|
2047
|
+
function notice_envelope2(notice) {
|
|
2048
|
+
return JSON.stringify({ systemMessage: notice });
|
|
2049
|
+
}
|
|
2050
|
+
function parse_stop_payload(raw_payload) {
|
|
2051
|
+
return json_value.parse_with(raw_payload, stop_payload_schema);
|
|
2052
|
+
}
|
|
2053
|
+
function is_enabled2() {
|
|
2054
|
+
return hook_decision.is_switch_enabled(SWITCH_ENV_KEY2);
|
|
2055
|
+
}
|
|
2056
|
+
var stop_rules = {
|
|
2057
|
+
FILING_OFFER_REASON,
|
|
2058
|
+
HEADLESS_REFUSAL_CAP,
|
|
2059
|
+
HEADLESS_WAIT_REASON,
|
|
2060
|
+
HOLD_RELEASE_REASON,
|
|
2061
|
+
LANE_INDEX_REASON,
|
|
2062
|
+
NO_OUTCOME: NO_OUTCOME2,
|
|
2063
|
+
STOP_NOTIFY_REASON,
|
|
2064
|
+
SWITCH_ENV_KEY: SWITCH_ENV_KEY2,
|
|
2065
|
+
block_envelope,
|
|
2066
|
+
build_language_reason,
|
|
2067
|
+
count_headless_refusals,
|
|
2068
|
+
fallback_reason,
|
|
2069
|
+
is_enabled: is_enabled2,
|
|
2070
|
+
notice_envelope: notice_envelope2,
|
|
2071
|
+
parse_stop_payload,
|
|
2072
|
+
stop_outcome
|
|
1305
2073
|
};
|
|
1306
2074
|
|
|
1307
2075
|
// scripts/run/ship/run-ship-detach.ts
|
|
1308
2076
|
import { randomUUID } from "node:crypto";
|
|
1309
2077
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
1310
|
-
import { z as
|
|
1311
|
-
var LOG_PREFIX =
|
|
2078
|
+
import { z as z6 } from "zod";
|
|
2079
|
+
var LOG_PREFIX = durable_state.PREFIX.SHIP_LOG;
|
|
1312
2080
|
var PID_PREFIX = "josh-ship-pid-";
|
|
1313
2081
|
var BODY_PREFIX = "josh-ship-notify-";
|
|
1314
2082
|
var KEY_SEPARATOR = "-";
|
|
@@ -1324,18 +2092,18 @@ var SUPERVISED_VALUE = "1";
|
|
|
1324
2092
|
var LAUNCHED = "launched";
|
|
1325
2093
|
var BUSY = "busy";
|
|
1326
2094
|
var FAILED = "failed";
|
|
1327
|
-
var RESULT_PREFIX =
|
|
2095
|
+
var RESULT_PREFIX = durable_state.PREFIX.SHIP_RESULT;
|
|
1328
2096
|
var RECORD_POLL_MS = 25;
|
|
1329
2097
|
var RECORD_WAIT_ATTEMPTS = 200;
|
|
1330
2098
|
var CLAIM_WINDOW_MS = 12e4;
|
|
1331
|
-
var ship_record_schema =
|
|
1332
|
-
pid:
|
|
1333
|
-
process_start:
|
|
1334
|
-
launched_at:
|
|
1335
|
-
launcher_pid:
|
|
1336
|
-
launcher_start:
|
|
1337
|
-
launch_id:
|
|
1338
|
-
result:
|
|
2099
|
+
var ship_record_schema = z6.object({
|
|
2100
|
+
pid: z6.number().int().positive().optional(),
|
|
2101
|
+
process_start: z6.string().optional(),
|
|
2102
|
+
launched_at: z6.number().optional(),
|
|
2103
|
+
launcher_pid: z6.number().int().positive().optional(),
|
|
2104
|
+
launcher_start: z6.string().optional(),
|
|
2105
|
+
launch_id: z6.string(),
|
|
2106
|
+
result: z6.enum(["success", "failed"]).optional()
|
|
1339
2107
|
});
|
|
1340
2108
|
var LAUNCH_MARK = " \xB7 started by process ";
|
|
1341
2109
|
var HEADER_START = "\n";
|
|
@@ -1343,10 +2111,10 @@ function key(prefix, request2) {
|
|
|
1343
2111
|
return stamp_file.stamp_path(`${prefix}${request2.number}${KEY_SEPARATOR}`, request2.repository);
|
|
1344
2112
|
}
|
|
1345
2113
|
function log_path(repository, number) {
|
|
1346
|
-
return
|
|
2114
|
+
return durable_state.path(`${LOG_PREFIX}${number}${KEY_SEPARATOR}`, repository, LOG_SUFFIX);
|
|
1347
2115
|
}
|
|
1348
2116
|
function result_path(repository, number) {
|
|
1349
|
-
return
|
|
2117
|
+
return durable_state.path(`${RESULT_PREFIX}${number}${KEY_SEPARATOR}`, repository);
|
|
1350
2118
|
}
|
|
1351
2119
|
function read_record(repository, number) {
|
|
1352
2120
|
try {
|
|
@@ -1373,56 +2141,56 @@ function supervisor_environment(launch_id) {
|
|
|
1373
2141
|
[LAUNCH_ID_KEY]: launch_id
|
|
1374
2142
|
};
|
|
1375
2143
|
}
|
|
1376
|
-
function is_within_claim_window(
|
|
1377
|
-
return
|
|
2144
|
+
function is_within_claim_window(record3) {
|
|
2145
|
+
return record3.launched_at !== void 0 && Date.now() - record3.launched_at < CLAIM_WINDOW_MS;
|
|
1378
2146
|
}
|
|
1379
|
-
function has_live_identity(pid,
|
|
1380
|
-
if (
|
|
1381
|
-
return is_within_claim_window(
|
|
2147
|
+
function has_live_identity(pid, record3, read4) {
|
|
2148
|
+
if (record3.process_start === void 0) {
|
|
2149
|
+
return is_within_claim_window(record3) && process_identity.is_live_pid(pid);
|
|
1382
2150
|
}
|
|
1383
|
-
return process_identity.is_same_process(pid,
|
|
2151
|
+
return process_identity.is_same_process(pid, record3.process_start, read4) !== false;
|
|
1384
2152
|
}
|
|
1385
|
-
function result_of(
|
|
1386
|
-
if (
|
|
1387
|
-
const { launcher_pid, launcher_start } =
|
|
1388
|
-
const is_launcher = process_identity.is_same_process(launcher_pid, launcher_start,
|
|
2153
|
+
function result_of(record3, read4) {
|
|
2154
|
+
if (record3.pid === void 0) {
|
|
2155
|
+
const { launcher_pid, launcher_start } = record3;
|
|
2156
|
+
const is_launcher = process_identity.is_same_process(launcher_pid, launcher_start, read4);
|
|
1389
2157
|
return is_launcher === false ? "abnormal" : "running";
|
|
1390
2158
|
}
|
|
1391
|
-
if (has_live_identity(
|
|
1392
|
-
return
|
|
1393
|
-
}
|
|
1394
|
-
function read_result(repository, number,
|
|
1395
|
-
const
|
|
1396
|
-
return
|
|
1397
|
-
launch_id:
|
|
1398
|
-
launched_at:
|
|
1399
|
-
result: result_of(
|
|
2159
|
+
if (has_live_identity(record3.pid, record3, read4)) return "running";
|
|
2160
|
+
return record3.result ?? "abnormal";
|
|
2161
|
+
}
|
|
2162
|
+
function read_result(repository, number, read4 = process_identity.read_start) {
|
|
2163
|
+
const record3 = read_record(repository, number);
|
|
2164
|
+
return record3 === void 0 ? void 0 : {
|
|
2165
|
+
launch_id: record3.launch_id,
|
|
2166
|
+
launched_at: record3.launched_at,
|
|
2167
|
+
result: result_of(record3, read4)
|
|
1400
2168
|
};
|
|
1401
2169
|
}
|
|
1402
2170
|
function current_record(repository, number) {
|
|
1403
|
-
const
|
|
1404
|
-
return
|
|
2171
|
+
const record3 = read_record(repository, number);
|
|
2172
|
+
return record3?.launch_id === process.env[LAUNCH_ID_KEY] ? record3 : void 0;
|
|
1405
2173
|
}
|
|
1406
2174
|
function running_since(repository, number) {
|
|
1407
|
-
const
|
|
1408
|
-
return
|
|
2175
|
+
const record3 = read_record(repository, number);
|
|
2176
|
+
return record3 !== void 0 && result_of(record3, process_identity.read_start) === "running" ? record3.launched_at : void 0;
|
|
1409
2177
|
}
|
|
1410
|
-
function is_pending(
|
|
1411
|
-
return
|
|
2178
|
+
function is_pending(record3) {
|
|
2179
|
+
return record3 !== void 0 && record3.pid === void 0;
|
|
1412
2180
|
}
|
|
1413
2181
|
async function ready_record(repository, number) {
|
|
1414
|
-
let
|
|
2182
|
+
let record3 = current_record(repository, number);
|
|
1415
2183
|
for (let attempt = 0; attempt < RECORD_WAIT_ATTEMPTS; attempt += 1) {
|
|
1416
|
-
if (!is_pending(
|
|
2184
|
+
if (!is_pending(record3)) return record3;
|
|
1417
2185
|
await sleep(RECORD_POLL_MS);
|
|
1418
|
-
|
|
2186
|
+
record3 = current_record(repository, number);
|
|
1419
2187
|
}
|
|
1420
2188
|
return void 0;
|
|
1421
2189
|
}
|
|
1422
2190
|
async function update_record(repository, number, fields) {
|
|
1423
|
-
const
|
|
1424
|
-
if (
|
|
1425
|
-
stamp_file.replace_stamp(result_path(repository, number), { ...
|
|
2191
|
+
const record3 = await ready_record(repository, number);
|
|
2192
|
+
if (record3 === void 0) return;
|
|
2193
|
+
stamp_file.replace_stamp(result_path(repository, number), { ...record3, ...fields });
|
|
1426
2194
|
}
|
|
1427
2195
|
async function mark_result(repository, number, code) {
|
|
1428
2196
|
await update_record(repository, number, { result: code === 0 ? "success" : "failed" });
|
|
@@ -1456,6 +2224,7 @@ function supervisor_argv(request2) {
|
|
|
1456
2224
|
"josh",
|
|
1457
2225
|
"ship",
|
|
1458
2226
|
...review,
|
|
2227
|
+
...request2.unpinned_ok,
|
|
1459
2228
|
...notify_arguments(request2),
|
|
1460
2229
|
...request2.body,
|
|
1461
2230
|
...cites,
|
|
@@ -1540,8 +2309,11 @@ var run_ship_detach = {
|
|
|
1540
2309
|
last_launch,
|
|
1541
2310
|
log_path,
|
|
1542
2311
|
read_log,
|
|
2312
|
+
read_record,
|
|
2313
|
+
result_path,
|
|
1543
2314
|
running_since,
|
|
1544
|
-
supervisor_argv
|
|
2315
|
+
supervisor_argv,
|
|
2316
|
+
supervisor_environment
|
|
1545
2317
|
};
|
|
1546
2318
|
|
|
1547
2319
|
// scripts/lane/lane-handoff.ts
|
|
@@ -1561,17 +2333,17 @@ async function read_repository() {
|
|
|
1561
2333
|
return void 0;
|
|
1562
2334
|
}
|
|
1563
2335
|
}
|
|
1564
|
-
async function ship_reader(
|
|
2336
|
+
async function ship_reader(read4) {
|
|
1565
2337
|
const repository = await read_repository();
|
|
1566
|
-
return (issue) => repository !== void 0 && run_ship_detach.read_result(repository, issue,
|
|
2338
|
+
return (issue) => repository !== void 0 && run_ship_detach.read_result(repository, issue, read4)?.result === "running";
|
|
1567
2339
|
}
|
|
1568
|
-
function is_merge_waiting(repository, issue,
|
|
1569
|
-
if (run_ship_detach.read_result(repository, issue,
|
|
2340
|
+
function is_merge_waiting(repository, issue, read4) {
|
|
2341
|
+
if (run_ship_detach.read_result(repository, issue, read4)?.result !== "running") return false;
|
|
1570
2342
|
return run_ship_stage.read_merge_waiting(run_ship_stage.record_path(repository, issue));
|
|
1571
2343
|
}
|
|
1572
|
-
async function merge_wait_reader(
|
|
2344
|
+
async function merge_wait_reader(read4) {
|
|
1573
2345
|
const repository = await read_repository();
|
|
1574
|
-
return (issue) => repository !== void 0 && is_merge_waiting(repository, issue,
|
|
2346
|
+
return (issue) => repository !== void 0 && is_merge_waiting(repository, issue, read4);
|
|
1575
2347
|
}
|
|
1576
2348
|
function is_place_waiting(issue, directory) {
|
|
1577
2349
|
const repository = git_common_directory.repository(directory);
|
|
@@ -1614,6 +2386,7 @@ var AUTO_OK_LABEL = "auto-ok";
|
|
|
1614
2386
|
var NEEDS_HUMAN_REVIEW_LABEL = "needs-human-review";
|
|
1615
2387
|
var ALREADY_DONE_LABEL = "already-done";
|
|
1616
2388
|
var MEASURED_LABEL = "measured";
|
|
2389
|
+
var MEASURED_UNMET_LABEL = "measured:unmet";
|
|
1617
2390
|
var RELEASE_LABEL = "release";
|
|
1618
2391
|
var DEFERRED_LABEL = "deferred";
|
|
1619
2392
|
var NOT_BEFORE_LABEL = "not-before";
|
|
@@ -1720,6 +2493,11 @@ var WORKFLOW_LABELS = [
|
|
|
1720
2493
|
color: "6f42c1",
|
|
1721
2494
|
description: "Measurement-only \u2014 a run recorded the result and closed it"
|
|
1722
2495
|
},
|
|
2496
|
+
{
|
|
2497
|
+
name: MEASURED_UNMET_LABEL,
|
|
2498
|
+
color: "6f42c1",
|
|
2499
|
+
description: "The measurement fell short of the expected effect \u2014 retire or shrink the mechanism"
|
|
2500
|
+
},
|
|
1723
2501
|
{
|
|
1724
2502
|
name: DEFERRED_LABEL,
|
|
1725
2503
|
color: "d4c5f9",
|
|
@@ -1765,17 +2543,20 @@ function label_name_of(labels, wanted) {
|
|
|
1765
2543
|
function has_label_name(labels, wanted) {
|
|
1766
2544
|
return label_name_of(labels, wanted) !== void 0;
|
|
1767
2545
|
}
|
|
2546
|
+
function parked_label_of(labels) {
|
|
2547
|
+
return [...PARKED_LABELS].find((label) => has_label_name(labels, label));
|
|
2548
|
+
}
|
|
1768
2549
|
function has_parked_label(labels) {
|
|
1769
|
-
return
|
|
2550
|
+
return parked_label_of(labels) !== void 0;
|
|
1770
2551
|
}
|
|
1771
2552
|
|
|
1772
2553
|
// scripts/run/park/run-park.ts
|
|
1773
|
-
import { z as
|
|
2554
|
+
import { z as z7 } from "zod";
|
|
1774
2555
|
var PARK_PREFIX = "josh-run-park-";
|
|
1775
2556
|
var PARK_MAX_AGE_MS = backlog_budget.DEFAULT_IDLE_MS;
|
|
1776
|
-
var run_park_schema =
|
|
1777
|
-
issue:
|
|
1778
|
-
parked_at:
|
|
2557
|
+
var run_park_schema = z7.object({
|
|
2558
|
+
issue: z7.string(),
|
|
2559
|
+
parked_at: z7.string()
|
|
1779
2560
|
});
|
|
1780
2561
|
function parse_park(raw) {
|
|
1781
2562
|
return json_value.parse_with(raw, run_park_schema);
|
|
@@ -1804,15 +2585,153 @@ function clear(issue, directory) {
|
|
|
1804
2585
|
function is_parked_sync(issue, directory, now = /* @__PURE__ */ new Date()) {
|
|
1805
2586
|
const repository = git_common_directory.repository(directory);
|
|
1806
2587
|
if (repository === void 0) return false;
|
|
1807
|
-
const
|
|
2588
|
+
const read4 = stamp_record.classify(
|
|
1808
2589
|
stamp_file.read_stamp_text(park_path(repository, issue)),
|
|
1809
2590
|
PARK_SPEC,
|
|
1810
2591
|
now
|
|
1811
2592
|
);
|
|
1812
|
-
return
|
|
2593
|
+
return read4.kind === "carried" && read4.record.issue === issue;
|
|
1813
2594
|
}
|
|
1814
2595
|
var run_park = { PARK_MAX_AGE_MS, clear, is_parked_sync, record };
|
|
1815
2596
|
|
|
2597
|
+
// scripts/rules/git-argv.ts
|
|
2598
|
+
var ENV_ASSIGNMENT = /^[A-Za-z_]\w*=/u;
|
|
2599
|
+
var WRAPPER_WORDS = /* @__PURE__ */ new Set([
|
|
2600
|
+
"pnpm",
|
|
2601
|
+
"npx",
|
|
2602
|
+
"exec",
|
|
2603
|
+
"run",
|
|
2604
|
+
"sudo",
|
|
2605
|
+
"command",
|
|
2606
|
+
"env",
|
|
2607
|
+
"time"
|
|
2608
|
+
]);
|
|
2609
|
+
var FLAGGED_WRAPPERS = /* @__PURE__ */ new Set(["time"]);
|
|
2610
|
+
var WRAPPER_VALUE_FLAGS = /* @__PURE__ */ new Set(["-o", "-f", "--output", "--format"]);
|
|
2611
|
+
var SUBSHELL_OPEN = "(";
|
|
2612
|
+
var VALUE_TAKING_GLOBALS = /* @__PURE__ */ new Set([
|
|
2613
|
+
"-C",
|
|
2614
|
+
"-c",
|
|
2615
|
+
"--git-dir",
|
|
2616
|
+
"--work-tree",
|
|
2617
|
+
"--namespace",
|
|
2618
|
+
"--exec-path",
|
|
2619
|
+
"--super-prefix"
|
|
2620
|
+
]);
|
|
2621
|
+
var FLAG_PREFIX = "-";
|
|
2622
|
+
var GIT_COMMAND = "git";
|
|
2623
|
+
var NEXT = 1;
|
|
2624
|
+
var AFTER_VALUE = 2;
|
|
2625
|
+
var WORD = /(?:\\.|'[^']*'|"(?:\\.|[^"\\])*"|\S)+/gsu;
|
|
2626
|
+
function words_of(segment) {
|
|
2627
|
+
return segment.match(WORD) ?? [];
|
|
2628
|
+
}
|
|
2629
|
+
var PATH_SEPARATOR = "/";
|
|
2630
|
+
function program_name(word) {
|
|
2631
|
+
return word.slice(word.lastIndexOf(PATH_SEPARATOR) + NEXT);
|
|
2632
|
+
}
|
|
2633
|
+
function is_wrapper_token(word) {
|
|
2634
|
+
return word === SUBSHELL_OPEN || ENV_ASSIGNMENT.test(word) || WRAPPER_WORDS.has(program_name(word));
|
|
2635
|
+
}
|
|
2636
|
+
function wrapper_flag_width(word = "") {
|
|
2637
|
+
if (!word.startsWith(FLAG_PREFIX)) return 0;
|
|
2638
|
+
return WRAPPER_VALUE_FLAGS.has(word) ? AFTER_VALUE : NEXT;
|
|
2639
|
+
}
|
|
2640
|
+
function after_wrapper_word(words, index) {
|
|
2641
|
+
let next = index + NEXT;
|
|
2642
|
+
if (!FLAGGED_WRAPPERS.has(program_name(words[index] ?? ""))) return next;
|
|
2643
|
+
let width = wrapper_flag_width(words[next]);
|
|
2644
|
+
while (width > 0) {
|
|
2645
|
+
next += width;
|
|
2646
|
+
width = wrapper_flag_width(words[next]);
|
|
2647
|
+
}
|
|
2648
|
+
return next;
|
|
2649
|
+
}
|
|
2650
|
+
function after_wrapper(words) {
|
|
2651
|
+
let index = 0;
|
|
2652
|
+
while (index < words.length && is_wrapper_token(words[index] ?? "")) {
|
|
2653
|
+
index = after_wrapper_word(words, index);
|
|
2654
|
+
}
|
|
2655
|
+
return index;
|
|
2656
|
+
}
|
|
2657
|
+
function global_step(flag) {
|
|
2658
|
+
return VALUE_TAKING_GLOBALS.has(flag) ? AFTER_VALUE : NEXT;
|
|
2659
|
+
}
|
|
2660
|
+
function after_globals(words, start) {
|
|
2661
|
+
let index = start;
|
|
2662
|
+
while (index < words.length) {
|
|
2663
|
+
const flag = words[index] ?? "";
|
|
2664
|
+
if (!flag.startsWith(FLAG_PREFIX)) return index;
|
|
2665
|
+
index += global_step(flag);
|
|
2666
|
+
}
|
|
2667
|
+
return index;
|
|
2668
|
+
}
|
|
2669
|
+
function program_of(segment) {
|
|
2670
|
+
const words = words_of(segment);
|
|
2671
|
+
const command_index = after_wrapper(words);
|
|
2672
|
+
const word = words[command_index];
|
|
2673
|
+
if (word === void 0) return void 0;
|
|
2674
|
+
return { name: program_name(word), args: words.slice(command_index + NEXT) };
|
|
2675
|
+
}
|
|
2676
|
+
function arguments_of(segment, command) {
|
|
2677
|
+
const call = program_of(segment);
|
|
2678
|
+
return call?.name === command ? call.args : void 0;
|
|
2679
|
+
}
|
|
2680
|
+
function parse(segment) {
|
|
2681
|
+
const words = arguments_of(segment, GIT_COMMAND);
|
|
2682
|
+
if (words === void 0) return void 0;
|
|
2683
|
+
const subcommand_index = after_globals(words, 0);
|
|
2684
|
+
return { subcommand: words[subcommand_index], args: words.slice(subcommand_index + NEXT) };
|
|
2685
|
+
}
|
|
2686
|
+
var SHORT_CLUSTER = /^-[A-Za-z]+$/u;
|
|
2687
|
+
function short_cluster_has(token, letters) {
|
|
2688
|
+
if (!SHORT_CLUSTER.test(token)) return false;
|
|
2689
|
+
const cluster = token.slice(FLAG_PREFIX.length);
|
|
2690
|
+
for (let index = 0; index < letters.length; index += 1) {
|
|
2691
|
+
if (cluster.includes(letters.charAt(index))) return true;
|
|
2692
|
+
}
|
|
2693
|
+
return false;
|
|
2694
|
+
}
|
|
2695
|
+
var git_argv = { arguments_of, parse, program_of, short_cluster_has };
|
|
2696
|
+
|
|
2697
|
+
// scripts/rules/bash-triggers.ts
|
|
2698
|
+
function on_bash_command(is_match) {
|
|
2699
|
+
return function is_trigger(call) {
|
|
2700
|
+
if (call.name !== cost_blocks.BASH_TOOL) return false;
|
|
2701
|
+
return is_match(time_shell.bash_command(call.input));
|
|
2702
|
+
};
|
|
2703
|
+
}
|
|
2704
|
+
var ISSUE_CREATE_COMMAND = /\bgh\s+(?:\S+\s+)*?issue\s+create\b/u;
|
|
2705
|
+
var ISSUES_ENDPOINT = /repos\/[^\s'"]*\/issues(?=$|["'\s])/u;
|
|
2706
|
+
var TITLE_FIELD = /(?:-f|-F|--field|--raw-field)\s*'?title=/u;
|
|
2707
|
+
var GH_API_COMMAND = /\bgh\s+api\b/u;
|
|
2708
|
+
var SHELL_SCRIPT_RUNNER = /\b(?:(?:ba|z|da|k)?sh\s+(?:-\w+\s+)*-\w*c\b|eval\b)/u;
|
|
2709
|
+
function spoken_line(command) {
|
|
2710
|
+
if (time_shell.has_heredoc(command)) return command;
|
|
2711
|
+
const plain = time_shell.unquoted(command);
|
|
2712
|
+
return SHELL_SCRIPT_RUNNER.test(plain) ? command : plain;
|
|
2713
|
+
}
|
|
2714
|
+
var LEADING_SHELL_SCRIPT_RUNNER = new RegExp(`^${SHELL_SCRIPT_RUNNER.source}`, "u");
|
|
2715
|
+
var QUOTE_MARK = /["']/gu;
|
|
2716
|
+
function shell_script_of(segment) {
|
|
2717
|
+
const call = git_argv.program_of(segment);
|
|
2718
|
+
if (call === void 0) return void 0;
|
|
2719
|
+
const spoken = [call.name, ...call.args].join(" ");
|
|
2720
|
+
const runner = LEADING_SHELL_SCRIPT_RUNNER.exec(spoken);
|
|
2721
|
+
if (runner === null) return void 0;
|
|
2722
|
+
return spoken.slice(runner[0].length).replaceAll(QUOTE_MARK, "").trim();
|
|
2723
|
+
}
|
|
2724
|
+
function is_direct_filing(command) {
|
|
2725
|
+
const spoken = spoken_line(command);
|
|
2726
|
+
if (ISSUE_CREATE_COMMAND.test(spoken)) return true;
|
|
2727
|
+
return GH_API_COMMAND.test(spoken) && ISSUES_ENDPOINT.test(command) && TITLE_FIELD.test(command);
|
|
2728
|
+
}
|
|
2729
|
+
var FILING_NAMES = /* @__PURE__ */ new Set(["issue:file"]);
|
|
2730
|
+
function is_issue_filing(command) {
|
|
2731
|
+
return shell_segments.segments_of(command).some((segment) => shell_segments.is_josh_command(segment, FILING_NAMES));
|
|
2732
|
+
}
|
|
2733
|
+
var bash_triggers = { is_direct_filing, is_issue_filing, on_bash_command, shell_script_of };
|
|
2734
|
+
|
|
1816
2735
|
// scripts/rules/lane-park.ts
|
|
1817
2736
|
var NOTIFY_COMMANDS = /* @__PURE__ */ new Set(["notify"]);
|
|
1818
2737
|
var CONFIRMATION_TASK_TYPE = /(?:^|\s)--task-type[=\s]+["']?confirmation\b/u;
|
|
@@ -1852,7 +2771,7 @@ function records_the_park(command) {
|
|
|
1852
2771
|
if (APPLIES_NEEDS_DECISION.test(command)) return true;
|
|
1853
2772
|
return shell_segments.segments_of(command).some((segment) => is_park_command(segment));
|
|
1854
2773
|
}
|
|
1855
|
-
var LANE_PARK_REASON = "\u26D4 lane child park: this session is a dispatched lane child, so a stop for a person parks first: `pnpm josh run:park <N> --body-file <path>` (question, options, stash \u2014 it applies `needs-decision`); a `needs-human-review` / `already-done` stop already is.
|
|
2774
|
+
var LANE_PARK_REASON = "\u26D4 lane child park: this session is a dispatched lane child, so a stop for a person parks first: `pnpm josh run:park <N> --body-file <path>` (question, options, stash \u2014 it applies `needs-decision`); a `needs-human-review` / `already-done` stop already is. The park is the stop: no notify after it. Refused once per run (`.claude/skills/workflow-commands/pre-gate-cut.md`).";
|
|
1856
2775
|
var ROW3 = {
|
|
1857
2776
|
id: "lane-park",
|
|
1858
2777
|
is_trigger: bash_triggers.on_bash_command(is_unparked_stop),
|
|
@@ -1879,19 +2798,19 @@ var lane_park = {
|
|
|
1879
2798
|
|
|
1880
2799
|
// scripts/cost-runtime/codex-usage.ts
|
|
1881
2800
|
import { globSync, readFileSync as readFileSync2 } from "node:fs";
|
|
1882
|
-
import
|
|
1883
|
-
import { z as
|
|
2801
|
+
import path5 from "node:path";
|
|
2802
|
+
import { z as z8 } from "zod";
|
|
1884
2803
|
var THREAD_ID_PATTERN = /^[A-Za-z0-9-]+$/u;
|
|
1885
|
-
var SESSION_META_SCHEMA =
|
|
1886
|
-
type:
|
|
1887
|
-
payload:
|
|
2804
|
+
var SESSION_META_SCHEMA = z8.looseObject({
|
|
2805
|
+
type: z8.literal("session_meta"),
|
|
2806
|
+
payload: z8.looseObject({ id: z8.string(), cwd: z8.string() })
|
|
1888
2807
|
});
|
|
1889
|
-
var TOTAL_USAGE_SCHEMA =
|
|
1890
|
-
var TOKEN_COUNT_SCHEMA =
|
|
1891
|
-
type:
|
|
1892
|
-
payload:
|
|
1893
|
-
type:
|
|
1894
|
-
info:
|
|
2808
|
+
var TOTAL_USAGE_SCHEMA = z8.looseObject({ input_tokens: z8.number().nonnegative() });
|
|
2809
|
+
var TOKEN_COUNT_SCHEMA = z8.looseObject({
|
|
2810
|
+
type: z8.literal("event_msg"),
|
|
2811
|
+
payload: z8.looseObject({
|
|
2812
|
+
type: z8.literal("token_count"),
|
|
2813
|
+
info: z8.looseObject({
|
|
1895
2814
|
total_token_usage: TOTAL_USAGE_SCHEMA,
|
|
1896
2815
|
last_token_usage: TOTAL_USAGE_SCHEMA
|
|
1897
2816
|
})
|
|
@@ -1900,52 +2819,197 @@ var TOKEN_COUNT_SCHEMA = z6.looseObject({
|
|
|
1900
2819
|
function same_project(cwd, target) {
|
|
1901
2820
|
return cost_transcript.session_cwd(cwd) === cost_transcript.session_cwd(target);
|
|
1902
2821
|
}
|
|
1903
|
-
function billed_per_request(usages) {
|
|
1904
|
-
return usages.map((usage) => usage.last_token_usage.input_tokens);
|
|
2822
|
+
function billed_per_request(usages) {
|
|
2823
|
+
return usages.map((usage) => usage.last_token_usage.input_tokens);
|
|
2824
|
+
}
|
|
2825
|
+
function measurement_from(content, target, thread_id) {
|
|
2826
|
+
const values = content.split("\n").map((line) => json_value.parse_or_undefined(line));
|
|
2827
|
+
const metadata = values.flatMap((value) => {
|
|
2828
|
+
const parsed = SESSION_META_SCHEMA.safeParse(value);
|
|
2829
|
+
return parsed.success ? [parsed.data] : [];
|
|
2830
|
+
});
|
|
2831
|
+
const usages = values.flatMap((value) => {
|
|
2832
|
+
const parsed = TOKEN_COUNT_SCHEMA.safeParse(value);
|
|
2833
|
+
return parsed.success ? [parsed.data.payload.info] : [];
|
|
2834
|
+
});
|
|
2835
|
+
const session = metadata.find((entry) => entry.payload.id === thread_id);
|
|
2836
|
+
if (session === void 0 || usages.length === 0 || !same_project(session.payload.cwd, target)) {
|
|
2837
|
+
return void 0;
|
|
2838
|
+
}
|
|
2839
|
+
return { billed_input_per_request: billed_per_request(usages) };
|
|
2840
|
+
}
|
|
2841
|
+
function rollout_files(home, thread_id) {
|
|
2842
|
+
if (!THREAD_ID_PATTERN.test(thread_id)) return [];
|
|
2843
|
+
return globSync(`sessions/**/*${thread_id}.jsonl`, { cwd: home }).map(
|
|
2844
|
+
(file) => path5.join(home, file)
|
|
2845
|
+
);
|
|
2846
|
+
}
|
|
2847
|
+
function read_measurement(file, target, thread_id) {
|
|
2848
|
+
try {
|
|
2849
|
+
return measurement_from(readFileSync2(file, "utf8"), target, thread_id);
|
|
2850
|
+
} catch {
|
|
2851
|
+
return void 0;
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
function latest_measurement(files, target, thread_id) {
|
|
2855
|
+
for (const file of files.toReversed()) {
|
|
2856
|
+
const measured = read_measurement(file, target, thread_id);
|
|
2857
|
+
if (measured !== void 0) return measured;
|
|
2858
|
+
}
|
|
2859
|
+
return void 0;
|
|
2860
|
+
}
|
|
2861
|
+
function measurement(target, default_home, environment = process.env) {
|
|
2862
|
+
const thread_id = environment["CODEX_THREAD_ID"];
|
|
2863
|
+
if (thread_id === void 0) return void 0;
|
|
2864
|
+
const home = environment["CODEX_HOME"] ?? path5.join(default_home, ".codex");
|
|
2865
|
+
return latest_measurement(rollout_files(home, thread_id), target, thread_id);
|
|
2866
|
+
}
|
|
2867
|
+
var codex_usage = { measurement };
|
|
2868
|
+
|
|
2869
|
+
// scripts/cost-runtime/cost-pricing.ts
|
|
2870
|
+
var CACHE_WRITE_5M_MULTIPLIER = 1.25;
|
|
2871
|
+
var CACHE_WRITE_1H_MULTIPLIER = 2;
|
|
2872
|
+
var DEFAULT_CACHE_READ_MULTIPLIER = 0.1;
|
|
2873
|
+
var HALVED_CACHE_READ_MULTIPLIER = 0.05;
|
|
2874
|
+
var QUARTERED_CACHE_READ_MULTIPLIER = 0.025;
|
|
2875
|
+
var TOKENS_PER_MILLION = 1e6;
|
|
2876
|
+
var LONG_PROMPT_SUFFIX = ":long-prompt";
|
|
2877
|
+
var LONG_PROMPT_THRESHOLD = 1e5;
|
|
2878
|
+
var MODEL_PRICES = {
|
|
2879
|
+
"claude-fable-5-1": {
|
|
2880
|
+
input: 10,
|
|
2881
|
+
output: 50,
|
|
2882
|
+
cache_read_multiplier: QUARTERED_CACHE_READ_MULTIPLIER
|
|
2883
|
+
},
|
|
2884
|
+
"claude-mythos-5-1": {
|
|
2885
|
+
input: 10,
|
|
2886
|
+
output: 50,
|
|
2887
|
+
cache_read_multiplier: QUARTERED_CACHE_READ_MULTIPLIER
|
|
2888
|
+
},
|
|
2889
|
+
"claude-fable-5": { input: 10, output: 50 },
|
|
2890
|
+
"claude-mythos-5": { input: 10, output: 50 },
|
|
2891
|
+
"claude-opus-5-5": { input: 4, output: 20, cache_read_multiplier: HALVED_CACHE_READ_MULTIPLIER },
|
|
2892
|
+
"claude-opus-5": { input: 5, output: 25 },
|
|
2893
|
+
"claude-opus-4-8": { input: 5, output: 25 },
|
|
2894
|
+
"claude-opus-4-7": { input: 5, output: 25 },
|
|
2895
|
+
"claude-opus-4-6": { input: 5, output: 25 },
|
|
2896
|
+
"claude-sonnet-5-5": {
|
|
2897
|
+
input: 2,
|
|
2898
|
+
output: 10,
|
|
2899
|
+
cache_read_multiplier: HALVED_CACHE_READ_MULTIPLIER
|
|
2900
|
+
},
|
|
2901
|
+
"claude-sonnet-5": { input: 2, output: 10 },
|
|
2902
|
+
"claude-sonnet-4-6": { input: 3, output: 15 },
|
|
2903
|
+
"claude-haiku-5-5": { input: 0.1, output: 0.5 },
|
|
2904
|
+
[`claude-haiku-5-5${LONG_PROMPT_SUFFIX}`]: { input: 0.5, output: 2.5 },
|
|
2905
|
+
"claude-haiku-4-5": { input: 1, output: 5 }
|
|
2906
|
+
};
|
|
2907
|
+
var CONTEXT_MARKER = "[";
|
|
2908
|
+
var DATE_SUFFIX = /-\d{8}$/u;
|
|
2909
|
+
function known_id(model) {
|
|
2910
|
+
const base = model.split(CONTEXT_MARKER)[0] ?? model;
|
|
2911
|
+
return [base, base.replace(DATE_SUFFIX, "")].find((id) => Object.hasOwn(MODEL_PRICES, id));
|
|
2912
|
+
}
|
|
2913
|
+
function resolve_price(model) {
|
|
2914
|
+
const id = known_id(model);
|
|
2915
|
+
return id === void 0 ? void 0 : MODEL_PRICES[id];
|
|
2916
|
+
}
|
|
2917
|
+
function cache_read_multiplier(price) {
|
|
2918
|
+
return price.cache_read_multiplier ?? DEFAULT_CACHE_READ_MULTIPLIER;
|
|
2919
|
+
}
|
|
2920
|
+
function cache_read_multiplier_of(model) {
|
|
2921
|
+
const price = model === void 0 ? void 0 : resolve_price(model);
|
|
2922
|
+
return price === void 0 ? DEFAULT_CACHE_READ_MULTIPLIER : cache_read_multiplier(price);
|
|
2923
|
+
}
|
|
2924
|
+
function estimate_cost(totals, price) {
|
|
2925
|
+
const weighted_input = totals.input_tokens + totals.cache_write_5m_tokens * CACHE_WRITE_5M_MULTIPLIER + totals.cache_write_1h_tokens * CACHE_WRITE_1H_MULTIPLIER + totals.cache_read_tokens * cache_read_multiplier(price);
|
|
2926
|
+
return (weighted_input * price.input + totals.output_tokens * price.output) / TOKENS_PER_MILLION;
|
|
2927
|
+
}
|
|
2928
|
+
function priced(tokens, rate) {
|
|
2929
|
+
return tokens * rate / TOKENS_PER_MILLION;
|
|
2930
|
+
}
|
|
2931
|
+
function estimate_composition(totals, price) {
|
|
2932
|
+
return {
|
|
2933
|
+
input_usd: priced(totals.input_tokens, price.input),
|
|
2934
|
+
cache_write_5m_usd: priced(
|
|
2935
|
+
totals.cache_write_5m_tokens * CACHE_WRITE_5M_MULTIPLIER,
|
|
2936
|
+
price.input
|
|
2937
|
+
),
|
|
2938
|
+
cache_write_1h_usd: priced(
|
|
2939
|
+
totals.cache_write_1h_tokens * CACHE_WRITE_1H_MULTIPLIER,
|
|
2940
|
+
price.input
|
|
2941
|
+
),
|
|
2942
|
+
cache_read_usd: priced(totals.cache_read_tokens * cache_read_multiplier(price), price.input),
|
|
2943
|
+
output_usd: priced(totals.output_tokens, price.output)
|
|
2944
|
+
};
|
|
2945
|
+
}
|
|
2946
|
+
function to_model_cost(model, totals) {
|
|
2947
|
+
const price = resolve_price(model);
|
|
2948
|
+
if (price === void 0) return { model, totals };
|
|
2949
|
+
return { model, totals, cost_usd: estimate_cost(totals, price) };
|
|
1905
2950
|
}
|
|
1906
|
-
function
|
|
1907
|
-
const
|
|
1908
|
-
const
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
const
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
if (session === void 0 || usages.length === 0 || !same_project(session.payload.cwd, target)) {
|
|
1918
|
-
return void 0;
|
|
2951
|
+
function billed_model(usage) {
|
|
2952
|
+
const long_id = `${known_id(usage.model) ?? usage.model}${LONG_PROMPT_SUFFIX}`;
|
|
2953
|
+
const is_long = cost_usage.billed_input(usage.totals) > LONG_PROMPT_THRESHOLD;
|
|
2954
|
+
return is_long && Object.hasOwn(MODEL_PRICES, long_id) ? long_id : usage.model;
|
|
2955
|
+
}
|
|
2956
|
+
function cost_by_model(records) {
|
|
2957
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
2958
|
+
for (const record3 of records) {
|
|
2959
|
+
const model = billed_model(record3);
|
|
2960
|
+
const running = grouped.get(model) ?? cost_usage.EMPTY_TOTALS;
|
|
2961
|
+
grouped.set(model, cost_usage.add_totals(running, record3.totals));
|
|
1919
2962
|
}
|
|
1920
|
-
return
|
|
2963
|
+
return [...grouped].map(([model, totals]) => to_model_cost(model, totals));
|
|
1921
2964
|
}
|
|
1922
|
-
function
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
(
|
|
1926
|
-
|
|
2965
|
+
function total_cost(costs) {
|
|
2966
|
+
return {
|
|
2967
|
+
usd: costs.reduce((sum, entry) => sum + (entry.cost_usd ?? 0), 0),
|
|
2968
|
+
unpriced: costs.filter((entry) => entry.cost_usd === void 0).map((entry) => entry.model)
|
|
2969
|
+
};
|
|
1927
2970
|
}
|
|
1928
|
-
function
|
|
1929
|
-
|
|
1930
|
-
return measurement_from(readFileSync2(file, "utf8"), target, thread_id);
|
|
1931
|
-
} catch {
|
|
1932
|
-
return void 0;
|
|
1933
|
-
}
|
|
2971
|
+
function cost_of(records) {
|
|
2972
|
+
return total_cost(cost_by_model(records)).usd;
|
|
1934
2973
|
}
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
2974
|
+
var cost_pricing = {
|
|
2975
|
+
CACHE_WRITE_5M_MULTIPLIER,
|
|
2976
|
+
CACHE_WRITE_1H_MULTIPLIER,
|
|
2977
|
+
DEFAULT_CACHE_READ_MULTIPLIER,
|
|
2978
|
+
LONG_PROMPT_THRESHOLD,
|
|
2979
|
+
resolve_price,
|
|
2980
|
+
cache_read_multiplier_of,
|
|
2981
|
+
estimate_cost,
|
|
2982
|
+
estimate_composition,
|
|
2983
|
+
cost_by_model,
|
|
2984
|
+
total_cost,
|
|
2985
|
+
cost_of
|
|
2986
|
+
};
|
|
2987
|
+
|
|
2988
|
+
// scripts/cost-runtime/context-cut-payback.ts
|
|
2989
|
+
var POST_CUT_CONTEXT = 6e4;
|
|
2990
|
+
var EXPECTED_REMAINING_REQUESTS = 23;
|
|
2991
|
+
function write_over_read(model) {
|
|
2992
|
+
return cost_pricing.CACHE_WRITE_5M_MULTIPLIER / cost_pricing.cache_read_multiplier_of(model);
|
|
1941
2993
|
}
|
|
1942
|
-
function
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
const home = environment["CODEX_HOME"] ?? path.join(default_home, ".codex");
|
|
1946
|
-
return latest_measurement(rollout_files(home, thread_id), target, thread_id);
|
|
2994
|
+
function break_even_context(model, remaining = EXPECTED_REMAINING_REQUESTS) {
|
|
2995
|
+
if (remaining <= 0) return Infinity;
|
|
2996
|
+
return Math.round(POST_CUT_CONTEXT * (1 + write_over_read(model) / remaining));
|
|
1947
2997
|
}
|
|
1948
|
-
|
|
2998
|
+
function break_even_requests(current_context, model) {
|
|
2999
|
+
const saved_per_request = current_context - POST_CUT_CONTEXT;
|
|
3000
|
+
if (saved_per_request <= 0) return Infinity;
|
|
3001
|
+
return POST_CUT_CONTEXT * write_over_read(model) / saved_per_request;
|
|
3002
|
+
}
|
|
3003
|
+
function pays_back(current_context, model, remaining = EXPECTED_REMAINING_REQUESTS) {
|
|
3004
|
+
return current_context > break_even_context(model, remaining);
|
|
3005
|
+
}
|
|
3006
|
+
var context_cut_payback = {
|
|
3007
|
+
POST_CUT_CONTEXT,
|
|
3008
|
+
EXPECTED_REMAINING_REQUESTS,
|
|
3009
|
+
break_even_context,
|
|
3010
|
+
break_even_requests,
|
|
3011
|
+
pays_back
|
|
3012
|
+
};
|
|
1949
3013
|
|
|
1950
3014
|
// scripts/cost-runtime/cost-corpus.ts
|
|
1951
3015
|
function accumulate_missing(sessions) {
|
|
@@ -1987,8 +3051,8 @@ function owner_sets(corpus, meta) {
|
|
|
1987
3051
|
}
|
|
1988
3052
|
function pairs_with_inherited(session, inherited, is_delegated) {
|
|
1989
3053
|
return cost_attribute.group_by_issue(session.records).flatMap(
|
|
1990
|
-
(group) => group.records.map((
|
|
1991
|
-
record:
|
|
3054
|
+
(group) => group.records.map((record3) => ({
|
|
3055
|
+
record: record3,
|
|
1992
3056
|
issue: group.issue === cost_attribute.UNATTRIBUTED_KEY ? inherited : group.issue,
|
|
1993
3057
|
baseline_tokens: session.baseline_tokens,
|
|
1994
3058
|
session_id: session.session_id,
|
|
@@ -2070,7 +3134,7 @@ var UNDER_VERDICT = "under";
|
|
|
2070
3134
|
function per_request_cost(measurement2) {
|
|
2071
3135
|
return measurement2.billed_input_per_request.at(-1) ?? 0;
|
|
2072
3136
|
}
|
|
2073
|
-
function
|
|
3137
|
+
function classify3(measurement2, limit) {
|
|
2074
3138
|
return per_request_cost(measurement2) > limit ? OVER_VERDICT : UNDER_VERDICT;
|
|
2075
3139
|
}
|
|
2076
3140
|
function over_summary(measurement2, limit) {
|
|
@@ -2082,22 +3146,22 @@ function report_over(measurement2, limit) {
|
|
|
2082
3146
|
console.error("No requests in this session; there is nothing to hand off.");
|
|
2083
3147
|
return FAILURE_EXIT_CODE;
|
|
2084
3148
|
}
|
|
2085
|
-
console.info(
|
|
3149
|
+
console.info(classify3(measurement2, limit));
|
|
2086
3150
|
console.error(over_summary(measurement2, limit));
|
|
2087
3151
|
return 0;
|
|
2088
3152
|
}
|
|
2089
3153
|
var cost_verdict = {
|
|
2090
3154
|
OVER_VERDICT,
|
|
2091
3155
|
UNDER_VERDICT,
|
|
2092
|
-
classify:
|
|
3156
|
+
classify: classify3,
|
|
2093
3157
|
per_request_cost,
|
|
2094
3158
|
report_over
|
|
2095
3159
|
};
|
|
2096
3160
|
|
|
2097
3161
|
// scripts/cost-runtime/transcript-cwd.ts
|
|
2098
|
-
import
|
|
3162
|
+
import path6 from "node:path";
|
|
2099
3163
|
function resolve(target, cwd) {
|
|
2100
|
-
return target === void 0 ? cwd :
|
|
3164
|
+
return target === void 0 ? cwd : path6.resolve(target);
|
|
2101
3165
|
}
|
|
2102
3166
|
var transcript_cwd = { resolve };
|
|
2103
3167
|
|
|
@@ -2105,6 +3169,7 @@ var transcript_cwd = { resolve };
|
|
|
2105
3169
|
var FAILURE_EXIT_CODE2 = 1;
|
|
2106
3170
|
var USAGE = "Usage: josh cost (--cut | --over <tokens-per-request>) [--path <dir>]";
|
|
2107
3171
|
var UNMEASURABLE_VERDICT = "unmeasurable";
|
|
3172
|
+
var CUT_LIMIT = "cut";
|
|
2108
3173
|
function to_threshold(raw) {
|
|
2109
3174
|
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
2110
3175
|
const parsed = Number(raw);
|
|
@@ -2113,19 +3178,24 @@ function to_threshold(raw) {
|
|
|
2113
3178
|
function is_unparsed(raw, parsed) {
|
|
2114
3179
|
return parsed === void 0 && raw !== void 0;
|
|
2115
3180
|
}
|
|
2116
|
-
function
|
|
2117
|
-
|
|
2118
|
-
|
|
3181
|
+
function cut_threshold(measurement2) {
|
|
3182
|
+
return context_cut_payback.break_even_context(measurement2?.model);
|
|
3183
|
+
}
|
|
3184
|
+
function limit_of(limit, measurement2) {
|
|
3185
|
+
return limit === CUT_LIMIT ? cut_threshold(measurement2) : limit;
|
|
2119
3186
|
}
|
|
2120
3187
|
function threshold_option(over) {
|
|
2121
3188
|
return over === void 0 ? {} : { over };
|
|
2122
3189
|
}
|
|
2123
|
-
function path_option(
|
|
2124
|
-
return
|
|
3190
|
+
function path_option(path19) {
|
|
3191
|
+
return path19 === void 0 ? {} : { path: path19 };
|
|
3192
|
+
}
|
|
3193
|
+
function cut_options(values) {
|
|
3194
|
+
return values.over === void 0 ? { over: CUT_LIMIT, ...path_option(values.path) } : void 0;
|
|
2125
3195
|
}
|
|
2126
3196
|
function to_options(values) {
|
|
2127
|
-
if (values.cut === true
|
|
2128
|
-
const over =
|
|
3197
|
+
if (values.cut === true) return cut_options(values);
|
|
3198
|
+
const over = to_threshold(values.over);
|
|
2129
3199
|
if (is_unparsed(values.over, over)) return void 0;
|
|
2130
3200
|
return { ...threshold_option(over), ...path_option(values.path) };
|
|
2131
3201
|
}
|
|
@@ -2144,15 +3214,16 @@ function report_empty(cwd, session_id) {
|
|
|
2144
3214
|
return FAILURE_EXIT_CODE2;
|
|
2145
3215
|
}
|
|
2146
3216
|
function provider_of(environment) {
|
|
2147
|
-
const
|
|
2148
|
-
if (
|
|
2149
|
-
return
|
|
3217
|
+
const resolved2 = agent_role_profile.resolve_provider(environment);
|
|
3218
|
+
if (resolved2.kind !== "provider" || resolved2.is_default === true) return void 0;
|
|
3219
|
+
return resolved2.provider;
|
|
2150
3220
|
}
|
|
2151
3221
|
function measurement_of(session) {
|
|
2152
3222
|
return {
|
|
2153
3223
|
billed_input_per_request: session.records.map(
|
|
2154
|
-
(
|
|
2155
|
-
)
|
|
3224
|
+
(record3) => cost_usage.billed_input(record3.totals)
|
|
3225
|
+
),
|
|
3226
|
+
model: session.records.at(-1)?.model
|
|
2156
3227
|
};
|
|
2157
3228
|
}
|
|
2158
3229
|
function anthropic_own(target, environment) {
|
|
@@ -2183,12 +3254,16 @@ function measure(target, provider, environment) {
|
|
|
2183
3254
|
return provider === "openai" ? codex_usage.measurement(target, cost_transcript.home_directory(), environment) : anthropic_measurement(target, environment);
|
|
2184
3255
|
}
|
|
2185
3256
|
function run_over_anthropic(own, target, limit) {
|
|
2186
|
-
if (own.kind === "measured")
|
|
3257
|
+
if (own.kind === "measured") {
|
|
3258
|
+
return cost_verdict.report_over(own.measurement, limit_of(limit, own.measurement));
|
|
3259
|
+
}
|
|
2187
3260
|
return report_empty(target, own.kind === "absent" ? own.session_id : void 0);
|
|
2188
3261
|
}
|
|
2189
3262
|
function run_over_codex(target, limit, environment) {
|
|
2190
3263
|
const measurement2 = measure(target, "openai", environment);
|
|
2191
|
-
if (measurement2 !== void 0)
|
|
3264
|
+
if (measurement2 !== void 0) {
|
|
3265
|
+
return cost_verdict.report_over(measurement2, limit_of(limit, measurement2));
|
|
3266
|
+
}
|
|
2192
3267
|
console.error(`No Codex usage found for the current OpenAI thread under ${target}.`);
|
|
2193
3268
|
return FAILURE_EXIT_CODE2;
|
|
2194
3269
|
}
|
|
@@ -2202,13 +3277,13 @@ function verdict_of(measurement2) {
|
|
|
2202
3277
|
if (measurement2 === void 0 || measurement2.billed_input_per_request.length === 0) {
|
|
2203
3278
|
return UNMEASURABLE_VERDICT;
|
|
2204
3279
|
}
|
|
2205
|
-
return cost_verdict.classify(measurement2,
|
|
3280
|
+
return cost_verdict.classify(measurement2, cut_threshold(measurement2));
|
|
2206
3281
|
}
|
|
2207
3282
|
function figures_of(measurement2) {
|
|
2208
3283
|
const verdict = verdict_of(measurement2);
|
|
2209
3284
|
const is_priced = measurement2 !== void 0 && verdict !== UNMEASURABLE_VERDICT;
|
|
2210
3285
|
const cost = is_priced ? cost_verdict.per_request_cost(measurement2) : void 0;
|
|
2211
|
-
return { verdict, cost, threshold:
|
|
3286
|
+
return { verdict, cost, threshold: cut_threshold(measurement2) };
|
|
2212
3287
|
}
|
|
2213
3288
|
function session_figures(cwd = process.cwd(), environment = process.env) {
|
|
2214
3289
|
const provider = provider_of(environment);
|
|
@@ -2291,7 +3366,7 @@ function is_uncut_gate(command, state = current_state2()) {
|
|
|
2291
3366
|
if (!runs_the_gate(command) || uncut_lane_issue(state) === void 0) return false;
|
|
2292
3367
|
return warrants_the_cut(state.context_verdict());
|
|
2293
3368
|
}
|
|
2294
|
-
var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at. Issue `pnpm josh run:cut <N>`: on `cut`, end the turn immediately \u2014 no Telegram is owed; on any other verdict (`not-a-lane`, `busy`, \u2026), reissue the gate \u2014 this fires once per run (`.claude/skills/workflow-commands/pre-gate-cut.md`).";
|
|
3369
|
+
var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at. Issue `pnpm josh run:cut <N>`: on `cut`, end the turn immediately \u2014 no Telegram is owed; on `split-unresolved`, answer its notice and rerun it; on any other verdict (`not-a-lane`, `busy`, \u2026), reissue the gate \u2014 this fires once per run (`.claude/skills/workflow-commands/pre-gate-cut.md`).";
|
|
2295
3370
|
function reaches_the_pre_gate_boundary(call, _turn, run2) {
|
|
2296
3371
|
if (!bash_triggers.on_bash_command(asks_about_the_cut)(call)) return false;
|
|
2297
3372
|
return run2.some((issued) => bash_triggers.on_bash_command(claims_the_hold)(issued));
|
|
@@ -2307,42 +3382,6 @@ var pre_gate_cut = {
|
|
|
2307
3382
|
uncut_lane_issue
|
|
2308
3383
|
};
|
|
2309
3384
|
|
|
2310
|
-
// scripts/discovery/repo-party.ts
|
|
2311
|
-
var FIRST_PARTY = "first-party";
|
|
2312
|
-
var THIRD_PARTY = "third-party";
|
|
2313
|
-
var UNKNOWN = "unknown";
|
|
2314
|
-
var GH_REPO_ENV_KEY = "GH_REPO";
|
|
2315
|
-
var GH_REPO_PATH_SEGMENTS = 2;
|
|
2316
|
-
function classify3(session_owner, target) {
|
|
2317
|
-
if (session_owner === void 0 || target === void 0) return UNKNOWN;
|
|
2318
|
-
return session_owner.toLowerCase() === target.toLowerCase() ? FIRST_PARTY : THIRD_PARTY;
|
|
2319
|
-
}
|
|
2320
|
-
function target_owner(owner_repo) {
|
|
2321
|
-
return repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${owner_repo}`)?.owner;
|
|
2322
|
-
}
|
|
2323
|
-
function current_owner(repository_path = process.cwd()) {
|
|
2324
|
-
return repo_discovery.resolve_current_owner(repository_path);
|
|
2325
|
-
}
|
|
2326
|
-
function gh_repo_owners(gh_repo) {
|
|
2327
|
-
return [target_owner(gh_repo.split("/").slice(-GH_REPO_PATH_SEGMENTS).join("/"))];
|
|
2328
|
-
}
|
|
2329
|
-
function remote_owners(repository_path) {
|
|
2330
|
-
return repo_discovery.read_remote_urls(repository_path).map((url) => repo_origin.parse_origin_url(url)?.owner);
|
|
2331
|
-
}
|
|
2332
|
-
function placeholder_owners(repository_path = process.cwd(), environment = process.env) {
|
|
2333
|
-
const gh_repo = environment[GH_REPO_ENV_KEY];
|
|
2334
|
-
return gh_repo === void 0 || gh_repo === "" ? remote_owners(repository_path) : gh_repo_owners(gh_repo);
|
|
2335
|
-
}
|
|
2336
|
-
var repo_party = {
|
|
2337
|
-
FIRST_PARTY,
|
|
2338
|
-
THIRD_PARTY,
|
|
2339
|
-
UNKNOWN,
|
|
2340
|
-
classify: classify3,
|
|
2341
|
-
current_owner,
|
|
2342
|
-
placeholder_owners,
|
|
2343
|
-
target_owner
|
|
2344
|
-
};
|
|
2345
|
-
|
|
2346
3385
|
// scripts/gh/git-gh-repo.ts
|
|
2347
3386
|
async function repo_get_name_with_owner() {
|
|
2348
3387
|
try {
|
|
@@ -2393,8 +3432,8 @@ function is_selected(rest, request2) {
|
|
|
2393
3432
|
return !git_gh_issue_rest.is_pull_request(rest) && matches_body(rest, request2.body_term);
|
|
2394
3433
|
}
|
|
2395
3434
|
async function fetch_page(request2, page) {
|
|
2396
|
-
const
|
|
2397
|
-
const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path:
|
|
3435
|
+
const path19 = listing_path(request2, page);
|
|
3436
|
+
const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path: path19 }));
|
|
2398
3437
|
return {
|
|
2399
3438
|
selected: rows.filter((row) => is_selected(row, request2)),
|
|
2400
3439
|
is_full: rows.length >= PER_PAGE
|
|
@@ -2489,8 +3528,8 @@ ${issue_watch_diff.RUN_MARKER}` }),
|
|
|
2489
3528
|
jq_filter: HTML_URL_FILTER
|
|
2490
3529
|
});
|
|
2491
3530
|
}
|
|
2492
|
-
async function issue_try_comment(issue_number, body) {
|
|
2493
|
-
return await did_write_succeed(async () => await issue_comment(issue_number, body));
|
|
3531
|
+
async function issue_try_comment(issue_number, body, repo) {
|
|
3532
|
+
return await did_write_succeed(async () => await issue_comment(issue_number, body, repo));
|
|
2494
3533
|
}
|
|
2495
3534
|
async function close_with(issue_number, comment, state) {
|
|
2496
3535
|
return await did_write_succeed(async () => {
|
|
@@ -2537,7 +3576,9 @@ function issue_create_request(input) {
|
|
|
2537
3576
|
...labels !== void 0 && { labels },
|
|
2538
3577
|
body: input.body
|
|
2539
3578
|
}),
|
|
2540
|
-
jq_filter: HTML_URL_FILTER
|
|
3579
|
+
jq_filter: HTML_URL_FILTER,
|
|
3580
|
+
// A 502 can follow an issue GitHub already opened, and a retry would open a second one.
|
|
3581
|
+
should_retry: false
|
|
2541
3582
|
};
|
|
2542
3583
|
}
|
|
2543
3584
|
async function issue_create_with_label(input) {
|
|
@@ -2647,10 +3688,10 @@ var LABELLED_FIELDS = "number,body,stateReason";
|
|
|
2647
3688
|
var BACKLOG_SCAN_FIELDS = `number,title,body,labels,${BLOCKED_BY_COUNT_FIELD}`;
|
|
2648
3689
|
var NUMBER_TITLE_AND_LABELS_FIELDS = "number,title,labels";
|
|
2649
3690
|
var SUMMARY_FIELDS = "number,title,labels,createdAt";
|
|
2650
|
-
var PICKUP_FIELDS = `${SUMMARY_FIELDS},blockedBy,body`;
|
|
3691
|
+
var PICKUP_FIELDS = `${SUMMARY_FIELDS},blockedBy,body,${gh_author_association.AUTHOR_FIELDS}`;
|
|
2651
3692
|
var { issue_list: issue_list2 } = git_gh_issue_list;
|
|
2652
3693
|
async function issue_list_recent(limit) {
|
|
2653
|
-
return await issue_list2({ json_fields: SUMMARY_FIELDS, limit });
|
|
3694
|
+
return await issue_list2({ json_fields: `${SUMMARY_FIELDS},body`, limit });
|
|
2654
3695
|
}
|
|
2655
3696
|
async function issue_list_open_bodies(limit) {
|
|
2656
3697
|
return await issue_list2({ json_fields: BACKLOG_SCAN_FIELDS, limit });
|
|
@@ -2702,18 +3743,18 @@ var git_gh_issue = {
|
|
|
2702
3743
|
|
|
2703
3744
|
// scripts/ci/pr-classification.ts
|
|
2704
3745
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
2705
|
-
import { z as
|
|
3746
|
+
import { z as z9 } from "zod";
|
|
2706
3747
|
var CLASSIFICATION_SET = new Set(RELEASE_CLASSIFICATION_NAMES);
|
|
2707
3748
|
var DECLARATION_PREFIX = "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: ";
|
|
2708
3749
|
var DECLARATION = new RegExp(`^${DECLARATION_PREFIX}(.+)$`, "gmu");
|
|
2709
3750
|
var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
|
|
2710
3751
|
var LABEL_NAMES_FILTER2 = ".[].name";
|
|
2711
|
-
var LABEL =
|
|
2712
|
-
var USER =
|
|
2713
|
-
var PULL_REQUEST =
|
|
2714
|
-
var EVENT =
|
|
3752
|
+
var LABEL = z9.object({ name: z9.string() });
|
|
3753
|
+
var USER = z9.object({ login: z9.string() });
|
|
3754
|
+
var PULL_REQUEST = z9.object({ number: z9.number(), user: USER });
|
|
3755
|
+
var EVENT = z9.object({
|
|
2715
3756
|
pull_request: PULL_REQUEST,
|
|
2716
|
-
repository:
|
|
3757
|
+
repository: z9.object({ full_name: z9.string() })
|
|
2717
3758
|
});
|
|
2718
3759
|
function classification_error(labels, author) {
|
|
2719
3760
|
const legacy = labels.filter((label) => LEGACY_LABELS.has(label.toLowerCase()));
|
|
@@ -2736,7 +3777,7 @@ function release_candidates(candidates) {
|
|
|
2736
3777
|
return candidates.filter((candidate) => candidate !== ENHANCEMENT_LABEL);
|
|
2737
3778
|
}
|
|
2738
3779
|
function issue_candidates(issue_json) {
|
|
2739
|
-
const issue =
|
|
3780
|
+
const issue = z9.object({ labels: z9.array(LABEL), body: z9.string().nullable() }).parse(JSON.parse(issue_json));
|
|
2740
3781
|
const names = issue.labels.map((label) => label.name.toLowerCase());
|
|
2741
3782
|
const declared = [...(issue.body ?? "").matchAll(DECLARATION)].map((match) => match[1] ?? "");
|
|
2742
3783
|
const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
|
|
@@ -2759,10 +3800,10 @@ function select_issue_classification(issue_json) {
|
|
|
2759
3800
|
return label;
|
|
2760
3801
|
}
|
|
2761
3802
|
function fetch_current_labels(repository, pull_number) {
|
|
2762
|
-
const
|
|
3803
|
+
const path19 = git_gh_api_path.issue_labels_api_path(String(pull_number), repository);
|
|
2763
3804
|
try {
|
|
2764
3805
|
const names = git_gh_exec.exec_gh_api_sync({
|
|
2765
|
-
path:
|
|
3806
|
+
path: path19,
|
|
2766
3807
|
should_paginate: true,
|
|
2767
3808
|
jq_filter: LABEL_NAMES_FILTER2
|
|
2768
3809
|
});
|
|
@@ -2795,25 +3836,35 @@ async function sleep2(duration_ms) {
|
|
|
2795
3836
|
async function wait_between(wait, interval_ms, attempt, attempts) {
|
|
2796
3837
|
if (attempt < attempts - 1) await wait(interval_ms);
|
|
2797
3838
|
}
|
|
2798
|
-
async function
|
|
3839
|
+
async function poll_for(read4, options) {
|
|
2799
3840
|
const wait = options.sleeper ?? sleep2;
|
|
2800
3841
|
for (let attempt = 0; attempt < options.attempts; attempt += 1) {
|
|
2801
|
-
|
|
3842
|
+
const value = await read4();
|
|
3843
|
+
if (value !== void 0) return value;
|
|
2802
3844
|
await wait_between(wait, options.interval_ms, attempt, options.attempts);
|
|
2803
3845
|
}
|
|
2804
|
-
return
|
|
3846
|
+
return void 0;
|
|
3847
|
+
}
|
|
3848
|
+
async function poll_until(is_done, options) {
|
|
3849
|
+
const is_reached = await poll_for(async () => await is_done() ? true : void 0, options);
|
|
3850
|
+
return is_reached === true;
|
|
3851
|
+
}
|
|
3852
|
+
async function wait_for(read4, options) {
|
|
3853
|
+
const value = await poll_for(read4, { ...options, attempts: Infinity });
|
|
3854
|
+
if (value === void 0) throw new Error("an unbounded poll ran out of attempts");
|
|
3855
|
+
return value;
|
|
2805
3856
|
}
|
|
2806
|
-
var poll = { poll_until, sleep: sleep2 };
|
|
3857
|
+
var poll = { poll_for, poll_until, sleep: sleep2, wait_for };
|
|
2807
3858
|
|
|
2808
3859
|
// scripts/gh/git-gh-branch-rules.ts
|
|
2809
|
-
import { z as
|
|
3860
|
+
import { z as z10 } from "zod";
|
|
2810
3861
|
var REQUIRED_STATUS_CHECKS_RULE = "required_status_checks";
|
|
2811
|
-
var required_check_schema =
|
|
2812
|
-
var rule_parameters_schema =
|
|
2813
|
-
required_status_checks:
|
|
3862
|
+
var required_check_schema = z10.looseObject({ context: z10.string() });
|
|
3863
|
+
var rule_parameters_schema = z10.looseObject({
|
|
3864
|
+
required_status_checks: z10.array(required_check_schema).optional()
|
|
2814
3865
|
});
|
|
2815
|
-
var branch_rule_schema =
|
|
2816
|
-
type:
|
|
3866
|
+
var branch_rule_schema = z10.looseObject({
|
|
3867
|
+
type: z10.string(),
|
|
2817
3868
|
parameters: rule_parameters_schema.nullish()
|
|
2818
3869
|
});
|
|
2819
3870
|
var required_contexts_by_branch = /* @__PURE__ */ new Map();
|
|
@@ -2844,33 +3895,33 @@ async function read_required_contexts(branch_name) {
|
|
|
2844
3895
|
var git_gh_branch_rules = { read_required_contexts };
|
|
2845
3896
|
|
|
2846
3897
|
// scripts/gh/git-gh-poll-read.ts
|
|
2847
|
-
import { z as
|
|
3898
|
+
import { z as z11 } from "zod";
|
|
2848
3899
|
var UNREADABLE_POLL_MESSAGE = "gh api could not read a merge-gate poll";
|
|
2849
3900
|
var PAGE_SIZE = 100;
|
|
2850
3901
|
var kept_by_path = /* @__PURE__ */ new Map();
|
|
2851
|
-
var page_schema =
|
|
2852
|
-
function unreadable(
|
|
3902
|
+
var page_schema = z11.object({ total_count: z11.number() });
|
|
3903
|
+
function unreadable(path19, answer) {
|
|
2853
3904
|
const cause = answer.kind === "unreadable" ? answer.cause : void 0;
|
|
2854
3905
|
const reason = cause === void 0 ? "" : `: ${error_text.message_of(cause)}`;
|
|
2855
|
-
return new Error(`${UNREADABLE_POLL_MESSAGE}: ${
|
|
3906
|
+
return new Error(`${UNREADABLE_POLL_MESSAGE}: ${path19}${reason}`, { cause });
|
|
2856
3907
|
}
|
|
2857
|
-
function to_body(
|
|
2858
|
-
const previous = kept_by_path.get(
|
|
3908
|
+
function to_body(path19, answer) {
|
|
3909
|
+
const previous = kept_by_path.get(path19);
|
|
2859
3910
|
if (previous !== void 0 && answer.kind === "unchanged") return previous.body;
|
|
2860
|
-
if (answer.kind !== "changed") throw unreadable(
|
|
2861
|
-
if (answer.etag !== void 0) kept_by_path.set(
|
|
3911
|
+
if (answer.kind !== "changed") throw unreadable(path19, answer);
|
|
3912
|
+
if (answer.etag !== void 0) kept_by_path.set(path19, { etag: answer.etag, body: answer.body });
|
|
2862
3913
|
return answer.body;
|
|
2863
3914
|
}
|
|
2864
|
-
async function read(
|
|
2865
|
-
const answer = await git_gh_conditional.read_conditional(
|
|
2866
|
-
return to_body(
|
|
3915
|
+
async function read(path19) {
|
|
3916
|
+
const answer = await git_gh_conditional.read_conditional(path19, kept_by_path.get(path19)?.etag);
|
|
3917
|
+
return to_body(path19, answer);
|
|
2867
3918
|
}
|
|
2868
3919
|
function is_whole_listing(page) {
|
|
2869
3920
|
const total = json_value.parse_with(page, page_schema)?.total_count;
|
|
2870
3921
|
return total !== void 0 && total <= PAGE_SIZE;
|
|
2871
3922
|
}
|
|
2872
|
-
async function read_object_pages(
|
|
2873
|
-
const full_path = `${
|
|
3923
|
+
async function read_object_pages(path19) {
|
|
3924
|
+
const full_path = `${path19}${FULL_PAGE_QUERY}`;
|
|
2874
3925
|
const page = await read(full_path);
|
|
2875
3926
|
if (is_whole_listing(page)) return `[${page}]`;
|
|
2876
3927
|
return await git_gh_exec.exec_gh_api({
|
|
@@ -2884,15 +3935,45 @@ function forget_poll_reads() {
|
|
|
2884
3935
|
}
|
|
2885
3936
|
var git_gh_poll_read = { UNREADABLE_POLL_MESSAGE, forget_poll_reads, read, read_object_pages };
|
|
2886
3937
|
|
|
3938
|
+
// scripts/gh/git-gh-pr-graphql-state.ts
|
|
3939
|
+
import { z as z12 } from "zod";
|
|
3940
|
+
var GRAPHQL_PATH = "graphql";
|
|
3941
|
+
var MERGE_STATE_QUERY = "query($id: ID!) { node(id: $id) { ... on PullRequest { mergeStateStatus } } }";
|
|
3942
|
+
var NO_MERGE_STATE_MESSAGE = "The merge state cannot be judged: GitHub refuses this pull request as too many files changed, and GraphQL did not answer its mergeStateStatus";
|
|
3943
|
+
var merge_state_node_schema = z12.looseObject({ mergeStateStatus: z12.string() });
|
|
3944
|
+
var merge_state_data_schema = z12.looseObject({ node: merge_state_node_schema });
|
|
3945
|
+
var merge_state_response_schema = z12.looseObject({ data: merge_state_data_schema });
|
|
3946
|
+
async function query_merge_state(node_id) {
|
|
3947
|
+
const json = await git_gh_exec.exec_gh_api({
|
|
3948
|
+
path: GRAPHQL_PATH,
|
|
3949
|
+
body: JSON.stringify({ query: MERGE_STATE_QUERY, variables: { id: node_id } })
|
|
3950
|
+
});
|
|
3951
|
+
return parse_json_object_or_undefined(json, merge_state_response_schema)?.data.node.mergeStateStatus;
|
|
3952
|
+
}
|
|
3953
|
+
async function try_query_merge_state(node_id) {
|
|
3954
|
+
if (node_id === void 0) return void 0;
|
|
3955
|
+
try {
|
|
3956
|
+
return await query_merge_state(node_id);
|
|
3957
|
+
} catch {
|
|
3958
|
+
return void 0;
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
async function read_merge_state_status(listed, detail_error) {
|
|
3962
|
+
const state = await try_query_merge_state(listed.node_id);
|
|
3963
|
+
if (state === void 0) throw new Error(NO_MERGE_STATE_MESSAGE, { cause: detail_error });
|
|
3964
|
+
return state;
|
|
3965
|
+
}
|
|
3966
|
+
var git_gh_pr_graphql_state = { read_merge_state_status };
|
|
3967
|
+
|
|
2887
3968
|
// scripts/gh/git-gh-pr-review.ts
|
|
2888
|
-
import { z as
|
|
3969
|
+
import { z as z13 } from "zod";
|
|
2889
3970
|
var REVIEW_APPROVED = "APPROVED";
|
|
2890
3971
|
var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
|
|
2891
3972
|
var REVIEW_NONE = "";
|
|
2892
3973
|
var STATE_CHANGING_REVIEWS = /* @__PURE__ */ new Set([REVIEW_APPROVED, REVIEW_CHANGES_REQUESTED]);
|
|
2893
|
-
var rest_review_schema =
|
|
2894
|
-
state:
|
|
2895
|
-
user:
|
|
3974
|
+
var rest_review_schema = z13.looseObject({
|
|
3975
|
+
state: z13.string().optional(),
|
|
3976
|
+
user: z13.looseObject({ login: z13.string().optional() }).nullish()
|
|
2896
3977
|
});
|
|
2897
3978
|
var NOT_A_REVIEW_LISTING = "gh api answered something other than a review listing";
|
|
2898
3979
|
function parse_rest_reviews(reviews_json) {
|
|
@@ -2925,18 +4006,18 @@ function to_review_decision(reviews_json) {
|
|
|
2925
4006
|
var git_gh_pr_review = { to_review_decision };
|
|
2926
4007
|
|
|
2927
4008
|
// scripts/gh/git-gh-pr-rollup.ts
|
|
2928
|
-
import { z as
|
|
4009
|
+
import { z as z14 } from "zod";
|
|
2929
4010
|
var STATUS_CONTEXT_TYPE_NAME = "StatusContext";
|
|
2930
4011
|
var TYPE_NAME_KEY = "__typename";
|
|
2931
|
-
var rollup_element_schema =
|
|
2932
|
-
var check_runs_page_schema =
|
|
4012
|
+
var rollup_element_schema = z14.looseObject({});
|
|
4013
|
+
var check_runs_page_schema = z14.looseObject({
|
|
2933
4014
|
// Required, not optional: GitHub always names the key, and accepting a page without one would
|
|
2934
4015
|
// answer an empty rollup — which `git-pr-followup.ts` reports as "this branch has no checks".
|
|
2935
|
-
check_runs:
|
|
4016
|
+
check_runs: z14.array(rollup_element_schema)
|
|
2936
4017
|
});
|
|
2937
|
-
var id_holder_schema =
|
|
2938
|
-
var status_page_schema =
|
|
2939
|
-
statuses:
|
|
4018
|
+
var id_holder_schema = z14.object({ id: z14.number() });
|
|
4019
|
+
var status_page_schema = z14.looseObject({
|
|
4020
|
+
statuses: z14.array(rollup_element_schema)
|
|
2940
4021
|
});
|
|
2941
4022
|
var NOT_A_CHECK_RUNS_LISTING = "gh api answered something other than a check run listing";
|
|
2942
4023
|
var NOT_A_STATUS_LISTING = "gh api answered something other than a commit status listing";
|
|
@@ -3002,9 +4083,9 @@ var git_gh_pr_rollup = {
|
|
|
3002
4083
|
|
|
3003
4084
|
// scripts/gh/git-gh-pr-snapshot.ts
|
|
3004
4085
|
var NO_HEAD_SHA_MESSAGE = "gh api answered a pull request with no head commit";
|
|
3005
|
-
async function read_array_pages(
|
|
4086
|
+
async function read_array_pages(path19) {
|
|
3006
4087
|
return await git_gh_exec.exec_gh_api({
|
|
3007
|
-
path: `${
|
|
4088
|
+
path: `${path19}${FULL_PAGE_QUERY}`,
|
|
3008
4089
|
should_paginate: true
|
|
3009
4090
|
});
|
|
3010
4091
|
}
|
|
@@ -3021,8 +4102,8 @@ async function read_status_check_rollup(commit_sha) {
|
|
|
3021
4102
|
return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json });
|
|
3022
4103
|
}
|
|
3023
4104
|
async function pr_get_review_decision(pr_number) {
|
|
3024
|
-
const
|
|
3025
|
-
return git_gh_pr_review.to_review_decision(await read_array_pages(
|
|
4105
|
+
const path19 = git_gh_api_path.pull_reviews_api_path(String(pr_number));
|
|
4106
|
+
return git_gh_pr_review.to_review_decision(await read_array_pages(path19));
|
|
3026
4107
|
}
|
|
3027
4108
|
async function build_checks_fields(pull) {
|
|
3028
4109
|
const head_sha = read_head_sha(pull);
|
|
@@ -3037,12 +4118,19 @@ async function build_checks_fields(pull) {
|
|
|
3037
4118
|
requiredContexts: required_contexts
|
|
3038
4119
|
};
|
|
3039
4120
|
}
|
|
4121
|
+
async function read_detail_or_listed(branch_name, pr_number) {
|
|
4122
|
+
try {
|
|
4123
|
+
return await read_pull(pr_number);
|
|
4124
|
+
} catch (error) {
|
|
4125
|
+
const listed = await read_listed_pull(error, branch_name, pr_number);
|
|
4126
|
+
if (listed === void 0) throw error;
|
|
4127
|
+
const state = await git_gh_pr_graphql_state.read_merge_state_status(listed, error);
|
|
4128
|
+
return { ...listed, mergeable_state: state };
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
3040
4131
|
async function resolve_pull(branch_name) {
|
|
3041
4132
|
const pr_number = await require_pr_number(branch_name);
|
|
3042
|
-
|
|
3043
|
-
path: git_gh_api_path.pull_api_path(String(pr_number))
|
|
3044
|
-
});
|
|
3045
|
-
return { pr_number, pull: git_gh_pr_rest.parse_rest_pull(json) };
|
|
4133
|
+
return { pr_number, pull: await read_detail_or_listed(branch_name, pr_number) };
|
|
3046
4134
|
}
|
|
3047
4135
|
async function pr_get_checks_snapshot(branch_name) {
|
|
3048
4136
|
const { pr_number, pull } = await resolve_pull(branch_name);
|
|
@@ -3141,9 +4229,9 @@ async function put_merge(pr_number, head_sha) {
|
|
|
3141
4229
|
function is_head_moved(error) {
|
|
3142
4230
|
return gh_failure.failure_of(error)?.status === HEAD_MOVED_STATUS;
|
|
3143
4231
|
}
|
|
3144
|
-
async function read_merge_state(pr_number) {
|
|
4232
|
+
async function read_merge_state(branch_name, pr_number) {
|
|
3145
4233
|
try {
|
|
3146
|
-
return git_gh_pr_rest.is_merged(await
|
|
4234
|
+
return git_gh_pr_rest.is_merged(await read_pull_or_listed(branch_name, pr_number, read_pull));
|
|
3147
4235
|
} catch (error) {
|
|
3148
4236
|
console.warn(`Could not read the pull request back: ${String(error)}`);
|
|
3149
4237
|
return void 0;
|
|
@@ -3152,9 +4240,9 @@ async function read_merge_state(pr_number) {
|
|
|
3152
4240
|
async function sleep_between_read_backs(attempt) {
|
|
3153
4241
|
if (attempt < MERGE_READ_BACK_ATTEMPTS - 1) await poll.sleep(MERGE_READ_BACK_INTERVAL_MS);
|
|
3154
4242
|
}
|
|
3155
|
-
async function has_merge_landed(pr_number, merge_error) {
|
|
4243
|
+
async function has_merge_landed(branch_name, pr_number, merge_error) {
|
|
3156
4244
|
for (let attempt = 0; attempt < MERGE_READ_BACK_ATTEMPTS; attempt += 1) {
|
|
3157
|
-
const is_merged = await read_merge_state(pr_number);
|
|
4245
|
+
const is_merged = await read_merge_state(branch_name, pr_number);
|
|
3158
4246
|
if (is_merged !== void 0) return is_merged;
|
|
3159
4247
|
await sleep_between_read_backs(attempt);
|
|
3160
4248
|
}
|
|
@@ -3165,7 +4253,7 @@ async function pr_merge(branch_name, head_sha) {
|
|
|
3165
4253
|
try {
|
|
3166
4254
|
await put_merge(pr_number, head_sha);
|
|
3167
4255
|
} catch (error) {
|
|
3168
|
-
if (!await has_merge_landed(pr_number, error)) throw error;
|
|
4256
|
+
if (!await has_merge_landed(branch_name, pr_number, error)) throw error;
|
|
3169
4257
|
}
|
|
3170
4258
|
}
|
|
3171
4259
|
var git_gh_pr = {
|
|
@@ -3181,12 +4269,14 @@ var git_gh_pr = {
|
|
|
3181
4269
|
};
|
|
3182
4270
|
|
|
3183
4271
|
// scripts/gh/git-gh-pr-auto-merge.ts
|
|
3184
|
-
var GRAPHQL_PATH = "graphql";
|
|
3185
4272
|
var OPEN_PULLS_QUERY = `${git_gh_api_path.FULL_PAGE_QUERY}&state=open`;
|
|
3186
4273
|
var MISSING_NODE_ID_MESSAGE = "gh api answered a pull request without a node_id";
|
|
3187
4274
|
var ENABLE_AUTO_MERGE_MUTATION = "mutation($id: ID!, $head: GitObjectID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE, expectedHeadOid: $head }) { clientMutationId } }";
|
|
4275
|
+
async function read_branch_pull(branch_name) {
|
|
4276
|
+
return await read_pull_or_listed(branch_name, await require_pr_number(branch_name), read_pull);
|
|
4277
|
+
}
|
|
3188
4278
|
async function pr_enable_auto_merge(branch_name, head_sha) {
|
|
3189
|
-
const pull = await
|
|
4279
|
+
const pull = await read_branch_pull(branch_name);
|
|
3190
4280
|
if (pull.node_id === void 0) throw new Error(MISSING_NODE_ID_MESSAGE);
|
|
3191
4281
|
await git_gh_exec.exec_gh_api({
|
|
3192
4282
|
path: GRAPHQL_PATH,
|
|
@@ -3198,7 +4288,7 @@ async function pr_enable_auto_merge(branch_name, head_sha) {
|
|
|
3198
4288
|
}
|
|
3199
4289
|
async function pr_is_merged(branch_name) {
|
|
3200
4290
|
try {
|
|
3201
|
-
return git_gh_pr_rest.is_merged(await
|
|
4291
|
+
return git_gh_pr_rest.is_merged(await read_branch_pull(branch_name));
|
|
3202
4292
|
} catch (error) {
|
|
3203
4293
|
error_text.trace_swallowed("git_gh_pr_auto_merge.pr_is_merged", error);
|
|
3204
4294
|
return false;
|
|
@@ -3304,16 +4394,16 @@ function to_exhaustion_error(last_read_failure) {
|
|
|
3304
4394
|
}
|
|
3305
4395
|
async function attempt_pr_success_poll(input) {
|
|
3306
4396
|
const evaluator = input.options.evaluator ?? MERGE_GATE_EVALUATOR;
|
|
3307
|
-
const
|
|
3308
|
-
if (
|
|
4397
|
+
const read4 = await read_pr_state(input, evaluator);
|
|
4398
|
+
if (read4.kind === "unreadable") return await retry_after_unreadable(input, read4.cause);
|
|
3309
4399
|
const classification = classify_poll_result({
|
|
3310
|
-
snapshot:
|
|
4400
|
+
snapshot: read4.snapshot,
|
|
3311
4401
|
stable_count: input.stable_count,
|
|
3312
4402
|
required_stable_reads: input.options.required_stable_reads,
|
|
3313
4403
|
evaluator
|
|
3314
4404
|
});
|
|
3315
4405
|
if (classification.is_done) {
|
|
3316
|
-
return { snapshot:
|
|
4406
|
+
return { snapshot: read4.snapshot, next_stable_count: 0, next_failure_count: 0 };
|
|
3317
4407
|
}
|
|
3318
4408
|
await sleep_before_next_attempt(input);
|
|
3319
4409
|
return { next_stable_count: classification.next_stable_count, next_failure_count: 0 };
|
|
@@ -3437,7 +4527,7 @@ function get_repo_name_with_owner_within(timeout_ms) {
|
|
|
3437
4527
|
var gh_spawn = { get_repo_name_with_owner, get_repo_name_with_owner_within };
|
|
3438
4528
|
|
|
3439
4529
|
// scripts/issue/issue-state.ts
|
|
3440
|
-
import { z as
|
|
4530
|
+
import { z as z15 } from "zod";
|
|
3441
4531
|
var NO_LABELS = "(none)";
|
|
3442
4532
|
var LABEL_SEPARATOR = ", ";
|
|
3443
4533
|
var STATE_LABEL = "state: ";
|
|
@@ -3447,9 +4537,9 @@ var YES = "yes";
|
|
|
3447
4537
|
var NO = "no";
|
|
3448
4538
|
var ISSUE_LABEL = "issue: ";
|
|
3449
4539
|
var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
|
|
3450
|
-
var label_schema =
|
|
3451
|
-
var issue_state_schema =
|
|
3452
|
-
state:
|
|
4540
|
+
var label_schema = z15.looseObject({ name: z15.string() });
|
|
4541
|
+
var issue_state_schema = z15.looseObject({
|
|
4542
|
+
state: z15.string(),
|
|
3453
4543
|
labels: label_schema.array().optional()
|
|
3454
4544
|
});
|
|
3455
4545
|
function parse_issue_state(json) {
|
|
@@ -3479,7 +4569,11 @@ function format_attributed_issue_state(issue_number, state) {
|
|
|
3479
4569
|
return `${ISSUE_LABEL}${issue_number}
|
|
3480
4570
|
${format_issue_state(state)}`;
|
|
3481
4571
|
}
|
|
4572
|
+
function is_planned(read4) {
|
|
4573
|
+
return read4.kind === "state" && has_label_name(read4.state.labels, PLANNED_LABEL);
|
|
4574
|
+
}
|
|
3482
4575
|
var issue_state = {
|
|
4576
|
+
is_planned,
|
|
3483
4577
|
NO_LABELS,
|
|
3484
4578
|
parse_issue_state,
|
|
3485
4579
|
format_issue_state,
|
|
@@ -3487,32 +4581,32 @@ var issue_state = {
|
|
|
3487
4581
|
};
|
|
3488
4582
|
|
|
3489
4583
|
// scripts/run/run-liveness.ts
|
|
3490
|
-
import { readFileSync as readFileSync4, realpathSync, statSync } from "node:fs";
|
|
4584
|
+
import { readFileSync as readFileSync4, realpathSync, statSync as statSync2 } from "node:fs";
|
|
3491
4585
|
import { homedir, tmpdir } from "node:os";
|
|
3492
|
-
import
|
|
4586
|
+
import path7 from "node:path";
|
|
3493
4587
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
3494
4588
|
|
|
3495
4589
|
// scripts/agent/agent-event.ts
|
|
3496
|
-
import { z as
|
|
4590
|
+
import { z as z18 } from "zod";
|
|
3497
4591
|
|
|
3498
4592
|
// scripts/agent/claude-result-event.ts
|
|
3499
|
-
import { z as
|
|
4593
|
+
import { z as z17 } from "zod";
|
|
3500
4594
|
|
|
3501
4595
|
// scripts/agent/interactive-ask.ts
|
|
3502
|
-
import { z as
|
|
4596
|
+
import { z as z16 } from "zod";
|
|
3503
4597
|
var INTERACTIVE_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion"]);
|
|
3504
4598
|
function is_interactive_tool(name) {
|
|
3505
4599
|
return INTERACTIVE_TOOLS.has(name);
|
|
3506
4600
|
}
|
|
3507
|
-
var OPTION_SCHEMA =
|
|
3508
|
-
var QUESTION_SCHEMA =
|
|
3509
|
-
question:
|
|
3510
|
-
options:
|
|
4601
|
+
var OPTION_SCHEMA = z16.looseObject({ label: z16.string().optional() });
|
|
4602
|
+
var QUESTION_SCHEMA = z16.looseObject({
|
|
4603
|
+
question: z16.string().optional(),
|
|
4604
|
+
options: z16.array(OPTION_SCHEMA).optional()
|
|
3511
4605
|
});
|
|
3512
|
-
var ASK_INPUT_SCHEMA =
|
|
3513
|
-
var DENIAL_SCHEMA =
|
|
3514
|
-
tool_name:
|
|
3515
|
-
tool_input:
|
|
4606
|
+
var ASK_INPUT_SCHEMA = z16.looseObject({ questions: z16.array(QUESTION_SCHEMA).optional() });
|
|
4607
|
+
var DENIAL_SCHEMA = z16.looseObject({
|
|
4608
|
+
tool_name: z16.string().optional(),
|
|
4609
|
+
tool_input: z16.unknown().optional()
|
|
3516
4610
|
});
|
|
3517
4611
|
var UNKNOWN_QUESTION = "(question text unavailable)";
|
|
3518
4612
|
var OPTION_SEPARATOR = " / ";
|
|
@@ -3541,20 +4635,20 @@ function refused_ask_of(permission_denials) {
|
|
|
3541
4635
|
var interactive_ask = { is_interactive_tool, refused_ask_of };
|
|
3542
4636
|
|
|
3543
4637
|
// scripts/agent/claude-result-event.ts
|
|
3544
|
-
var RESULT_EVENT_SCHEMA =
|
|
3545
|
-
type:
|
|
3546
|
-
is_error:
|
|
3547
|
-
subtype:
|
|
3548
|
-
num_turns:
|
|
3549
|
-
permission_denials:
|
|
3550
|
-
result:
|
|
3551
|
-
session_id:
|
|
3552
|
-
usage:
|
|
4638
|
+
var RESULT_EVENT_SCHEMA = z17.looseObject({
|
|
4639
|
+
type: z17.literal("result"),
|
|
4640
|
+
is_error: z17.unknown().optional(),
|
|
4641
|
+
subtype: z17.unknown().optional(),
|
|
4642
|
+
num_turns: z17.unknown().optional(),
|
|
4643
|
+
permission_denials: z17.unknown().optional(),
|
|
4644
|
+
result: z17.unknown().optional(),
|
|
4645
|
+
session_id: z17.unknown().optional(),
|
|
4646
|
+
usage: z17.unknown().optional()
|
|
3553
4647
|
});
|
|
3554
|
-
var USAGE_SCHEMA =
|
|
3555
|
-
input_tokens:
|
|
3556
|
-
cache_read_input_tokens:
|
|
3557
|
-
output_tokens:
|
|
4648
|
+
var USAGE_SCHEMA = z17.looseObject({
|
|
4649
|
+
input_tokens: z17.unknown().optional(),
|
|
4650
|
+
cache_read_input_tokens: z17.unknown().optional(),
|
|
4651
|
+
output_tokens: z17.unknown().optional()
|
|
3558
4652
|
});
|
|
3559
4653
|
function usable_reason(value) {
|
|
3560
4654
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
@@ -3594,25 +4688,25 @@ var claude_result_event = { decode };
|
|
|
3594
4688
|
|
|
3595
4689
|
// scripts/agent/agent-event.ts
|
|
3596
4690
|
var ASSISTANT_TYPE = "assistant";
|
|
3597
|
-
var CLAUDE_INIT_SCHEMA =
|
|
3598
|
-
var USAGE_SCHEMA2 =
|
|
3599
|
-
input_tokens:
|
|
3600
|
-
cached_input_tokens:
|
|
3601
|
-
output_tokens:
|
|
4691
|
+
var CLAUDE_INIT_SCHEMA = z18.looseObject({ type: z18.literal("system"), subtype: z18.literal("init") });
|
|
4692
|
+
var USAGE_SCHEMA2 = z18.looseObject({
|
|
4693
|
+
input_tokens: z18.number().optional(),
|
|
4694
|
+
cached_input_tokens: z18.number().optional(),
|
|
4695
|
+
output_tokens: z18.number().optional()
|
|
3602
4696
|
});
|
|
3603
|
-
var CODEX_START_SCHEMA =
|
|
3604
|
-
var CODEX_PROGRESS_SCHEMA =
|
|
3605
|
-
type:
|
|
3606
|
-
item:
|
|
4697
|
+
var CODEX_START_SCHEMA = z18.looseObject({ type: z18.enum(["thread.started", "turn.started"]) });
|
|
4698
|
+
var CODEX_PROGRESS_SCHEMA = z18.looseObject({
|
|
4699
|
+
type: z18.enum(["item.started", "item.updated", "item.completed"]),
|
|
4700
|
+
item: z18.looseObject({ type: z18.string(), text: z18.string().optional() }).optional()
|
|
3607
4701
|
});
|
|
3608
|
-
var CODEX_COMPLETE_SCHEMA =
|
|
3609
|
-
type:
|
|
4702
|
+
var CODEX_COMPLETE_SCHEMA = z18.looseObject({
|
|
4703
|
+
type: z18.literal("turn.completed"),
|
|
3610
4704
|
usage: USAGE_SCHEMA2.optional()
|
|
3611
4705
|
});
|
|
3612
|
-
var CODEX_FAILURE_SCHEMA =
|
|
3613
|
-
type:
|
|
3614
|
-
error:
|
|
3615
|
-
message:
|
|
4706
|
+
var CODEX_FAILURE_SCHEMA = z18.looseObject({
|
|
4707
|
+
type: z18.enum(["turn.failed", "error"]),
|
|
4708
|
+
error: z18.looseObject({ message: z18.string().optional() }).optional(),
|
|
4709
|
+
message: z18.string().optional()
|
|
3616
4710
|
});
|
|
3617
4711
|
var EMPTY_STATE = {
|
|
3618
4712
|
provider: void 0,
|
|
@@ -3627,11 +4721,11 @@ var LAUNCH_HEADER_MARKER = " \xB7 started by process ";
|
|
|
3627
4721
|
function usable_text(value) {
|
|
3628
4722
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
3629
4723
|
}
|
|
3630
|
-
function claude_progress(
|
|
3631
|
-
return transcript_record.blocks_of(
|
|
4724
|
+
function claude_progress(record3) {
|
|
4725
|
+
return transcript_record.blocks_of(record3).filter((block) => block.type === transcript_record.TEXT_TYPE).map((block) => usable_text(block.text)).findLast((text2) => text2 !== void 0);
|
|
3632
4726
|
}
|
|
3633
|
-
function is_claude_assistant(
|
|
3634
|
-
return
|
|
4727
|
+
function is_claude_assistant(record3) {
|
|
4728
|
+
return record3?.type === ASSISTANT_TYPE && record3.message !== void 0 && record3.message !== null;
|
|
3635
4729
|
}
|
|
3636
4730
|
function claude_result(value, state) {
|
|
3637
4731
|
const result = claude_result_event.decode(value);
|
|
@@ -3645,9 +4739,9 @@ function claude_result(value, state) {
|
|
|
3645
4739
|
};
|
|
3646
4740
|
}
|
|
3647
4741
|
function claude_assistant(value, state) {
|
|
3648
|
-
const
|
|
3649
|
-
if (!is_claude_assistant(
|
|
3650
|
-
const progress = claude_progress(
|
|
4742
|
+
const record3 = transcript_record.read(value);
|
|
4743
|
+
if (!is_claude_assistant(record3)) return void 0;
|
|
4744
|
+
const progress = claude_progress(record3) ?? state.progress;
|
|
3651
4745
|
return { ...state, provider: "anthropic", progress };
|
|
3652
4746
|
}
|
|
3653
4747
|
function claude_terminal(value, state) {
|
|
@@ -3774,7 +4868,7 @@ function to_advice(verdict, has_work_to_stash) {
|
|
|
3774
4868
|
if (verdict !== STOPPED_VERDICT) return ADVICE[verdict];
|
|
3775
4869
|
return has_work_to_stash ? STOPPED_DIRTY_ADVICE : STOPPED_CLEAN_ADVICE;
|
|
3776
4870
|
}
|
|
3777
|
-
function
|
|
4871
|
+
function decide3(traces) {
|
|
3778
4872
|
const verdict = to_verdict(traces);
|
|
3779
4873
|
const has_work_to_stash = verdict === STOPPED_VERDICT && traces.is_tree_dirty;
|
|
3780
4874
|
return {
|
|
@@ -3797,18 +4891,18 @@ var ALLOWED_ROOTS = [
|
|
|
3797
4891
|
)
|
|
3798
4892
|
];
|
|
3799
4893
|
function is_within(candidate, root) {
|
|
3800
|
-
const relative =
|
|
3801
|
-
return relative !== "" && !relative.startsWith("..") && !
|
|
4894
|
+
const relative = path7.relative(root, candidate);
|
|
4895
|
+
return relative !== "" && !relative.startsWith("..") && !path7.isAbsolute(relative);
|
|
3802
4896
|
}
|
|
3803
4897
|
function to_safe_path(output_path) {
|
|
3804
|
-
const normalized2 =
|
|
3805
|
-
if (!
|
|
4898
|
+
const normalized2 = path7.normalize(output_path);
|
|
4899
|
+
if (!path7.isAbsolute(normalized2)) return void 0;
|
|
3806
4900
|
return ALLOWED_ROOTS.some((root) => is_within(normalized2, root)) ? normalized2 : void 0;
|
|
3807
4901
|
}
|
|
3808
4902
|
function sample_output(output_path) {
|
|
3809
4903
|
const safe_path = to_safe_path(output_path);
|
|
3810
4904
|
if (safe_path === void 0) return void 0;
|
|
3811
|
-
const stats =
|
|
4905
|
+
const stats = statSync2(safe_path, { throwIfNoEntry: false });
|
|
3812
4906
|
if (!stats?.isFile()) return void 0;
|
|
3813
4907
|
return { mtime_ms: stats.mtimeMs, size: stats.size };
|
|
3814
4908
|
}
|
|
@@ -3854,7 +4948,7 @@ function freshness_of(request2) {
|
|
|
3854
4948
|
};
|
|
3855
4949
|
}
|
|
3856
4950
|
async function read_traces(request2) {
|
|
3857
|
-
const [is_initial_child_settled, is_output_frozen, is_tree_dirty,
|
|
4951
|
+
const [is_initial_child_settled, is_output_frozen, is_tree_dirty, record3] = await Promise.all([
|
|
3858
4952
|
read_child_settled(request2.issue, request2.repo),
|
|
3859
4953
|
read_output_frozen(freshness_of(request2)),
|
|
3860
4954
|
run_hold.is_tree_dirty(),
|
|
@@ -3868,17 +4962,17 @@ async function read_traces(request2) {
|
|
|
3868
4962
|
is_child_settled,
|
|
3869
4963
|
is_output_frozen,
|
|
3870
4964
|
is_tree_dirty,
|
|
3871
|
-
lane_state:
|
|
4965
|
+
lane_state: record3?.state,
|
|
3872
4966
|
process_trace: request2.process_trace
|
|
3873
4967
|
};
|
|
3874
4968
|
}
|
|
3875
4969
|
async function check(request2) {
|
|
3876
4970
|
issue_number_shape.require_issue_number(request2.issue);
|
|
3877
|
-
return
|
|
4971
|
+
return decide3(await read_traces(request2));
|
|
3878
4972
|
}
|
|
3879
4973
|
var run_liveness = {
|
|
3880
4974
|
check,
|
|
3881
|
-
decide:
|
|
4975
|
+
decide: decide3,
|
|
3882
4976
|
describe_agent_state,
|
|
3883
4977
|
read_child_settled,
|
|
3884
4978
|
read_output_frozen,
|
|
@@ -3886,6 +4980,199 @@ var run_liveness = {
|
|
|
3886
4980
|
to_safe_path
|
|
3887
4981
|
};
|
|
3888
4982
|
|
|
4983
|
+
// scripts/backlog/backlog-overlap.ts
|
|
4984
|
+
var CODE_SPAN = /`([^`\s]+)`/gu;
|
|
4985
|
+
var LINE_SUFFIX = /:\d+(?:[-:]\d+)?$/u;
|
|
4986
|
+
var FILE_EXTENSION = /\.[a-z]\w*$/iu;
|
|
4987
|
+
var ROOT_FILE_EXTENSION = /\.(?:[cm]?[jt]sx?|svelte|jsonc?|md|ya?ml|css|html|sh|toml|txt|properties)$/u;
|
|
4988
|
+
var GLOB = "*";
|
|
4989
|
+
var ISSUE_MARK = "#";
|
|
4990
|
+
var SEPARATOR = "/";
|
|
4991
|
+
var MIN_DIRECTORY_DEPTH = 2;
|
|
4992
|
+
var DOCS_DIRECTORY = "docs/";
|
|
4993
|
+
var MARKDOWN = ".md";
|
|
4994
|
+
function without_glob(path19) {
|
|
4995
|
+
const glob = path19.indexOf(GLOB);
|
|
4996
|
+
return glob === -1 ? path19 : path19.slice(0, path19.lastIndexOf(SEPARATOR, glob) + 1);
|
|
4997
|
+
}
|
|
4998
|
+
function is_narrow(directory) {
|
|
4999
|
+
return directory.split(SEPARATOR).filter(Boolean).length >= MIN_DIRECTORY_DEPTH;
|
|
5000
|
+
}
|
|
5001
|
+
function is_file(path19) {
|
|
5002
|
+
return (path19.includes(SEPARATOR) ? FILE_EXTENSION : ROOT_FILE_EXTENSION).test(path19);
|
|
5003
|
+
}
|
|
5004
|
+
function claim_of(path19) {
|
|
5005
|
+
if (path19.endsWith(SEPARATOR)) return is_narrow(path19) ? path19 : void 0;
|
|
5006
|
+
return is_file(path19) ? path19 : void 0;
|
|
5007
|
+
}
|
|
5008
|
+
function path_claims(tokens) {
|
|
5009
|
+
const paths = tokens.filter((token) => !token.includes(ISSUE_MARK)).map((token) => claim_of(without_glob(token.replace(LINE_SUFFIX, ""))));
|
|
5010
|
+
return new Set(paths.filter((path19) => path19 !== void 0));
|
|
5011
|
+
}
|
|
5012
|
+
function declared_paths(body) {
|
|
5013
|
+
return path_claims([...body.matchAll(CODE_SPAN)].map((match) => match[1] ?? ""));
|
|
5014
|
+
}
|
|
5015
|
+
function declared_of(issues) {
|
|
5016
|
+
return new Map(issues.map((issue) => [issue.number, declared_paths(issue.body ?? "")]));
|
|
5017
|
+
}
|
|
5018
|
+
function contains(outer, inner) {
|
|
5019
|
+
return outer.endsWith(SEPARATOR) ? inner.startsWith(outer) : outer === inner;
|
|
5020
|
+
}
|
|
5021
|
+
function is_shared_document(path19) {
|
|
5022
|
+
return path19.startsWith(DOCS_DIRECTORY) && (path19.endsWith(SEPARATOR) || path19.endsWith(MARKDOWN));
|
|
5023
|
+
}
|
|
5024
|
+
function overlaps(left, right) {
|
|
5025
|
+
if (is_shared_document(left) || is_shared_document(right)) return false;
|
|
5026
|
+
return contains(left, right) || contains(right, left);
|
|
5027
|
+
}
|
|
5028
|
+
function claims_of(declared, holders) {
|
|
5029
|
+
const pairs = holders.flatMap(
|
|
5030
|
+
(number) => [...declared.get(number) ?? []].map((path19) => [path19, number])
|
|
5031
|
+
);
|
|
5032
|
+
return new Map(pairs);
|
|
5033
|
+
}
|
|
5034
|
+
function running_claims(declared, read4) {
|
|
5035
|
+
return claims_of(declared, read4.kind === "busy" ? read4.issues.map((issue) => issue.number) : []);
|
|
5036
|
+
}
|
|
5037
|
+
function paths_of(child, declared, repo) {
|
|
5038
|
+
if (child.repo !== repo) return /* @__PURE__ */ new Set();
|
|
5039
|
+
return declared.get(child.number) ?? /* @__PURE__ */ new Set();
|
|
5040
|
+
}
|
|
5041
|
+
function clash_of(claims, paths) {
|
|
5042
|
+
const clashes = [...paths].flatMap(
|
|
5043
|
+
(path19) => [...claims].filter(([claimed]) => overlaps(claimed, path19)).map(([claimed, holder]) => ({ path: path19, claimed, holder }))
|
|
5044
|
+
);
|
|
5045
|
+
return clashes[0];
|
|
5046
|
+
}
|
|
5047
|
+
function path_clash(paths, declared, holders) {
|
|
5048
|
+
return clash_of(claims_of(declared, holders), paths);
|
|
5049
|
+
}
|
|
5050
|
+
function running_clash(child, declared, holding) {
|
|
5051
|
+
return path_clash(paths_of(child, declared, holding.repo), declared, holding.holders);
|
|
5052
|
+
}
|
|
5053
|
+
function holds(declared, holder, waiting) {
|
|
5054
|
+
return clash_of(claims_of(declared, [holder]), declared.get(waiting) ?? /* @__PURE__ */ new Set()) !== void 0;
|
|
5055
|
+
}
|
|
5056
|
+
function paused_tail(clash, lanes) {
|
|
5057
|
+
const note = lane_state.paused_note(lanes.get(String(clash.holder)));
|
|
5058
|
+
return note === void 0 ? "" : ` \u2014 ${note}`;
|
|
5059
|
+
}
|
|
5060
|
+
function clash_note(child, clash, lanes) {
|
|
5061
|
+
const waiting = session_cite.issue(child.number, void 0, child.repo);
|
|
5062
|
+
const holder = session_cite.issue(clash.holder, void 0, child.repo);
|
|
5063
|
+
return `${waiting} waits: its \`${clash.path}\` overlaps \`${clash.claimed}\`, which ${holder} declares${paused_tail(clash, lanes)}.`;
|
|
5064
|
+
}
|
|
5065
|
+
function visit(walk, child, paths) {
|
|
5066
|
+
const clash = clash_of(walk.claims, paths);
|
|
5067
|
+
if (clash === void 0) {
|
|
5068
|
+
walk.offered.push(child);
|
|
5069
|
+
for (const path19 of paths) walk.claims.set(path19, child.number);
|
|
5070
|
+
return;
|
|
5071
|
+
}
|
|
5072
|
+
walk.withheld.push(child);
|
|
5073
|
+
walk.notes.push(clash_note(child, clash, walk.lanes));
|
|
5074
|
+
}
|
|
5075
|
+
function merged_notice(notice, notes) {
|
|
5076
|
+
const parts = notice === void 0 ? notes : [notice, ...notes];
|
|
5077
|
+
return parts.length === 0 ? void 0 : parts.join("\n");
|
|
5078
|
+
}
|
|
5079
|
+
function separate(selection, declared, context) {
|
|
5080
|
+
const walk = {
|
|
5081
|
+
claims: running_claims(declared, context.read),
|
|
5082
|
+
lanes: context.lanes ?? /* @__PURE__ */ new Map(),
|
|
5083
|
+
offered: [],
|
|
5084
|
+
withheld: [],
|
|
5085
|
+
notes: []
|
|
5086
|
+
};
|
|
5087
|
+
for (const child of selection.offered) visit(walk, child, paths_of(child, declared, context.repo));
|
|
5088
|
+
const notice = merged_notice(selection.notice, walk.notes);
|
|
5089
|
+
const withheld = [...walk.withheld, ...selection.withheld];
|
|
5090
|
+
return { offered: walk.offered, withheld, ...notice !== void 0 && { notice } };
|
|
5091
|
+
}
|
|
5092
|
+
var backlog_overlap = {
|
|
5093
|
+
declared_of,
|
|
5094
|
+
declared_paths,
|
|
5095
|
+
holds,
|
|
5096
|
+
path_claims,
|
|
5097
|
+
path_clash,
|
|
5098
|
+
running_clash,
|
|
5099
|
+
separate
|
|
5100
|
+
};
|
|
5101
|
+
|
|
5102
|
+
// scripts/lane/lane-plan.ts
|
|
5103
|
+
import { z as z19 } from "zod";
|
|
5104
|
+
var lane_plan_schema = z19.object({
|
|
5105
|
+
issue: z19.number(),
|
|
5106
|
+
paths: z19.array(z19.string()),
|
|
5107
|
+
planned_at: z19.string(),
|
|
5108
|
+
cleared: z19.boolean().optional(),
|
|
5109
|
+
// The lane gave its lane back on this plan (`lane-yield.ts`), so the plan outlives the lane.
|
|
5110
|
+
yielded: z19.boolean().optional()
|
|
5111
|
+
});
|
|
5112
|
+
function plan_path(repository, issue) {
|
|
5113
|
+
return durable_state.path(durable_state.PREFIX.LANE_PLAN, repository, `-${String(issue)}.json`);
|
|
5114
|
+
}
|
|
5115
|
+
function record2(plan, directory) {
|
|
5116
|
+
const repository = git_common_directory.repository(directory);
|
|
5117
|
+
if (repository === void 0) return false;
|
|
5118
|
+
stamp_file.replace_stamp(plan_path(repository, plan.issue), plan);
|
|
5119
|
+
return true;
|
|
5120
|
+
}
|
|
5121
|
+
function remove(issue, directory) {
|
|
5122
|
+
const repository = git_common_directory.repository(directory);
|
|
5123
|
+
if (repository !== void 0) stamp_file.remove_stamp(plan_path(repository, issue));
|
|
5124
|
+
}
|
|
5125
|
+
function read3(issue, directory) {
|
|
5126
|
+
const repository = git_common_directory.repository(directory);
|
|
5127
|
+
const text2 = repository === void 0 ? void 0 : stamp_file.read_stamp_text(plan_path(repository, issue));
|
|
5128
|
+
return text2 === void 0 ? void 0 : json_value.parse_with(text2, lane_plan_schema);
|
|
5129
|
+
}
|
|
5130
|
+
function is_uncleared(issue, directory) {
|
|
5131
|
+
return git_common_directory.repository(directory) !== void 0 && read3(issue, directory)?.cleared !== true;
|
|
5132
|
+
}
|
|
5133
|
+
function release(issue, directory) {
|
|
5134
|
+
if (read3(issue, directory)?.yielded !== true) remove(issue, directory);
|
|
5135
|
+
}
|
|
5136
|
+
function with_plans(declared, directory) {
|
|
5137
|
+
const replaced = [...declared].map(([issue, paths]) => [
|
|
5138
|
+
issue,
|
|
5139
|
+
new Set(read3(issue, directory)?.paths ?? paths)
|
|
5140
|
+
]);
|
|
5141
|
+
return new Map(replaced);
|
|
5142
|
+
}
|
|
5143
|
+
function goes_before(other, plan) {
|
|
5144
|
+
return other.cleared === true || other.planned_at < plan.planned_at;
|
|
5145
|
+
}
|
|
5146
|
+
function earlier_holders(plan, holders, directory) {
|
|
5147
|
+
return holders.filter((holder) => {
|
|
5148
|
+
const other = holder === plan.issue ? void 0 : read3(holder, directory);
|
|
5149
|
+
return other !== void 0 && goes_before(other, plan);
|
|
5150
|
+
});
|
|
5151
|
+
}
|
|
5152
|
+
function clash_of2(plan, declared, directory) {
|
|
5153
|
+
const holders = earlier_holders(plan, [...declared.keys()], directory);
|
|
5154
|
+
return backlog_overlap.path_clash(new Set(plan.paths), declared, holders);
|
|
5155
|
+
}
|
|
5156
|
+
function is_yielded(issue, directory) {
|
|
5157
|
+
return read3(issue, directory)?.yielded === true;
|
|
5158
|
+
}
|
|
5159
|
+
function is_yield_held(issue, declared, directory) {
|
|
5160
|
+
const plan = read3(issue, directory);
|
|
5161
|
+
return plan?.yielded === true && clash_of2(plan, declared, directory) !== void 0;
|
|
5162
|
+
}
|
|
5163
|
+
var lane_plan = {
|
|
5164
|
+
clash_of: clash_of2,
|
|
5165
|
+
earlier_holders,
|
|
5166
|
+
is_uncleared,
|
|
5167
|
+
is_yield_held,
|
|
5168
|
+
is_yielded,
|
|
5169
|
+
read: read3,
|
|
5170
|
+
record: record2,
|
|
5171
|
+
release,
|
|
5172
|
+
remove,
|
|
5173
|
+
with_plans
|
|
5174
|
+
};
|
|
5175
|
+
|
|
3889
5176
|
// scripts/run/run-stage.ts
|
|
3890
5177
|
var KICKOFF = "kickoff";
|
|
3891
5178
|
var HALFRUN = "halfrun";
|
|
@@ -3928,7 +5215,7 @@ function state_of(facts) {
|
|
|
3928
5215
|
if (facts.is_halfrun_stopped) return HALFRUN_STOPPED;
|
|
3929
5216
|
return facts.is_planned ? PLANNED : FRESH;
|
|
3930
5217
|
}
|
|
3931
|
-
function
|
|
5218
|
+
function decide4(state, command) {
|
|
3932
5219
|
const is_reached = STATES.indexOf(state) > COMMANDS.indexOf(command);
|
|
3933
5220
|
const start = is_reached ? REACHED : STARTS[state];
|
|
3934
5221
|
return { state, command, start, end: ENDS[command], is_reached };
|
|
@@ -3945,7 +5232,7 @@ function format_decision(issue, decision) {
|
|
|
3945
5232
|
return `stage ${issue_cite.plain(issue)} \u2014 ${fields.join(" \xB7 ")}`;
|
|
3946
5233
|
}
|
|
3947
5234
|
function cell(state, command) {
|
|
3948
|
-
const decision =
|
|
5235
|
+
const decision = decide4(state, command);
|
|
3949
5236
|
return decision.is_reached ? REACHED_CELL : `${decision.start}${CELL_ARROW}${decision.end}`;
|
|
3950
5237
|
}
|
|
3951
5238
|
function table_rows() {
|
|
@@ -3970,7 +5257,7 @@ var run_stage = {
|
|
|
3970
5257
|
REACHED,
|
|
3971
5258
|
START_TOKENS,
|
|
3972
5259
|
STATES,
|
|
3973
|
-
decide:
|
|
5260
|
+
decide: decide4,
|
|
3974
5261
|
format_decision,
|
|
3975
5262
|
next_commands,
|
|
3976
5263
|
next_line,
|
|
@@ -3990,8 +5277,8 @@ function format_holder(issue, repo, ages) {
|
|
|
3990
5277
|
function format_holders(issues, repo, ages) {
|
|
3991
5278
|
return issues.map((issue) => format_holder(issue, repo, ages)).join(", ");
|
|
3992
5279
|
}
|
|
3993
|
-
function occupied_lanes(
|
|
3994
|
-
return
|
|
5280
|
+
function occupied_lanes(read4) {
|
|
5281
|
+
return read4.kind === "busy" ? read4.issues.length : 0;
|
|
3995
5282
|
}
|
|
3996
5283
|
function occupancy_message(issues, repo, limit, ages = NO_AGES) {
|
|
3997
5284
|
return `${String(issues.length)} of ${String(limit)} lanes in use in ${repo}: ${format_holders(issues, repo, ages)}.`;
|
|
@@ -4009,18 +5296,18 @@ var BUSY_REASONS = {
|
|
|
4009
5296
|
unreadable: unreadable_message2,
|
|
4010
5297
|
truncated: truncated_message
|
|
4011
5298
|
};
|
|
4012
|
-
function busy_reason(
|
|
4013
|
-
if (
|
|
4014
|
-
if (
|
|
4015
|
-
return BUSY_REASONS[
|
|
5299
|
+
function busy_reason(read4, repo, limit, ages = NO_AGES) {
|
|
5300
|
+
if (read4.kind === "busy") return lanes_full_message(read4.issues, repo, limit, ages);
|
|
5301
|
+
if (read4.kind === "idle") return "";
|
|
5302
|
+
return BUSY_REASONS[read4.kind](repo);
|
|
4016
5303
|
}
|
|
4017
5304
|
function is_parked(issue) {
|
|
4018
5305
|
return has_any_label(issue.labels, PARKED_LABELS);
|
|
4019
5306
|
}
|
|
4020
5307
|
function parse_listing(raw, is_capped) {
|
|
4021
|
-
const
|
|
4022
|
-
if (
|
|
4023
|
-
const holders =
|
|
5308
|
+
const read4 = read_json_listing(raw, open_issue_schema);
|
|
5309
|
+
if (read4.kind !== "read") return { kind: "unreadable" };
|
|
5310
|
+
const holders = read4.rows.filter((row) => !is_parked(row));
|
|
4024
5311
|
if (holders.length > 0) return { kind: "busy", issues: holders };
|
|
4025
5312
|
return { kind: is_capped ? "truncated" : "idle" };
|
|
4026
5313
|
}
|
|
@@ -4047,26 +5334,26 @@ var epic_busy = {
|
|
|
4047
5334
|
|
|
4048
5335
|
// scripts/doctor/doctor-consumer.ts
|
|
4049
5336
|
import { existsSync } from "node:fs";
|
|
4050
|
-
import
|
|
5337
|
+
import path8 from "node:path";
|
|
4051
5338
|
|
|
4052
5339
|
// scripts/version/kit-descriptor.ts
|
|
4053
5340
|
var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
|
|
4054
5341
|
|
|
4055
5342
|
// scripts/doctor/doctor-consumer.ts
|
|
4056
|
-
import { z as
|
|
5343
|
+
import { z as z20 } from "zod";
|
|
4057
5344
|
var NODE_MODULES = "node_modules";
|
|
4058
|
-
var SETTINGS_PATH =
|
|
5345
|
+
var SETTINGS_PATH = path8.join(".claude", "settings.json");
|
|
4059
5346
|
var CLAUDE_MD = "CLAUDE.md";
|
|
4060
5347
|
var PLUGIN_ID = "kit@kit";
|
|
4061
5348
|
var CLAUDE_MD_POINTER = `@${NODE_MODULES}/${KIT_PACKAGE_NAME}/dist/${CLAUDE_MD}`;
|
|
4062
|
-
var SECRETLINT_BIN =
|
|
4063
|
-
var manifest_schema =
|
|
4064
|
-
name:
|
|
4065
|
-
dependencies:
|
|
4066
|
-
devDependencies:
|
|
5349
|
+
var SECRETLINT_BIN = path8.join(NODE_MODULES, ".bin", "secretlint");
|
|
5350
|
+
var manifest_schema = z20.object({
|
|
5351
|
+
name: z20.string().optional(),
|
|
5352
|
+
dependencies: z20.record(z20.string(), z20.string()).optional(),
|
|
5353
|
+
devDependencies: z20.record(z20.string(), z20.string()).optional()
|
|
4067
5354
|
});
|
|
4068
|
-
var settings_schema =
|
|
4069
|
-
enabledPlugins:
|
|
5355
|
+
var settings_schema = z20.object({
|
|
5356
|
+
enabledPlugins: z20.record(z20.string(), z20.boolean()).optional()
|
|
4070
5357
|
});
|
|
4071
5358
|
var STATE_OK = "ok";
|
|
4072
5359
|
var STATE_TARGET_MISSING = "target-missing";
|
|
@@ -4081,10 +5368,10 @@ function lists_kit_dependency(manifest) {
|
|
|
4081
5368
|
function is_kit_consumer(root) {
|
|
4082
5369
|
const manifest = parse_manifest(root);
|
|
4083
5370
|
if (manifest?.name === KIT_PACKAGE_NAME) return false;
|
|
4084
|
-
return lists_kit_dependency(manifest) || existsSync(
|
|
5371
|
+
return lists_kit_dependency(manifest) || existsSync(path8.join(root, NODE_MODULES, KIT_PACKAGE_NAME));
|
|
4085
5372
|
}
|
|
4086
5373
|
function is_plugin_declared(root) {
|
|
4087
|
-
const content = file_reader.read_if_readable(
|
|
5374
|
+
const content = file_reader.read_if_readable(path8.join(root, SETTINGS_PATH));
|
|
4088
5375
|
if (content === void 0) return false;
|
|
4089
5376
|
const parsed = settings_schema.safeParse(json_value.parse_or_undefined(content));
|
|
4090
5377
|
return parsed.success && parsed.data.enabledPlugins?.[PLUGIN_ID] === true;
|
|
@@ -4096,13 +5383,13 @@ function configured_hooks_path(root) {
|
|
|
4096
5383
|
return value === "" ? void 0 : value;
|
|
4097
5384
|
}
|
|
4098
5385
|
function claude_md_state(root) {
|
|
4099
|
-
const content = file_reader.read_if_readable(
|
|
5386
|
+
const content = file_reader.read_if_readable(path8.join(root, CLAUDE_MD));
|
|
4100
5387
|
if (content === void 0) return STATE_MISSING;
|
|
4101
5388
|
if (!content.includes(CLAUDE_MD_POINTER)) return STATE_OK;
|
|
4102
|
-
return existsSync(
|
|
5389
|
+
return existsSync(path8.join(root, NODE_MODULES, KIT_PACKAGE_NAME, "dist", CLAUDE_MD)) ? STATE_OK : STATE_TARGET_MISSING;
|
|
4103
5390
|
}
|
|
4104
5391
|
function is_secretlint_runnable(root) {
|
|
4105
|
-
return existsSync(
|
|
5392
|
+
return existsSync(path8.join(root, SECRETLINT_BIN));
|
|
4106
5393
|
}
|
|
4107
5394
|
function status_line(is_ok, ok_text, warn_text) {
|
|
4108
5395
|
return is_ok ? ` \u2713 ${ok_text}` : ` \u26A0 ${warn_text}`;
|
|
@@ -4164,11 +5451,11 @@ var doctor_consumer = {
|
|
|
4164
5451
|
|
|
4165
5452
|
// scripts/gate/project-checks.ts
|
|
4166
5453
|
import { existsSync as existsSync6, globSync as globSync2 } from "node:fs";
|
|
4167
|
-
import
|
|
5454
|
+
import path18 from "node:path";
|
|
4168
5455
|
|
|
4169
5456
|
// scripts/init/own-formatter.ts
|
|
4170
5457
|
import { existsSync as existsSync2 } from "node:fs";
|
|
4171
|
-
import
|
|
5458
|
+
import path9 from "node:path";
|
|
4172
5459
|
var OWN_FORMATTER_CONFIGS = [
|
|
4173
5460
|
"biome.json",
|
|
4174
5461
|
"biome.jsonc",
|
|
@@ -4178,23 +5465,23 @@ var OWN_FORMATTER_CONFIGS = [
|
|
|
4178
5465
|
".dprint.jsonc"
|
|
4179
5466
|
];
|
|
4180
5467
|
function find_config(root) {
|
|
4181
|
-
return OWN_FORMATTER_CONFIGS.find((name) => existsSync2(
|
|
5468
|
+
return OWN_FORMATTER_CONFIGS.find((name) => existsSync2(path9.join(root, name)));
|
|
4182
5469
|
}
|
|
4183
5470
|
var own_formatter = { find_config };
|
|
4184
5471
|
|
|
4185
5472
|
// scripts/init/project-profile.ts
|
|
4186
5473
|
import { existsSync as existsSync5, readdirSync } from "node:fs";
|
|
4187
|
-
import
|
|
4188
|
-
import { z as
|
|
5474
|
+
import path17 from "node:path";
|
|
5475
|
+
import { z as z26 } from "zod";
|
|
4189
5476
|
|
|
4190
5477
|
// scripts/sync/file-content.ts
|
|
4191
|
-
import
|
|
4192
|
-
var PATH_SEPARATORS =
|
|
5478
|
+
import path10 from "node:path";
|
|
5479
|
+
var PATH_SEPARATORS = path10.sep === "\\" ? /[/\\]/u : /\//u;
|
|
4193
5480
|
|
|
4194
5481
|
// scripts/safe-chain/pack-hook.ts
|
|
4195
|
-
import { z as
|
|
5482
|
+
import { z as z21 } from "zod";
|
|
4196
5483
|
var PACK_HOOK_FILE = ".pnpmfile.mjs";
|
|
4197
|
-
var manifest_schema2 =
|
|
5484
|
+
var manifest_schema2 = z21.looseObject({ private: z21.boolean().optional() });
|
|
4198
5485
|
var MESSAGES = {
|
|
4199
5486
|
written: ` \u2714 synced ${PACK_HOOK_FILE} (run \`pnpm install\` to refresh pnpmfileChecksum)`,
|
|
4200
5487
|
unchanged: ` \u2714 unchanged ${PACK_HOOK_FILE}`,
|
|
@@ -4229,17 +5516,17 @@ function parse_yaml_documents(content) {
|
|
|
4229
5516
|
var yaml_document = { is_mapping_document, parse_yaml, parse_yaml_documents };
|
|
4230
5517
|
|
|
4231
5518
|
// scripts/version/release-window.ts
|
|
4232
|
-
import { z as
|
|
5519
|
+
import { z as z23 } from "zod";
|
|
4233
5520
|
|
|
4234
5521
|
// scripts/version/release-age.ts
|
|
4235
5522
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
4236
|
-
import
|
|
5523
|
+
import path11 from "node:path";
|
|
4237
5524
|
import semver from "semver";
|
|
4238
|
-
import { z as
|
|
5525
|
+
import { z as z22 } from "zod";
|
|
4239
5526
|
var NO_QUARANTINE_MINUTES = 0;
|
|
4240
5527
|
var WORKSPACE_PATH = "pnpm-workspace.yaml";
|
|
4241
|
-
var workspace_age_schema =
|
|
4242
|
-
var release_times_schema =
|
|
5528
|
+
var workspace_age_schema = z22.object({ minimumReleaseAge: z22.number().int().nonnegative() });
|
|
5529
|
+
var release_times_schema = z22.record(z22.string(), z22.string());
|
|
4243
5530
|
function parse_workspace(workspace_content) {
|
|
4244
5531
|
try {
|
|
4245
5532
|
return yaml_document.parse_yaml(workspace_content);
|
|
@@ -4280,14 +5567,14 @@ function read_minimum_release_age(workspace_path = WORKSPACE_PATH) {
|
|
|
4280
5567
|
return read_declared_minimum_release_age(workspace_path) ?? NO_QUARANTINE_MINUTES;
|
|
4281
5568
|
}
|
|
4282
5569
|
function find_declared_minimum_release_age(start, boundary) {
|
|
4283
|
-
const declared = read_declared_minimum_release_age(
|
|
5570
|
+
const declared = read_declared_minimum_release_age(path11.join(start, WORKSPACE_PATH));
|
|
4284
5571
|
if (declared !== void 0) return declared;
|
|
4285
5572
|
if (start === boundary) return void 0;
|
|
4286
|
-
const parent =
|
|
5573
|
+
const parent = path11.dirname(start);
|
|
4287
5574
|
return parent === start ? void 0 : find_declared_minimum_release_age(parent, boundary);
|
|
4288
5575
|
}
|
|
4289
5576
|
function read_nearest_minimum_release_age(start, boundary) {
|
|
4290
|
-
return find_declared_minimum_release_age(
|
|
5577
|
+
return find_declared_minimum_release_age(path11.resolve(start), boundary) ?? NO_QUARANTINE_MINUTES;
|
|
4291
5578
|
}
|
|
4292
5579
|
var release_age = {
|
|
4293
5580
|
release_times_schema,
|
|
@@ -4299,7 +5586,7 @@ var release_age = {
|
|
|
4299
5586
|
};
|
|
4300
5587
|
|
|
4301
5588
|
// scripts/version/release-window.ts
|
|
4302
|
-
var exclusions_schema =
|
|
5589
|
+
var exclusions_schema = z23.object({ minimumReleaseAgeExclude: z23.array(z23.string()).optional() });
|
|
4303
5590
|
|
|
4304
5591
|
// scripts/safe-chain/project-config.ts
|
|
4305
5592
|
import { dump } from "js-yaml";
|
|
@@ -4323,7 +5610,7 @@ function flatten_elements(elements) {
|
|
|
4323
5610
|
const scalars = elements.map((line) => line.trim().replace(/,$/u, ""));
|
|
4324
5611
|
return `[${scalars.join(", ")}]`;
|
|
4325
5612
|
}
|
|
4326
|
-
function
|
|
5613
|
+
function collect_block(lines, start) {
|
|
4327
5614
|
const close = lines.findIndex((line, index) => index > start && ARRAY_CLOSE.test(line));
|
|
4328
5615
|
if (close === -1) return void 0;
|
|
4329
5616
|
const elements = lines.slice(start + 1, close);
|
|
@@ -4337,7 +5624,7 @@ function try_inline(open, block) {
|
|
|
4337
5624
|
}
|
|
4338
5625
|
function rewrite_at(lines, index, line) {
|
|
4339
5626
|
const verbatim = { lines: [line], next: index + 1 };
|
|
4340
|
-
const block = is_array_open(line) ?
|
|
5627
|
+
const block = is_array_open(line) ? collect_block(lines, index) : void 0;
|
|
4341
5628
|
if (block === void 0) return verbatim;
|
|
4342
5629
|
const inlined = try_inline(line, block);
|
|
4343
5630
|
if (inlined === void 0) return verbatim;
|
|
@@ -4425,9 +5712,9 @@ function is_matching(entry, matchers) {
|
|
|
4425
5712
|
(matcher) => typeof matcher === "string" ? matcher === entry : matcher.test(entry)
|
|
4426
5713
|
);
|
|
4427
5714
|
}
|
|
4428
|
-
function apply_remove(existing,
|
|
4429
|
-
if (
|
|
4430
|
-
return existing.filter((entry) => !is_matching(entry,
|
|
5715
|
+
function apply_remove(existing, remove2) {
|
|
5716
|
+
if (remove2 === void 0 || remove2.length === 0) return existing;
|
|
5717
|
+
return existing.filter((entry) => !is_matching(entry, remove2));
|
|
4431
5718
|
}
|
|
4432
5719
|
function collect_additions(kept, ensure) {
|
|
4433
5720
|
if (ensure === void 0) return [];
|
|
@@ -4666,10 +5953,10 @@ function set_json_key(content, key2, value) {
|
|
|
4666
5953
|
const indented = fit_value(content, value_text, line_indent(content, existing.offset));
|
|
4667
5954
|
return with_trailing_newline(replace_range(content, existing, indented));
|
|
4668
5955
|
}
|
|
4669
|
-
function resolve_parent(content,
|
|
5956
|
+
function resolve_parent(content, path19) {
|
|
4670
5957
|
const root = parse_root(content);
|
|
4671
5958
|
if (root === void 0) return void 0;
|
|
4672
|
-
const parent =
|
|
5959
|
+
const parent = path19.length > 1 ? findNodeAtLocation(root, path19.slice(0, -1)) : root;
|
|
4673
5960
|
return parent?.type === "object" ? parent : void 0;
|
|
4674
5961
|
}
|
|
4675
5962
|
function cut_ranges(content, parent, ranges) {
|
|
@@ -4680,24 +5967,24 @@ function cut_ranges(content, parent, ranges) {
|
|
|
4680
5967
|
}
|
|
4681
5968
|
return next;
|
|
4682
5969
|
}
|
|
4683
|
-
function rebalance_new_last(content,
|
|
4684
|
-
const parent = resolve_parent(content,
|
|
5970
|
+
function rebalance_new_last(content, path19) {
|
|
5971
|
+
const parent = resolve_parent(content, path19);
|
|
4685
5972
|
const last = parent?.children?.at(-1);
|
|
4686
5973
|
if (parent === void 0 || last === void 0) return content;
|
|
4687
5974
|
return rebalance(content, last, has_separator_after(content, parent.offset, parent.offset));
|
|
4688
5975
|
}
|
|
4689
|
-
function cut_property(content, parent,
|
|
4690
|
-
const index = property_index(parent,
|
|
5976
|
+
function cut_property(content, parent, path19) {
|
|
5977
|
+
const index = property_index(parent, path19.at(-1) ?? "");
|
|
4691
5978
|
const ranges = removal_ranges(content, parent, index);
|
|
4692
5979
|
if (ranges.length === 0) return content;
|
|
4693
5980
|
const cut = cut_ranges(content, parent, ranges);
|
|
4694
5981
|
const did_end_object = index === (parent.children ?? []).length - 1;
|
|
4695
|
-
return did_end_object ? rebalance_new_last(cut,
|
|
5982
|
+
return did_end_object ? rebalance_new_last(cut, path19) : cut;
|
|
4696
5983
|
}
|
|
4697
|
-
function remove_json_path(content,
|
|
4698
|
-
const parent = resolve_parent(content,
|
|
5984
|
+
function remove_json_path(content, path19) {
|
|
5985
|
+
const parent = resolve_parent(content, path19);
|
|
4699
5986
|
if (parent === void 0) return content;
|
|
4700
|
-
const next = cut_property(content, parent,
|
|
5987
|
+
const next = cut_property(content, parent, path19);
|
|
4701
5988
|
return next === content ? content : with_trailing_newline(next);
|
|
4702
5989
|
}
|
|
4703
5990
|
function remove_json_key(content, key2) {
|
|
@@ -4864,13 +6151,13 @@ var kit_base_preset = {
|
|
|
4864
6151
|
|
|
4865
6152
|
// scripts/init/tsconfig-preset-migration.ts
|
|
4866
6153
|
import { existsSync as existsSync3 } from "node:fs";
|
|
4867
|
-
import
|
|
6154
|
+
import path12 from "node:path";
|
|
4868
6155
|
var LEGACY_PRESET_ENTRY = /@joshuafolkken\/[^/]+\/tsconfig\/[^/]+\.jsonc$/u;
|
|
4869
6156
|
var LEGACY_SUFFIX = ".jsonc";
|
|
4870
6157
|
var CURRENT_SUFFIX = ".json";
|
|
4871
6158
|
var EXTENDS_FIELD = "extends";
|
|
4872
6159
|
function is_migration_target_present(base_directory, entry) {
|
|
4873
|
-
return existsSync3(
|
|
6160
|
+
return existsSync3(path12.resolve(base_directory, entry));
|
|
4874
6161
|
}
|
|
4875
6162
|
function migrate_entry(base_directory, entry) {
|
|
4876
6163
|
if (!LEGACY_PRESET_ENTRY.test(entry)) return entry;
|
|
@@ -4966,11 +6253,11 @@ function merge_owned_entries(current, update) {
|
|
|
4966
6253
|
return { ...owned, ...Object.fromEntries(missing) };
|
|
4967
6254
|
}
|
|
4968
6255
|
function collect_applicable_updates(parsed, updates) {
|
|
4969
|
-
const
|
|
6256
|
+
const resolved2 = Object.entries(updates).map(([key2, value]) => [
|
|
4970
6257
|
key2,
|
|
4971
6258
|
Object.hasOwn(parsed, key2) ? merge_owned_entries(parsed[key2], value) : value
|
|
4972
6259
|
]);
|
|
4973
|
-
return Object.fromEntries(
|
|
6260
|
+
return Object.fromEntries(resolved2.filter(([, merged]) => merged !== void 0));
|
|
4974
6261
|
}
|
|
4975
6262
|
function merge_json_object(content, updates) {
|
|
4976
6263
|
const parsed = parse_jsonc(content);
|
|
@@ -5102,10 +6389,10 @@ var init_logic_json_merge = {
|
|
|
5102
6389
|
};
|
|
5103
6390
|
|
|
5104
6391
|
// scripts/init/kit-development-versions.ts
|
|
5105
|
-
import { z as
|
|
5106
|
-
var kit_manifest_schema =
|
|
5107
|
-
peerDependencies:
|
|
5108
|
-
devDependencies:
|
|
6392
|
+
import { z as z24 } from "zod";
|
|
6393
|
+
var kit_manifest_schema = z24.object({
|
|
6394
|
+
peerDependencies: z24.record(z24.string(), z24.string()).default({}),
|
|
6395
|
+
devDependencies: z24.record(z24.string(), z24.string())
|
|
5109
6396
|
});
|
|
5110
6397
|
function read_kit_manifest() {
|
|
5111
6398
|
return package_manifest.read_manifest(PACKAGE_DIR, kit_manifest_schema);
|
|
@@ -5236,14 +6523,14 @@ function resolve_multicriteria_conflicts(existing, template) {
|
|
|
5236
6523
|
const existing_ids = get_multicriteria_ids(existing);
|
|
5237
6524
|
const template_ids = get_multicriteria_ids(template);
|
|
5238
6525
|
const reusable_ids = existing_ids.filter((id) => !template_ids.includes(id));
|
|
5239
|
-
let
|
|
6526
|
+
let resolved2 = template;
|
|
5240
6527
|
for (const id of template_ids) {
|
|
5241
|
-
if (!existing_ids.includes(id) || !has_criterion_conflict(existing,
|
|
5242
|
-
const matching_id = find_matching_criterion(existing,
|
|
5243
|
-
const replacement_id = matching_id ?? allocate_criterion_id(/* @__PURE__ */ new Set([...existing_ids, ...get_multicriteria_ids(
|
|
5244
|
-
|
|
6528
|
+
if (!existing_ids.includes(id) || !has_criterion_conflict(existing, resolved2, id)) continue;
|
|
6529
|
+
const matching_id = find_matching_criterion(existing, resolved2, reusable_ids, id);
|
|
6530
|
+
const replacement_id = matching_id ?? allocate_criterion_id(/* @__PURE__ */ new Set([...existing_ids, ...get_multicriteria_ids(resolved2)]));
|
|
6531
|
+
resolved2 = rename_criterion(resolved2, id, replacement_id);
|
|
5245
6532
|
}
|
|
5246
|
-
return
|
|
6533
|
+
return resolved2;
|
|
5247
6534
|
}
|
|
5248
6535
|
function merge_multicriteria_ids(existing, template_content) {
|
|
5249
6536
|
const existing_value = get_multicriteria_value(existing);
|
|
@@ -5284,7 +6571,7 @@ var init_logic_sonar = {
|
|
|
5284
6571
|
|
|
5285
6572
|
// scripts/init/init-logic-templates.ts
|
|
5286
6573
|
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "node:fs";
|
|
5287
|
-
import
|
|
6574
|
+
import path13 from "node:path";
|
|
5288
6575
|
var ESLINT_VANILLA = `import { create_vanilla_config } from '@joshuafolkken/kit/eslint/vanilla'
|
|
5289
6576
|
|
|
5290
6577
|
export default create_vanilla_config({
|
|
@@ -5369,7 +6656,7 @@ function merge_eslint_config(existing) {
|
|
|
5369
6656
|
return apply_rules_template(rules_blocks.join(",\n"));
|
|
5370
6657
|
}
|
|
5371
6658
|
function detect_tailwind_stylesheet(project_root2) {
|
|
5372
|
-
return existsSync4(
|
|
6659
|
+
return existsSync4(path13.join(project_root2, DEFAULT_TAILWIND_STYLESHEET)) ? DEFAULT_TAILWIND_STYLESHEET : void 0;
|
|
5373
6660
|
}
|
|
5374
6661
|
function generate_prettier_config(stylesheet) {
|
|
5375
6662
|
const stylesheet_line = stylesheet === void 0 ? "" : ` tailwindStylesheet: '${stylesheet}',
|
|
@@ -5383,7 +6670,7 @@ ${stylesheet_line}}
|
|
|
5383
6670
|
}
|
|
5384
6671
|
function existing_stylesheet(existing, project_root2) {
|
|
5385
6672
|
const named = TAILWIND_STYLESHEET_PATTERN.exec(existing)?.[1];
|
|
5386
|
-
return named !== void 0 && existsSync4(
|
|
6673
|
+
return named !== void 0 && existsSync4(path13.resolve(project_root2, named)) ? named : void 0;
|
|
5387
6674
|
}
|
|
5388
6675
|
function merge_prettier_config(existing, project_root2) {
|
|
5389
6676
|
const stylesheet = existing_stylesheet(existing, project_root2) ?? detect_tailwind_stylesheet(project_root2);
|
|
@@ -5899,23 +7186,23 @@ var AI_COPY_DIRECTORIES_LIST = "AI_COPY_DIRECTORIES";
|
|
|
5899
7186
|
var SYNCED_PATHS_LIST = "SYNCED_PATHS";
|
|
5900
7187
|
var PLUGIN_SKILL_DIRECTORIES_LIST = "PLUGIN_SKILL_DIRECTORIES";
|
|
5901
7188
|
var PATH_SEPARATOR2 = "/";
|
|
5902
|
-
function is_inside(
|
|
5903
|
-
return
|
|
7189
|
+
function is_inside(path19, directory) {
|
|
7190
|
+
return path19 === directory || path19.startsWith(`${directory}${PATH_SEPARATOR2}`);
|
|
5904
7191
|
}
|
|
5905
|
-
function matches_file(
|
|
5906
|
-
return init_logic.get_ai_copy_files().includes(
|
|
7192
|
+
function matches_file(path19) {
|
|
7193
|
+
return init_logic.get_ai_copy_files().includes(path19);
|
|
5907
7194
|
}
|
|
5908
|
-
function matches_mapping(
|
|
5909
|
-
return init_logic.get_ai_copy_file_mappings().some((mapping) => mapping.src ===
|
|
7195
|
+
function matches_mapping(path19) {
|
|
7196
|
+
return init_logic.get_ai_copy_file_mappings().some((mapping) => mapping.src === path19 || mapping.dest === path19);
|
|
5910
7197
|
}
|
|
5911
|
-
function matches_directory(
|
|
5912
|
-
return init_logic.get_ai_copy_directories().some((directory) => is_inside(
|
|
7198
|
+
function matches_directory(path19) {
|
|
7199
|
+
return init_logic.get_ai_copy_directories().some((directory) => is_inside(path19, directory));
|
|
5913
7200
|
}
|
|
5914
|
-
function matches_plugin_skill(
|
|
5915
|
-
return PLUGIN_SKILL_DIRECTORIES.some((directory) => is_inside(
|
|
7201
|
+
function matches_plugin_skill(path19) {
|
|
7202
|
+
return PLUGIN_SKILL_DIRECTORIES.some((directory) => is_inside(path19, directory));
|
|
5916
7203
|
}
|
|
5917
|
-
function matches_synced_path(
|
|
5918
|
-
return synced_paths.get_synced_paths().includes(
|
|
7204
|
+
function matches_synced_path(path19) {
|
|
7205
|
+
return synced_paths.get_synced_paths().includes(path19);
|
|
5919
7206
|
}
|
|
5920
7207
|
var MATCHERS = [
|
|
5921
7208
|
{ list: AI_COPY_FILES_LIST, matches: matches_file },
|
|
@@ -5924,18 +7211,18 @@ var MATCHERS = [
|
|
|
5924
7211
|
{ list: PLUGIN_SKILL_DIRECTORIES_LIST, matches: matches_plugin_skill },
|
|
5925
7212
|
{ list: SYNCED_PATHS_LIST, matches: matches_synced_path }
|
|
5926
7213
|
];
|
|
5927
|
-
function find_list(
|
|
5928
|
-
return MATCHERS.find((matcher) => matcher.matches(
|
|
7214
|
+
function find_list(path19) {
|
|
7215
|
+
return MATCHERS.find((matcher) => matcher.matches(path19))?.list;
|
|
5929
7216
|
}
|
|
5930
|
-
function to_hit(
|
|
5931
|
-
const list = find_list(
|
|
5932
|
-
return list === void 0 ? void 0 : { path:
|
|
7217
|
+
function to_hit(path19) {
|
|
7218
|
+
const list = find_list(path19);
|
|
7219
|
+
return list === void 0 ? void 0 : { path: path19, list };
|
|
5933
7220
|
}
|
|
5934
7221
|
function find_managed_paths(paths) {
|
|
5935
|
-
return paths.flatMap((
|
|
7222
|
+
return paths.flatMap((path19) => to_hit(path19) ?? []);
|
|
5936
7223
|
}
|
|
5937
7224
|
function has_managed_path(paths) {
|
|
5938
|
-
return paths.some((
|
|
7225
|
+
return paths.some((path19) => find_list(path19) !== void 0);
|
|
5939
7226
|
}
|
|
5940
7227
|
function format_hit(hit) {
|
|
5941
7228
|
return `${hit.path} (${hit.list})`;
|
|
@@ -5951,8 +7238,8 @@ var managed_config_scope = {
|
|
|
5951
7238
|
};
|
|
5952
7239
|
|
|
5953
7240
|
// scripts/init/session-language-environment.ts
|
|
5954
|
-
import
|
|
5955
|
-
var CLAUDE_SETTINGS_PATH =
|
|
7241
|
+
import path14 from "node:path";
|
|
7242
|
+
var CLAUDE_SETTINGS_PATH = path14.join(".claude", "settings.json");
|
|
5956
7243
|
var KEY_LINE_PATTERN = new RegExp(
|
|
5957
7244
|
String.raw`^\s*(?:export\s+)?${session_language.ENV_KEY}\s*=`,
|
|
5958
7245
|
"mu"
|
|
@@ -5962,8 +7249,8 @@ var KEY_LINE_PATTERN = new RegExp(
|
|
|
5962
7249
|
import { findNodeAtLocation as findNodeAtLocation2, getNodeValue as getNodeValue2, parseTree as parseTree3 } from "jsonc-parser";
|
|
5963
7250
|
|
|
5964
7251
|
// scripts/init/vscode-tasks.ts
|
|
5965
|
-
import { z as
|
|
5966
|
-
var task_array_schema =
|
|
7252
|
+
import { z as z25 } from "zod";
|
|
7253
|
+
var task_array_schema = z25.array(json_object_schema);
|
|
5967
7254
|
|
|
5968
7255
|
// scripts/init/init-actions.ts
|
|
5969
7256
|
var BASIC_PRETTIER_CONFIG = "prettier.config.mjs";
|
|
@@ -5973,11 +7260,11 @@ var MARKER_TOKEN = "josh-managed-workflow:";
|
|
|
5973
7260
|
var MARKER_PREFIX = `# ${MARKER_TOKEN}`;
|
|
5974
7261
|
|
|
5975
7262
|
// scripts/init/claude-plugin-config.ts
|
|
5976
|
-
import
|
|
7263
|
+
import path15 from "node:path";
|
|
5977
7264
|
var MARKETPLACE_NAME = "kit";
|
|
5978
7265
|
var PLUGIN_ID2 = "kit@kit";
|
|
5979
7266
|
var MARKETPLACE_PATH = "./node_modules/@joshuafolkken/kit";
|
|
5980
|
-
var CLAUDE_SETTINGS_DESTINATION =
|
|
7267
|
+
var CLAUDE_SETTINGS_DESTINATION = path15.join(".claude", "settings.json");
|
|
5981
7268
|
var PLUGIN_SETTINGS = {
|
|
5982
7269
|
extraKnownMarketplaces: {
|
|
5983
7270
|
[MARKETPLACE_NAME]: { source: { source: "directory", path: MARKETPLACE_PATH } }
|
|
@@ -6003,7 +7290,7 @@ var HOOK_DIST_DIR = "dist/hooks";
|
|
|
6003
7290
|
var RUN_HOOK_SCRIPT = "scripts/hooks/run-hook.sh";
|
|
6004
7291
|
var ROOT_LOOKUP = "git rev-parse --show-toplevel";
|
|
6005
7292
|
var CODEX_ROOT = `$( (unset ${GIT_LOCATION_VARIABLES.join(" ")}; ${ROOT_LOOKUP} 2>/dev/null) || ${ROOT_LOOKUP})`;
|
|
6006
|
-
var PROJECT_ROOT_PREFIX = `project_root="\${CLAUDE_PROJECT_DIR:-${CODEX_ROOT}}" && cd "$project_root" && `;
|
|
7293
|
+
var PROJECT_ROOT_PREFIX = `export JOSH_HOOK_CWD="$PWD" && project_root="\${CLAUDE_PROJECT_DIR:-${CODEX_ROOT}}" && cd "$project_root" && `;
|
|
6007
7294
|
function hook_launch_command(name) {
|
|
6008
7295
|
return `${PROJECT_ROOT_PREFIX}sh ${RUN_HOOK_SCRIPT} ${name}`;
|
|
6009
7296
|
}
|
|
@@ -6039,14 +7326,16 @@ var PLAIN_KIT_COMMANDS = new Set(
|
|
|
6039
7326
|
var LOCATION_VARIABLES = "GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_COMMON_DIR GIT_DIR GIT_INDEX_FILE GIT_NAMESPACE GIT_OBJECT_DIRECTORY GIT_WORK_TREE";
|
|
6040
7327
|
var ROOT_LOOKUP2 = "git rev-parse --show-toplevel";
|
|
6041
7328
|
var LEGACY_ROOT_PREFIX = `if project_root="$(unset ${LOCATION_VARIABLES}; ${ROOT_LOOKUP2} 2>/dev/null)"; then unset ${LOCATION_VARIABLES}; else project_root="$(${ROOT_LOOKUP2})"; fi && cd "$project_root" && `;
|
|
7329
|
+
var PRE_WORKTREE_ROOT_PREFIX = `project_root="\${CLAUDE_PROJECT_DIR:-$( (unset ${LOCATION_VARIABLES}; ${ROOT_LOOKUP2} 2>/dev/null) || ${ROOT_LOOKUP2})}" && cd "$project_root" && `;
|
|
6042
7330
|
var ROOT_PREFIXES = [
|
|
6043
7331
|
hook_launch.PROJECT_ROOT_PREFIX,
|
|
7332
|
+
PRE_WORKTREE_ROOT_PREFIX,
|
|
6044
7333
|
LEGACY_ROOT_PREFIX
|
|
6045
7334
|
].map((prefix) => JSON.stringify(prefix).slice(1, -1));
|
|
6046
7335
|
var [PROJECT_ROOT_PREFIX2 = ""] = ROOT_PREFIXES;
|
|
6047
7336
|
|
|
6048
7337
|
// scripts/init/security-policy.ts
|
|
6049
|
-
import
|
|
7338
|
+
import path16 from "node:path";
|
|
6050
7339
|
var SECURITY_MD = "SECURITY.md";
|
|
6051
7340
|
var SECURITY_TEMPLATE = "templates/SECURITY.md";
|
|
6052
7341
|
var REPOSITORY_PLACEHOLDER = "{{REPOSITORY}}";
|
|
@@ -6062,15 +7351,15 @@ function apply_repository(content, repository) {
|
|
|
6062
7351
|
return content.replaceAll(REPOSITORY_PLACEHOLDER, () => repository);
|
|
6063
7352
|
}
|
|
6064
7353
|
function apply_repository_for_destination(destination_path, content) {
|
|
6065
|
-
if (
|
|
6066
|
-
const repository = repository_at(
|
|
7354
|
+
if (path16.basename(destination_path) !== SECURITY_MD) return content;
|
|
7355
|
+
const repository = repository_at(path16.dirname(destination_path));
|
|
6067
7356
|
if (repository === void 0) {
|
|
6068
7357
|
throw new Error(`${SECURITY_MD} needs a GitHub origin to name the repository it reports to`);
|
|
6069
7358
|
}
|
|
6070
7359
|
return apply_repository(content, repository);
|
|
6071
7360
|
}
|
|
6072
7361
|
function does_report_to_kit(root) {
|
|
6073
|
-
const existing = file_reader.read_if_readable(
|
|
7362
|
+
const existing = file_reader.read_if_readable(path16.join(root, SECURITY_MD)) ?? "";
|
|
6074
7363
|
return new Set(existing.split(LINK_DELIMITER)).has(KIT_ADVISORY_URL);
|
|
6075
7364
|
}
|
|
6076
7365
|
function unresolved_warning(root) {
|
|
@@ -6190,7 +7479,7 @@ function requested_profile(args, usage = "josh init [--profile basic|full]") {
|
|
|
6190
7479
|
}
|
|
6191
7480
|
function read_manifest(root) {
|
|
6192
7481
|
if (!existsSync5(package_manifest.manifest_path(root))) return void 0;
|
|
6193
|
-
const parsed = package_manifest.read_manifest(root,
|
|
7482
|
+
const parsed = package_manifest.read_manifest(root, z26.unknown());
|
|
6194
7483
|
if (!json_value.is_record(parsed)) throw new Error("package.json must contain an object");
|
|
6195
7484
|
return parsed;
|
|
6196
7485
|
}
|
|
@@ -6231,12 +7520,12 @@ function should_visit(entry) {
|
|
|
6231
7520
|
function scan_directory(directory, pending) {
|
|
6232
7521
|
const entries = readdirSync(directory, { withFileTypes: true });
|
|
6233
7522
|
pending.push(
|
|
6234
|
-
...entries.filter((entry) => should_visit(entry)).map((entry) =>
|
|
7523
|
+
...entries.filter((entry) => should_visit(entry)).map((entry) => path17.join(directory, entry.name))
|
|
6235
7524
|
);
|
|
6236
|
-
return entries.filter((entry) => entry.isFile()).map((entry) =>
|
|
7525
|
+
return entries.filter((entry) => entry.isFile()).map((entry) => path17.join(directory, entry.name));
|
|
6237
7526
|
}
|
|
6238
7527
|
function is_project_file(root, file) {
|
|
6239
|
-
const relative_path =
|
|
7528
|
+
const relative_path = path17.relative(root, file).split(path17.sep).join(path17.posix.sep);
|
|
6240
7529
|
return !kit_written_paths.is_kit_written(relative_path);
|
|
6241
7530
|
}
|
|
6242
7531
|
function list_files(root) {
|
|
@@ -6248,7 +7537,7 @@ function list_files(root) {
|
|
|
6248
7537
|
return files;
|
|
6249
7538
|
}
|
|
6250
7539
|
function file_extensions(root) {
|
|
6251
|
-
return list_files(root).filter((file) => is_project_file(root, file)).map((file) =>
|
|
7540
|
+
return list_files(root).filter((file) => is_project_file(root, file)).map((file) => path17.extname(file));
|
|
6252
7541
|
}
|
|
6253
7542
|
function scan_files(root) {
|
|
6254
7543
|
const extensions = file_extensions(root);
|
|
@@ -6262,7 +7551,7 @@ function has_github_remote(root) {
|
|
|
6262
7551
|
return url !== void 0 && repo_origin.parse_origin_url(url) !== void 0;
|
|
6263
7552
|
}
|
|
6264
7553
|
function has_git(root) {
|
|
6265
|
-
return existsSync5(
|
|
7554
|
+
return existsSync5(path17.join(root, ".git"));
|
|
6266
7555
|
}
|
|
6267
7556
|
function has_workflow(root) {
|
|
6268
7557
|
return workflow_mark.is_requested() || workflow_mark.is_recorded(read_manifest(root));
|
|
@@ -6295,7 +7584,7 @@ var SKIP_MARKER = "\u2014 skipping";
|
|
|
6295
7584
|
var NOT_USED_MARKER = "which this project does not use";
|
|
6296
7585
|
|
|
6297
7586
|
// scripts/gate/project-checks.ts
|
|
6298
|
-
import { z as
|
|
7587
|
+
import { z as z27 } from "zod";
|
|
6299
7588
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
6300
7589
|
"node_modules",
|
|
6301
7590
|
".git",
|
|
@@ -6329,7 +7618,7 @@ var CSPELL_CONFIGS = [
|
|
|
6329
7618
|
];
|
|
6330
7619
|
var TYPE_CONFIGS = ["tsconfig.json", "jsconfig.json"];
|
|
6331
7620
|
var DEPENDENCY_FIELDS = ["dependencies", "devDependencies"];
|
|
6332
|
-
var object_schema =
|
|
7621
|
+
var object_schema = z27.record(z27.string(), z27.unknown());
|
|
6333
7622
|
function project_root(directory) {
|
|
6334
7623
|
return ancestor_directories.nearest(
|
|
6335
7624
|
directory,
|
|
@@ -6346,7 +7635,7 @@ function has_files(directory, pattern) {
|
|
|
6346
7635
|
return globSync2(pattern, { cwd: project_root(directory), exclude: is_ignored }).length > 0;
|
|
6347
7636
|
}
|
|
6348
7637
|
function has_config(directory, names) {
|
|
6349
|
-
return names.some((name) => existsSync6(
|
|
7638
|
+
return names.some((name) => existsSync6(path18.join(project_root(directory), name)));
|
|
6350
7639
|
}
|
|
6351
7640
|
function has_bin(directory, bin_name) {
|
|
6352
7641
|
return find_local_bin_upwards(directory, bin_name) !== void 0;
|
|
@@ -6360,7 +7649,7 @@ function is_basic_manifest(manifest) {
|
|
|
6360
7649
|
return project_profile.parse_profile(josh["profile"]) === "basic";
|
|
6361
7650
|
}
|
|
6362
7651
|
function read_manifest2(directory) {
|
|
6363
|
-
return package_manifest.read_manifest_if_valid(project_root(directory),
|
|
7652
|
+
return package_manifest.read_manifest_if_valid(project_root(directory), z27.unknown());
|
|
6364
7653
|
}
|
|
6365
7654
|
function is_basic(directory) {
|
|
6366
7655
|
return is_basic_manifest(read_manifest2(directory));
|
|
@@ -6424,24 +7713,31 @@ var project_checks = {
|
|
|
6424
7713
|
export {
|
|
6425
7714
|
hook_decision,
|
|
6426
7715
|
bounded_pool,
|
|
7716
|
+
lane_guard_policy,
|
|
7717
|
+
delegation_policy,
|
|
7718
|
+
investigation_reads,
|
|
7719
|
+
duplicate_read_outcome,
|
|
6427
7720
|
git_argv,
|
|
6428
7721
|
shell_segments,
|
|
6429
7722
|
bash_triggers,
|
|
7723
|
+
stop_decision,
|
|
7724
|
+
concise_reply,
|
|
7725
|
+
repo_party,
|
|
6430
7726
|
tail_commands,
|
|
6431
|
-
|
|
6432
|
-
CONTEXT_CUT_THRESHOLD,
|
|
7727
|
+
run_cut_handoff,
|
|
6433
7728
|
cost_verdict,
|
|
6434
7729
|
cost_cli,
|
|
6435
7730
|
backlog_budget,
|
|
6436
|
-
run_cut_handoff,
|
|
6437
7731
|
run_cut,
|
|
6438
7732
|
run_tail_rule,
|
|
6439
7733
|
lane_background,
|
|
6440
7734
|
interactive_ask,
|
|
7735
|
+
stop_rules,
|
|
6441
7736
|
EPIC_LABEL,
|
|
6442
7737
|
BUG_LABEL,
|
|
6443
7738
|
ENHANCEMENT_LABEL,
|
|
6444
7739
|
IN_PROGRESS_LABEL,
|
|
7740
|
+
PLANNED_LABEL,
|
|
6445
7741
|
RUN_SOLO_LABEL,
|
|
6446
7742
|
RUN_LANE_LABEL,
|
|
6447
7743
|
PRIORITY_HIGH_LABEL,
|
|
@@ -6467,7 +7763,6 @@ export {
|
|
|
6467
7763
|
release_age,
|
|
6468
7764
|
gh_spawn,
|
|
6469
7765
|
project_checks,
|
|
6470
|
-
repo_party,
|
|
6471
7766
|
MAX_SCANNED,
|
|
6472
7767
|
git_gh_issue_write,
|
|
6473
7768
|
SUMMARY_FIELDS,
|
|
@@ -6479,5 +7774,7 @@ export {
|
|
|
6479
7774
|
PROCESS_ALIVE,
|
|
6480
7775
|
PROCESS_NONE,
|
|
6481
7776
|
PROCESS_UNKNOWN,
|
|
6482
|
-
run_liveness
|
|
7777
|
+
run_liveness,
|
|
7778
|
+
backlog_overlap,
|
|
7779
|
+
lane_plan
|
|
6483
7780
|
};
|