@joshuafolkken/kit 1.1050.0 → 1.1094.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 +19 -11
- package/.claude/skills/workflow-commands/background-commands.md +4 -3
- 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 +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
- 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 +3 -2
- package/.claude/skills/workflow-commands/halfrun.md +16 -19
- 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 +1 -1
- 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/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/working-tree-hold.md +22 -2
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/ci.yml +26 -128
- package/.github/workflows/pr-classification.yml +5 -41
- package/.github/workflows/publish.yml +33 -38
- package/.github/workflows/sonar-qube.yml +37 -4
- package/AGENTS.md +12 -2
- package/CLAUDE.md +15 -16
- package/GEMINI.md +14 -2
- package/README.md +59 -18
- package/SECURITY.md +36 -6
- package/cspell/index.yaml +2 -1
- package/dist/CLAUDE.md +15 -16
- package/dist/config-merge/index.js +15 -3
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-HJIISEAC.js → chunk-3C4YCCEF.js} +5 -13
- package/dist/hooks/{chunk-EJDX2TOB.js → chunk-7ZPFAVR7.js} +7 -88
- package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-E54KGFEQ.js} +2 -2
- package/dist/hooks/{chunk-GQ7KP45M.js → chunk-IL27YTPH.js} +2 -2
- package/dist/hooks/{chunk-DMQN45FN.js → chunk-KHWHKJOM.js} +3 -3
- package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M2XDCUKD.js} +997 -478
- package/dist/hooks/{chunk-7VPDUBRN.js → chunk-NKOG3XAV.js} +150 -153
- package/dist/hooks/{chunk-NJQOBE6L.js → chunk-O4LL4HTI.js} +2 -7
- package/dist/hooks/{chunk-NAS4C7GP.js → chunk-OIZUHPJI.js} +2 -2
- package/dist/hooks/{chunk-RLDX5SOC.js → chunk-UD24EAIL.js} +2084 -1412
- package/dist/hooks/codex-hook-adapter.js +10 -11
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +279 -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 +178 -324
- package/dist/josh.js +162 -119
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +34 -58
- package/eslint/rules/promise.js +5 -0
- package/package.json +9 -4
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/operating-rules.md +4 -4
- package/prompts/collaboration-workflow/overview.md +13 -1
- 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 +5 -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-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 +0 -5
- package/scripts/backlog/backlog-plan-cli.ts +1 -7
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +3 -6
- package/scripts/backlog/backlog-rank.ts +2 -2
- package/scripts/backlog/backlog-ready.ts +19 -3
- 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/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 +0 -3
- 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 +4 -6
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/document-byte-budget.ts +4 -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 +10 -2
- package/scripts/document/lane-child-read-set.ts +1 -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 +1 -0
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +1 -1
- 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 +5 -4
- 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 +2 -0
- 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-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-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-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} +1 -1
- 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-logic.ts +7 -0
- package/scripts/init/init.ts +0 -3
- package/scripts/init/project-profile.ts +6 -11
- package/scripts/init/start-exec.ts +1 -1
- package/scripts/init/start-setup-pr.ts +6 -6
- package/scripts/init/start-steps.ts +1 -0
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +3 -3
- 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-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +0 -2
- 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 +2 -2
- 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 +1 -1
- package/scripts/issue/measure-rerun-cli.ts +1 -1
- 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 +6 -0
- 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 +2 -2
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +3 -6
- 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 +1 -3
- 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 +21 -11
- 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 +3 -0
- package/scripts/lib/bounded-pool.ts +1 -0
- 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/lines-command.ts +0 -1
- 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 +0 -2
- 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 +0 -1
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +0 -2
- package/scripts/registry-migration/migrate.ts +19 -9
- package/scripts/release/github-release-cli.ts +8 -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 +2 -3
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- 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-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 +1 -1
- 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/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 +13 -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 +13 -5
- 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-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-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +1 -1
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +101 -24
- 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.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 +25 -5
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +1 -1
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +5 -13
- 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 +0 -1
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +2 -2
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-cli.ts +4 -7
- package/scripts/run/run-progress-clock.ts +6 -34
- 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 +21 -3
- 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-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 +1 -1
- 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 +2 -1
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +2 -3
- 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 +9 -7
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- 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-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-logic.ts +0 -1
- package/scripts/test/test-declared.ts +0 -2
- 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-remote.ts +3 -3
- package/scripts/version/version-targets.ts +4 -4
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/dependabot-auto-merge.yml +5 -3
- package/templates/workflows/github-release.yml +81 -0
- 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-write.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-auto-merge.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
|
@@ -45,6 +45,9 @@ interface StopContext {
|
|
|
45
45
|
hold_present: boolean
|
|
46
46
|
// `git status --porcelain` came back empty.
|
|
47
47
|
tree_clean: boolean
|
|
48
|
+
// That record carries a `prrun` stop mark (joshuafolkken/kit#3023): the run stopped at a green pull
|
|
49
|
+
// request and keeps the hold over a clean tree on purpose, so a person can look before it merges.
|
|
50
|
+
prrun_stopped: boolean
|
|
48
51
|
// A `confirmation` notify is on this run's transcript tail.
|
|
49
52
|
notified: boolean
|
|
50
53
|
// The turn's session-facing reply text.
|
|
@@ -75,6 +78,9 @@ interface StopContext {
|
|
|
75
78
|
// A backgrounded subagent this run launched has not finished — `lane_background.pending_agent_ids`
|
|
76
79
|
// (joshuafolkken/kit#2774). Apart from `background_pending`, since only a subagent is sure to end.
|
|
77
80
|
agent_pending: boolean
|
|
81
|
+
// This lane child handed its region to a running detached ship — `lane_handoff.is_handed_off`
|
|
82
|
+
// (joshuafolkken/kit#2962). The supervisor notifies on its own outcome, so nobody waits on this stop.
|
|
83
|
+
handed_off: boolean
|
|
78
84
|
// The resolved `JOSH_SESSION_LANG` — `session_language.resolve_session_lang` (joshuafolkken/kit#2470).
|
|
79
85
|
session_lang: string
|
|
80
86
|
}
|
|
@@ -105,8 +111,8 @@ const HOLD_RELEASE_REASON =
|
|
|
105
111
|
'place, so the next run here runs `git switch main && git pull` believing the tree is free while ' +
|
|
106
112
|
'you hold it. `.claude/skills/workflow-commands/SKILL.md` → §2f: a stop that leaves the tree clean ' +
|
|
107
113
|
'releases the hold with `pnpm josh run:release <N>` (bare for a `new` entry). A `halfrun` ' +
|
|
108
|
-
'pre-commit stop and a `needs-human-review` stop keep the hold because their tree is dirty
|
|
109
|
-
'row is silent there. Release it, then end with a one-line confirmation that it was released — do ' +
|
|
114
|
+
'pre-commit stop and a `needs-human-review` stop keep the hold because their tree is dirty, and a ' +
|
|
115
|
+
'`prrun` stop keeps it by its stop mark — this row is silent there. Release it, then end with a one-line confirmation that it was released — do ' +
|
|
110
116
|
'not repeat your previous reply.'
|
|
111
117
|
|
|
112
118
|
// **A refusal that corrects rather than advises** (joshuafolkken/kit#2247). The bare `#N` is already
|
|
@@ -232,8 +238,11 @@ function needs_filing(context: StopContext): boolean {
|
|
|
232
238
|
// notify there says "nothing needed" and dilutes the ones that do. A backgrounded command does not
|
|
233
239
|
// count: a dev server never ends, and a stop behind it would leave a person silently waiting. A lane
|
|
234
240
|
// child never reaches this with a task running: `needs_background_wait` answers it first.
|
|
241
|
+
//
|
|
242
|
+
// **A lane handed to the detached ship stands them down too** (joshuafolkken/kit#2962): the hold now
|
|
243
|
+
// belongs to the supervisor driving the merge, and the person hears from that supervisor's own notify.
|
|
235
244
|
function is_held_idle(context: StopContext): boolean {
|
|
236
|
-
return context.hold_present && !context.agent_pending
|
|
245
|
+
return context.hold_present && !context.agent_pending && !context.handed_off
|
|
237
246
|
}
|
|
238
247
|
|
|
239
248
|
function needs_notify(context: StopContext): boolean {
|
|
@@ -241,7 +250,7 @@ function needs_notify(context: StopContext): boolean {
|
|
|
241
250
|
}
|
|
242
251
|
|
|
243
252
|
function needs_release(context: StopContext): boolean {
|
|
244
|
-
return is_held_idle(context) && context.tree_clean
|
|
253
|
+
return is_held_idle(context) && context.tree_clean && !context.prrun_stopped
|
|
245
254
|
}
|
|
246
255
|
|
|
247
256
|
function citation_reason(context: StopContext): string | undefined {
|
|
@@ -345,7 +354,6 @@ const stop_rules = {
|
|
|
345
354
|
STOP_NOTIFY_REASON,
|
|
346
355
|
SWITCH_ENV_KEY,
|
|
347
356
|
block_envelope,
|
|
348
|
-
block_reason,
|
|
349
357
|
build_language_reason,
|
|
350
358
|
count_headless_refusals,
|
|
351
359
|
is_enabled,
|
|
@@ -30,6 +30,6 @@ function prior_bash_commands(tail: string): ReadonlyArray<string> {
|
|
|
30
30
|
return tail.split('\n').flatMap((line) => bash_commands_of(line))
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const tail_commands = {
|
|
33
|
+
const tail_commands = { is_bash_use, prior_bash_commands }
|
|
34
34
|
|
|
35
35
|
export { tail_commands }
|
|
@@ -46,6 +46,6 @@ const REASON =
|
|
|
46
46
|
// reason above.
|
|
47
47
|
const ROW = { id: 'test-declared', is_trigger: is_untested_commit, reason: REASON }
|
|
48
48
|
|
|
49
|
-
const test_declared_commit = { REASON, ROW
|
|
49
|
+
const test_declared_commit = { REASON, ROW }
|
|
50
50
|
|
|
51
51
|
export { test_declared_commit }
|
|
@@ -36,8 +36,8 @@ function is_worktree_checkout(args: ReadonlyArray<string>): boolean {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// `git restore <path>` discards working-tree changes. `--staged` / `-S` alone is an index restore —
|
|
39
|
-
// that is the
|
|
40
|
-
//
|
|
39
|
+
// that is the `index-mutation` row's (`index-guard.ts`), so a pure index restore is not claimed by two
|
|
40
|
+
// rows. Anything touching the worktree (the default, or an explicit `--worktree` / `-W`) is this row's.
|
|
41
41
|
const STAGED_LONG = '--staged'
|
|
42
42
|
const STAGED_LETTER = 'S'
|
|
43
43
|
const WORKTREE_LONG = '--worktree'
|
|
@@ -83,14 +83,33 @@ function is_unauthorized_stash(args: ReadonlyArray<string>): boolean {
|
|
|
83
83
|
return true
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// `git clean` deletes untracked files, which no commit can bring back (joshuafolkken/kit#2983). It
|
|
87
|
+
// refuses to act without a force (`clean.requireForce`), so a force — `--force`, or a cluster carrying
|
|
88
|
+
// `f` — is what marks the destructive call; `git clean -n` is a dry run and passes.
|
|
89
|
+
const CLEAN_SUBCOMMAND = 'clean'
|
|
90
|
+
const FORCE_LONG = '--force'
|
|
91
|
+
const FORCE_LETTER = 'f'
|
|
92
|
+
|
|
93
|
+
function is_forced_clean(args: ReadonlyArray<string>): boolean {
|
|
94
|
+
return args.some(
|
|
95
|
+
(argument) => argument === FORCE_LONG || git_argv.short_cluster_has(argument, FORCE_LETTER),
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Each subcommand this row judges, with the predicate that reads its arguments.
|
|
100
|
+
const JUDGED_SUBCOMMANDS: ReadonlyMap<string, (args: ReadonlyArray<string>) => boolean> = new Map([
|
|
101
|
+
[CHECKOUT_SUBCOMMAND, is_worktree_checkout],
|
|
102
|
+
[RESTORE_SUBCOMMAND, touches_worktree],
|
|
103
|
+
[CLEAN_SUBCOMMAND, is_forced_clean],
|
|
104
|
+
[STASH_SUBCOMMAND, is_unauthorized_stash],
|
|
105
|
+
])
|
|
106
|
+
|
|
86
107
|
function is_unauthorized_segment(segment: string): boolean {
|
|
87
108
|
const call = git_argv.parse(segment)
|
|
88
109
|
|
|
89
110
|
if (call === undefined) return false
|
|
90
|
-
if (call.subcommand === CHECKOUT_SUBCOMMAND) return is_worktree_checkout(call.args)
|
|
91
|
-
if (call.subcommand === RESTORE_SUBCOMMAND) return touches_worktree(call.args)
|
|
92
111
|
|
|
93
|
-
return call.subcommand
|
|
112
|
+
return JUDGED_SUBCOMMANDS.get(call.subcommand ?? '')?.(call.args) === true
|
|
94
113
|
}
|
|
95
114
|
|
|
96
115
|
function is_unauthorized_worktree_change(command: string): boolean {
|
|
@@ -101,8 +120,8 @@ function is_unauthorized_worktree_change(command: string): boolean {
|
|
|
101
120
|
// and — for a stash — the message form that is allowed. `pnpm josh git` and `pnpm josh stash:pop` are
|
|
102
121
|
// invisible to this trigger, so a run that uses them is never refused.
|
|
103
122
|
const WORKTREE_MUTATION_REASON =
|
|
104
|
-
'⛔ unauthorized working-tree change: `git checkout -- <path>`, `git restore <path
|
|
105
|
-
'unauthorized `git stash`
|
|
123
|
+
'⛔ unauthorized working-tree change: `git checkout -- <path>`, `git restore <path>`, a forced ' +
|
|
124
|
+
'`git clean` and an unauthorized `git stash` discard work or mutate the repository-wide stash every work tree ' +
|
|
106
125
|
'shares, and none is on the `.claude/settings.json` deny list (`operating-rules.md`). Do not run ' +
|
|
107
126
|
'them on your own judgement. A commit goes through `pnpm josh git`; a stash pop goes through `pnpm ' +
|
|
108
127
|
'josh stash:pop "<message>"`, never a positional `git stash pop` a shared stack lets another lane ' +
|
|
@@ -121,9 +140,7 @@ const ROW = {
|
|
|
121
140
|
const worktree_guard = {
|
|
122
141
|
ROW,
|
|
123
142
|
WORKTREE_MUTATION_REASON,
|
|
124
|
-
is_unauthorized_stash,
|
|
125
143
|
is_unauthorized_worktree_change,
|
|
126
|
-
is_worktree_checkout,
|
|
127
144
|
touches_worktree,
|
|
128
145
|
}
|
|
129
146
|
|
|
@@ -447,11 +447,9 @@ const run_carry_cli = {
|
|
|
447
447
|
RESUMED_VERDICT,
|
|
448
448
|
STANDING_VERDICT,
|
|
449
449
|
UNKNOWN_VERDICT,
|
|
450
|
-
UNREADABLE_VERDICT,
|
|
451
450
|
// Re-exported rather than restated: the usage line belongs to the half that parses, and a second
|
|
452
451
|
// copy of it here would drift from the flags it describes.
|
|
453
452
|
USAGE: run_carry_args.USAGE,
|
|
454
|
-
main,
|
|
455
453
|
run,
|
|
456
454
|
}
|
|
457
455
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { git_stash } from '#scripts/git/git-stash'
|
|
2
|
-
import { stash_orphans } from '#scripts/git/stash-orphans'
|
|
1
|
+
import { git_stash } from '#scripts/git/stash/git-stash'
|
|
2
|
+
import { stash_orphans } from '#scripts/git/stash/stash-orphans'
|
|
3
3
|
import { issue_state_cli } from '#scripts/issue/issue-state-cli'
|
|
4
4
|
import { bounded_pool } from '#scripts/lib/bounded-pool'
|
|
5
5
|
|
|
@@ -107,7 +107,7 @@ function next_state(carry: StreakCarry, change: StreakChange, now: Date): Streak
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
const run_carry_streak = {
|
|
110
|
+
const run_carry_streak = { next_state }
|
|
111
111
|
|
|
112
112
|
export type { StreakCarry, StreakChange, StreakState }
|
|
113
113
|
export { run_carry_streak }
|
|
@@ -45,8 +45,6 @@ const {
|
|
|
45
45
|
STALE_VERDICT,
|
|
46
46
|
SUCCESS_EXIT_CODE,
|
|
47
47
|
UNDER_THRESHOLD_VERDICT,
|
|
48
|
-
UNKNOWN_VERDICT,
|
|
49
|
-
UNREADABLE_VERDICT,
|
|
50
48
|
UNREADY_VERDICT,
|
|
51
49
|
refuse_unready,
|
|
52
50
|
report,
|
|
@@ -423,18 +421,13 @@ const run_cut_cli = {
|
|
|
423
421
|
FAILED_VERDICT,
|
|
424
422
|
FRESH_VERDICT,
|
|
425
423
|
HANDED_OFF_VERDICT,
|
|
426
|
-
INCOMPLETE_VERDICT,
|
|
427
424
|
NOT_A_LANE_VERDICT,
|
|
428
425
|
OVER_VERDICT,
|
|
429
426
|
RESUME_IMPL_VERDICT,
|
|
430
427
|
RESUME_VERDICT,
|
|
431
428
|
STALE_VERDICT,
|
|
432
429
|
UNDER_THRESHOLD_VERDICT,
|
|
433
|
-
UNKNOWN_VERDICT,
|
|
434
|
-
UNREADABLE_VERDICT,
|
|
435
430
|
UNREADY_VERDICT,
|
|
436
|
-
USAGE: run_cut_args.USAGE,
|
|
437
|
-
main,
|
|
438
431
|
run,
|
|
439
432
|
}
|
|
440
433
|
|
package/scripts/run/run-cut.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process'
|
|
2
1
|
import { agent_role_profile } from '#scripts/agent/agent-role-profile'
|
|
3
2
|
import { backlog_budget } from '#scripts/backlog/backlog-budget'
|
|
4
3
|
import { CONTEXT_CUT_THRESHOLD } from '#scripts/cost-runtime/context-cut-threshold'
|
|
5
|
-
import { git_utilities } from '#scripts/git/constants'
|
|
6
4
|
import { git_command } from '#scripts/git/git-command'
|
|
7
|
-
import {
|
|
5
|
+
import { git_common_directory } from '#scripts/git/git-common-directory'
|
|
8
6
|
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
9
7
|
import { lane_child_invocation } from '#scripts/lane/lane-child-invocation'
|
|
10
8
|
import { z } from 'zod'
|
|
@@ -60,14 +58,6 @@ const IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD
|
|
|
60
58
|
const CUT_MAX_AGE_MS = backlog_budget.WHOLE_RUN_BUDGET_MS
|
|
61
59
|
const CUT_MAX_AGE_HOURS = backlog_budget.WHOLE_RUN_BUDGET_HOURS
|
|
62
60
|
|
|
63
|
-
// The synchronous git read runs inside a `PreToolUse` hook, which holds the tool call for as long as
|
|
64
|
-
// it takes; `rev-parse` takes no lock, so anything past a second is a fault rather than slow work.
|
|
65
|
-
const GIT_READ_TIMEOUT_MS = 5000
|
|
66
|
-
|
|
67
|
-
// The two lines `GIT_DIRECTORY_ARGUMENTS` prints, in order: the work tree's own git directory, then the
|
|
68
|
-
// common one every lane of a repository shares. `git_directories` reads the same two asynchronously.
|
|
69
|
-
const WORKTREE_DIRECTORY_INDEX = 0
|
|
70
|
-
|
|
71
61
|
const END_COMMAND = 'pnpm josh run:cut --end'
|
|
72
62
|
const READ_COMMAND = 'pnpm josh run:cut --json'
|
|
73
63
|
|
|
@@ -224,10 +214,10 @@ function read_cut(target: string, now: Date = new Date()): CutRead {
|
|
|
224
214
|
|
|
225
215
|
// **The same read as `read_cut(cut_path(await worktree_directory()))`, taken synchronously**
|
|
226
216
|
// (joshuafolkken/kit#1864). The pre-gate cut is enforced from a `PreToolUse` guard, and a guard
|
|
227
|
-
// answers synchronously or not at all — so the one git call the path derivation needs is
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
//
|
|
217
|
+
// answers synchronously or not at all — so the one git call the path derivation needs is
|
|
218
|
+
// `git_common_directory.own()`, the synchronous twin of the asynchronous reader, rather than a second
|
|
219
|
+
// spelling of it. Everything after the path is already shared: `cut_path` keys the record and
|
|
220
|
+
// `classify` parses and expires it.
|
|
231
221
|
//
|
|
232
222
|
// **A fault reads as "no cut was taken", and that direction is deliberate rather than fail-open.** A
|
|
233
223
|
// checkout git cannot describe, a record that will not parse and an expired one all come back
|
|
@@ -235,47 +225,11 @@ function read_cut(target: string, now: Date = new Date()): CutRead {
|
|
|
235
225
|
// The alternative errs the other way: a read fault would be taken for "already cut" and the guard
|
|
236
226
|
// would go quiet on exactly the run it exists for. The cost of this direction is one refusal a lane
|
|
237
227
|
// can answer by reissuing, since that row is delivered once per run.
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
// The binary is resolved through `git_utilities` exactly as `git-spawn.ts` resolves it, so this
|
|
241
|
-
// call does not answer to whatever `PATH` happens to hold. It runs the binary directly with an
|
|
242
|
-
// argument array and no `shell` option, and both are internally controlled, never untrusted
|
|
243
|
-
// input.
|
|
244
|
-
const output = execFileSync(
|
|
245
|
-
git_utilities.get_git_command_for_spawn(),
|
|
246
|
-
[...git_command.GIT_DIRECTORY_ARGUMENTS],
|
|
247
|
-
// git's own diagnostics are discarded: a checkout it cannot describe is already the
|
|
248
|
-
// `undefined` below, and a hook that let `fatal: not a git repository` through would print it
|
|
249
|
-
// in front of a tool call that is about to be allowed.
|
|
250
|
-
// A `PreToolUse` hook holds the tool call while it runs, so the read is bounded rather than
|
|
251
|
-
// left to whatever git does.
|
|
252
|
-
// `cwd` is set only by `lane_cut_sync`, which reads another lane's record from the parent.
|
|
253
|
-
// With a `cwd`, the git location variables are cleared so it is what git answers for: a hook
|
|
254
|
-
// exports `GIT_DIR`, which beats `cwd` and would name the hook's checkout instead
|
|
255
|
-
// (joshuafolkken/kit#2515). Without one the environment is kept, so this read resolves the same
|
|
256
|
-
// checkout as the asynchronous `git_directories` that writes the record.
|
|
257
|
-
{
|
|
258
|
-
cwd,
|
|
259
|
-
env:
|
|
260
|
-
cwd === undefined
|
|
261
|
-
? process.env
|
|
262
|
-
: { ...process.env, ...git_location_environment.location_free_environment() },
|
|
263
|
-
encoding: 'utf8',
|
|
264
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
265
|
-
timeout: GIT_READ_TIMEOUT_MS,
|
|
266
|
-
},
|
|
267
|
-
) // NOSONAR
|
|
268
|
-
|
|
269
|
-
return output.split('\n').filter((line) => line !== '')
|
|
270
|
-
} catch {
|
|
271
|
-
return []
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
228
|
+
//
|
|
275
229
|
// The work tree's own git directory (index 0), the same read `git_directories` makes asynchronously —
|
|
276
230
|
// the record and the pre-gate guard both key on it.
|
|
277
231
|
function worktree_git_directory_sync(): string | undefined {
|
|
278
|
-
return
|
|
232
|
+
return git_common_directory.own()
|
|
279
233
|
}
|
|
280
234
|
|
|
281
235
|
// **The directory is injectable so a test never has to write to the live record.** Keyed to the work
|
|
@@ -297,7 +251,7 @@ function carried_cut_sync(
|
|
|
297
251
|
// lane's own git directory, so the parent — standing in the main checkout — resolves that directory
|
|
298
252
|
// from the lane's path rather than its own, and gets the record path back to mark it.
|
|
299
253
|
function lane_cut_sync(lane_directory: string): { target: string; cut: RunCut } | undefined {
|
|
300
|
-
const directory =
|
|
254
|
+
const directory = git_common_directory.own(lane_directory)
|
|
301
255
|
|
|
302
256
|
if (directory === undefined) return undefined
|
|
303
257
|
|
|
@@ -101,7 +101,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
101
101
|
process.exitCode = await run(argv)
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const run_ending_cli = { USAGE,
|
|
104
|
+
const run_ending_cli = { USAGE, parse_request, run }
|
|
105
105
|
|
|
106
106
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
107
107
|
|
|
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs'
|
|
|
2
2
|
import { agent_exit_record } from '#scripts/agent/agent-exit-record'
|
|
3
3
|
import { api_outage } from '#scripts/agent/api-outage'
|
|
4
4
|
import type { ClaudeResultEvent } from '#scripts/agent/claude-result-event'
|
|
5
|
-
import { git_gh_issue_read } from '#scripts/
|
|
5
|
+
import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
|
|
6
6
|
import { issue_state } from '#scripts/issue/issue-state'
|
|
7
7
|
import { run_cut } from './run-cut'
|
|
8
8
|
import { run_hold } from './run-hold'
|
|
@@ -222,9 +222,6 @@ async function check(request: EndingRequest): Promise<EndingDecision> {
|
|
|
222
222
|
const run_ending = {
|
|
223
223
|
check,
|
|
224
224
|
decide,
|
|
225
|
-
describe_exit,
|
|
226
|
-
read_child_closed,
|
|
227
|
-
read_cut_taken,
|
|
228
225
|
read_exit,
|
|
229
226
|
}
|
|
230
227
|
|
|
@@ -9,6 +9,9 @@ import { run_hold_cli } from './run-hold-cli'
|
|
|
9
9
|
import { run_next } from './run-next'
|
|
10
10
|
import { run_prep } from './run-prep'
|
|
11
11
|
import { run_prep_cli } from './run-prep-cli'
|
|
12
|
+
import { run_prrun_resume } from './run-prrun-resume'
|
|
13
|
+
import { run_stage, type StageCommand, type StageDecision } from './run-stage'
|
|
14
|
+
import { run_stage_read, type StageRead } from './run-stage-read'
|
|
12
15
|
import { run_step } from './run-step'
|
|
13
16
|
|
|
14
17
|
// `josh run:entry <N>` — one call for the fixed entry sequence a lane opens on (joshuafolkken/kit#2372).
|
|
@@ -27,7 +30,10 @@ const ARGV_OFFSET = 2
|
|
|
27
30
|
const SUCCESS_EXIT_CODE = 0
|
|
28
31
|
const FAILURE_EXIT_CODE = 1
|
|
29
32
|
const ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u
|
|
30
|
-
const USAGE = 'Usage: josh run:entry <issue-number>'
|
|
33
|
+
const USAGE = 'Usage: josh run:entry <issue-number> [--to kickoff|halfrun|prrun|fullrun]'
|
|
34
|
+
const TO_FLAG = '--to'
|
|
35
|
+
// The flag and its command.
|
|
36
|
+
const TO_ARGUMENT_COUNT = 2
|
|
31
37
|
const should_forward_stderr = true
|
|
32
38
|
const NEWLINE = '\n'
|
|
33
39
|
|
|
@@ -48,16 +54,42 @@ function parse_number(argv: ReadonlyArray<string>): string | undefined {
|
|
|
48
54
|
return first
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
interface EntryRequest {
|
|
58
|
+
issue_number: string
|
|
59
|
+
command: StageCommand
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// `--to <command>` names how far the run goes (joshuafolkken/kit#3042); absent, it is `fullrun`.
|
|
63
|
+
// Anything else is refused.
|
|
64
|
+
function parse_command(rest: ReadonlyArray<string>): StageCommand | undefined {
|
|
65
|
+
if (rest.length === 0) return run_stage.DEFAULT_COMMAND
|
|
66
|
+
|
|
67
|
+
const [flag, value] = rest
|
|
68
|
+
|
|
69
|
+
if (flag !== TO_FLAG || rest.length !== TO_ARGUMENT_COUNT) return undefined
|
|
70
|
+
|
|
71
|
+
return run_stage.to_command(value)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function parse_request(argv: ReadonlyArray<string>): EntryRequest | undefined {
|
|
75
|
+
const issue_number = parse_number(argv.slice(0, 1))
|
|
76
|
+
const command = parse_command(argv.slice(1))
|
|
77
|
+
|
|
78
|
+
return issue_number === undefined || command === undefined ? undefined : { issue_number, command }
|
|
79
|
+
}
|
|
80
|
+
|
|
51
81
|
function first_line(out: string): string {
|
|
52
82
|
return out.split(NEWLINE)[0] ?? ''
|
|
53
83
|
}
|
|
54
84
|
|
|
55
85
|
// `run:hold <N>` prints one token — `hold`, `busy` or `unknown` — and forwards its explanation to
|
|
56
86
|
// stderr, so the composite branches on the token and the reader still sees why. `--fullrun` marks the
|
|
57
|
-
// hold as
|
|
58
|
-
|
|
87
|
+
// hold as a run whose implementation cut resumes as `fullrun #N` (joshuafolkken/kit#2760) — a
|
|
88
|
+
// `fullrun`'s, and a `prrun`'s, which runs `fullrun`'s steps; a `halfrun`'s hold is never marked.
|
|
89
|
+
async function claim_hold(issue_number: string, command: StageCommand): Promise<string> {
|
|
90
|
+
const mark = command === run_stage.HALFRUN ? [] : ['--fullrun']
|
|
59
91
|
const held = await josh_command.josh_run(
|
|
60
|
-
['run:hold', issue_number,
|
|
92
|
+
['run:hold', issue_number, ...mark],
|
|
61
93
|
should_forward_stderr,
|
|
62
94
|
)
|
|
63
95
|
|
|
@@ -131,31 +163,51 @@ function resume_report(issue_number: string, resume: Resume): number {
|
|
|
131
163
|
// **A `halfrun` stopped before its commit is resumed, not claimed** (joshuafolkken/kit#2796): its hold
|
|
132
164
|
// is kept over the verified diff, so the claim below would answer `busy` against it. The budget is asked
|
|
133
165
|
// first, as for any run; then the hold is adopted and the run goes to the gate, skipping everything up
|
|
134
|
-
// to and including implementation.
|
|
135
|
-
|
|
166
|
+
// to and including implementation. **A `prrun` stopped before its merge is resumed the same way**
|
|
167
|
+
// (joshuafolkken/kit#3023), under the token that says what is left of it.
|
|
168
|
+
async function resume_stopped(
|
|
169
|
+
issue_number: string,
|
|
170
|
+
token: string,
|
|
171
|
+
stopped_run: { adopt: (issue: string) => Promise<boolean> },
|
|
172
|
+
): Promise<number> {
|
|
136
173
|
const cost = await check_cost()
|
|
137
174
|
|
|
138
|
-
if (cost === run_entry.COST_OVER)
|
|
139
|
-
return stop_report(issue_number, HALFRUN_RESUME_TOKEN, cost, COST_STOP_NOTE)
|
|
140
|
-
}
|
|
175
|
+
if (cost === run_entry.COST_OVER) return stop_report(issue_number, token, cost, COST_STOP_NOTE)
|
|
141
176
|
|
|
142
|
-
if (!(await
|
|
177
|
+
if (!(await stopped_run.adopt(issue_number))) {
|
|
143
178
|
return stop_report(issue_number, run_hold_cli.BUSY_VERDICT, cost, HOLD_STOP_NOTE)
|
|
144
179
|
}
|
|
145
180
|
|
|
146
|
-
console.info(`entry #${issue_number} — resume: ${
|
|
181
|
+
console.info(`entry #${issue_number} — resume: ${token}`)
|
|
147
182
|
|
|
148
183
|
return SUCCESS_EXIT_CODE
|
|
149
184
|
}
|
|
150
185
|
|
|
151
|
-
|
|
152
|
-
|
|
186
|
+
// The stopped run a decision picks up: a `halfrun` stop resumes at the gate, a `prrun` stop at
|
|
187
|
+
// `followup` under its own token. `undefined` for any other start, so the ordinary claim decides.
|
|
188
|
+
async function resume_any(
|
|
189
|
+
issue_number: string,
|
|
190
|
+
decision: StageDecision,
|
|
191
|
+
stage: StageRead,
|
|
192
|
+
): Promise<number | undefined> {
|
|
193
|
+
if (decision.state === run_stage.HALFRUN_STOPPED) {
|
|
194
|
+
return await resume_stopped(issue_number, HALFRUN_RESUME_TOKEN, run_halfrun_resume)
|
|
195
|
+
}
|
|
153
196
|
|
|
154
|
-
|
|
197
|
+
return stage.prrun_token === undefined
|
|
198
|
+
? undefined
|
|
199
|
+
: await resume_stopped(issue_number, stage.prrun_token, run_prrun_resume)
|
|
200
|
+
}
|
|
155
201
|
|
|
156
|
-
|
|
202
|
+
// **A command whose stopping point the issue has already reached redoes nothing** (joshuafolkken/kit#3042)
|
|
203
|
+
// — the stage line is the whole report. A merged issue is the exception: the ordinary entry already
|
|
204
|
+
// answers it (`already-done`, or `keep-work` over a lane's uncommitted work), so it is left to that.
|
|
205
|
+
function is_settled(decision: StageDecision): boolean {
|
|
206
|
+
return decision.is_reached && decision.state !== run_stage.MERGED
|
|
207
|
+
}
|
|
157
208
|
|
|
158
|
-
|
|
209
|
+
async function claim_run({ issue_number, command }: EntryRequest): Promise<number> {
|
|
210
|
+
const hold = await claim_hold(issue_number, command)
|
|
159
211
|
|
|
160
212
|
if (hold !== run_hold_cli.HOLD_VERDICT) {
|
|
161
213
|
return stop_report(issue_number, hold, run_entry.COST_SKIPPED, HOLD_STOP_NOTE)
|
|
@@ -170,16 +222,45 @@ async function open_run(issue_number: string): Promise<number> {
|
|
|
170
222
|
return emit({ issue_number, hold, cost, verdict: reads.verdict, report: reads.report })
|
|
171
223
|
}
|
|
172
224
|
|
|
225
|
+
// A carried cut is asked first, before anything is read (`run:cut --resume`); `kickoff` claims and cuts
|
|
226
|
+
// nothing, so it never asks. `undefined` when no cut is waiting.
|
|
227
|
+
async function resume_cut(request: EntryRequest): Promise<number | undefined> {
|
|
228
|
+
if (request.command === run_stage.KICKOFF) return undefined
|
|
229
|
+
|
|
230
|
+
const resume = await ask_resume(request.issue_number)
|
|
231
|
+
|
|
232
|
+
return resume.token === run_cut_report.FRESH_VERDICT
|
|
233
|
+
? undefined
|
|
234
|
+
: resume_report(request.issue_number, resume)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// `kickoff` stops at the stage line whatever it says — it plans, and claims nothing.
|
|
238
|
+
async function open_run(request: EntryRequest): Promise<number> {
|
|
239
|
+
const { issue_number, command } = request
|
|
240
|
+
const cut = await resume_cut(request)
|
|
241
|
+
|
|
242
|
+
if (cut !== undefined) return cut
|
|
243
|
+
|
|
244
|
+
const stage = await run_stage_read.read_stage(issue_number)
|
|
245
|
+
const decision = run_stage.decide(stage.state, command)
|
|
246
|
+
|
|
247
|
+
console.info(run_stage.format_decision(issue_number, decision))
|
|
248
|
+
|
|
249
|
+
if (command === run_stage.KICKOFF || is_settled(decision)) return SUCCESS_EXIT_CODE
|
|
250
|
+
|
|
251
|
+
return (await resume_any(issue_number, decision, stage)) ?? (await claim_run(request))
|
|
252
|
+
}
|
|
253
|
+
|
|
173
254
|
async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
174
|
-
const
|
|
255
|
+
const request = parse_request(argv)
|
|
175
256
|
|
|
176
|
-
if (
|
|
257
|
+
if (request === undefined) {
|
|
177
258
|
console.error(USAGE)
|
|
178
259
|
|
|
179
260
|
return FAILURE_EXIT_CODE
|
|
180
261
|
}
|
|
181
262
|
|
|
182
|
-
return await open_run(
|
|
263
|
+
return await open_run(request)
|
|
183
264
|
}
|
|
184
265
|
|
|
185
266
|
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
@@ -188,12 +269,8 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
188
269
|
|
|
189
270
|
const run_entry_cli = {
|
|
190
271
|
HALFRUN_RESUME_TOKEN,
|
|
191
|
-
SUCCESS_EXIT_CODE,
|
|
192
|
-
USAGE,
|
|
193
|
-
check_cost,
|
|
194
|
-
claim_hold,
|
|
195
|
-
main,
|
|
196
272
|
parse_number,
|
|
273
|
+
parse_request,
|
|
197
274
|
run,
|
|
198
275
|
}
|
|
199
276
|
|
package/scripts/run/run-entry.ts
CHANGED
|
@@ -52,6 +52,7 @@ async function follow(
|
|
|
52
52
|
let read = ports.read(position)
|
|
53
53
|
|
|
54
54
|
while (read.events.length === 0 && ports.now() < deadline) {
|
|
55
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
55
56
|
await ports.sleep(options.tick_ms)
|
|
56
57
|
read = ports.read(position)
|
|
57
58
|
}
|
|
@@ -69,7 +69,7 @@ function render(event: RunEvent, lang: string): string {
|
|
|
69
69
|
return [clock_of(event.at), label_of(event.kind, lang), event.text].join(FIELD_SEPARATOR)
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
const run_event_render = {
|
|
72
|
+
const run_event_render = { clock_of, label_of, render }
|
|
73
73
|
|
|
74
74
|
export type { KindLabel }
|
|
75
75
|
export { run_event_render }
|
|
@@ -91,6 +91,22 @@ const SHIP_POSITION_KINDS: ReadonlySet<string> = new Set([
|
|
|
91
91
|
run_event_stream.EVENT_KIND.SHIP_STOP,
|
|
92
92
|
])
|
|
93
93
|
|
|
94
|
+
const KIND = run_event_stream.EVENT_KIND
|
|
95
|
+
|
|
96
|
+
// The parent's record of the batch around a child — its dispatch, park and split, the retrospective
|
|
97
|
+
// whose summary may name an issue it filed, and the strand whose text carries the whole invocation
|
|
98
|
+
// (`backlogrun #<N1> #<N2> …`). Each can name the child, yet none is a position the child itself is at,
|
|
99
|
+
// so a lane child never reads one as its own.
|
|
100
|
+
const BATCH_RECORD_KINDS: ReadonlySet<string> = new Set([
|
|
101
|
+
KIND.CHILD_LAUNCH,
|
|
102
|
+
KIND.PARK,
|
|
103
|
+
KIND.SPLIT,
|
|
104
|
+
KIND.RETROSPECTIVE,
|
|
105
|
+
KIND.STRANDED,
|
|
106
|
+
])
|
|
107
|
+
|
|
108
|
+
const ISSUE_REFERENCE = /#(\d+)/u
|
|
109
|
+
|
|
94
110
|
function is_foreign_ship_event(event: RunEvent, issue: string): boolean {
|
|
95
111
|
return SHIP_POSITION_KINDS.has(event.kind) && !event.text.startsWith(`#${issue} `)
|
|
96
112
|
}
|
|
@@ -99,16 +115,49 @@ function is_own_ship_event(event: RunEvent, issue: string): boolean {
|
|
|
99
115
|
return SHIP_POSITION_KINDS.has(event.kind) && !is_foreign_ship_event(event, issue)
|
|
100
116
|
}
|
|
101
117
|
|
|
118
|
+
// **A lane child's position is read only from events that name its own issue** (joshuafolkken/kit#3039).
|
|
119
|
+
// The parent and every lane append to one stream under one carry scope, so anything else on it is another
|
|
120
|
+
// run's: another lane's merge told a planned child to stop, the parent's stall (which names no issue)
|
|
121
|
+
// pointed it at `backlog:next`, and another lane's cut at `run:cut --resume`. The child's own merge and
|
|
122
|
+
// outage stay, so the parent-only stop in `run-step.ts` still holds; the parent keeps reading everything.
|
|
123
|
+
function names_issue(event: RunEvent, issue: string): boolean {
|
|
124
|
+
return ISSUE_REFERENCE.exec(event.text)?.[1] === issue
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function is_lane_position(event: RunEvent, issue: string): boolean {
|
|
128
|
+
return !BATCH_RECORD_KINDS.has(event.kind) && names_issue(event, issue)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// A lane child's attempt begins at its own newest launch. A child re-dispatched after an outage — or
|
|
132
|
+
// relaunched after a cut, whose resume `run:cut --resume` answers at the entry — shares the scope with
|
|
133
|
+
// its previous attempt, and that attempt's outage would otherwise stop the new one at its entry `run:step`.
|
|
134
|
+
function since_own_launch(events: ReadonlyArray<RunEvent>, issue: string): ReadonlyArray<RunEvent> {
|
|
135
|
+
const launch = events.findLastIndex(
|
|
136
|
+
(event) => event.kind === KIND.CHILD_LAUNCH && names_issue(event, issue),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return events.slice(launch + 1)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function is_foreign_event(event: RunEvent, issue: string, is_lane_child: boolean): boolean {
|
|
143
|
+
if (is_lane_child) return !is_lane_position(event, issue)
|
|
144
|
+
|
|
145
|
+
return is_foreign_ship_event(event, issue)
|
|
146
|
+
}
|
|
147
|
+
|
|
102
148
|
// The newest position for one issue's run: the scoped last event with other issues' ship positions left
|
|
103
|
-
// out
|
|
104
|
-
//
|
|
105
|
-
//
|
|
149
|
+
// out — and, for a lane child, every event not naming its issue — and, where no scope applies, as in
|
|
150
|
+
// an interactive `fullrun` with no carry record, the issue's own newest ship position, which its issue
|
|
151
|
+
// number already scopes. A determined scope with nothing in it yet reads nothing: an earlier invocation's
|
|
152
|
+
// stop for the same issue is not this invocation's position.
|
|
106
153
|
function last_issue_event(
|
|
107
154
|
events: ReadonlyArray<RunEvent>,
|
|
108
155
|
scope: EventScope,
|
|
109
156
|
issue: string,
|
|
157
|
+
is_lane_child: boolean,
|
|
110
158
|
): RunEvent | undefined {
|
|
111
|
-
const
|
|
159
|
+
const attempt = is_lane_child ? since_own_launch(events, issue) : events
|
|
160
|
+
const own = attempt.filter((event) => !is_foreign_event(event, issue, is_lane_child))
|
|
112
161
|
|
|
113
162
|
if (scope.kind === SINCE_SCOPE) return last_scoped_event(own, scope)
|
|
114
163
|
|