@joshuafolkken/kit 1.1229.0 → 1.1370.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/investigator.md +1 -0
- package/.claude/settings.json +4 -0
- package/.claude/skills/dependency-update/SKILL.md +5 -3
- package/.claude/skills/epic-commands/SKILL.md +82 -113
- package/.claude/skills/epic-commands/epic-bundle.md +38 -63
- package/.claude/skills/epic-commands/execution-waves.md +30 -51
- package/.claude/skills/verify-ui/SKILL.md +13 -20
- package/.claude/skills/workflow-commands/SKILL.md +10 -10
- package/.claude/skills/workflow-commands/background-commands.md +4 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +30 -105
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +29 -0
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +45 -131
- package/.claude/skills/workflow-commands/backlogrun-park.md +36 -53
- package/.claude/skills/workflow-commands/backlogrun-progress.md +81 -331
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +29 -83
- package/.claude/skills/workflow-commands/backlogrun-steps.md +105 -424
- package/.claude/skills/workflow-commands/backlogrun.md +50 -61
- package/.claude/skills/workflow-commands/chain-rule.md +36 -40
- package/.claude/skills/workflow-commands/entry-sequence.md +6 -6
- package/.claude/skills/workflow-commands/followup.md +24 -20
- package/.claude/skills/workflow-commands/fullrun-steps.md +23 -27
- package/.claude/skills/workflow-commands/fullrun.md +10 -10
- package/.claude/skills/workflow-commands/halfrun.md +9 -8
- package/.claude/skills/workflow-commands/into-target.md +12 -18
- package/.claude/skills/workflow-commands/issue-comments.md +11 -26
- package/.claude/skills/workflow-commands/kickoff.md +27 -16
- package/.claude/skills/workflow-commands/latest-gate.md +18 -29
- package/.claude/skills/workflow-commands/needs-human-review.md +13 -24
- package/.claude/skills/workflow-commands/observation-filing.md +37 -28
- package/.claude/skills/workflow-commands/observation-ledger.md +48 -38
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -9
- package/.claude/skills/workflow-commands/prerequisite.md +23 -15
- package/.claude/skills/workflow-commands/progress-watcher.md +17 -11
- package/.claude/skills/workflow-commands/prrun.md +3 -3
- package/.claude/skills/workflow-commands/retrospective.md +13 -18
- package/.claude/skills/workflow-commands/split-assessment.md +6 -4
- package/.claude/skills/workflow-commands/target-repository.md +25 -28
- package/.claude/skills/workflow-commands/working-tree-hold.md +11 -17
- package/.gitattributes +2 -1
- package/.github/workflows/ci.yml +14 -0
- package/.github/workflows/publish.yml +2 -0
- package/.vscode/tasks.json +14 -0
- package/CLAUDE.md +10 -61
- package/README.md +38 -57
- package/SECURITY.md +1 -1
- package/dist/CLAUDE.md +10 -61
- package/dist/commands/document-section-cli.js +42 -10
- package/dist/config-merge/index.js +11 -2
- package/dist/hooks/audit-provision.js +2 -2
- package/dist/hooks/batch-guard.js +7 -7
- package/dist/hooks/{chunk-FIVDHQGT.js → chunk-43G45XJF.js} +18 -20
- package/dist/hooks/{chunk-JUDKDCDP.js → chunk-4TW4MQUL.js} +284 -362
- package/dist/hooks/{chunk-5VMKCCC4.js → chunk-76RK6E3H.js} +13 -11
- package/dist/hooks/{chunk-RNWHN5BP.js → chunk-DZWZ3DKY.js} +4 -4
- package/dist/hooks/{chunk-5VNDSNG3.js → chunk-FZ6FUSBM.js} +1 -1
- package/dist/hooks/{chunk-VC3PZPZO.js → chunk-GG72ANKI.js} +1 -1
- package/dist/hooks/{chunk-6HJJXRBX.js → chunk-KPM4YIIX.js} +8 -44
- package/dist/hooks/chunk-MXVQMLDP.js +3705 -0
- package/dist/hooks/{chunk-ELCN5LCH.js → chunk-NEC4AT4Z.js} +34 -12
- package/dist/hooks/{chunk-TQNPDZNH.js → chunk-NZBHG6FW.js} +7 -5
- package/dist/hooks/chunk-NZN2UFI6.js +2409 -0
- package/dist/hooks/{chunk-F56MFS4B.js → chunk-R6CRQEAL.js} +4 -4
- package/dist/hooks/chunk-SYSRHRWU.js +1589 -0
- package/dist/hooks/{chunk-55HHG5PX.js → chunk-TLJYAGZK.js} +799 -903
- package/dist/hooks/chunk-Z5TMJIPW.js +45 -0
- package/dist/hooks/codex-hook-adapter.js +26 -21
- package/dist/hooks/duplicate-read-guard.js +8 -8
- package/dist/hooks/format-edited.js +4 -4
- package/dist/hooks/inputs.json +213 -197
- package/dist/hooks/investigation-guard.js +8 -8
- package/dist/hooks/pretool-guard.js +15 -15
- package/dist/hooks/session-lang.js +406 -8
- package/dist/hooks/stop-guard.js +122 -201
- package/dist/josh.js +540 -137
- package/dist/version/index.js +15 -13
- package/eslint/base.js +43 -5
- package/eslint/rules/english-only-prose.js +3 -3
- package/eslint/rules/import.js +12 -0
- package/eslint/rules/namespace-object-export.js +2 -2
- package/package.json +16 -10
- package/pnpm-workspace.yaml +2 -4
- package/prompts/coding-standards.md +14 -48
- package/prompts/collaboration-workflow/file-edits.md +1 -1
- package/prompts/collaboration-workflow/issue-citation.md +1 -1
- package/prompts/collaboration-workflow/issue-template.md +4 -10
- package/prompts/collaboration-workflow/operating-rules.md +7 -8
- package/prompts/collaboration-workflow/output-bounds.md +1 -1
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/plan-comment.md +2 -1
- package/prompts/collaboration-workflow/principles.md +21 -3
- package/prompts/collaboration-workflow/report-format.md +16 -29
- package/prompts/collaboration-workflow/residency.md +1 -1
- package/prompts/collaboration-workflow/rule-delivery.md +7 -95
- package/prompts/collaboration-workflow/shell-body.md +3 -23
- package/prompts/collaboration-workflow/turn-batching.md +4 -13
- package/prompts/collaboration-workflow/wip-cap.md +5 -11
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +3 -22
- package/prompts/review.md +15 -38
- package/prompts/testing-guide.md +2 -4
- package/scripts/adopt/adopt-logic.ts +5 -5
- package/scripts/adopt/adopt-toolkits.ts +4 -5
- package/scripts/adopt/adopt.ts +2 -3
- package/scripts/agent/agent-argv.ts +7 -7
- package/scripts/agent/agent-diagnostics.ts +2 -2
- package/scripts/agent/agent-exit-record.ts +1 -1
- package/scripts/agent/agent-headless.ts +1 -1
- package/scripts/agent/agent-launch-environment.ts +6 -1
- package/scripts/agent/agent-role-profile.ts +49 -22
- package/scripts/agent/agent-session-role.ts +32 -0
- package/scripts/agent/api-outage.ts +1 -1
- package/scripts/agent/claude-agent-argv.ts +4 -4
- package/scripts/agent/claude-result-event.ts +4 -4
- package/scripts/agent/codex-hooks.ts +2 -2
- package/scripts/agent/interactive-ask.ts +3 -6
- package/scripts/auto-ok/auto-ok-cli.ts +46 -60
- package/scripts/backlog/backlog-arrival-added.ts +34 -0
- package/scripts/backlog/backlog-arrival.ts +54 -17
- package/scripts/backlog/backlog-budget-cli.ts +34 -6
- package/scripts/backlog/backlog-budget.ts +17 -24
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-args.ts +5 -4
- package/scripts/backlog/backlog-drive-cli.ts +14 -10
- package/scripts/backlog/backlog-drive-epic.ts +85 -0
- package/scripts/backlog/backlog-drive-launch.ts +1 -1
- package/scripts/backlog/backlog-drive-named-offer.ts +60 -9
- package/scripts/backlog/backlog-drive-named.ts +39 -9
- package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +1 -1
- package/scripts/backlog/backlog-drive-retrospective.ts +2 -2
- package/scripts/backlog/backlog-drive.ts +43 -28
- package/scripts/backlog/backlog-idle.ts +88 -0
- package/scripts/backlog/backlog-named.ts +11 -15
- package/scripts/backlog/backlog-next.ts +26 -30
- package/scripts/backlog/backlog-offer-cli.ts +28 -23
- package/scripts/backlog/backlog-offer.ts +7 -7
- package/scripts/backlog/backlog-overlap.ts +178 -0
- package/scripts/backlog/backlog-plan-cli.ts +14 -90
- package/scripts/backlog/backlog-plan-read.ts +111 -0
- package/scripts/backlog/backlog-plan.ts +11 -10
- package/scripts/backlog/backlog-pool.ts +13 -14
- package/scripts/backlog/backlog-rank.ts +11 -11
- package/scripts/backlog/backlog-ready.ts +15 -10
- package/scripts/backlog/backlog-scope.ts +14 -15
- package/scripts/backlog/backlog-stalled-cli.ts +2 -2
- package/scripts/backlog/backlog-stalled-detect.ts +4 -4
- package/scripts/backlog/backlog-stalled.ts +5 -6
- package/scripts/backlog/backlog-waves.ts +4 -4
- package/scripts/backlog/backlogrun-args.ts +74 -0
- package/scripts/backlog/backlogrun-cli.ts +113 -0
- package/scripts/backlog/backlogrun-launch.ts +178 -0
- package/scripts/behavior/behavior-assertion.ts +6 -8
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/behavior/behavior-rules.ts +3 -3
- package/scripts/build/build-claude-md.ts +4 -4
- package/scripts/build/build-codex-hooks.ts +2 -2
- package/scripts/build/build-commands.ts +1 -1
- package/scripts/build/build-hooks.ts +5 -5
- package/scripts/build/build.ts +1 -1
- package/scripts/build/hook-bundle-stamp.ts +109 -7
- package/scripts/build/local-bin.ts +2 -2
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +2 -2
- package/scripts/ci/composite-actions.ts +1 -2
- package/scripts/ci/pr-classification.ts +2 -2
- package/scripts/claude/workflow-destination.ts +1 -1
- package/scripts/clone/clone-aggregate.ts +1 -1
- package/scripts/clone/clone-fingerprint.ts +1 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/index.ts +1 -1
- package/scripts/config-merge/json-format.ts +1 -3
- package/scripts/config-merge/patch-json-array.ts +90 -0
- package/scripts/config-merge/patch-json-key.ts +6 -3
- package/scripts/config-merge/patch-json-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +1 -1
- package/scripts/cost-runtime/context-cut-payback.ts +4 -5
- package/scripts/cost-runtime/context-cut-threshold.ts +4 -6
- package/scripts/cost-runtime/cost-attribute.ts +3 -3
- package/scripts/cost-runtime/cost-blocks.ts +3 -4
- package/scripts/cost-runtime/cost-cli.ts +14 -11
- package/scripts/cost-runtime/cost-corpus.ts +11 -11
- package/scripts/cost-runtime/cost-pricing.ts +4 -4
- package/scripts/cost-runtime/cost-tokens.ts +1 -2
- package/scripts/cost-runtime/cost-transcript.ts +29 -29
- package/scripts/cost-runtime/cost-usage.ts +6 -7
- package/scripts/cost-runtime/cost-verdict.ts +10 -11
- package/scripts/cost-runtime/own-session.ts +1 -1
- package/scripts/cost-runtime/transcript-cwd.ts +2 -2
- package/scripts/delegation/delegation-cli.ts +4 -4
- package/scripts/delegation/delegation-policy.ts +13 -15
- package/scripts/delegation/duplicate-read-guard.ts +9 -10
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +1 -1
- package/scripts/delegation/investigation-guard.ts +18 -22
- package/scripts/delegation/investigation-reads.ts +48 -238
- package/scripts/discovery/repo-discovery.ts +1 -1
- package/scripts/discovery/repo-map-logic.ts +1 -2
- package/scripts/discovery/repo-origin.ts +3 -3
- package/scripts/discovery/repo-party-cli.ts +2 -2
- package/scripts/discovery/repo-party.ts +2 -2
- package/scripts/doctor/doctor-consumer.ts +1 -1
- package/scripts/doctor/doctor-io.ts +6 -7
- package/scripts/doctor/doctor-logic.ts +1 -1
- package/scripts/doctor/doctor-ports.ts +1 -1
- package/scripts/doctor/doctor.ts +8 -9
- package/scripts/document/backlogrun-parent-read-set.ts +5 -6
- package/scripts/document/bash-output-cap.ts +5 -7
- package/scripts/document/capped-print-part.ts +1 -1
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/document-byte-budget.ts +33 -64
- package/scripts/document/document-byte-check.ts +4 -4
- package/scripts/document/document-reachability.ts +7 -8
- package/scripts/document/document-read-cli.ts +2 -2
- package/scripts/document/document-scan.ts +26 -2
- package/scripts/document/document-section-cli.ts +6 -8
- package/scripts/document/document-section.ts +8 -12
- package/scripts/document/edit-files-cli.ts +3 -4
- package/scripts/document/entry-read-budget.ts +8 -70
- package/scripts/document/entry-read-set.ts +51 -34
- package/scripts/document/lane-child-read-set.ts +9 -9
- package/scripts/document/read-files-cli.ts +1 -2
- package/scripts/document/read-set-cli.ts +16 -19
- package/scripts/document/read-set-cost.ts +4 -4
- package/scripts/document/read-set-point-of-use.ts +28 -38
- package/scripts/document/read-set-pricing.ts +1 -1
- package/scripts/document/read-set-trim.ts +3 -3
- package/scripts/document/resident-budget.ts +8 -10
- package/scripts/epic/epic-add-body.ts +15 -18
- package/scripts/epic/epic-add-plan.ts +26 -28
- package/scripts/epic/epic-add.ts +32 -25
- package/scripts/epic/epic-audit-checks.ts +27 -37
- package/scripts/epic/epic-audit-cli.ts +21 -22
- package/scripts/epic/epic-audit-orphans.ts +16 -17
- package/scripts/epic/epic-audit-rationale.ts +10 -15
- package/scripts/epic/epic-audit-report.ts +2 -5
- package/scripts/epic/epic-audit.ts +18 -14
- package/scripts/epic/epic-body.ts +10 -10
- package/scripts/epic/epic-bundle-cli.ts +36 -34
- package/scripts/epic/epic-bundle-evidence.ts +5 -5
- package/scripts/epic/epic-bundle-gaps.ts +6 -9
- package/scripts/epic/epic-bundle-poll.ts +1 -1
- package/scripts/epic/epic-bundle-referenced.ts +11 -14
- package/scripts/epic/epic-bundle.ts +19 -20
- package/scripts/epic/epic-busy.ts +44 -21
- package/scripts/epic/epic-candidate-confirm.ts +15 -18
- package/scripts/epic/epic-chains.ts +18 -23
- package/scripts/epic/epic-classify.ts +11 -12
- package/scripts/epic/epic-cli-argv.ts +5 -6
- package/scripts/epic/epic-cli-remove.ts +9 -4
- package/scripts/epic/epic-cli.ts +38 -26
- package/scripts/epic/epic-close-comment.ts +14 -15
- package/scripts/epic/epic-close.ts +25 -29
- package/scripts/epic/epic-cross-repo.ts +18 -21
- package/scripts/epic/epic-decision.ts +14 -18
- package/scripts/epic/epic-fetch.ts +25 -31
- package/scripts/epic/epic-graph.ts +15 -17
- package/scripts/epic/epic-index.ts +14 -16
- package/scripts/epic/epic-issue.ts +9 -11
- package/scripts/epic/epic-label-age.ts +74 -0
- package/scripts/epic/epic-lane-offer.ts +35 -24
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +8 -8
- package/scripts/epic/epic-next-views.ts +12 -12
- package/scripts/epic/epic-next.ts +29 -33
- package/scripts/epic/epic-outside-blocker.ts +11 -10
- package/scripts/epic/epic-parse.ts +22 -24
- package/scripts/epic/epic-promote.ts +3 -2
- package/scripts/epic/epic-rank.ts +1 -1
- package/scripts/epic/epic-read.ts +10 -8
- package/scripts/epic/epic-reconcile.ts +8 -6
- package/scripts/epic/epic-reference.ts +5 -4
- package/scripts/epic/epic-relation-recheck.ts +10 -11
- package/scripts/epic/epic-relations.ts +9 -8
- package/scripts/epic/epic-remove-plan.ts +4 -5
- package/scripts/epic/epic-remove.ts +7 -5
- package/scripts/epic/epic-report.ts +18 -20
- package/scripts/epic/epic-run.ts +6 -5
- package/scripts/epic/epic-sections.ts +2 -2
- package/scripts/epic/epic-shape.ts +3 -3
- package/scripts/epic/epic-solo-stale.ts +3 -2
- package/scripts/epic/epic-solo.ts +8 -8
- package/scripts/epic/epic-triage.ts +5 -4
- package/scripts/epic/epic-validate.ts +8 -7
- package/scripts/epic/epic.ts +5 -5
- package/scripts/exports/unused-members-cli.ts +1 -1
- package/scripts/followup/followup-issue-number.ts +1 -2
- package/scripts/followup/git-followup-cleanup.ts +6 -7
- package/scripts/followup/git-followup-finish.ts +11 -13
- package/scripts/followup/git-followup-flush.ts +11 -7
- package/scripts/followup/git-followup-issue-close.ts +16 -13
- package/scripts/followup/git-followup-label.ts +9 -6
- package/scripts/followup/git-followup-merged.ts +1 -1
- package/scripts/followup/git-followup-pending.ts +7 -9
- package/scripts/followup/git-followup-stages.ts +28 -17
- package/scripts/followup/git-followup-workflow.ts +19 -21
- package/scripts/followup/git-pr-followup-checks.ts +13 -20
- package/scripts/followup/git-pr-followup-wrapup.ts +7 -7
- package/scripts/followup/git-pr-followup.ts +18 -17
- package/scripts/gate/core-admission.ts +162 -0
- package/scripts/gate/core-budget.ts +134 -91
- package/scripts/gate/gate-ledger.ts +114 -0
- package/scripts/gate/gate-log.ts +7 -9
- package/scripts/gate/gate-plan.ts +103 -35
- package/scripts/gate/gate-report.ts +39 -21
- package/scripts/gate/gate-skip.ts +11 -13
- package/scripts/gate/gate-steps.ts +5 -1
- package/scripts/gate/gate-tree.ts +3 -4
- package/scripts/gate/hook-gate-reuse.ts +9 -9
- package/scripts/gate/machine-capacity.ts +313 -0
- package/scripts/gate/pre-commit-type-check.ts +4 -4
- package/scripts/gate/project-checks.ts +12 -4
- package/scripts/gate/scoped-green.ts +11 -18
- package/scripts/gate/type-check-command.ts +2 -2
- package/scripts/gate/type-check-step.ts +4 -4
- package/scripts/gate/verification-gate.ts +60 -53
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/gh/git-ai-review-scan.ts +3 -2
- package/scripts/gh/git-gh-api-path.ts +10 -11
- package/scripts/gh/git-gh-exec.ts +43 -48
- package/scripts/gh/git-gh-failure.ts +6 -9
- package/scripts/gh/git-gh-helpers.ts +1 -1
- package/scripts/gh/git-gh-issue-list.ts +15 -19
- package/scripts/gh/git-gh-issue-read.ts +43 -60
- package/scripts/gh/git-gh-issue-rest.ts +14 -15
- package/scripts/gh/git-gh-issue-write.ts +52 -40
- package/scripts/gh/git-gh-issue.ts +23 -24
- package/scripts/gh/git-gh-pr-auto-merge.ts +3 -3
- package/scripts/gh/git-gh-pr-read.ts +46 -50
- package/scripts/gh/git-gh-pr-rest.ts +23 -26
- package/scripts/gh/git-gh-pr-review.ts +2 -2
- package/scripts/gh/git-gh-pr-rollup.ts +4 -4
- package/scripts/gh/git-gh-pr-snapshot.ts +8 -10
- package/scripts/gh/git-gh-pr.ts +16 -16
- package/scripts/gh/git-gh-reachability.ts +11 -12
- package/scripts/gh/git-gh-repo.ts +2 -3
- package/scripts/gh/git-gh-rest-state.ts +1 -1
- package/scripts/gh/git-pr-ai-review.ts +6 -5
- package/scripts/gh/git-pr-checks-eval.ts +28 -30
- package/scripts/gh/git-pr-checks-parse.ts +14 -16
- package/scripts/gh/git-pr-checks-watch.ts +17 -17
- package/scripts/gh/git-pr-checks.ts +20 -23
- package/scripts/gh/git-pr-coderabbit.ts +8 -6
- package/scripts/gh/git-pr-confirmation.ts +5 -5
- package/scripts/gh/git-pr-managed-config.ts +7 -9
- package/scripts/gh/git-pr-messages.ts +1 -1
- package/scripts/gh/git-pr.ts +15 -16
- package/scripts/gh/github-issue-url.ts +8 -9
- package/scripts/git/base-tree.ts +66 -0
- package/scripts/git/change-base.ts +42 -2
- package/scripts/git/changed-file-scope.ts +5 -5
- package/scripts/git/changed-paths.ts +1 -2
- package/scripts/git/constants.ts +2 -2
- package/scripts/git/git-branch.ts +1 -1
- package/scripts/git/git-closes-keyword.ts +3 -3
- package/scripts/git/git-command.ts +53 -41
- package/scripts/git/git-common-directory.ts +3 -3
- package/scripts/git/git-diff-reads.ts +14 -15
- package/scripts/git/git-error.ts +1 -1
- package/scripts/git/git-execa-error.ts +1 -2
- package/scripts/git/git-issue.ts +10 -8
- package/scripts/git/git-location-environment.ts +3 -4
- package/scripts/git/git-ls-remote.ts +6 -8
- package/scripts/git/git-pre-push-hook.ts +11 -10
- package/scripts/git/git-preflight.ts +5 -5
- package/scripts/git/git-push-transport.ts +2 -2
- package/scripts/git/git-remote-branch.ts +1 -2
- package/scripts/git/git-schemas.ts +16 -23
- package/scripts/git/git-spawn-sync.ts +1 -1
- package/scripts/git/git-spawn.ts +37 -14
- package/scripts/git/git-ssh-keepalive.ts +12 -5
- package/scripts/git/git-staging.ts +7 -8
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/git-worktree.ts +35 -27
- package/scripts/git/gone-branch.ts +2 -2
- package/scripts/git/listing-cutoff.ts +1 -2
- package/scripts/git/lockfile-sync.ts +65 -0
- package/scripts/git/main-merge-guard.ts +1 -2
- package/scripts/git/main-merge.ts +7 -7
- package/scripts/git/main-sync.ts +23 -8
- package/scripts/git/parse-json-array.ts +18 -23
- package/scripts/git/repository-lock.ts +34 -2
- package/scripts/git/stash/git-stash.ts +4 -5
- package/scripts/git/stash/stash-orphans.ts +5 -3
- package/scripts/git/stash/stash-pop-args.ts +1 -1
- package/scripts/git/stash/stash-pop-cli.ts +3 -3
- package/scripts/git/stash/stash-sweep-lock.ts +2 -2
- package/scripts/hooks/batch-guard.ts +11 -13
- package/scripts/hooks/check-commit-message.ts +12 -9
- package/scripts/hooks/codex-hook-adapter.ts +16 -10
- package/scripts/hooks/edited-cspell.ts +3 -4
- package/scripts/hooks/format-edited-cli.ts +1 -1
- package/scripts/hooks/format-edited-file.ts +11 -17
- package/scripts/hooks/format-rewrite-notice.ts +19 -17
- package/scripts/hooks/pre-push-unit.ts +10 -14
- package/scripts/hooks/pretool-guard-cli.ts +4 -4
- package/scripts/hooks/pretool-guard.ts +93 -18
- package/scripts/hooks/reserved-run.ts +2 -2
- package/scripts/hooks/step-zero-notice.ts +1 -1
- package/scripts/hooks/stop-guard.ts +21 -10
- package/scripts/init/basic-path-migration.ts +2 -2
- package/scripts/init/claude-kit-only-settings.ts +2 -2
- package/scripts/init/claude-plugin-config.ts +2 -2
- package/scripts/init/distributed-paths.ts +4 -4
- package/scripts/init/hook-command-rewrite.ts +3 -3
- package/scripts/init/hook-launch.ts +5 -5
- package/scripts/init/init-actions.ts +13 -0
- package/scripts/init/init-ai-copy.ts +11 -11
- package/scripts/init/init-bootstrap.ts +3 -3
- package/scripts/init/init-copy-content.ts +4 -4
- package/scripts/init/init-logic-json-merge.ts +7 -9
- package/scripts/init/init-logic-migrate.ts +1 -1
- package/scripts/init/init-logic-templates.ts +1 -1
- package/scripts/init/init-logic-workspace.ts +4 -4
- package/scripts/init/init-logic-yaml-merge.ts +2 -2
- package/scripts/init/init-logic.ts +19 -22
- package/scripts/init/init.ts +12 -8
- package/scripts/init/kit-base-preset.ts +1 -1
- package/scripts/init/kit-setup-state.ts +1 -1
- package/scripts/init/kit-written-paths.ts +1 -2
- package/scripts/init/package-manager-pin.ts +35 -0
- package/scripts/init/project-profile-cli.ts +1 -1
- package/scripts/init/project-profile.ts +3 -3
- package/scripts/init/session-language-environment.ts +1 -1
- package/scripts/init/start-exec.ts +3 -4
- package/scripts/init/start-plan.ts +2 -2
- package/scripts/init/start-setup-pr.ts +3 -2
- package/scripts/init/start-steps.ts +2 -2
- package/scripts/init/tsconfig-preset-migration.ts +1 -1
- package/scripts/init/vscode-tasks.ts +62 -0
- package/scripts/issue/baseline-measure.ts +2 -2
- package/scripts/issue/behavior-change-lint.ts +2 -2
- package/scripts/issue/defect-rate-cli.ts +6 -7
- package/scripts/issue/defect-rate.ts +37 -27
- package/scripts/issue/git-next-issues.ts +9 -8
- package/scripts/issue/issue-auto-ok.ts +49 -11
- package/scripts/issue/issue-backlinks-cli.ts +5 -5
- package/scripts/issue/issue-backlinks.ts +6 -6
- package/scripts/issue/issue-cite-cli.ts +20 -18
- package/scripts/issue/issue-cite.ts +18 -8
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +6 -4
- package/scripts/issue/issue-file-cli.ts +75 -15
- package/scripts/issue/issue-file-fold.ts +155 -0
- package/scripts/issue/issue-file.ts +14 -6
- package/scripts/issue/issue-fold-cli.ts +14 -9
- package/scripts/issue/issue-fold.ts +23 -8
- package/scripts/issue/issue-labels.ts +46 -37
- package/scripts/issue/issue-lint-cli.ts +2 -2
- package/scripts/issue/issue-lint.ts +1 -1
- package/scripts/issue/issue-merged.ts +10 -4
- package/scripts/issue/issue-number-shape.ts +27 -0
- package/scripts/issue/issue-rank.ts +1 -1
- package/scripts/issue/issue-read-cli.ts +4 -5
- package/scripts/issue/issue-read.ts +4 -5
- package/scripts/issue/issue-reference.ts +5 -5
- package/scripts/issue/issue-release-cli.ts +165 -0
- package/scripts/issue/issue-release.ts +58 -0
- package/scripts/issue/issue-report-failures.ts +7 -4
- package/scripts/issue/issue-scout-cli.ts +11 -11
- package/scripts/issue/issue-scout-closed.ts +4 -4
- package/scripts/issue/issue-scout.ts +4 -5
- package/scripts/issue/issue-state-cli.ts +17 -10
- package/scripts/issue/issue-state.ts +12 -13
- package/scripts/issue/issue-wip.ts +7 -7
- package/scripts/issue/markdown-section.ts +3 -3
- package/scripts/issue/measure-rerun-cli.ts +10 -9
- package/scripts/issue/reproduction-measure.ts +3 -3
- package/scripts/issue/session-cite.ts +56 -0
- package/scripts/josh/agent-session-environment.ts +10 -8
- package/scripts/josh/cli-body.ts +2 -2
- package/scripts/josh/command-suggest.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +20 -23
- package/scripts/josh/hook-decision.ts +24 -28
- package/scripts/josh/josh-command-map.ts +4 -1
- package/scripts/josh/josh-command-types.ts +32 -34
- package/scripts/josh/josh-commands-ai.ts +6 -6
- package/scripts/josh/josh-commands-backlog.ts +15 -3
- package/scripts/josh/josh-commands-clone.ts +1 -1
- package/scripts/josh/josh-commands-development.ts +33 -4
- package/scripts/josh/josh-commands-document.ts +3 -3
- package/scripts/josh/josh-commands-guard.ts +3 -3
- package/scripts/josh/josh-commands-issue.ts +11 -5
- package/scripts/josh/josh-commands-lane.ts +16 -5
- package/scripts/josh/josh-commands-lint.ts +1 -1
- package/scripts/josh/josh-commands-maintenance.ts +2 -2
- package/scripts/josh/josh-commands-run.ts +20 -6
- package/scripts/josh/josh-commands-split.ts +1 -2
- package/scripts/josh/josh-commands-versioning.ts +5 -5
- package/scripts/josh/josh-commands-workflow.ts +30 -22
- package/scripts/josh/josh-environment-file.ts +1 -1
- package/scripts/josh/josh-in-process.ts +3 -3
- package/scripts/josh/josh-logic.ts +10 -10
- package/scripts/josh/josh-run.ts +3 -3
- package/scripts/josh/josh-verdict.ts +9 -12
- package/scripts/josh/josh.ts +3 -3
- package/scripts/josh/kit-only.ts +2 -2
- package/scripts/josh/path-decision.ts +3 -3
- package/scripts/josh/platform-temporary.ts +7 -5
- package/scripts/josh/process-identity.ts +24 -6
- package/scripts/josh/process-owner.ts +4 -4
- package/scripts/josh/session-language-cli.ts +53 -11
- package/scripts/josh/session-language.ts +1 -1
- package/scripts/josh/stamp-file.ts +48 -29
- package/scripts/josh/stamp-record.ts +57 -0
- package/scripts/lane/lane-await.ts +35 -11
- package/scripts/lane/lane-cache.ts +6 -6
- package/scripts/lane/lane-capacity.ts +32 -17
- package/scripts/lane/lane-child-invocation.ts +17 -15
- package/scripts/lane/lane-child-marker.ts +12 -12
- package/scripts/lane/lane-cli.ts +20 -13
- package/scripts/lane/lane-close.ts +6 -6
- package/scripts/lane/lane-dispatch.ts +61 -72
- package/scripts/lane/lane-environment.ts +5 -5
- package/scripts/lane/lane-guard-policy.ts +7 -21
- package/scripts/lane/lane-handoff.ts +2 -2
- package/scripts/lane/lane-install.ts +9 -10
- package/scripts/lane/lane-launch-cli.ts +13 -8
- package/scripts/lane/lane-ledger.ts +73 -11
- package/scripts/lane/lane-leftover.ts +44 -30
- package/scripts/lane/lane-limit-cli.ts +160 -0
- package/scripts/lane/lane-limit-override.ts +74 -0
- package/scripts/lane/lane-load.ts +19 -68
- package/scripts/lane/lane-measure-cli.ts +15 -25
- package/scripts/lane/lane-occupancy.ts +6 -4
- package/scripts/lane/lane-open.ts +25 -24
- package/scripts/lane/lane-output.ts +4 -3
- package/scripts/lane/lane-paths.ts +22 -8
- package/scripts/lane/lane-phase.ts +33 -0
- package/scripts/lane/lane-reap.ts +2 -2
- package/scripts/lane/lane-registry.ts +27 -15
- package/scripts/lane/lane-relaunch.ts +9 -9
- package/scripts/lane/lane-report.ts +5 -4
- package/scripts/lane/lane-resume.ts +2 -2
- package/scripts/lane/lane-sampler.ts +55 -0
- package/scripts/lane/lane-seed.ts +7 -7
- package/scripts/lane/lane-stage-stats.ts +135 -0
- package/scripts/lane/lane-start-point.ts +8 -11
- package/scripts/lane/lane-stats.ts +60 -15
- package/scripts/lane/lane-stray.ts +140 -0
- package/scripts/lane/lane-vacant.ts +1 -1
- package/scripts/lane/openai-lane-supervisor-decision.ts +3 -7
- package/scripts/lane/openai-lane-supervisor-owner.ts +3 -9
- package/scripts/lane/openai-review-broker.ts +2 -4
- package/scripts/lib/ancestor-directories.ts +1 -1
- package/scripts/lib/bounded-pool.ts +2 -2
- package/scripts/lib/buffered-process.ts +4 -6
- package/scripts/lib/caddy-logs.sh +0 -0
- package/scripts/lib/cli-flags.ts +39 -6
- package/scripts/lib/error-message.ts +1 -1
- package/scripts/lib/json-value.ts +17 -3
- package/scripts/lib/poll.ts +1 -1
- package/scripts/lib/status-icons.ts +3 -3
- package/scripts/lib/timed-fetch.ts +1 -1
- package/scripts/lib/timeouts.ts +1 -1
- package/scripts/lines/bytes-command.ts +3 -4
- package/scripts/lines/effective-limit.ts +25 -12
- package/scripts/lines/line-budget.ts +47 -55
- package/scripts/lines/line-targets.ts +6 -2
- package/scripts/lines/lines-command.ts +3 -3
- package/scripts/lint/cspell-cached.ts +1 -1
- package/scripts/lint/cycle-recheck.ts +122 -0
- package/scripts/lint/format.ts +1 -2
- package/scripts/lint/lint-parallel.ts +34 -19
- package/scripts/lint/lint-related-scope.ts +25 -15
- package/scripts/lint/lint-related.ts +6 -7
- package/scripts/managed-marker/index.ts +1 -1
- package/scripts/managed-marker/managed-marker-logic.ts +1 -2
- package/scripts/notify/git-notify.ts +9 -7
- package/scripts/notify/telegram-notify.ts +53 -37
- package/scripts/notify/telegram-test-logic.ts +3 -3
- package/scripts/notify/telegram-test.ts +45 -30
- package/scripts/observations/observation-ledger-home.ts +14 -8
- package/scripts/observations/observation-ledger-line.ts +3 -2
- package/scripts/observations/observation-ledger-migrate.ts +3 -4
- package/scripts/observations/observation-ledger-prepare.ts +4 -4
- package/scripts/observations/observation-ledger.ts +14 -15
- package/scripts/observations/observation-record-cli.ts +83 -0
- package/scripts/observations/observation-record.ts +91 -0
- package/scripts/observations/observations-flush-cli.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +7 -6
- package/scripts/observations/observations-flush.ts +26 -27
- package/scripts/overrides/overrides-check.ts +18 -8
- package/scripts/package/package-scout-cli.ts +1 -1
- package/scripts/package/package-scout-format.ts +2 -2
- package/scripts/package/package-scout.ts +1 -1
- package/scripts/propagate/propagate-git-failure.ts +1 -1
- package/scripts/propagate/propagate-git.ts +7 -7
- package/scripts/propagate/propagate-plan.ts +2 -2
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -7
- package/scripts/propagate/propagate-select.ts +1 -1
- package/scripts/propagate/propagate-steps.ts +19 -20
- package/scripts/propagate/propagate-targets.ts +6 -10
- package/scripts/propagate/propagate.ts +5 -5
- package/scripts/refactor/import-graph.ts +1 -1
- package/scripts/refactor/refactor-lint.ts +4 -10
- package/scripts/refactor/refactor-scan-cli.ts +1 -1
- package/scripts/refactor/refactor-scan.ts +2 -2
- package/scripts/refactor/refactor-targets.ts +1 -1
- package/scripts/release/github-release-cli.ts +25 -3
- package/scripts/release/github-release-environment.ts +1 -0
- package/scripts/release/github-release-runs.ts +115 -0
- package/scripts/release/github-release.ts +13 -67
- package/scripts/release/release-cli.ts +21 -4
- package/scripts/release/release-history.ts +6 -10
- package/scripts/release/release-plan.ts +3 -3
- package/scripts/release/release-progress.ts +3 -4
- package/scripts/release/release-publish.ts +8 -9
- package/scripts/release/release-scope-cli.ts +8 -10
- package/scripts/release/release-tag.ts +6 -8
- package/scripts/release/release-worktree.ts +5 -5
- package/scripts/repo/auto-merge-setting-logic.ts +7 -9
- package/scripts/repo/auto-merge-setting.ts +1 -1
- package/scripts/repo/repo-setting.ts +4 -4
- package/scripts/repo/repository-labels.ts +1 -1
- package/scripts/repo/required-checks-logic.ts +3 -3
- package/scripts/repo/required-checks-report.ts +1 -1
- package/scripts/repo/ruleset-check-cli.ts +1 -1
- package/scripts/repo/ruleset-check.ts +1 -1
- package/scripts/report/report-format-reference.ts +26 -0
- package/scripts/report/report-lint-cli.ts +2 -2
- package/scripts/report/report-lint.ts +16 -2
- package/scripts/review/disposition-cli.ts +2 -2
- package/scripts/review/disposition-logic.ts +1 -1
- package/scripts/review/live-evidence.ts +9 -6
- package/scripts/review/review-attest-cli.ts +1 -2
- package/scripts/review/review-attest.ts +3 -3
- package/scripts/review/review-brief-cli.ts +19 -20
- package/scripts/review/review-brief.ts +29 -32
- package/scripts/review/review-checkout.ts +2 -2
- package/scripts/review/review-diff-parts.ts +3 -5
- package/scripts/review/review-diff-write.ts +1 -1
- package/scripts/review/review-finding-ledger.ts +7 -4
- package/scripts/review/review-findings-cli.ts +2 -2
- package/scripts/review/review-level.ts +4 -7
- package/scripts/review/review-record-cli.ts +73 -16
- package/scripts/review/review-record.ts +5 -4
- package/scripts/review/review-round2-cli.ts +2 -3
- package/scripts/review/review-round2.ts +13 -21
- package/scripts/review/review-stamps.ts +9 -71
- package/scripts/review/review-tree.ts +4 -5
- package/scripts/rules/bash-triggers.ts +4 -4
- package/scripts/rules/decision-oracle-batch.ts +5 -6
- package/scripts/rules/decision-oracle-stage.ts +1 -1
- package/scripts/rules/decision-oracle-tokens.ts +1 -2
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/delivered-rules.ts +61 -406
- package/scripts/rules/destructive-command.ts +2 -2
- package/scripts/rules/direct-filing.ts +4 -4
- package/scripts/rules/direct-pr-create.ts +2 -2
- package/scripts/rules/early-heartbeat.ts +15 -19
- package/scripts/rules/file-body.ts +5 -6
- package/scripts/rules/filing-cap.ts +6 -7
- package/scripts/rules/filing-offer.ts +1 -1
- package/scripts/rules/firing-point.ts +6 -6
- package/scripts/rules/gh-api.ts +2 -2
- package/scripts/rules/git-argv.ts +3 -3
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/hook-context-line.ts +31 -0
- package/scripts/rules/implementation-cut-verdict.ts +5 -8
- package/scripts/rules/implementation-cut.ts +35 -32
- package/scripts/rules/index-guard.ts +2 -2
- package/scripts/rules/issue-citation.ts +7 -7
- package/scripts/rules/issue-comments.ts +21 -13
- package/scripts/rules/josh-git-bare.ts +2 -2
- package/scripts/rules/lane-background.ts +14 -16
- package/scripts/rules/lane-carry-conflict.ts +41 -5
- package/scripts/rules/lane-interactive-ask.ts +6 -9
- package/scripts/rules/lane-park.ts +12 -16
- package/scripts/rules/lane-split-park.ts +1 -2
- package/scripts/rules/lane-switch-main.ts +10 -13
- package/scripts/rules/last-prompt.ts +1 -1
- package/scripts/rules/oracle-consulted.ts +5 -5
- package/scripts/rules/oracle-firing.ts +6 -9
- package/scripts/rules/oracle-list-cli.ts +2 -2
- package/scripts/rules/permission-guards.ts +2 -2
- package/scripts/rules/piped-verification.ts +79 -9
- package/scripts/rules/poll-loop.ts +9 -11
- package/scripts/rules/pre-gate-cut.ts +33 -30
- package/scripts/rules/prior-comment-read.ts +3 -3
- package/scripts/rules/protected-files.ts +25 -13
- package/scripts/rules/raw-field-body.ts +3 -4
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +10 -12
- package/scripts/rules/rule-guard.ts +1 -1
- package/scripts/rules/rule-list.ts +51 -0
- package/scripts/rules/rule-registry-rows.ts +282 -0
- package/scripts/rules/rule-registry.ts +109 -0
- package/scripts/rules/rule-value-cache.ts +2 -2
- package/scripts/rules/rule-value-cli.ts +6 -4
- package/scripts/rules/rule-value.ts +61 -22
- package/scripts/rules/run-tail-rule.ts +11 -15
- package/scripts/rules/shell-body-trigger.ts +7 -7
- package/scripts/rules/shell-segments.ts +2 -4
- package/scripts/rules/stop-rules.ts +54 -41
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +2 -2
- package/scripts/rules/third-party-write.ts +3 -3
- package/scripts/rules/worktree-guard.ts +12 -5
- package/scripts/run/add/run-add-cli.ts +165 -0
- package/scripts/run/add/run-add.ts +124 -0
- package/scripts/run/board/run-board-cli.ts +207 -0
- package/scripts/run/board/run-board-closed.ts +95 -0
- package/scripts/run/board/run-board-every.ts +60 -0
- package/scripts/run/board/run-board-fetch.ts +38 -0
- package/scripts/run/board/run-board-fit.ts +219 -0
- package/scripts/run/board/run-board-github.ts +162 -0
- package/scripts/run/board/run-board-header.ts +275 -0
- package/scripts/run/board/run-board-kind.ts +35 -0
- package/scripts/run/board/run-board-labels.ts +299 -0
- package/scripts/run/board/run-board-layout.ts +222 -0
- package/scripts/run/board/run-board-link.ts +31 -0
- package/scripts/run/board/run-board-machine.ts +198 -0
- package/scripts/run/board/run-board-notes.ts +103 -0
- package/scripts/run/board/run-board-phase.ts +136 -0
- package/scripts/run/board/run-board-plan.ts +129 -0
- package/scripts/run/board/run-board-read.ts +62 -0
- package/scripts/run/board/run-board-render-legend.ts +82 -0
- package/scripts/run/board/run-board-render-notes.ts +77 -0
- package/scripts/run/board/run-board-render-slot.ts +50 -0
- package/scripts/run/board/run-board-render.ts +407 -0
- package/scripts/run/board/run-board-scope.ts +17 -0
- package/scripts/run/board/run-board-screen.ts +43 -0
- package/scripts/run/board/run-board-span.ts +66 -0
- package/scripts/run/board/run-board-spin.ts +115 -0
- package/scripts/run/board/run-board-state.ts +113 -0
- package/scripts/run/board/run-board-status.ts +279 -0
- package/scripts/run/board/run-board-tick.ts +210 -0
- package/scripts/run/board/run-board-track.ts +22 -0
- package/scripts/run/board/run-board-usage-read.ts +255 -0
- package/scripts/run/board/run-board-usage-rusage.ts +124 -0
- package/scripts/run/board/run-board-usage-text.ts +80 -0
- package/scripts/run/board/run-board-usage.ts +165 -0
- package/scripts/run/carry/run-carry-added.ts +62 -0
- package/scripts/run/carry/run-carry-args.ts +25 -22
- package/scripts/run/carry/run-carry-change.ts +1 -1
- package/scripts/run/carry/run-carry-cli.ts +71 -48
- package/scripts/run/carry/run-carry-conversation.ts +6 -7
- package/scripts/run/carry/run-carry-ended.ts +85 -0
- package/scripts/run/carry/run-carry-reclaim.ts +1 -1
- package/scripts/run/carry/run-carry-stash.ts +3 -2
- package/scripts/run/carry/run-carry-streak.ts +8 -10
- package/scripts/run/carry/run-carry.ts +85 -89
- package/scripts/run/cut/run-cut-args.ts +7 -7
- package/scripts/run/cut/run-cut-cli.ts +68 -37
- package/scripts/run/cut/run-cut-handoff.ts +15 -15
- package/scripts/run/cut/run-cut-report.ts +37 -16
- package/scripts/run/cut/run-cut.ts +63 -77
- package/scripts/run/detached-launch.ts +35 -50
- package/scripts/run/entry/run-entry-cli.ts +48 -27
- package/scripts/run/entry/run-entry-stop.ts +7 -9
- package/scripts/run/entry/run-entry.ts +5 -6
- package/scripts/run/event/run-event-cli.ts +5 -6
- package/scripts/run/event/run-event-filed.ts +69 -0
- package/scripts/run/event/run-event-follow.ts +3 -3
- package/scripts/run/event/run-event-plan.ts +38 -0
- package/scripts/run/event/run-event-render.ts +10 -4
- package/scripts/run/event/run-event-scope.ts +47 -18
- package/scripts/run/event/run-event-stream-emit.ts +64 -11
- package/scripts/run/event/run-event-stream.ts +172 -43
- package/scripts/run/event/run-event-watch.ts +4 -6
- package/scripts/run/hold/run-hold-cli.ts +65 -62
- package/scripts/run/hold/run-hold.ts +88 -46
- package/scripts/run/merge/run-merge-cli.ts +116 -77
- package/scripts/run/merge/run-merge-collect.ts +107 -0
- package/scripts/run/merge/run-merge-steps.ts +112 -65
- package/scripts/run/merge/run-merge-token.ts +30 -0
- package/scripts/run/merge/run-merge.ts +31 -22
- package/scripts/run/progress/run-progress-args.ts +4 -4
- package/scripts/run/progress/run-progress-cli.ts +39 -50
- package/scripts/run/progress/run-progress-clock.ts +25 -32
- package/scripts/run/progress/run-progress-config.ts +6 -9
- package/scripts/run/progress/run-progress-read.ts +9 -10
- package/scripts/run/progress/run-progress.ts +48 -53
- package/scripts/run/review/run-review-cli.ts +6 -6
- package/scripts/run/review/run-review-steps.ts +6 -6
- package/scripts/run/review/run-review.ts +9 -11
- package/scripts/run/run-cli-fault.ts +29 -0
- package/scripts/run/run-ending-cli.ts +3 -3
- package/scripts/run/run-ending.ts +10 -14
- package/scripts/run/run-halfrun-resume.ts +6 -8
- package/scripts/run/run-headless.ts +25 -12
- package/scripts/run/run-invocation.ts +17 -22
- package/scripts/run/run-label.ts +7 -5
- package/scripts/run/run-liveness-cli.ts +19 -6
- package/scripts/run/run-liveness.ts +27 -38
- package/scripts/run/run-next-cli.ts +5 -9
- package/scripts/run/run-next.ts +4 -5
- package/scripts/run/run-parent-cut-hook.ts +10 -12
- package/scripts/run/run-preflight.ts +25 -29
- package/scripts/run/run-prep-cli.ts +17 -13
- package/scripts/run/run-prep-locate.ts +4 -5
- package/scripts/run/run-prep.ts +7 -10
- package/scripts/run/run-prrun-resume.ts +2 -2
- package/scripts/run/run-report-cli.ts +4 -4
- package/scripts/run/run-report.ts +9 -14
- package/scripts/run/run-retrospective.ts +3 -3
- package/scripts/run/run-section.ts +42 -0
- package/scripts/run/run-stage-read.ts +2 -2
- package/scripts/run/run-stage.ts +6 -4
- package/scripts/run/run-status-cli.ts +7 -5
- package/scripts/run/run-status.ts +6 -7
- package/scripts/run/run-step-cli.ts +13 -15
- package/scripts/run/run-step.ts +62 -48
- package/scripts/run/run-stop-notify.ts +7 -8
- package/scripts/run/run-stranded-cli.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +4 -4
- package/scripts/run/run-stranded.ts +11 -13
- package/scripts/run/run-tail-cli.ts +15 -16
- package/scripts/run/run-tail.ts +14 -33
- package/scripts/run/run-watcher-guard-cli.ts +3 -4
- package/scripts/run/run-watcher-guard.ts +11 -12
- package/scripts/run/run-watcher-hook.ts +6 -12
- package/scripts/run/ship/run-ship-cli.ts +67 -33
- package/scripts/run/ship/run-ship-detach.ts +15 -13
- package/scripts/run/ship/run-ship-lock.ts +1 -1
- package/scripts/run/ship/run-ship-next.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +27 -11
- package/scripts/run/ship/run-ship-preflight.ts +10 -11
- package/scripts/run/ship/run-ship-probe.ts +4 -4
- package/scripts/run/ship/run-ship-return.ts +1 -1
- package/scripts/run/ship/run-ship-review-steps.ts +43 -24
- package/scripts/run/ship/run-ship-review.ts +12 -14
- package/scripts/run/ship/run-ship-scoped.ts +15 -6
- package/scripts/run/ship/run-ship-stage.ts +80 -26
- package/scripts/run/ship/run-ship-steps.ts +26 -16
- package/scripts/run/ship/run-ship-stop-text.ts +4 -2
- package/scripts/run/ship/run-ship-sync.ts +9 -8
- package/scripts/run/ship/run-ship.ts +17 -32
- package/scripts/run/tidy/run-tidy-cli.ts +9 -5
- package/scripts/run/tidy/run-tidy-lanes.ts +18 -7
- package/scripts/run/tidy/run-tidy-stashes.ts +8 -8
- package/scripts/run/tidy/run-tidy.ts +4 -3
- package/scripts/run/wake/run-wake-cli.ts +27 -33
- package/scripts/run/wake/run-wake-describe.ts +76 -29
- package/scripts/run/wake/run-wake-driver.ts +14 -14
- package/scripts/run/wake/run-wake-handoff.ts +6 -6
- package/scripts/run/wake/run-wake-loop.ts +13 -21
- package/scripts/run/wake/run-wake-restart.ts +4 -5
- package/scripts/run/wake/run-wake-session.ts +23 -27
- package/scripts/run/wake/run-wake.ts +57 -328
- package/scripts/safe-chain/ci-installer-pin.ts +3 -3
- package/scripts/safe-chain/pack-hook.ts +2 -2
- package/scripts/safe-chain/preinstall-command.ts +2 -2
- package/scripts/security/security-audit-logic.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +1 -1
- package/scripts/security/security-audit-provision.ts +2 -2
- package/scripts/security/security-audit.ts +5 -5
- package/scripts/security/security-updates-logic.ts +2 -3
- package/scripts/security/security-updates.ts +2 -4
- package/scripts/self-sync-guard/index.ts +1 -1
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +2 -2
- package/scripts/self-sync-guard/self-sync-refusal.ts +1 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +1 -1
- package/scripts/sonar/sonar-hotspots.ts +1 -1
- package/scripts/sonar/sonar-new-code-cli.ts +1 -1
- package/scripts/sonar/sonar-new-code.ts +1 -1
- package/scripts/sonar/sonar-project.ts +1 -1
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +3 -3
- package/scripts/sync/directory-copy-guard.ts +2 -3
- package/scripts/sync/managed-config-scope-cli.ts +1 -2
- package/scripts/sync/managed-config-scope.ts +4 -4
- package/scripts/sync/plugin-skill-directories.ts +2 -2
- package/scripts/sync/reconcile-templates.ts +17 -8
- package/scripts/sync/removed-skill-manifest.ts +2 -3
- package/scripts/sync/sync-ai-files.ts +7 -7
- package/scripts/sync/sync-configs.ts +30 -3
- package/scripts/sync/sync-hook-safety.ts +2 -2
- package/scripts/sync/sync.ts +23 -10
- package/scripts/sync/synced-paths.ts +2 -1
- package/scripts/sync/workflow-pin-logic.ts +1 -1
- package/scripts/test/test-declared-changed.ts +4 -4
- package/scripts/test/test-declared-logic.ts +2 -3
- package/scripts/test/test-declared-match.ts +25 -4
- package/scripts/test/test-declared.ts +26 -9
- package/scripts/test/test-red-commit.ts +3 -2
- package/scripts/test/test-red-logic.ts +7 -14
- package/scripts/test/test-red.ts +12 -47
- package/scripts/test/test-related-scope.ts +2 -3
- package/scripts/test/test-related.ts +3 -3
- package/scripts/test/test-type-logic.ts +1 -2
- package/scripts/test/test-unit-guard.ts +13 -17
- package/scripts/test/unit-worker-share.ts +7 -8
- package/scripts/time-runtime/time-agent-bundles.ts +2 -4
- package/scripts/time-runtime/time-background.ts +17 -21
- package/scripts/time-runtime/time-batch-guard.ts +67 -342
- package/scripts/time-runtime/time-bundle-call.ts +26 -28
- package/scripts/time-runtime/time-bundles.ts +11 -12
- package/scripts/time-runtime/time-call-identity.ts +1 -1
- package/scripts/time-runtime/time-command-key.ts +2 -2
- package/scripts/time-runtime/time-density-hook.ts +8 -11
- package/scripts/time-runtime/time-density.ts +5 -5
- package/scripts/time-runtime/time-followup-stage.ts +7 -7
- package/scripts/time-runtime/time-format.ts +5 -5
- package/scripts/time-runtime/time-hook-transcript.ts +3 -3
- package/scripts/time-runtime/time-instant.ts +1 -1
- package/scripts/time-runtime/time-markers.ts +15 -19
- package/scripts/time-runtime/time-phase-names.ts +3 -3
- package/scripts/time-runtime/time-reported-failure.ts +15 -19
- package/scripts/time-runtime/time-round-trips.ts +20 -23
- package/scripts/time-runtime/time-shell.ts +8 -8
- package/scripts/time-runtime/time-single-check.ts +1 -2
- package/scripts/time-runtime/time-spans.ts +35 -40
- package/scripts/time-runtime/time-tool-call.ts +15 -16
- package/scripts/time-runtime/time-transcript-line.ts +53 -34
- package/scripts/time-runtime/time-writes.ts +5 -5
- package/scripts/ui/ui-routes-cli.ts +1 -2
- package/scripts/ui/ui-routes.ts +1 -2
- package/scripts/version/bump-version.ts +1 -1
- package/scripts/version/fresh-metadata-cache.ts +2 -2
- package/scripts/version/latest-corepack.ts +129 -98
- package/scripts/version/latest-lane-guard.ts +1 -1
- package/scripts/version/latest-scope-cli.ts +2 -2
- package/scripts/version/latest-stamp.ts +1 -2
- package/scripts/version/latest-update.ts +2 -2
- package/scripts/version/npm-registry.ts +2 -2
- package/scripts/version/package-manager-version.ts +18 -0
- package/scripts/version/publishable-range-check.ts +2 -1
- package/scripts/version/publishable-range.ts +1 -1
- package/scripts/version/release-age.ts +11 -11
- package/scripts/version/release-hold.ts +2 -2
- package/scripts/version/safe-chain-version-update.ts +3 -3
- package/scripts/version/version-check-logic.ts +2 -3
- package/scripts/version/version-check.ts +1 -2
- package/scripts/version/version-command-config.ts +2 -2
- package/scripts/version/version-commands.ts +3 -3
- package/scripts/version/version-remote.ts +4 -4
- package/scripts/version/version-targets.ts +2 -2
- package/templates/gitignore +7 -0
- package/templates/workflows/github-release.yml +4 -0
- package/dist/hooks/chunk-NV2JRZZO.js +0 -6385
- package/dist/hooks/chunk-RKUAD3I6.js +0 -90
- package/dist/hooks/chunk-WPALEIRX.js +0 -18
- package/scripts/backlog/backlog-restructure.ts +0 -152
- package/scripts/rules/issue-fold-rule.ts +0 -72
- package/scripts/rules/wip-cap.ts +0 -63
- package/scripts/run/run-issue-number.ts +0 -19
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { agent_role_profile } from '#scripts/agent/agent-role-profile'
|
|
2
2
|
import { issue_cite, type IssueCiter } from '#scripts/issue/issue-cite'
|
|
3
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
3
4
|
import { run_liveness } from '#scripts/run/run-liveness'
|
|
4
5
|
import type { LaneInfo } from './lane-registry'
|
|
5
6
|
|
|
6
|
-
// What a person reads when they ask what is open
|
|
7
|
+
// What a person reads when they ask what is open.
|
|
7
8
|
//
|
|
8
9
|
// The dev and preview ports are the ones the registry already resolved through `ports/index.js`
|
|
9
10
|
// when it read each lane's `.env`, so the numbers printed here are the same ones `josh port` and
|
|
@@ -31,7 +32,7 @@ function value_or_unknown(value: number | undefined): string {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
// The recorded output path goes last and is labelled, so it is told apart from the directory beside
|
|
34
|
-
// it
|
|
35
|
+
// it. A lane that records none prints `output -` rather than nothing at
|
|
35
36
|
// all: a session that did not open the lane has to be able to see that the record is missing, not
|
|
36
37
|
// read a shorter row as one field it failed to notice.
|
|
37
38
|
function output_column(output: string | undefined): string {
|
|
@@ -52,7 +53,7 @@ function event_column(lane: LaneInfo): string {
|
|
|
52
53
|
// The plain `#N`, for a caller that could not read the repository the issue would link into.
|
|
53
54
|
const PLAIN_CITE: IssueCiter = issue_cite.citer(undefined, new Map())
|
|
54
55
|
|
|
55
|
-
// The issue leads as a citation
|
|
56
|
+
// The issue leads as a citation: a lane status report copies this row, and a
|
|
56
57
|
// bare `#N` copied into it is what the Stop guard sends back.
|
|
57
58
|
function describe_lane(lane: LaneInfo, cite: IssueCiter = PLAIN_CITE): string {
|
|
58
59
|
return [
|
|
@@ -84,7 +85,7 @@ function describe_ports(lane: LaneInfo): string {
|
|
|
84
85
|
// The one-line confirmation a person reads on standard error while standard output carries the
|
|
85
86
|
// directory alone, so `dir=$(pnpm josh lane:open 1490)` stays usable.
|
|
86
87
|
function describe_opened(lane: LaneInfo): string {
|
|
87
|
-
return `Opened a lane for
|
|
88
|
+
return `Opened a lane for ${session_cite.issue(lane.issue)} on ${lane.branch}: ${describe_ports(lane)}.`
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
const lane_report = {
|
|
@@ -3,8 +3,8 @@ import { api_outage } from '#scripts/agent/api-outage'
|
|
|
3
3
|
import type { ClaudeResultEvent } from '#scripts/agent/claude-result-event'
|
|
4
4
|
import { lane_child_invocation } from './lane-child-invocation'
|
|
5
5
|
|
|
6
|
-
// How a lane re-dispatch chooses between resuming the disconnected child's session and starting fresh
|
|
7
|
-
//
|
|
6
|
+
// How a lane re-dispatch chooses between resuming the disconnected child's session and starting fresh.
|
|
7
|
+
// The premise the whole issue rests on: a child that could not reach the API
|
|
8
8
|
// left a `session_id` in its exit record, and re-dispatching it as a bare `fullrun #<N>` threw that
|
|
9
9
|
// context away — a resumed child keeps it and loses only the last round-trip.
|
|
10
10
|
//
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { lane_ledger } from './lane-ledger'
|
|
2
|
+
import { lane_load } from './lane-load'
|
|
3
|
+
|
|
4
|
+
// The machine-load sampler: one `load` entry appended to the lane ledger, once or on a timer.
|
|
5
|
+
//
|
|
6
|
+
// **`start` is how a `backlogrun` samples itself.** `backlog:drive` starts it for as long as its loop
|
|
7
|
+
// runs, so a period needs nobody to remember a second terminal — the sampler `josh lane:sample` offers
|
|
8
|
+
// was started by hand, and a run nobody started it beside recorded no load at all. The timer lives in
|
|
9
|
+
// the drive's own process and is unreferenced: it ends with the drive, never holds it open, and leaves
|
|
10
|
+
// no process or pid file behind to stop.
|
|
11
|
+
|
|
12
|
+
const SAMPLE_INTERVAL_MS = 60_000
|
|
13
|
+
|
|
14
|
+
// Where the ledger is and what "now" is, overridable so a test reads a fixed ledger at a fixed instant.
|
|
15
|
+
interface MeasureContext {
|
|
16
|
+
ledger_path?: string
|
|
17
|
+
now_ms?: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function take(context: MeasureContext = {}): Promise<void> {
|
|
21
|
+
const at = new Date(context.now_ms ?? Date.now()).toISOString()
|
|
22
|
+
|
|
23
|
+
await lane_ledger.record(await lane_load.sample(at), context.ledger_path)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// A timer tick has no caller to raise into, and a sample that could not be read must never end the run
|
|
27
|
+
// it measures.
|
|
28
|
+
async function take_quietly(context: MeasureContext): Promise<void> {
|
|
29
|
+
try {
|
|
30
|
+
await take(context)
|
|
31
|
+
} catch {
|
|
32
|
+
// Best-effort: an unread sample is a gap in the measurement, not a failure of the run.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Sample now and then every minute; the returned function stops it. */
|
|
37
|
+
function start(context: MeasureContext = {}): () => void {
|
|
38
|
+
void take_quietly(context)
|
|
39
|
+
const timer = setInterval(() => {
|
|
40
|
+
void take_quietly(context)
|
|
41
|
+
}, SAMPLE_INTERVAL_MS).unref()
|
|
42
|
+
|
|
43
|
+
return () => {
|
|
44
|
+
clearInterval(timer)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const lane_sampler = {
|
|
49
|
+
SAMPLE_INTERVAL_MS,
|
|
50
|
+
start,
|
|
51
|
+
take,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type { MeasureContext }
|
|
55
|
+
export { lane_sampler }
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
// Which seat a lane gets
|
|
1
|
+
// Which seat a lane gets.
|
|
2
2
|
|
|
3
3
|
// **The main work tree is seat 0, and nothing here can move it.** Lanes take seats 1..9, so a
|
|
4
4
|
// project that has never opened one stays on exactly the ports `ports/index.js` already gives it —
|
|
5
5
|
// `seed × 10` for its seed, the bases themselves for an unset seed, which is what CI runs on.
|
|
6
6
|
const FIRST_LANE_SEAT = 1
|
|
7
|
-
// **Nine seats, because the seat is the units digit of the offset `seed × 10 + lane`.** The
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
7
|
+
// **Nine seats, because the seat is the units digit of the offset `seed × 10 + lane`.** The seed,
|
|
8
|
+
// multiplied by ten, carries the port band rather than the seat, so a lane holds a single seat number
|
|
9
|
+
// rather than an absolute seed, and there is no ceiling to check and no "multiple of ten" convention
|
|
10
|
+
// for anyone to break.
|
|
11
11
|
const LAST_LANE_SEAT = 9
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -20,8 +20,8 @@ const LAST_LANE_SEAT = 9
|
|
|
20
20
|
* wrapped, because wrapping is that same collision under a friendlier name.
|
|
21
21
|
*
|
|
22
22
|
* The whole ascending list is returned rather than only the lowest, because the caller claims each
|
|
23
|
-
* seat atomically and steps to the next when a concurrent `lane:open` claimed it first
|
|
24
|
-
*
|
|
23
|
+
* seat atomically and steps to the next when a concurrent `lane:open` claimed it first:
|
|
24
|
+
* reading a free set and picking from it are two moments, and the gap
|
|
25
25
|
* between them is where two opens once chose the same seat.
|
|
26
26
|
*/
|
|
27
27
|
function free_seats(used: ReadonlyArray<number>): Array<number> {
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { run_ship_stage } from '#scripts/run/ship/run-ship-stage'
|
|
2
|
+
import { lane_ledger, type DispatchEntry, type LedgerEntry, type StageEntry } from './lane-ledger'
|
|
3
|
+
import { lane_stats, type StatsWindow } from './lane-stats'
|
|
4
|
+
|
|
5
|
+
// Where a lane's time goes: the ledger's `stage` and `dispatch` entries of one period reduced to one
|
|
6
|
+
// row per stage — median, maximum and how many runs — printed by `josh lane:stats` under the lane-limit
|
|
7
|
+
// row. The rows are in the order a lane passes them.
|
|
8
|
+
//
|
|
9
|
+
// **A stage nothing recorded prints `not measured`, never `0`.** A period that ran no second review
|
|
10
|
+
// round has no `round-2` duration, which is not a round that took no time.
|
|
11
|
+
//
|
|
12
|
+
// **`implement` is derived, not recorded**: from a lane's dispatch to the start of the first ship stage
|
|
13
|
+
// of the same issue that followed it. Nothing has to know, at the hand-off, when the child was
|
|
14
|
+
// dispatched, and a ship resumed after a fix cannot record the implementation twice.
|
|
15
|
+
//
|
|
16
|
+
// **`ci-wait` is `followup`'s own lap, inside the `followup` stage** — a row of its own so the wait for
|
|
17
|
+
// CI reads beside `review`, the round-one review it would overlap.
|
|
18
|
+
|
|
19
|
+
const MS_PER_MINUTE = 60_000
|
|
20
|
+
const DECIMALS = 1
|
|
21
|
+
const NOT_MEASURED = 'not measured'
|
|
22
|
+
const IMPLEMENT = 'implement'
|
|
23
|
+
const COLUMNS = ['stage', 'median (min)', 'max (min)', 'runs'] as const
|
|
24
|
+
const { STAGE } = run_ship_stage
|
|
25
|
+
const STAGES = [
|
|
26
|
+
IMPLEMENT,
|
|
27
|
+
STAGE.PREFLIGHT,
|
|
28
|
+
STAGE.REVIEW,
|
|
29
|
+
STAGE.SYNC,
|
|
30
|
+
STAGE.GATE,
|
|
31
|
+
STAGE.COMMIT,
|
|
32
|
+
STAGE.ROUND_TWO,
|
|
33
|
+
STAGE.FOLLOWUP,
|
|
34
|
+
lane_ledger.CI_WAIT_STAGE,
|
|
35
|
+
STAGE.REPORT,
|
|
36
|
+
] as const
|
|
37
|
+
|
|
38
|
+
interface Measured {
|
|
39
|
+
implement: ReadonlyArray<number>
|
|
40
|
+
stages: ReadonlyArray<StageEntry>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function is_stage(entry: LedgerEntry): entry is StageEntry {
|
|
44
|
+
return entry.kind === lane_ledger.KIND.STAGE
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function is_dispatch(entry: LedgerEntry): entry is DispatchEntry {
|
|
48
|
+
return entry.kind === lane_ledger.KIND.DISPATCH
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function is_number(value: number | undefined): value is number {
|
|
52
|
+
return value !== undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function started_ms(stage: StageEntry): number {
|
|
56
|
+
return Date.parse(stage.at) - stage.elapsed_ms
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// When the same issue was dispatched again, or never: a child that died before its ship must not have
|
|
60
|
+
// its implementation stretched to the ship of the child that replaced it.
|
|
61
|
+
function next_dispatch_ms(sorted: ReadonlyArray<DispatchEntry>, index: number): number {
|
|
62
|
+
const next = sorted.slice(index + 1).find((entry) => entry.issue === sorted[index]?.issue)
|
|
63
|
+
|
|
64
|
+
return next === undefined ? Infinity : Date.parse(next.at)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function implement_ms(
|
|
68
|
+
dispatch: DispatchEntry,
|
|
69
|
+
until_ms: number,
|
|
70
|
+
stages: ReadonlyArray<StageEntry>,
|
|
71
|
+
): number | undefined {
|
|
72
|
+
const from_ms = Date.parse(dispatch.at)
|
|
73
|
+
const starts = stages
|
|
74
|
+
.filter((stage) => stage.issue === dispatch.issue)
|
|
75
|
+
.map((stage) => started_ms(stage))
|
|
76
|
+
.filter((start) => start >= from_ms && start < until_ms)
|
|
77
|
+
|
|
78
|
+
return starts.length === 0 ? undefined : Math.min(...starts) - from_ms
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function implement_durations(
|
|
82
|
+
dispatches: ReadonlyArray<DispatchEntry>,
|
|
83
|
+
stages: ReadonlyArray<StageEntry>,
|
|
84
|
+
): Array<number> {
|
|
85
|
+
const sorted = dispatches.toSorted((left, right) => Date.parse(left.at) - Date.parse(right.at))
|
|
86
|
+
|
|
87
|
+
return sorted
|
|
88
|
+
.map((dispatch, index) => implement_ms(dispatch, next_dispatch_ms(sorted, index), stages))
|
|
89
|
+
.filter(is_number)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function durations_of(stage: string, measured: Measured): ReadonlyArray<number> {
|
|
93
|
+
if (stage === IMPLEMENT) return measured.implement
|
|
94
|
+
|
|
95
|
+
return measured.stages.filter((entry) => entry.stage === stage).map((entry) => entry.elapsed_ms)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function cell(milliseconds: number | undefined): string {
|
|
99
|
+
return milliseconds === undefined
|
|
100
|
+
? NOT_MEASURED
|
|
101
|
+
: (milliseconds / MS_PER_MINUTE).toFixed(DECIMALS)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function stage_row(stage: string, measured: Measured): string {
|
|
105
|
+
const durations = durations_of(stage, measured)
|
|
106
|
+
|
|
107
|
+
return lane_stats.to_row([
|
|
108
|
+
stage,
|
|
109
|
+
cell(lane_stats.median(durations)),
|
|
110
|
+
cell(lane_stats.peak(durations)),
|
|
111
|
+
String(durations.length),
|
|
112
|
+
])
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// The period's table: `entries` is the whole ledger, filtered here to `window`.
|
|
116
|
+
function table(entries: ReadonlyArray<LedgerEntry>, window: StatsWindow): string {
|
|
117
|
+
const period = lane_stats.in_window(entries, window)
|
|
118
|
+
const stages = period.filter(is_stage)
|
|
119
|
+
const measured = { implement: implement_durations(period.filter(is_dispatch), stages), stages }
|
|
120
|
+
|
|
121
|
+
return [
|
|
122
|
+
lane_stats.to_row(COLUMNS),
|
|
123
|
+
lane_stats.to_row(COLUMNS.map(() => '---')),
|
|
124
|
+
...STAGES.map((stage) => stage_row(stage, measured)),
|
|
125
|
+
].join('\n')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const lane_stage_stats = {
|
|
129
|
+
IMPLEMENT,
|
|
130
|
+
NOT_MEASURED,
|
|
131
|
+
STAGES,
|
|
132
|
+
table,
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export { lane_stage_stats }
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { git_command } from '#scripts/git/git-command'
|
|
2
2
|
import { git_remote_branch } from '#scripts/git/git-remote-branch'
|
|
3
3
|
|
|
4
|
-
// Where a lane is cut from
|
|
4
|
+
// Where a lane is cut from.
|
|
5
5
|
//
|
|
6
6
|
// **The bare default-branch name is the wrong start point, because git resolves it to the *local*
|
|
7
7
|
// `refs/heads/<default>` — a ref nothing in this workflow ever advances.** Merges happen on GitHub
|
|
8
8
|
// through `pnpm josh followup`, and this repository's main work tree does not have the
|
|
9
9
|
// default branch checked out, so there is no fast-forward for it to receive. It falls one commit
|
|
10
10
|
// further behind on every merge, and a lane opened from it starts without the work that was just
|
|
11
|
-
// merged.
|
|
12
|
-
// was `78f746f9`.
|
|
11
|
+
// merged.
|
|
13
12
|
//
|
|
14
13
|
// **The remote-tracking ref is the one that is current**, because a fetch updates it without anyone
|
|
15
14
|
// checking anything out — which is exactly the property the local branch lacks. It is named in full
|
|
@@ -20,9 +19,9 @@ const REFS_REMOTES_ORIGIN_PREFIX = 'refs/remotes/origin/'
|
|
|
20
19
|
|
|
21
20
|
// A fetch *failure* is reported and stepped over rather than raised. `lane:open` has to keep working
|
|
22
21
|
// with no network at all — offline, and on a clone with no `origin` — and what it degrades to is
|
|
23
|
-
// whatever `origin/<default>` already holds, which is still never *behind* the local branch.
|
|
24
|
-
//
|
|
25
|
-
//
|
|
22
|
+
// whatever `origin/<default>` already holds, which is still never *behind* the local branch. A
|
|
23
|
+
// connection that hangs rather than failing degrades the same way: `fetch_branch` runs through
|
|
24
|
+
// `git_spawn.read_remote`, whose budget ends the wait as a failure.
|
|
26
25
|
async function refresh_default_branch(default_branch: string): Promise<void> {
|
|
27
26
|
try {
|
|
28
27
|
await git_command.fetch_branch(default_branch)
|
|
@@ -65,7 +64,7 @@ async function resolve(): Promise<string> {
|
|
|
65
64
|
return start_point
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
// **A branch that already exists is attached to, never cut afresh
|
|
67
|
+
// **A branch that already exists is attached to, never cut afresh**. Its
|
|
69
68
|
// commits are a child's finished work: `epicrun` leaves a lane's branch behind whenever a child is
|
|
70
69
|
// parked after pushing, and `lane:close` deletes the local branch while the remote one and the pull
|
|
71
70
|
// request stay. Cutting a new `<N>-lane` from the default branch there orphans both — and it did so
|
|
@@ -130,8 +129,7 @@ async function present_reference(branch_name: string): Promise<string> {
|
|
|
130
129
|
|
|
131
130
|
// `absent` is the one answer that refuses the ref: the branch is gone from origin, so a ref still
|
|
132
131
|
// pointing at it is stale and the lane is cut from the default branch as any new one is. Why origin
|
|
133
|
-
// itself is asked rather than the remote-tracking ref is `git_remote_branch`'s own comment
|
|
134
|
-
// (joshuafolkken/kit#1641 moved the asking there, so `pnpm josh release` could reuse it).
|
|
132
|
+
// itself is asked rather than the remote-tracking ref is `git_remote_branch`'s own comment.
|
|
135
133
|
async function remote_reference_for(branch_name: string): Promise<string | undefined> {
|
|
136
134
|
const answer = await git_remote_branch.ask(branch_name)
|
|
137
135
|
|
|
@@ -148,8 +146,7 @@ async function remote_reference_for(branch_name: string): Promise<string | undef
|
|
|
148
146
|
*
|
|
149
147
|
* `undefined` means **attach**: the branch is already here, so the work tree is put on it and no
|
|
150
148
|
* branch is created. Every other answer is a commit-ish a new branch is cut from — the remote-tracking
|
|
151
|
-
* ref of the lane branch when only the remote has it, and the default branch's when neither does
|
|
152
|
-
* which is the behavior every lane had before joshuafolkken/kit#1627.
|
|
149
|
+
* ref of the lane branch when only the remote has it, and the default branch's when neither does.
|
|
153
150
|
*
|
|
154
151
|
* **Nothing here deletes a branch to simplify the call.** That is what would lose the commits this
|
|
155
152
|
* function exists to keep.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { machine_capacity } from '#scripts/gate/machine-capacity'
|
|
1
2
|
import type { GateEntry, LedgerEntry, LoadEntry } from './lane-ledger'
|
|
3
|
+
import { lane_sampler } from './lane-sampler'
|
|
2
4
|
|
|
3
|
-
// The lane-limit measurement's one table row
|
|
5
|
+
// The lane-limit measurement's one table row: the ledger entries of one period
|
|
4
6
|
// reduced to throughput, gate duration and machine load, in the column order
|
|
5
7
|
// `docs/maintainers/lane-limit-measurement.md` documents, so the row pastes into #3347's table as is.
|
|
6
8
|
//
|
|
@@ -15,6 +17,9 @@ import type { GateEntry, LedgerEntry, LoadEntry } from './lane-ledger'
|
|
|
15
17
|
//
|
|
16
18
|
// **The means take working samples only** for the same reason: the sampler runs through the nights,
|
|
17
19
|
// and their idle samples would read four busy lanes as about one. Peaks and minima take every sample.
|
|
20
|
+
//
|
|
21
|
+
// **Swap is a rate, not a level.** A sample carries `machine_capacity`'s counter — every page swapped
|
|
22
|
+
// since boot — so the swap columns are what was swapped between consecutive samples, per hour.
|
|
18
23
|
|
|
19
24
|
const MS_PER_MINUTE = 60_000
|
|
20
25
|
const MS_PER_HOUR = 3_600_000
|
|
@@ -23,6 +28,8 @@ const ACTIVE_GAP_MS = MS_PER_HOUR
|
|
|
23
28
|
const MS_PER_DAY = 86_400_000
|
|
24
29
|
const MB_PER_GB = 1024
|
|
25
30
|
const HALF = 2
|
|
31
|
+
// Half the sampler's interval: two samples closer than this are not one interval apart.
|
|
32
|
+
const MIN_RATE_GAP_MS = lane_sampler.SAMPLE_INTERVAL_MS / HALF
|
|
26
33
|
const DECIMALS = 1
|
|
27
34
|
const MISSING = '—'
|
|
28
35
|
const CELL_SEPARATOR = ' | '
|
|
@@ -37,8 +44,8 @@ const COLUMNS = [
|
|
|
37
44
|
'gate max (min)',
|
|
38
45
|
'load peak',
|
|
39
46
|
'load mean',
|
|
40
|
-
'
|
|
41
|
-
'
|
|
47
|
+
'swapped peak (GB/h)',
|
|
48
|
+
'swapped mean (GB/h)',
|
|
42
49
|
'free memory min (GB)',
|
|
43
50
|
'free memory mean (GB)',
|
|
44
51
|
'load samples',
|
|
@@ -107,6 +114,22 @@ function is_working(sample: LoadEntry): sample is WorkingEntry {
|
|
|
107
114
|
return (sample.lanes ?? 0) > 0
|
|
108
115
|
}
|
|
109
116
|
|
|
117
|
+
interface SamplePair {
|
|
118
|
+
sample: LoadEntry
|
|
119
|
+
next: LoadEntry
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Each sample beside the one that followed it, in time order.
|
|
123
|
+
function sample_pairs(samples: ReadonlyArray<LoadEntry>): Array<SamplePair> {
|
|
124
|
+
const sorted = samples.toSorted((left, right) => Date.parse(left.at) - Date.parse(right.at))
|
|
125
|
+
|
|
126
|
+
return sorted.slice(1).map((next, index) => ({ sample: sorted[index] ?? next, next }))
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function elapsed_ms({ sample, next }: SamplePair): number {
|
|
130
|
+
return Date.parse(next.at) - Date.parse(sample.at)
|
|
131
|
+
}
|
|
132
|
+
|
|
110
133
|
function sum_hours(gaps: ReadonlyArray<number>): number | undefined {
|
|
111
134
|
const active = gaps.filter((gap) => gap <= ACTIVE_GAP_MS).reduce((sum, gap) => sum + gap, 0)
|
|
112
135
|
|
|
@@ -117,7 +140,7 @@ function sum_hours(gaps: ReadonlyArray<number>): number | undefined {
|
|
|
117
140
|
// and gates) no longer than `ACTIVE_GAP_MS`.
|
|
118
141
|
function gap_hours(entries: ReadonlyArray<LedgerEntry>): number | undefined {
|
|
119
142
|
const instants = entries
|
|
120
|
-
.filter((entry) =>
|
|
143
|
+
.filter((entry) => entry.kind === 'merge' || is_gate(entry))
|
|
121
144
|
.map((entry) => Date.parse(entry.at))
|
|
122
145
|
.toSorted((left, right) => left - right)
|
|
123
146
|
|
|
@@ -129,16 +152,27 @@ function gap_hours(entries: ReadonlyArray<LedgerEntry>): number | undefined {
|
|
|
129
152
|
// The time from each working sample to the next sample. The cap still applies, so a sampler stopped
|
|
130
153
|
// mid-run does not count its silence as work.
|
|
131
154
|
function sampled_hours(samples: ReadonlyArray<LoadEntry>): number | undefined {
|
|
132
|
-
const
|
|
133
|
-
const gaps = sorted
|
|
134
|
-
.slice(1)
|
|
135
|
-
.map((next, index) => ({ sample: sorted[index] ?? next, next }))
|
|
155
|
+
const gaps = sample_pairs(samples)
|
|
136
156
|
.filter(({ sample }) => is_working(sample))
|
|
137
|
-
.map((
|
|
157
|
+
.map((pair) => elapsed_ms(pair))
|
|
138
158
|
|
|
139
159
|
return sum_hours(gaps)
|
|
140
160
|
}
|
|
141
161
|
|
|
162
|
+
// The GB swapped per hour from one sample to the next. `swapped_mb` is a counter, so only a difference
|
|
163
|
+
// says anything; a gap past `ACTIVE_GAP_MS` is a stopped sampler, whose silence is no rate. A gap under
|
|
164
|
+
// `MIN_RATE_GAP_MS` is no rate either: a drive restarted seconds after its last sample, or a second
|
|
165
|
+
// sampler beside it, would stretch a few seconds' burst to an hour and own the peak.
|
|
166
|
+
function swap_rate(pair: SamplePair): number | undefined {
|
|
167
|
+
const swapped = machine_capacity.swapped_between(pair.sample.swapped_mb, pair.next.swapped_mb)
|
|
168
|
+
const elapsed = elapsed_ms(pair)
|
|
169
|
+
const is_one_interval = elapsed >= MIN_RATE_GAP_MS && elapsed <= ACTIVE_GAP_MS
|
|
170
|
+
|
|
171
|
+
if (swapped === undefined || !is_one_interval) return undefined
|
|
172
|
+
|
|
173
|
+
return swapped / MB_PER_GB / (elapsed / MS_PER_HOUR)
|
|
174
|
+
}
|
|
175
|
+
|
|
142
176
|
// The hours work was under way; `undefined` when nothing leaves any active time.
|
|
143
177
|
function active_hours(entries: ReadonlyArray<LedgerEntry>): number | undefined {
|
|
144
178
|
const samples = entries.filter(is_load)
|
|
@@ -172,18 +206,26 @@ function gate_cells(entries: ReadonlyArray<LedgerEntry>): Array<string> {
|
|
|
172
206
|
return [cell(median(minutes)), cell(peak(minutes))]
|
|
173
207
|
}
|
|
174
208
|
|
|
209
|
+
function swap_cells(samples: ReadonlyArray<LoadEntry>): Array<string> {
|
|
210
|
+
const pairs = sample_pairs(samples)
|
|
211
|
+
const rates = pairs.map((pair) => swap_rate(pair)).filter(is_number)
|
|
212
|
+
const working_rates = pairs
|
|
213
|
+
.filter(({ sample }) => is_working(sample))
|
|
214
|
+
.map((pair) => swap_rate(pair))
|
|
215
|
+
.filter(is_number)
|
|
216
|
+
|
|
217
|
+
return [cell(peak(rates)), cell(mean(working_rates))]
|
|
218
|
+
}
|
|
219
|
+
|
|
175
220
|
function load_cells(samples: ReadonlyArray<LoadEntry>): Array<string> {
|
|
176
221
|
const working = samples.filter(is_working)
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
const free = samples.map((sample) => sample.free_mb)
|
|
180
|
-
const working_free = working.map((sample) => sample.free_mb)
|
|
222
|
+
const free = samples.map((sample) => sample.available_mb).filter(is_number)
|
|
223
|
+
const working_free = working.map((sample) => sample.available_mb).filter(is_number)
|
|
181
224
|
|
|
182
225
|
return [
|
|
183
226
|
cell(peak(samples.map((sample) => sample.load))),
|
|
184
227
|
cell(mean(working.map((sample) => sample.load))),
|
|
185
|
-
|
|
186
|
-
cell(gigabytes(mean(working_swap))),
|
|
228
|
+
...swap_cells(samples),
|
|
187
229
|
cell(gigabytes(lowest(free))),
|
|
188
230
|
cell(gigabytes(mean(working_free))),
|
|
189
231
|
String(samples.length),
|
|
@@ -215,8 +257,11 @@ const lane_stats = {
|
|
|
215
257
|
COLUMNS,
|
|
216
258
|
MISSING,
|
|
217
259
|
header,
|
|
260
|
+
in_window,
|
|
218
261
|
median,
|
|
262
|
+
peak,
|
|
219
263
|
row,
|
|
264
|
+
to_row,
|
|
220
265
|
window_of,
|
|
221
266
|
}
|
|
222
267
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { existsSync, lstatSync, readdirSync, rmSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
4
|
+
import { lane_leftover } from './lane-leftover'
|
|
5
|
+
import { lane_open } from './lane-open'
|
|
6
|
+
import { lane_paths } from './lane-paths'
|
|
7
|
+
import { lane_registry } from './lane-registry'
|
|
8
|
+
|
|
9
|
+
// What the lanes root holds that no registered work tree accounts for.
|
|
10
|
+
//
|
|
11
|
+
// **Every other sweep starts from `git worktree list`**, so a directory whose registration is gone —
|
|
12
|
+
// a lane whose `rmSync` stopped half-way, one whose `.git` points at a registration git pruned, an
|
|
13
|
+
// empty lanes root a lane once nested inside itself — is invisible to all of them, and stays on disk
|
|
14
|
+
// for good. This reads the root itself.
|
|
15
|
+
//
|
|
16
|
+
// **A stray is removed only when removing it loses nothing** — `lane_leftover.foreign_paths`, the one
|
|
17
|
+
// test `lane:open`'s reclaim also applies. One that holds anything else is kept and reported with what
|
|
18
|
+
// it holds; so is every entry whose name the lane machinery never writes, because nothing here knows
|
|
19
|
+
// who put it there. The root's own `.seat-locks` and every registered work tree are not strays.
|
|
20
|
+
|
|
21
|
+
type StrayVerdict = 'foreign' | 'not-a-lane' | 'opening' | 'removed' | 'stuck' | 'unreadable'
|
|
22
|
+
|
|
23
|
+
interface Stray {
|
|
24
|
+
path: string
|
|
25
|
+
verdict: StrayVerdict
|
|
26
|
+
// The paths inside it whose removal would lose something — only on `foreign`.
|
|
27
|
+
foreign: Array<string>
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function stray_names(root: string, registered: ReadonlySet<string>): Array<string> {
|
|
31
|
+
if (!existsSync(root)) return []
|
|
32
|
+
|
|
33
|
+
return readdirSync(root).filter(
|
|
34
|
+
(name) => name !== lane_paths.SEAT_LOCK_DIR && !registered.has(path.join(root, name)),
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function is_lane_directory(directory: string): boolean {
|
|
39
|
+
return lane_paths.is_lane_entry(path.basename(directory)) && lstatSync(directory).isDirectory()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// A removal that stops part-way is judged by what is left, exactly as `lane:close` judges its own —
|
|
43
|
+
// and what is left is a stray the next sweep reads again.
|
|
44
|
+
function remove(directory: string): StrayVerdict {
|
|
45
|
+
try {
|
|
46
|
+
rmSync(directory, { force: true, recursive: true })
|
|
47
|
+
} catch (error) {
|
|
48
|
+
error_text.trace_swallowed('lane_stray.remove', error)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return existsSync(directory) ? 'stuck' : 'removed'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// **A `lane:open` in flight holds a seat lock from before its `worktree add` until after the
|
|
55
|
+
// registration**, so while any lock is held a numbered directory may be a lane being created, not a
|
|
56
|
+
// leftover — it is kept, and the next sweep reads it again.
|
|
57
|
+
interface SweepContext {
|
|
58
|
+
recoverable: ReadonlySet<string>
|
|
59
|
+
is_opening: boolean
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function judge(directory: string, context: SweepContext): Stray {
|
|
63
|
+
if (!is_lane_directory(directory)) return { path: directory, verdict: 'not-a-lane', foreign: [] }
|
|
64
|
+
if (context.is_opening) return { path: directory, verdict: 'opening', foreign: [] }
|
|
65
|
+
|
|
66
|
+
const foreign = lane_leftover.foreign_paths(directory, context.recoverable)
|
|
67
|
+
|
|
68
|
+
if (foreign.length > 0) return { path: directory, verdict: 'foreign', foreign }
|
|
69
|
+
|
|
70
|
+
return { path: directory, verdict: remove(directory), foreign: [] }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// One stray that cannot be read — a permission, a file vanishing mid-walk — is kept and reported
|
|
74
|
+
// rather than thrown, so it never stops the sweep of the rest.
|
|
75
|
+
function judge_safely(directory: string, context: SweepContext): Stray {
|
|
76
|
+
try {
|
|
77
|
+
return judge(directory, context)
|
|
78
|
+
} catch (error) {
|
|
79
|
+
error_text.trace_swallowed('lane_stray.judge', error)
|
|
80
|
+
|
|
81
|
+
return { path: directory, verdict: 'unreadable', foreign: [] }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Remove the lanes root's unregistered leftovers that hold nothing worth keeping; report the rest. */
|
|
86
|
+
async function sweep_strays(): Promise<Array<Stray>> {
|
|
87
|
+
const root = lane_paths.lane_root(await lane_registry.main_repository_root())
|
|
88
|
+
const registered = new Set(await lane_registry.registered_directories())
|
|
89
|
+
const names = stray_names(root, registered)
|
|
90
|
+
|
|
91
|
+
if (names.length === 0) return []
|
|
92
|
+
|
|
93
|
+
const context: SweepContext = {
|
|
94
|
+
recoverable: await lane_leftover.recoverable_objects(),
|
|
95
|
+
is_opening: lane_open.open_in_flight_count(root) > 0,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return names.map((name) => judge_safely(path.join(root, name), context))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// The foreign paths a report names before it summarizes the rest as a count.
|
|
102
|
+
const NAMED_PATH_LIMIT = 5
|
|
103
|
+
|
|
104
|
+
function named_paths(foreign: ReadonlyArray<string>): string {
|
|
105
|
+
const rest = foreign.length - NAMED_PATH_LIMIT
|
|
106
|
+
const more = rest > 0 ? ` and ${String(rest)} more` : ''
|
|
107
|
+
|
|
108
|
+
return `${foreign.slice(0, NAMED_PATH_LIMIT).join(', ')}${more}`
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const KEPT_REASONS: Record<Exclude<StrayVerdict, 'foreign' | 'removed'>, string> = {
|
|
112
|
+
'not-a-lane': 'not a name the lane machinery writes, so it was left alone',
|
|
113
|
+
opening:
|
|
114
|
+
'a `lane:open` holds a seat lock and this may be its lane; the next sweep reads it again — if no `lane:open` is running, the lock outlived a crash: remove the lanes root `.seat-locks` directory',
|
|
115
|
+
stuck: 'the removal did not finish; the next `pnpm josh lane:prune` tries again',
|
|
116
|
+
unreadable: 'it could not be read, so it was left in place',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** One line per stray, for standard error. */
|
|
120
|
+
function describe(stray: Stray): string {
|
|
121
|
+
if (stray.verdict === 'removed') return `Removed unregistered lane leftover ${stray.path}.`
|
|
122
|
+
|
|
123
|
+
if (stray.verdict === 'foreign') {
|
|
124
|
+
return `Kept ${stray.path}: it holds files git cannot restore (${named_paths(stray.foreign)}). Move them out and delete the directory.`
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return `Kept ${stray.path}: ${KEPT_REASONS[stray.verdict]}.`
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Sweep, and say on standard error what was removed and what was kept. */
|
|
131
|
+
async function sweep_and_report(): Promise<void> {
|
|
132
|
+
const strays = await sweep_strays()
|
|
133
|
+
|
|
134
|
+
for (const stray of strays) console.error(describe(stray))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const lane_stray = { describe, sweep_and_report, sweep_strays }
|
|
138
|
+
|
|
139
|
+
export type { Stray, StrayVerdict }
|
|
140
|
+
export { lane_stray }
|
|
@@ -3,7 +3,7 @@ import { run_hold } from '#scripts/run/hold/run-hold'
|
|
|
3
3
|
import { lane_await } from './lane-await'
|
|
4
4
|
import type { LaneInfo } from './lane-registry'
|
|
5
5
|
|
|
6
|
-
// Whether an open lane holds nothing worth keeping
|
|
6
|
+
// Whether an open lane holds nothing worth keeping: no commit on its branch
|
|
7
7
|
// beyond the default branch, a clean work tree, and no child or ship supervisor alive for its issue. A
|
|
8
8
|
// `backlogrun` cut between `lane:open` and `lane:dispatch` leaves exactly such a lane, and `lane:open`
|
|
9
9
|
// refuses it as `already-open` — so the next launch of that issue failed on a lane with nothing in it.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
2
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
|
|
4
5
|
const DECISION_PREFIX = 'josh-openai-lane-supervisor-decision-'
|
|
@@ -16,14 +17,9 @@ function target(lane_directory: string, nonce: string): string {
|
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
function read(lane_directory: string, nonce: string): Decision | undefined {
|
|
19
|
-
|
|
20
|
-
const raw = stamp_file.read_stamp_text(target(lane_directory, nonce)) ?? ''
|
|
21
|
-
const value: unknown = JSON.parse(raw)
|
|
20
|
+
const raw = stamp_file.read_stamp_text(target(lane_directory, nonce)) ?? ''
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
} catch {
|
|
25
|
-
return undefined
|
|
26
|
-
}
|
|
22
|
+
return json_value.parse_with(raw, schema)
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
function decide(lane_directory: string, nonce: string, decision: Decision['decision']): boolean {
|