@joshuafolkken/kit 1.1050.0 → 1.1128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +9 -8
- package/.claude/skills/epic-commands/SKILL.md +5 -7
- package/.claude/skills/workflow-commands/SKILL.md +20 -12
- package/.claude/skills/workflow-commands/background-commands.md +36 -84
- package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +8 -6
- package/.claude/skills/workflow-commands/backlogrun-progress.md +30 -33
- package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -12
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +4 -2
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +1 -1
- package/.claude/skills/workflow-commands/followup.md +7 -3
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/fullrun.md +8 -6
- package/.claude/skills/workflow-commands/halfrun.md +19 -21
- package/.claude/skills/workflow-commands/issue-comments.md +1 -1
- package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +9 -4
- package/.claude/skills/workflow-commands/latest-gate.md +8 -16
- package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +3 -3
- package/.claude/skills/workflow-commands/pre-gate-cut.md +4 -8
- package/.claude/skills/workflow-commands/prerequisite.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +36 -0
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/split-assessment.md +4 -18
- package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-node/action.yml +33 -0
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/auto-tag.yml +2 -3
- package/.github/workflows/ci.yml +31 -134
- package/.github/workflows/dependabot-auto-merge.yml +1 -0
- package/.github/workflows/pr-classification.yml +6 -44
- package/.github/workflows/production.yml +1 -0
- package/.github/workflows/publish.yml +43 -47
- package/.github/workflows/sonar-qube.yml +41 -4
- package/.pnpmfile.mjs +29 -0
- package/AGENTS.md +5 -2
- package/CLAUDE.md +33 -27
- package/GEMINI.md +5 -2
- package/README.md +66 -20
- package/SECURITY.md +37 -6
- package/cspell/index.yaml +6 -1
- package/dist/CLAUDE.basic.md +6 -6
- package/dist/CLAUDE.md +33 -27
- package/dist/CLAUDE.static.md +6 -6
- package/dist/config-merge/index.js +48 -12
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-7VPDUBRN.js → chunk-4JZDP5X5.js} +152 -155
- package/dist/hooks/{chunk-HJIISEAC.js → chunk-5SD2YM7Z.js} +5 -13
- package/dist/hooks/{chunk-NAS4C7GP.js → chunk-77J7IEQM.js} +2 -2
- package/dist/hooks/{chunk-DMQN45FN.js → chunk-7HVB7SZG.js} +3 -3
- package/dist/hooks/{chunk-RLDX5SOC.js → chunk-AIOIOMPX.js} +4413 -1970
- package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M7QKEKWO.js} +873 -2049
- package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-MKVGBQPA.js} +2 -2
- package/dist/hooks/{chunk-EJDX2TOB.js → chunk-NXYMNPUQ.js} +7 -88
- package/dist/hooks/{chunk-NJQOBE6L.js → chunk-QVLT52OV.js} +2 -7
- package/dist/hooks/{chunk-GQ7KP45M.js → chunk-XYUIQOW3.js} +2 -2
- package/dist/hooks/codex-hook-adapter.js +12 -48
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +280 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +9 -9
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +192 -333
- package/dist/josh.js +240 -148
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +70 -78
- package/eslint/rules/promise.js +5 -0
- package/eslint/rules/unicorn.js +3 -2
- package/package.json +26 -5
- package/pnpm-workspace.yaml +5 -7
- package/prompts/collaboration-workflow/glossary.md +17 -0
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/issue-template.md +1 -1
- package/prompts/collaboration-workflow/operating-rules.md +5 -5
- package/prompts/collaboration-workflow/overview.md +13 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +3 -3
- package/prompts/collaboration-workflow/rule-delivery.md +1 -1
- package/prompts/collaboration-workflow/turn-batching.md +3 -3
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +25 -22
- package/prompts/collaboration-workflow.md +6 -8
- package/prompts/review-rubric.md +1 -1
- package/prompts/review.md +3 -3
- package/prompts/sonar-hotspot-handling.md +11 -3
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +0 -2
- package/scripts/adopt/adopt.ts +0 -2
- package/scripts/agent/agent-argv.ts +0 -2
- package/scripts/agent/agent-diagnostics.ts +1 -1
- package/scripts/agent/agent-role-profile.ts +0 -7
- package/scripts/agent/claude-agent-argv.ts +0 -2
- package/scripts/agent/codex-agent-argv.ts +1 -1
- package/scripts/agent/codex-hooks.ts +92 -0
- package/scripts/agent/interactive-ask.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +6 -16
- package/scripts/backlog/backlog-arrival.ts +30 -10
- package/scripts/backlog/backlog-budget-cli.ts +15 -16
- package/scripts/backlog/backlog-budget.ts +0 -2
- package/scripts/backlog/backlog-defect-priority.ts +2 -2
- package/scripts/backlog/backlog-drive-cli.ts +10 -8
- package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
- package/scripts/backlog/backlog-drive-named.ts +2 -1
- package/scripts/backlog/backlog-drive.ts +76 -16
- package/scripts/backlog/backlog-named.ts +0 -3
- package/scripts/backlog/backlog-next.ts +9 -15
- package/scripts/backlog/backlog-offer-cli.ts +6 -19
- package/scripts/backlog/backlog-plan-cli.ts +1 -7
- package/scripts/backlog/backlog-plan.ts +30 -19
- package/scripts/backlog/backlog-pool.ts +3 -6
- package/scripts/backlog/backlog-rank.ts +2 -2
- package/scripts/backlog/backlog-ready.ts +39 -10
- package/scripts/backlog/backlog-scope.ts +1 -3
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +0 -1
- package/scripts/backlog/backlog-waves.ts +5 -2
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +85 -9
- package/scripts/build/hook-bundle-stamp.ts +111 -0
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +1 -1
- package/scripts/ci/composite-actions.ts +30 -0
- package/scripts/ci/pr-classification.ts +3 -3
- package/scripts/claude/workflow-destination.ts +10 -1
- package/scripts/clone/clone-fingerprint.ts +0 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/json-format.ts +0 -1
- package/scripts/config-merge/parse-jsonc.ts +33 -3
- package/scripts/config-merge/patch-json-key.ts +13 -6
- package/scripts/config-merge/patch-yaml-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +2 -9
- package/scripts/cost-runtime/cost-attribute.ts +0 -1
- package/scripts/cost-runtime/cost-cli.ts +3 -10
- package/scripts/cost-runtime/cost-corpus.ts +0 -2
- package/scripts/cost-runtime/cost-format.ts +0 -3
- package/scripts/cost-runtime/cost-pricing.ts +0 -1
- package/scripts/cost-runtime/cost-tokens.ts +0 -1
- package/scripts/delegation/delegation-cli.ts +1 -1
- package/scripts/delegation/delegation-policy.ts +0 -1
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +0 -2
- package/scripts/delegation/investigation-reads.ts +1 -164
- package/scripts/discovery/repo-map-logic.ts +0 -1
- package/scripts/discovery/repo-party-cli.ts +1 -1
- package/scripts/doctor/doctor-consumer.ts +6 -10
- package/scripts/doctor/doctor-io.ts +9 -13
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/backlogrun-parent-read-set.ts +12 -1
- package/scripts/document/document-byte-budget.ts +5 -5
- package/scripts/document/document-byte-check.ts +0 -1
- package/scripts/document/document-read-cli.ts +0 -2
- package/scripts/document/document-section-cli.ts +1 -1
- package/scripts/document/document-section.ts +0 -3
- package/scripts/document/edit-files-cli.ts +0 -1
- package/scripts/document/entry-read-budget.ts +21 -7
- package/scripts/document/entry-read-set.ts +32 -8
- package/scripts/document/lane-child-read-set.ts +8 -6
- package/scripts/document/read-files-cli.ts +0 -4
- package/scripts/document/read-set-cli.ts +0 -2
- package/scripts/document/read-set-point-of-use.ts +9 -3
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +4 -2
- package/scripts/epic/epic-add.ts +1 -1
- package/scripts/epic/epic-audit-cli.ts +1 -4
- package/scripts/epic/epic-audit-orphans.ts +1 -3
- package/scripts/epic/epic-audit-rationale.ts +0 -1
- package/scripts/epic/epic-audit-report.ts +0 -2
- package/scripts/epic/epic-audit.ts +8 -22
- package/scripts/epic/epic-bundle-cli.ts +1 -1
- package/scripts/epic/epic-bundle-evidence.ts +0 -1
- package/scripts/epic/epic-bundle-referenced.ts +1 -5
- package/scripts/epic/epic-bundle.ts +0 -4
- package/scripts/epic/epic-busy.ts +4 -5
- package/scripts/epic/epic-candidate-confirm.ts +0 -5
- package/scripts/epic/epic-classify.ts +2 -2
- package/scripts/epic/epic-cli-argv.ts +0 -1
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +5 -2
- package/scripts/epic/epic-cross-repo.ts +2 -4
- package/scripts/epic/epic-decision.ts +0 -1
- package/scripts/epic/epic-fetch.ts +2 -2
- package/scripts/epic/epic-index.ts +2 -3
- package/scripts/epic/epic-issue.ts +1 -15
- package/scripts/epic/epic-lane-offer.ts +9 -8
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +1 -3
- package/scripts/epic/epic-next-views.ts +0 -1
- package/scripts/epic/epic-next.ts +1 -10
- package/scripts/epic/epic-parse.ts +0 -1
- package/scripts/epic/epic-promote.ts +0 -9
- package/scripts/epic/epic-rank.ts +2 -2
- package/scripts/epic/epic-read.ts +1 -2
- package/scripts/epic/epic-reconcile.ts +1 -1
- package/scripts/epic/epic-reference.ts +1 -13
- package/scripts/epic/epic-relation-recheck.ts +1 -1
- package/scripts/epic/epic-relations.ts +1 -1
- package/scripts/epic/epic-remove.ts +1 -1
- package/scripts/epic/epic-report.ts +0 -1
- package/scripts/epic/epic-run.ts +2 -3
- package/scripts/epic/epic-shape.ts +1 -1
- package/scripts/epic/epic-solo-stale.ts +107 -0
- package/scripts/epic/epic-solo.ts +3 -2
- package/scripts/epic/epic-triage.ts +1 -1
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/epic/epic.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +53 -0
- package/scripts/{git → followup}/followup-issue-number.ts +1 -6
- package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
- package/scripts/{git → followup}/git-followup-finish.ts +1 -3
- package/scripts/{git → followup}/git-followup-flush.ts +2 -2
- package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
- package/scripts/{git → followup}/git-followup-label.ts +4 -4
- package/scripts/followup/git-followup-merged.ts +112 -0
- package/scripts/{git → followup}/git-followup-pending.ts +1 -1
- package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
- package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
- package/scripts/{git → followup}/git-pr-followup.ts +53 -16
- package/scripts/gate/core-budget.ts +3 -9
- package/scripts/gate/gate-plan.ts +7 -4
- package/scripts/gate/gate-report.ts +0 -6
- package/scripts/gate/gate-tree.ts +1 -1
- package/scripts/gate/pre-commit-type-check.ts +0 -6
- package/scripts/gate/project-checks.ts +7 -8
- package/scripts/gate/scoped-green.ts +0 -1
- package/scripts/gate/type-check-step.ts +1 -1
- package/scripts/gate/verification-gate.ts +0 -2
- package/scripts/gh/fix-gh-packages.ts +15 -12
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
- package/scripts/{git → gh}/git-gh-check.ts +2 -1
- package/scripts/{git → gh}/git-gh-exec.ts +1 -1
- package/scripts/{git → gh}/git-gh-failure.ts +1 -1
- package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
- package/scripts/{git → gh}/git-gh-issue-list.ts +13 -10
- package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
- package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
- package/scripts/{git → gh}/git-gh-issue-write.ts +4 -1
- package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +4 -1
- package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
- package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
- package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
- package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
- package/scripts/{git → gh}/git-gh-pr.ts +3 -1
- package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
- package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
- package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
- package/scripts/{git → gh}/git-pr-checks.ts +2 -1
- package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
- package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
- package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
- package/scripts/{git → gh}/git-pr.ts +3 -3
- package/scripts/git/changed-file-scope.ts +0 -1
- package/scripts/git/git-branch.ts +3 -6
- package/scripts/git/git-command.ts +6 -1
- package/scripts/git/git-commit.ts +1 -1
- package/scripts/git/git-common-directory.ts +80 -24
- package/scripts/git/git-error.ts +66 -9
- package/scripts/git/git-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +2 -2
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-spawn-sync.ts +65 -0
- package/scripts/git/git-spawn.ts +5 -4
- package/scripts/git/git-staging.ts +1 -0
- package/scripts/git/git-status.ts +1 -1
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/gone-branch.ts +1 -0
- package/scripts/git/listing-cutoff.ts +1 -1
- package/scripts/git/main-merge.ts +1 -1
- package/scripts/git/main-sync.ts +19 -1
- package/scripts/git/parse-json-array.ts +0 -3
- package/scripts/git/repository-lock.ts +16 -16
- package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
- package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +2 -7
- package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
- package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
- package/scripts/hooks/codex-hook-adapter.ts +0 -1
- package/scripts/hooks/edited-cspell.ts +1 -1
- package/scripts/hooks/format-edited-file.ts +2 -0
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard.ts +22 -4
- package/scripts/hooks/reserved-run.ts +1 -1
- package/scripts/hooks/step-zero-notice.ts +76 -0
- package/scripts/hooks/stop-guard.ts +47 -21
- package/scripts/init/claude-plugin-config.ts +4 -5
- package/scripts/init/hook-command-rewrite.ts +16 -8
- package/scripts/init/hook-launch.ts +41 -15
- package/scripts/init/init-basic.ts +2 -5
- package/scripts/init/init-file-action.ts +54 -0
- package/scripts/init/init-logic-migrate.ts +35 -17
- package/scripts/init/init-logic-secretlint.ts +1 -1
- package/scripts/init/init-logic.ts +10 -19
- package/scripts/init/init.ts +11 -71
- package/scripts/init/kit-written-paths.ts +2 -0
- package/scripts/init/project-profile.ts +9 -17
- package/scripts/init/start-exec.ts +1 -1
- package/scripts/init/start-setup-pr.ts +6 -6
- package/scripts/init/start-steps.ts +3 -1
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +64 -23
- package/scripts/issue/defect-rate.ts +1 -2
- package/scripts/{git → issue}/git-next-issues.ts +3 -3
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-backlinks.ts +7 -14
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +12 -8
- package/scripts/issue/issue-classification.ts +1 -9
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +2 -2
- package/scripts/issue/issue-file-cli.ts +5 -5
- package/scripts/issue/issue-file.ts +7 -14
- package/scripts/issue/issue-fold-cli.ts +1 -1
- package/scripts/issue/issue-fold-existing-cli.ts +1 -1
- package/scripts/{git → issue}/issue-labels.ts +8 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/{git → issue}/issue-rank.ts +1 -1
- package/scripts/issue/issue-read-cli.ts +8 -47
- package/scripts/issue/issue-read.ts +0 -2
- package/scripts/issue/issue-report-failures.ts +80 -0
- package/scripts/issue/issue-scout-cli.ts +1 -7
- package/scripts/issue/issue-scout-closed.ts +2 -2
- package/scripts/issue/issue-scout.ts +0 -2
- package/scripts/issue/issue-state-cli.ts +5 -46
- package/scripts/issue/issue-state.ts +1 -5
- package/scripts/issue/markdown-section.ts +21 -6
- package/scripts/issue/measure-rerun-cli.ts +74 -15
- package/scripts/issue/reproduction-measure.ts +1 -1
- package/scripts/josh/cli-body.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +0 -3
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-commands-ai.ts +9 -102
- package/scripts/josh/josh-commands-backlog.ts +5 -1
- package/scripts/josh/josh-commands-development.ts +8 -1
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/josh/josh-commands-maintenance.ts +7 -0
- package/scripts/josh/josh-commands-project.ts +7 -1
- package/scripts/josh/josh-commands-run.ts +114 -0
- package/scripts/josh/josh-commands-versioning.ts +8 -0
- package/scripts/josh/josh-commands-workflow.ts +3 -3
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/run-github-prerequisite.ts +3 -6
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +46 -19
- package/scripts/lane/lane-capacity.ts +6 -3
- package/scripts/lane/lane-child-invocation.ts +20 -7
- package/scripts/lane/lane-cli.ts +1 -4
- package/scripts/lane/lane-close.ts +5 -4
- package/scripts/lane/lane-dispatch.ts +3 -4
- package/scripts/lane/lane-environment.ts +0 -9
- package/scripts/lane/lane-handoff.ts +38 -0
- package/scripts/lane/lane-launch-cli.ts +31 -27
- package/scripts/lane/lane-open.ts +0 -3
- package/scripts/lane/lane-output.ts +0 -1
- package/scripts/lane/lane-registry.ts +9 -0
- package/scripts/lane/openai-lane-ship.ts +2 -0
- package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
- package/scripts/lane/openai-lane-supervisor.ts +6 -4
- package/scripts/lane/openai-review-broker.ts +7 -1
- package/scripts/lib/bounded-pool.ts +1 -0
- package/scripts/lib/cli-flags.ts +31 -2
- package/scripts/lib/error-message.ts +12 -1
- package/scripts/lib/json-value.ts +5 -4
- package/scripts/lib/poll.ts +3 -1
- package/scripts/lib/timed-fetch.ts +15 -0
- package/scripts/lib/timeouts.ts +13 -0
- package/scripts/{yaml → lib}/yaml-document.ts +3 -1
- package/scripts/{bytes → lines}/bytes-command.ts +0 -2
- package/scripts/lines/line-targets.ts +0 -11
- package/scripts/lines/lines-command.ts +5 -4
- package/scripts/lint/lint-related-scope.ts +0 -1
- package/scripts/lint/lint-related.ts +1 -1
- package/scripts/{git → notify}/telegram-notify.ts +2 -2
- package/scripts/{git → notify}/telegram-test.ts +4 -4
- package/scripts/observations/observation-ledger-home.ts +0 -1
- package/scripts/observations/observation-ledger-line.ts +0 -1
- package/scripts/observations/observation-ledger-migrate.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +3 -3
- package/scripts/observations/observations-flush.ts +2 -2
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/package/package-scout-cli.ts +2 -7
- package/scripts/package/package-scout.ts +0 -2
- package/scripts/propagate/propagate-git-failure.ts +0 -1
- package/scripts/propagate/propagate-git.ts +3 -10
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +0 -2
- package/scripts/propagate/propagate-steps.ts +3 -5
- package/scripts/propagate/propagate-targets.ts +0 -4
- package/scripts/propagate/propagate.ts +0 -4
- package/scripts/refactor/import-graph.ts +0 -1
- package/scripts/refactor/refactor-lint.ts +0 -2
- package/scripts/refactor/refactor-scan.ts +2 -2
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +28 -21
- package/scripts/registry-migration/migrate.ts +25 -14
- package/scripts/release/github-release-cli.ts +19 -6
- package/scripts/release/github-release-environment.ts +46 -0
- package/scripts/release/github-release.ts +151 -94
- package/scripts/release/release-history.ts +0 -1
- package/scripts/release/release-plan.ts +0 -1
- package/scripts/release/release-publish.ts +38 -5
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- package/scripts/release/release-worktree.ts +97 -2
- package/scripts/repo/auto-merge-setting-logic.ts +1 -4
- package/scripts/repo/repo-setting.ts +1 -1
- package/scripts/repo/repository-labels.ts +3 -3
- package/scripts/repo/required-checks-logic.ts +206 -0
- package/scripts/repo/required-checks-report.ts +71 -0
- package/scripts/repo/ruleset-check-cli.ts +53 -0
- package/scripts/repo/ruleset-check.ts +147 -0
- package/scripts/report/report-lint-cli.ts +0 -4
- package/scripts/review/disposition-cli.ts +1 -1
- package/scripts/review/live-evidence.ts +1 -1
- package/scripts/review/review-attest-cli.ts +0 -6
- package/scripts/review/review-attest.ts +4 -16
- package/scripts/review/review-brief-cli.ts +23 -6
- package/scripts/review/review-brief.ts +21 -8
- package/scripts/review/review-checkout.ts +3 -2
- package/scripts/review/review-diff-parts.ts +89 -0
- package/scripts/review/review-diff-write.ts +97 -0
- package/scripts/review/review-finding-ledger.ts +0 -1
- package/scripts/review/review-record-cli.ts +10 -17
- package/scripts/review/review-record.ts +0 -1
- package/scripts/review/review-round2-cli.ts +1 -1
- package/scripts/review/review-stamps.ts +0 -3
- package/scripts/review/review-tree.ts +14 -2
- package/scripts/rules/decision-oracle-stage.ts +18 -0
- package/scripts/rules/decision-oracle.ts +10 -7
- package/scripts/rules/delivered-rules.ts +9 -1
- package/scripts/rules/destructive-command.ts +119 -0
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/early-heartbeat.ts +4 -3
- package/scripts/rules/file-body.ts +0 -3
- package/scripts/rules/filing-cap.ts +0 -2
- package/scripts/rules/gh-api.ts +7 -2
- package/scripts/rules/git-argv.ts +18 -7
- package/scripts/rules/git-force.ts +0 -2
- package/scripts/rules/implementation-cut.ts +0 -1
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-park.ts +22 -6
- package/scripts/rules/last-prompt.ts +1 -0
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +0 -3
- package/scripts/rules/permission-guards.ts +14 -0
- package/scripts/rules/protected-files.ts +74 -0
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +0 -3
- package/scripts/rules/rule-value-cli.ts +0 -1
- package/scripts/rules/shell-body-trigger.ts +0 -1
- package/scripts/rules/shell-segments.ts +0 -1
- package/scripts/rules/stop-rules.ts +20 -9
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +0 -1
- package/scripts/rules/worktree-guard.ts +26 -9
- package/scripts/run/run-carry-args.ts +8 -12
- package/scripts/run/run-carry-cli.ts +0 -2
- package/scripts/run/run-carry-stash.ts +2 -2
- package/scripts/run/run-carry-streak.ts +1 -1
- package/scripts/run/run-cut-args.ts +1 -6
- package/scripts/run/run-cut-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +2 -6
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +133 -25
- package/scripts/run/run-entry-stop.ts +104 -0
- package/scripts/run/run-entry.ts +0 -1
- package/scripts/run/run-event-cli.ts +0 -2
- package/scripts/run/run-event-follow.ts +1 -0
- package/scripts/run/run-event-render.ts +1 -1
- package/scripts/run/run-event-scope.ts +53 -4
- package/scripts/run/run-event-stream-emit.ts +7 -2
- package/scripts/run/run-event-stream.ts +0 -3
- package/scripts/run/run-event-watch.ts +1 -0
- package/scripts/run/run-halfrun-resume.ts +20 -7
- package/scripts/run/run-headless.ts +2 -2
- package/scripts/run/run-hold-cli.ts +33 -10
- package/scripts/run/run-hold.ts +29 -6
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +2 -6
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +7 -23
- package/scripts/run/run-merge-steps.ts +5 -5
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-next-cli.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +4 -2
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +6 -3
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-args.ts +20 -4
- package/scripts/run/run-progress-cli.ts +35 -36
- package/scripts/run/run-progress-clock.ts +10 -35
- package/scripts/run/run-progress-config.ts +0 -4
- package/scripts/run/run-progress-read.ts +1 -2
- package/scripts/run/run-progress.ts +1 -2
- package/scripts/run/run-prrun-resume.ts +117 -0
- package/scripts/run/run-report-cli.ts +1 -2
- package/scripts/run/run-report.ts +0 -1
- package/scripts/run/run-retrospective.ts +1 -1
- package/scripts/run/run-review-cli.ts +0 -3
- package/scripts/run/run-review-steps.ts +2 -0
- package/scripts/run/run-review.ts +0 -2
- package/scripts/run/run-ship-cli.ts +29 -19
- package/scripts/run/run-ship-detach.ts +1 -0
- package/scripts/run/run-ship-next.ts +106 -0
- package/scripts/run/run-ship-preflight.ts +1 -1
- package/scripts/run/run-ship-probe.ts +4 -1
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +18 -4
- package/scripts/run/run-ship-review.ts +11 -0
- package/scripts/run/run-ship-scoped.ts +1 -0
- package/scripts/run/run-ship-steps.ts +1 -1
- package/scripts/run/run-ship.ts +0 -1
- package/scripts/run/run-stage-read.ts +62 -0
- package/scripts/run/run-stage.ts +160 -0
- package/scripts/run/run-status-cli.ts +3 -16
- package/scripts/run/run-step-cli.ts +21 -14
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stop-notify.ts +1 -3
- package/scripts/run/run-stranded-cli.ts +0 -4
- package/scripts/run/run-stranded-detect.ts +2 -2
- package/scripts/run/run-tail-cli.ts +17 -11
- package/scripts/run/run-tail.ts +2 -0
- package/scripts/run/run-tidy-lanes.ts +6 -2
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +4 -13
- package/scripts/run/run-wake-loop.ts +2 -2
- package/scripts/run/run-wake.ts +2 -4
- package/scripts/run/run-watcher-guard-cli.ts +0 -4
- package/scripts/run/run-watcher-guard.ts +18 -12
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- package/scripts/safe-chain/pack-hook.ts +92 -0
- package/scripts/safe-chain/project-config.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +0 -1
- package/scripts/security/security-audit-provision.ts +3 -2
- package/scripts/security/security-audit.ts +0 -1
- package/scripts/security/security-updates-logic.ts +0 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
- package/scripts/sonar/sonar-hotspots.ts +0 -1
- package/scripts/sonar/sonar-new-code-cli.ts +150 -0
- package/scripts/sonar/sonar-new-code.ts +79 -0
- package/scripts/sonar/sonar-project.ts +97 -0
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +2 -5
- package/scripts/sync/managed-config-scope-cli.ts +1 -1
- package/scripts/sync/skill-migration.ts +0 -1
- package/scripts/sync/sync-ai-files.ts +4 -0
- package/scripts/sync/sync-hook-safety.ts +2 -3
- package/scripts/sync/sync.ts +1 -8
- package/scripts/sync/template-source-logic.ts +0 -1
- package/scripts/sync/workflow-pin-logic.ts +16 -28
- package/scripts/test/test-declared-changed.ts +13 -16
- package/scripts/test/test-declared-logic.ts +0 -1
- package/scripts/test/test-declared.ts +3 -9
- package/scripts/test/test-red-commit.ts +2 -2
- package/scripts/test/test-red.ts +14 -7
- package/scripts/test/test-type-logic.ts +1 -1
- package/scripts/test/unit-worker-share.ts +7 -16
- package/scripts/time-runtime/time-batch-guard.ts +1 -2
- package/scripts/time-runtime/time-bundle-call.ts +0 -1
- package/scripts/time-runtime/time-bundles.ts +0 -4
- package/scripts/time-runtime/time-density-hook.ts +0 -2
- package/scripts/time-runtime/time-followup-stage.ts +1 -1
- package/scripts/time-runtime/time-format.ts +0 -73
- package/scripts/time-runtime/time-round-trips.ts +0 -4
- package/scripts/time-runtime/time-single-check.ts +1 -1
- package/scripts/time-runtime/time-spans.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +1 -2
- package/scripts/ui/ui-routes-cli.ts +0 -5
- package/scripts/ui/ui-routes.ts +0 -5
- package/scripts/version/effective-upstream.ts +2 -2
- package/scripts/version/latest-corepack.ts +7 -9
- package/scripts/version/latest-scope-cli.ts +0 -2
- package/scripts/version/latest-update.ts +0 -2
- package/scripts/version/npm-registry.ts +2 -2
- package/scripts/version/publishable-range-check.ts +1 -1
- package/scripts/version/release-hold.ts +0 -4
- package/scripts/version/running-binary.ts +2 -2
- package/scripts/version/version-check-logic.ts +0 -2
- package/scripts/version/version-commands.ts +11 -1
- package/scripts/version/version-remote.ts +3 -3
- package/scripts/version/version-targets.ts +4 -4
- package/templates/CLAUDE.basic.md +6 -6
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/ci.yml +16 -82
- package/templates/workflows/dependabot-auto-merge.yml +6 -3
- package/templates/workflows/github-release.yml +79 -0
- package/tsconfig.sonar.json +4 -22
- package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
- package/prompts/collaboration-workflow/epic-audit.md +0 -5
- package/prompts/collaboration-workflow/epic-bundle.md +0 -5
- package/scripts/init/plugin-install-hint.ts +0 -47
- package/scripts/version/parse-json.ts +0 -13
- /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
- /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
- /package/scripts/{git → gh}/git-gh-command.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
- /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
- /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
- /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
- /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
- /package/scripts/{git → gh}/git-pr-error.ts +0 -0
- /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
- /package/scripts/{git → gh}/github-issue-url.ts +0 -0
- /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
- /package/scripts/{git → issue}/issue-reference.ts +0 -0
- /package/scripts/{git → lib}/animation-helpers.ts +0 -0
- /package/scripts/{git → lib}/git-animation.ts +0 -0
- /package/scripts/{git → notify}/git-notify.ts +0 -0
- /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
|
@@ -28,7 +28,7 @@ import { run_progress_read, type ObservationRead } from './run-progress-read'
|
|
|
28
28
|
// `backlogrun` parent — `ready #N · free lanes N` — which is itself something the parent acts on.
|
|
29
29
|
//
|
|
30
30
|
// **It cannot send a Telegram.** That is structural rather than a promise — nothing here imports
|
|
31
|
-
// `scripts/
|
|
31
|
+
// `scripts/notify/telegram-notify`, which is the only egress there is. A heartbeat every twenty minutes on
|
|
32
32
|
// a phone is notification fatigue, and it would cheapen the `confirmation` and `completion` messages
|
|
33
33
|
// that do need to interrupt someone.
|
|
34
34
|
|
|
@@ -51,7 +51,7 @@ const TICK_SECONDS = 30
|
|
|
51
51
|
const DECLINE_RETRY_SECONDS = 120
|
|
52
52
|
// The clock a fresh loop starts with: nothing has declined yet, so nothing is being waited out.
|
|
53
53
|
const NO_RETRY = 0
|
|
54
|
-
const {
|
|
54
|
+
const { DEFAULT_WAIT_MAX_HOURS } = run_progress_args
|
|
55
55
|
const ENVIRONMENT_KEY = 'JOSH_PROGRESS'
|
|
56
56
|
const DISABLED_VALUE = '0'
|
|
57
57
|
|
|
@@ -74,7 +74,7 @@ const UNREADABLE_NOTICE =
|
|
|
74
74
|
'The `in-progress` listing could not be read, so nothing is reported. That is not "nothing is running" — check `gh auth status` and ask again.'
|
|
75
75
|
const FAILED_TICK_PREFIX =
|
|
76
76
|
'A progress reading failed, so nothing is reported for it. The watcher is still running, and will read again after the cooldown:'
|
|
77
|
-
const WAIT_EXPIRED_NOTICE = `The watch bound (\`--hours\`, ${String(
|
|
77
|
+
const WAIT_EXPIRED_NOTICE = `The watch bound (\`--hours\`, ${String(DEFAULT_WAIT_MAX_HOURS)} by default for \`--wait\`) ran out with no newly runnable work arriving. Every report it made is already on the run's event stream (\`pnpm josh run:event --watch\`), so there is nothing to relay. Starting another \`--wait\` resumes the same clock.`
|
|
78
78
|
// The repository name is only ever printed, never written against, so the bounded lookup is the right
|
|
79
79
|
// one: a `gh` call that hangs would otherwise block the synchronous read at startup and leave the
|
|
80
80
|
// watcher neither running nor saying so.
|
|
@@ -104,6 +104,10 @@ interface WatchOptions {
|
|
|
104
104
|
output_paths: ReadonlyArray<string>
|
|
105
105
|
repo: string
|
|
106
106
|
tick_ms: number
|
|
107
|
+
// `--wait` alone: the line goes to the run's event stream and the ambient log, never to standard
|
|
108
|
+
// output, because a background command's output reaches the session only as a wake
|
|
109
|
+
// (joshuafolkken/kit#3102).
|
|
110
|
+
is_stream_only?: boolean
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
interface EmitContext {
|
|
@@ -202,7 +206,7 @@ async function emit(options: WatchOptions, context: EmitContext): Promise<EmitRe
|
|
|
202
206
|
unchanged_since_ms: state.unchanged_since_ms,
|
|
203
207
|
})
|
|
204
208
|
|
|
205
|
-
console.info(line)
|
|
209
|
+
if (options.is_stream_only !== true) console.info(line)
|
|
206
210
|
|
|
207
211
|
return { kind: 'observed', state, line }
|
|
208
212
|
}
|
|
@@ -287,8 +291,8 @@ async function step(options: WatchOptions, target: string, loop: WatchLoop): Pro
|
|
|
287
291
|
/**
|
|
288
292
|
* The loop both reporting forms are, with one difference between them.
|
|
289
293
|
*
|
|
290
|
-
* `watch` runs until `--hours` expires; `--wait` stops at the first
|
|
291
|
-
* (joshuafolkken/kit#
|
|
294
|
+
* `watch` runs until `--hours` expires; `--wait` stops at the first arrival and keeps its lines off
|
|
295
|
+
* standard output (joshuafolkken/kit#3102). Everything else — where the clock is seeded from, the tick, the decline
|
|
292
296
|
* cooldown `step` keeps — is one implementation on purpose: two copies would let a fix to the bound or
|
|
293
297
|
* to the initial silence reach one form and not the other, and `--wait` is the form a run starts.
|
|
294
298
|
*/
|
|
@@ -301,17 +305,14 @@ function seed_loop(target: string, started_ms: number): WatchLoop {
|
|
|
301
305
|
// Why the loop stopped, so `drive` prints the bound-expired notice only when the bound is what
|
|
302
306
|
// expired — not when `josh followup` ended the watcher, which is a clean stop with nothing to report.
|
|
303
307
|
// `arrived` is a `--wait` ended early by newly runnable work (joshuafolkken/kit#2503).
|
|
304
|
-
type WatchExit = '
|
|
308
|
+
type WatchExit = 'arrived' | 'ended' | 'bound'
|
|
305
309
|
|
|
306
|
-
// `wait` is present for `--wait` alone, which ends at the first
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
wait: ArrivalProbe | undefined,
|
|
312
|
-
): Promise<WatchExit | undefined> {
|
|
310
|
+
// `wait` is present for `--wait` alone, which ends at the first arrival its probe sees. **A report is
|
|
311
|
+
// not an exit** (joshuafolkken/kit#3102): every exit wakes the session that started it, and a wake
|
|
312
|
+
// spent relaying a line the event stream already carries is the most expensive turn a run takes, so
|
|
313
|
+
// only what the parent has to act on ends the wait.
|
|
314
|
+
async function wait_exit(wait: ArrivalProbe | undefined): Promise<WatchExit | undefined> {
|
|
313
315
|
if (wait === undefined) return undefined
|
|
314
|
-
if (loop.state !== undefined) return 'reported'
|
|
315
316
|
|
|
316
317
|
return (await wait.has_arrived(Date.now())) ? 'arrived' : undefined
|
|
317
318
|
}
|
|
@@ -335,8 +336,8 @@ function final_exit(life: string): WatchExit {
|
|
|
335
336
|
// The loop both reporting forms share, reading its own liveness record at the top of each pass — the
|
|
336
337
|
// `run-wake-loop.ts` `run_loop` shape (joshuafolkken/kit#1727). A record gone means `josh followup`
|
|
337
338
|
// removed it at the merge, so the watcher stops at once instead of waiting out its bound
|
|
338
|
-
// (joshuafolkken/kit#1821); `--wait` also stops at the first
|
|
339
|
-
//
|
|
339
|
+
// (joshuafolkken/kit#1821); `--wait` also stops at the first arrival, and otherwise the loop runs
|
|
340
|
+
// until `--hours` expires.
|
|
340
341
|
async function run_ticks(
|
|
341
342
|
options: WatchOptions,
|
|
342
343
|
target: string,
|
|
@@ -347,11 +348,14 @@ async function run_ticks(
|
|
|
347
348
|
let loop = seed_loop(target, started_ms)
|
|
348
349
|
|
|
349
350
|
while (Date.now() - started_ms < options.max_ms && !run_progress_clock.is_life_ended(life)) {
|
|
351
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
350
352
|
await sleep(options.tick_ms)
|
|
351
353
|
run_progress_clock.ping_life(life)
|
|
354
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
352
355
|
loop = await step(options, target, loop)
|
|
353
356
|
|
|
354
|
-
|
|
357
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
358
|
+
const exit = await wait_exit(wait)
|
|
355
359
|
|
|
356
360
|
if (exit !== undefined) return exit
|
|
357
361
|
}
|
|
@@ -394,14 +398,16 @@ async function once(options: WatchOptions): Promise<number> {
|
|
|
394
398
|
}
|
|
395
399
|
|
|
396
400
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
401
|
+
* The form a run starts in the background: it reports on its own and wakes the caller only for work
|
|
402
|
+
* (joshuafolkken/kit#3102).
|
|
399
403
|
*
|
|
400
|
-
* **
|
|
401
|
-
* output
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
404
|
+
* **A report is not a wake.** It once ended at its first line so a harness that delivers a background
|
|
405
|
+
* command's output only on exit would relay it (joshuafolkken/kit#1576) — which cost the orchestrating
|
|
406
|
+
* session one turn per heartbeat, re-reading a hundred thousand tokens of context to pass on a line it
|
|
407
|
+
* was forbidden to change. Every line already reaches the run's event stream as a `heartbeat` and the
|
|
408
|
+
* ambient log, which a person's `run:event --watch` pane reads with no model in between, so this form
|
|
409
|
+
* keeps its lines off standard output and exits only on an arrival, on `josh followup` ending its life
|
|
410
|
+
* record, or on its bound. The caller starts it once and restarts it only after one of those.
|
|
405
411
|
*
|
|
406
412
|
* **The clock is still this command's, not the caller's.** It is the watch loop itself, a tick at a
|
|
407
413
|
* time, rather than a second reading of the same record — so a real report elsewhere pushes the next
|
|
@@ -416,10 +422,10 @@ async function once(options: WatchOptions): Promise<number> {
|
|
|
416
422
|
* carried budget, no lane, and no `in-progress` child — so a genuinely idle repository keeps the loop
|
|
417
423
|
* waiting instead of ending it; returning there would hand the caller an instant answer to restart,
|
|
418
424
|
* and the documented restart makes that a poll rather than a heartbeat. Once a run has started the
|
|
419
|
-
* loop reports
|
|
425
|
+
* loop reports even before the first child carries `in-progress` (joshuafolkken/kit#1900).
|
|
420
426
|
*/
|
|
421
427
|
async function wait_once(options: WatchOptions): Promise<number> {
|
|
422
|
-
return await drive(options, true)
|
|
428
|
+
return await drive({ ...options, is_stream_only: true }, true)
|
|
423
429
|
}
|
|
424
430
|
|
|
425
431
|
async function mark_now(): Promise<number> {
|
|
@@ -445,7 +451,7 @@ function to_options(values: ParsedValues): WatchOptions | undefined {
|
|
|
445
451
|
|
|
446
452
|
return {
|
|
447
453
|
interval_ms: run_progress_args.to_interval_ms(values.interval),
|
|
448
|
-
max_ms: run_progress_args.to_max_ms(values.hours),
|
|
454
|
+
max_ms: run_progress_args.to_max_ms(values.hours, values.wait === true),
|
|
449
455
|
output_paths: values.output ?? [],
|
|
450
456
|
repo,
|
|
451
457
|
tick_ms: TICK_SECONDS * run_progress.MS_PER_SECOND,
|
|
@@ -491,27 +497,20 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
491
497
|
}
|
|
492
498
|
|
|
493
499
|
const run_progress_cli = {
|
|
494
|
-
|
|
495
|
-
DEFAULT_MAX_HOURS,
|
|
500
|
+
DEFAULT_WAIT_MAX_HOURS,
|
|
496
501
|
DISABLED_NOTICE,
|
|
497
502
|
FAILED_TICK_PREFIX,
|
|
498
503
|
FRESH_LOOP,
|
|
499
504
|
IDLE_NOTICE,
|
|
500
505
|
LANE_CHILD_NOTICE,
|
|
501
|
-
MARKED_NOTICE,
|
|
502
506
|
REPO_UNRESOLVED_NOTICE,
|
|
503
|
-
TICK_SECONDS,
|
|
504
507
|
UNREADABLE_NOTICE,
|
|
505
508
|
USAGE,
|
|
506
509
|
WAIT_EXPIRED_NOTICE,
|
|
507
|
-
main,
|
|
508
510
|
read_arguments: run_progress_args.read_arguments,
|
|
509
|
-
report_decline,
|
|
510
511
|
run,
|
|
511
512
|
step,
|
|
512
513
|
to_interval_ms: run_progress_args.to_interval_ms,
|
|
513
|
-
to_max_ms: run_progress_args.to_max_ms,
|
|
514
|
-
to_options,
|
|
515
514
|
wait_once,
|
|
516
515
|
}
|
|
517
516
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { git_common_directory } from '#scripts/git/git-common-directory'
|
|
2
2
|
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
3
|
-
import {
|
|
3
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
4
4
|
import { z } from 'zod'
|
|
5
5
|
|
|
6
6
|
// The report clock `josh run:progress` keeps, in the one form both of its readers can use
|
|
@@ -16,9 +16,10 @@ import { z } from 'zod'
|
|
|
16
16
|
//
|
|
17
17
|
// **The key is the work tree's own git directory**, the way `run_hold` keys its record: two lanes of
|
|
18
18
|
// one repository are two runs, and one lane's report must not silence the other's clock. The
|
|
19
|
-
// synchronous twin
|
|
20
|
-
// `git_command.git_directories` reads and
|
|
21
|
-
//
|
|
19
|
+
// synchronous twin is `git_common_directory.own()`, which asks the same two lines
|
|
20
|
+
// `git_command.git_directories` reads and takes the first — so the two spellings cannot name different
|
|
21
|
+
// files. A git read that fails or times out answers `undefined`, which reads as "no clock here" and
|
|
22
|
+
// lets the call through.
|
|
22
23
|
|
|
23
24
|
const PROGRESS_PREFIX = 'josh-run-progress-'
|
|
24
25
|
// The watcher's own liveness record, kept apart from the report clock above: that one says *when* the
|
|
@@ -55,14 +56,6 @@ const MS_PER_MINUTE = 60_000
|
|
|
55
56
|
const LOG_STALE_MINUTES = 90
|
|
56
57
|
const LOG_STALE_MS = LOG_STALE_MINUTES * MS_PER_MINUTE
|
|
57
58
|
const BLOCK_SEPARATOR = '\n\n'
|
|
58
|
-
// The lookup only ever decides whether a rule speaks, so a git call that hangs must not hold the hook
|
|
59
|
-
// that is holding the user's call. A timeout answers `undefined`, which reads as "no clock here" and
|
|
60
|
-
// lets the call through — the direction every other failure in this path already takes.
|
|
61
|
-
const GIT_TIMEOUT_MS = 5000
|
|
62
|
-
// The first of the two lines `git_command.git_directories` reads, asked on its own because that is the
|
|
63
|
-
// one the record is keyed on. Asking git rather than assuming a directory named `.git` is what makes a
|
|
64
|
-
// linked work tree, a bare repository and a `--separate-git-dir` clone all answer correctly.
|
|
65
|
-
const GIT_DIRECTORY_ARGUMENTS: ReadonlyArray<string> = ['rev-parse', '--absolute-git-dir']
|
|
66
59
|
|
|
67
60
|
// `line` is the last heartbeat the watcher printed, kept verbatim beside the clock so a reader that
|
|
68
61
|
// cannot see the watcher's transcript — a person checking a woken headless `backlogrun` through
|
|
@@ -240,7 +233,9 @@ function is_life_fresh(target: string, threshold_ms: number): boolean {
|
|
|
240
233
|
const pinged_ms = parse_pinged_at(raw)
|
|
241
234
|
|
|
242
235
|
return pinged_ms !== undefined && Date.now() - pinged_ms < threshold_ms
|
|
243
|
-
} catch {
|
|
236
|
+
} catch (error) {
|
|
237
|
+
error_text.trace_swallowed('run_progress_clock.is_life_fresh', error)
|
|
238
|
+
|
|
244
239
|
return false
|
|
245
240
|
}
|
|
246
241
|
}
|
|
@@ -259,25 +254,8 @@ function end_life(target: string): void {
|
|
|
259
254
|
stamp_file.remove_stamp(target)
|
|
260
255
|
}
|
|
261
256
|
|
|
262
|
-
// execa runs the binary directly with an argument array and no `shell` option, so CLI args cannot
|
|
263
|
-
// break out of a shell sandbox; the git command and args are internally controlled, never untrusted
|
|
264
|
-
// input. tssecurity:S8705 is a false positive here.
|
|
265
|
-
function git_directory_sync(): string | undefined {
|
|
266
|
-
const git_binary = git_utilities.get_git_command_for_spawn()
|
|
267
|
-
const result = execaSync(git_binary, GIT_DIRECTORY_ARGUMENTS, {
|
|
268
|
-
reject: false,
|
|
269
|
-
timeout: GIT_TIMEOUT_MS,
|
|
270
|
-
}) // NOSONAR
|
|
271
|
-
|
|
272
|
-
if (result.exitCode !== 0) return undefined
|
|
273
|
-
|
|
274
|
-
const output = result.stdout.trim()
|
|
275
|
-
|
|
276
|
-
return output === '' ? undefined : output
|
|
277
|
-
}
|
|
278
|
-
|
|
279
257
|
function stamp_target_sync(): string | undefined {
|
|
280
|
-
const directory =
|
|
258
|
+
const directory = git_common_directory.own()
|
|
281
259
|
|
|
282
260
|
return directory === undefined ? undefined : stamp_target_of(directory)
|
|
283
261
|
}
|
|
@@ -299,8 +277,6 @@ const run_progress_clock = {
|
|
|
299
277
|
LIFE_PREFIX,
|
|
300
278
|
LOG_KEEP,
|
|
301
279
|
LOG_STALE_MS,
|
|
302
|
-
PROGRESS_PREFIX,
|
|
303
|
-
append_line,
|
|
304
280
|
begin_life,
|
|
305
281
|
end_life,
|
|
306
282
|
is_life_ended,
|
|
@@ -314,7 +290,6 @@ const run_progress_clock = {
|
|
|
314
290
|
read_last_report,
|
|
315
291
|
read_last_report_sync,
|
|
316
292
|
stamp_target_of,
|
|
317
|
-
stamp_target_sync,
|
|
318
293
|
}
|
|
319
294
|
|
|
320
295
|
export { run_progress_clock }
|
|
@@ -27,8 +27,6 @@ import { run_progress } from './run-progress'
|
|
|
27
27
|
// watcher it guards kept the default, which is the one state this module exists to prevent.
|
|
28
28
|
|
|
29
29
|
const PACKAGE_FILE = 'package.json'
|
|
30
|
-
const CONFIG_FIELD = 'josh'
|
|
31
|
-
const INTERVAL_FIELD = 'progress_interval_minutes'
|
|
32
30
|
|
|
33
31
|
// Deep enough to cross a workspace package and its root, and bounded so a path that never reaches a
|
|
34
32
|
// root — a broken mount, a mocked `dirname` — cannot spin.
|
|
@@ -108,8 +106,6 @@ function configured_interval_ms(directory: string = process.cwd()): number {
|
|
|
108
106
|
}
|
|
109
107
|
|
|
110
108
|
const run_progress_config = {
|
|
111
|
-
CONFIG_FIELD,
|
|
112
|
-
INTERVAL_FIELD,
|
|
113
109
|
PACKAGE_FILE,
|
|
114
110
|
configured_interval_ms,
|
|
115
111
|
read_package_minutes,
|
|
@@ -28,7 +28,7 @@ import { run_progress_clock } from './run-progress-clock'
|
|
|
28
28
|
// `run-progress-clock.ts`, because the trigger-delivered rule that refuses an early heartbeat reads
|
|
29
29
|
// the same record from inside a `PreToolUse` hook and cannot await the git call this file makes
|
|
30
30
|
// (joshuafolkken/kit#1570). What stays here is the asynchronous way of naming the work tree.
|
|
31
|
-
const {
|
|
31
|
+
const { mark, parse_stamp, read_last_report } = run_progress_clock
|
|
32
32
|
|
|
33
33
|
const FIRST_LOAD_AVERAGE = 0
|
|
34
34
|
|
|
@@ -182,7 +182,6 @@ async function read_observations(request: ObservationRequest): Promise<Observati
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
const run_progress_read = {
|
|
185
|
-
PROGRESS_PREFIX,
|
|
186
185
|
has_run_started,
|
|
187
186
|
live_target,
|
|
188
187
|
log_target,
|
|
@@ -257,7 +257,7 @@ interface LineTiming {
|
|
|
257
257
|
* this is that same move for one value.
|
|
258
258
|
*
|
|
259
259
|
* **It is a schedule rather than an observation, and the two conditions on it are said in prose**
|
|
260
|
-
* (`docs/josh-commands.md` → `josh run:progress`): it holds only while the silence continues, and a
|
|
260
|
+
* (`docs/josh-commands-automation.md` → `josh run:progress`): it holds only while the silence continues, and a
|
|
261
261
|
* real report arriving first restarts the clock through `--mark` and supersedes it. The line printing
|
|
262
262
|
* it is itself a report, so the clock starts at this observation.
|
|
263
263
|
*/
|
|
@@ -367,7 +367,6 @@ const run_progress = {
|
|
|
367
367
|
format_line,
|
|
368
368
|
format_next_line,
|
|
369
369
|
format_next_report,
|
|
370
|
-
format_record,
|
|
371
370
|
format_report,
|
|
372
371
|
is_due,
|
|
373
372
|
minutes_from,
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
2
|
+
import type { PullMergeState } from '#scripts/gh/git-gh-pr-read'
|
|
3
|
+
import { git_branch } from '#scripts/git/git-branch'
|
|
4
|
+
import { git_command } from '#scripts/git/git-command'
|
|
5
|
+
import { run_halfrun_resume, type StopMark } from './run-halfrun-resume'
|
|
6
|
+
import { run_hold, type HoldRead } from './run-hold'
|
|
7
|
+
|
|
8
|
+
// joshuafolkken/kit#3023: a `prrun` stops at a green, mergeable pull request and **keeps** its hold, so
|
|
9
|
+
// a person can look before anything merges. What comes next is one of three, and `run:entry` answers
|
|
10
|
+
// which as the resume token `fullrun #N` acts on — read, never inferred:
|
|
11
|
+
//
|
|
12
|
+
// - `prrun-merged` — the person merged it by hand. Only `followup`'s tail is left.
|
|
13
|
+
// - `prrun-merge` — the branch is where the stop left it, both here and on the pull request, and the
|
|
14
|
+
// tree is clean. What was verified is what would merge, so `followup` merges without the gate and
|
|
15
|
+
// the review again.
|
|
16
|
+
// - `prrun-gate` — the branch moved since the stop, or the tree is dirty: a person changed something,
|
|
17
|
+
// so the gate and the review run again before `followup`. **The pull request's own head is asked
|
|
18
|
+
// too**: a commit pushed on GitHub (a suggestion applied, "Update branch") moves only the remote,
|
|
19
|
+
// and `followup` merges the remote — an unread or moved one is never taken as untouched.
|
|
20
|
+
//
|
|
21
|
+
// **Only a marked record is adopted**, as for the `halfrun` stop (`run-halfrun-resume.ts`): the stop
|
|
22
|
+
// writes the commit it stopped on (`run:hold <N> --prrun-stop`), and a hold without it is a run still
|
|
23
|
+
// working, never one waiting for a person.
|
|
24
|
+
|
|
25
|
+
const PRRUN_MERGED = 'prrun-merged'
|
|
26
|
+
const PRRUN_MERGE = 'prrun-merge'
|
|
27
|
+
const PRRUN_GATE = 'prrun-gate'
|
|
28
|
+
|
|
29
|
+
type PrrunToken = typeof PRRUN_GATE | typeof PRRUN_MERGE | typeof PRRUN_MERGED
|
|
30
|
+
|
|
31
|
+
interface ResumeFacts {
|
|
32
|
+
is_merged: boolean
|
|
33
|
+
stop_head: string
|
|
34
|
+
head: string
|
|
35
|
+
// The commit the pull request's head is on, or `undefined` when it could not be read.
|
|
36
|
+
pr_head: string | undefined
|
|
37
|
+
is_dirty: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function is_untouched(facts: ResumeFacts): boolean {
|
|
41
|
+
return facts.head === facts.stop_head && facts.pr_head === facts.stop_head && !facts.is_dirty
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function decide(facts: ResumeFacts): PrrunToken {
|
|
45
|
+
if (facts.is_merged) return PRRUN_MERGED
|
|
46
|
+
|
|
47
|
+
return is_untouched(facts) ? PRRUN_MERGE : PRRUN_GATE
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function stop_head_of(read: HoldRead, issue: string): string | undefined {
|
|
51
|
+
const hold = run_halfrun_resume.hold_of(read)
|
|
52
|
+
|
|
53
|
+
return hold?.issue === issue ? hold.prrun_stop_head : undefined
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function read_merge_state(): Promise<PullMergeState | undefined> {
|
|
57
|
+
return await git_gh_command.pr_get_merge_state(await git_branch.current())
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function read_facts(stop_head: string): Promise<ResumeFacts> {
|
|
61
|
+
const [state, head, is_dirty] = await Promise.all([
|
|
62
|
+
read_merge_state(),
|
|
63
|
+
git_command.head_commit(),
|
|
64
|
+
run_hold.is_tree_dirty(),
|
|
65
|
+
])
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
is_merged: state?.is_merged === true,
|
|
69
|
+
stop_head,
|
|
70
|
+
head,
|
|
71
|
+
pr_head: state?.head_sha,
|
|
72
|
+
is_dirty,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Read-only, so `run:entry` can ask the session budget before it takes anything over. `undefined` is
|
|
77
|
+
// "no `prrun` stop for this issue here", and the ordinary claim decides the tree as before.
|
|
78
|
+
async function resume_token(issue: string): Promise<PrrunToken | undefined> {
|
|
79
|
+
const target = await run_halfrun_resume.hold_target()
|
|
80
|
+
|
|
81
|
+
if (target === undefined) return undefined
|
|
82
|
+
|
|
83
|
+
const stop_head = stop_head_of(run_hold.read_hold(target), issue)
|
|
84
|
+
|
|
85
|
+
return stop_head === undefined ? undefined : decide(await read_facts(stop_head))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function adopt(issue: string): Promise<boolean> {
|
|
89
|
+
const target = await run_halfrun_resume.hold_target()
|
|
90
|
+
|
|
91
|
+
if (target === undefined || stop_head_of(run_hold.read_hold(target), issue) === undefined) {
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return run_halfrun_resume.take_over(target, issue)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// The `--prrun-stop` mark: the run's own record re-written with the commit the pull request is on.
|
|
99
|
+
async function mark_stop_at(target: string, issue: string): Promise<StopMark> {
|
|
100
|
+
const head = await git_command.head_commit()
|
|
101
|
+
|
|
102
|
+
return run_halfrun_resume.mark_stop_at(target, issue, { prrun_stop_head: head })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const run_prrun_resume = {
|
|
106
|
+
PRRUN_GATE,
|
|
107
|
+
PRRUN_MERGE,
|
|
108
|
+
PRRUN_MERGED,
|
|
109
|
+
adopt,
|
|
110
|
+
decide,
|
|
111
|
+
mark_stop_at,
|
|
112
|
+
resume_token,
|
|
113
|
+
stop_head_of,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type { PrrunToken, ResumeFacts }
|
|
117
|
+
export { run_prrun_resume }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { git_followup_pending } from '#scripts/
|
|
3
|
+
import { git_followup_pending } from '#scripts/followup/git-followup-pending'
|
|
4
4
|
import { release_scope_cli } from '#scripts/release/release-scope-cli'
|
|
5
5
|
import { run_carry } from './run-carry'
|
|
6
6
|
import { run_event_scope, type EventScope } from './run-event-scope'
|
|
@@ -62,7 +62,6 @@ async function main(): Promise<void> {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
const run_report_cli = {
|
|
65
|
-
main,
|
|
66
65
|
run,
|
|
67
66
|
}
|
|
68
67
|
|
|
@@ -28,7 +28,7 @@ function is_owed(facts: RetrospectiveFacts): boolean {
|
|
|
28
28
|
return !facts.is_lane_child && !facts.is_retrospective_done && !facts.is_consumer
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
const run_retrospective = {
|
|
31
|
+
const run_retrospective = { is_enabled, is_owed }
|
|
32
32
|
|
|
33
33
|
export type { RetrospectiveFacts }
|
|
34
34
|
export { run_retrospective }
|
|
@@ -94,7 +94,9 @@ async function wait_for_gate_finish(now: Clock = () => Date.now()): Promise<Gate
|
|
|
94
94
|
let state = await read_gate_state()
|
|
95
95
|
|
|
96
96
|
while (!run_review.is_gate_settled(state) && now() - started < MAX_JOIN_WAIT_MS) {
|
|
97
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
97
98
|
await sleep(POLL_INTERVAL_MS)
|
|
99
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
98
100
|
state = await read_gate_state()
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -105,12 +105,10 @@ const run_review = {
|
|
|
105
105
|
GATE_RED,
|
|
106
106
|
GATE_RUNNING,
|
|
107
107
|
adopt_verdict,
|
|
108
|
-
format_seconds,
|
|
109
108
|
format_timing,
|
|
110
109
|
gate_state,
|
|
111
110
|
is_gate_settled,
|
|
112
111
|
overlap_seconds,
|
|
113
|
-
span_seconds,
|
|
114
112
|
}
|
|
115
113
|
|
|
116
114
|
export type { AdoptVerdict, GateState, ReviewTiming, TimingStart }
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { parseArgs } from 'node:util'
|
|
4
3
|
import { lane_child_marker } from '#scripts/lane/lane-child-marker'
|
|
4
|
+
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
5
5
|
import { run_event_stream } from './run-event-stream'
|
|
6
6
|
import { run_event_stream_emit } from './run-event-stream-emit'
|
|
7
7
|
import { run_ship, type ShipSection } from './run-ship'
|
|
8
8
|
import { run_ship_detach } from './run-ship-detach'
|
|
9
|
+
import { run_ship_next } from './run-ship-next'
|
|
9
10
|
import { run_ship_probe } from './run-ship-probe'
|
|
10
11
|
import { run_ship_return } from './run-ship-return'
|
|
11
12
|
import { run_ship_stage, type Phase, type ShipState, type Stage } from './run-ship-stage'
|
|
@@ -120,13 +121,6 @@ interface ParsedValues extends NotifyValues {
|
|
|
120
121
|
cite?: Array<string>
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
function parse_values(argv: ReadonlyArray<string>): {
|
|
124
|
-
values: ParsedValues
|
|
125
|
-
positionals: Array<string>
|
|
126
|
-
} {
|
|
127
|
-
return parseArgs({ args: [...argv], options: OPTIONS, allowPositionals: true, strict: true })
|
|
128
|
-
}
|
|
129
|
-
|
|
130
124
|
function ship_args(
|
|
131
125
|
title: string,
|
|
132
126
|
rest: ReadonlyArray<string>,
|
|
@@ -154,9 +148,10 @@ function log_command(number: string, positionals: ReadonlyArray<string>): ShipCo
|
|
|
154
148
|
return CITE_PATTERN.test(number) && positionals.length === 0 ? { kind: 'log', number } : undefined
|
|
155
149
|
}
|
|
156
150
|
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
|
|
151
|
+
function command_of(
|
|
152
|
+
values: ParsedValues,
|
|
153
|
+
positionals: ReadonlyArray<string>,
|
|
154
|
+
): ShipCommand | undefined {
|
|
160
155
|
if (values.log !== undefined) return log_command(values.log, positionals)
|
|
161
156
|
|
|
162
157
|
const title = positionals[FIRST]
|
|
@@ -169,11 +164,9 @@ function read_args(argv: ReadonlyArray<string>): ShipCommand | undefined {
|
|
|
169
164
|
// Numbers-only tail and a strict parse, so a title with no `#<N>` or a stray flag is refused rather
|
|
170
165
|
// than shipped past the wrong step.
|
|
171
166
|
function parse(argv: ReadonlyArray<string>): ShipCommand | undefined {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return undefined
|
|
176
|
-
}
|
|
167
|
+
const parsed = cli_flags.arguments_of(argv, OPTIONS)
|
|
168
|
+
|
|
169
|
+
return parsed === undefined ? undefined : command_of(parsed.values, parsed.positionals)
|
|
177
170
|
}
|
|
178
171
|
|
|
179
172
|
async function run_step(step: Step, args: ShipArguments, state: ShipState): Promise<ShipSection> {
|
|
@@ -255,7 +248,9 @@ async function stopped(
|
|
|
255
248
|
args: ShipArguments,
|
|
256
249
|
stage: Stage,
|
|
257
250
|
): Promise<ReadonlyArray<ShipSection>> {
|
|
258
|
-
if (run_ship_detach.is_supervised())
|
|
251
|
+
if (run_ship_detach.is_supervised()) {
|
|
252
|
+
await run_ship_return.return_control(args.number, stage, run_ship_next.resume_of(args))
|
|
253
|
+
}
|
|
259
254
|
|
|
260
255
|
return sections
|
|
261
256
|
}
|
|
@@ -268,10 +263,12 @@ async function ship(args: ShipArguments): Promise<ReadonlyArray<ShipSection>> {
|
|
|
268
263
|
const sections: Array<ShipSection> = []
|
|
269
264
|
|
|
270
265
|
for (const step of run_ship_steps.steps(args)) {
|
|
266
|
+
// eslint-disable-next-line no-await-in-loop -- stages run in order and the first failure stops the ship
|
|
271
267
|
const section = await run_stage(step, args, context)
|
|
272
268
|
|
|
273
269
|
sections.push(section)
|
|
274
270
|
|
|
271
|
+
// eslint-disable-next-line no-await-in-loop -- stages run in order and the first failure stops the ship
|
|
275
272
|
if (section.code !== SUCCESS_EXIT_CODE) return await stopped(sections, args, step.stage)
|
|
276
273
|
}
|
|
277
274
|
|
|
@@ -324,6 +321,19 @@ function should_detach(args: ShipArguments): boolean {
|
|
|
324
321
|
return !run_ship_detach.is_supervised() && lane_child_marker.is_child_of(process.cwd())
|
|
325
322
|
}
|
|
326
323
|
|
|
324
|
+
// joshuafolkken/kit#2966: the preflight is deterministic and fast, so it runs here, in the agent's own
|
|
325
|
+
// turn, before the hand-off — a stop it finds is fixed by the same session instead of relaunching one
|
|
326
|
+
// from the supervisor. Only the slow stages go to the supervisor, which re-asks the preflight itself.
|
|
327
|
+
async function detach_after_preflight(args: ShipArguments): Promise<number> {
|
|
328
|
+
const section = await run_stage(run_ship_steps.PREFLIGHT_STEP, args, await open_context(args))
|
|
329
|
+
|
|
330
|
+
if (section.code === SUCCESS_EXIT_CODE) return await detach(args)
|
|
331
|
+
|
|
332
|
+
console.info(run_ship.format_report([section]))
|
|
333
|
+
|
|
334
|
+
return run_ship.exit_code([section])
|
|
335
|
+
}
|
|
336
|
+
|
|
327
337
|
async function supervised_repository(): Promise<string | undefined> {
|
|
328
338
|
return run_ship_detach.is_supervised() ? await run_ship_probe.repository_directory() : undefined
|
|
329
339
|
}
|
|
@@ -346,7 +356,7 @@ async function run_ship_command(args: ShipArguments): Promise<number> {
|
|
|
346
356
|
if (should_detach(args)) {
|
|
347
357
|
if (!args.is_detach) console.error(LANE_CHILD_DETACH_NOTE)
|
|
348
358
|
|
|
349
|
-
return await
|
|
359
|
+
return await detach_after_preflight(args)
|
|
350
360
|
}
|
|
351
361
|
|
|
352
362
|
await claim_supervised_identity(args)
|
|
@@ -376,7 +386,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
376
386
|
process.exitCode = await run(argv)
|
|
377
387
|
}
|
|
378
388
|
|
|
379
|
-
const run_ship_cli = {
|
|
389
|
+
const run_ship_cli = { run }
|
|
380
390
|
|
|
381
391
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
382
392
|
|
|
@@ -195,6 +195,7 @@ async function ready_record(repository: string, number: string): Promise<ShipRec
|
|
|
195
195
|
for (let attempt = 0; attempt < RECORD_WAIT_ATTEMPTS; attempt += 1) {
|
|
196
196
|
if (!is_pending(record)) return record
|
|
197
197
|
|
|
198
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
198
199
|
await sleep(RECORD_POLL_MS)
|
|
199
200
|
record = current_record(repository, number)
|
|
200
201
|
}
|