@joshuafolkken/kit 1.1035.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/verify-ui/SKILL.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +21 -13
- package/.claude/skills/workflow-commands/background-commands.md +5 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -3
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -7
- package/.claude/skills/workflow-commands/backlogrun-park.md +6 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +31 -37
- package/.claude/skills/workflow-commands/backlogrun-steps.md +25 -25
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +6 -4
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +3 -3
- 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 +2 -2
- 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 +44 -89
- package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -36
- 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 +24 -4
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/auto-tag.yml +21 -0
- package/.github/workflows/ci.yml +26 -128
- package/.github/workflows/pr-classification.yml +5 -41
- package/.github/workflows/publish.yml +42 -48
- 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-Y27M6A7X.js → chunk-3C4YCCEF.js} +5 -13
- package/dist/hooks/{chunk-D67KVGGY.js → chunk-7ZPFAVR7.js} +17 -88
- package/dist/hooks/{chunk-HOYJU5RM.js → chunk-E54KGFEQ.js} +11 -4
- package/dist/hooks/{chunk-KG6PZD72.js → chunk-IL27YTPH.js} +2 -2
- package/dist/hooks/{chunk-GJT4BNVE.js → chunk-KHWHKJOM.js} +3 -3
- package/dist/hooks/{chunk-HU66PWWL.js → chunk-M2XDCUKD.js} +1076 -509
- package/dist/hooks/{chunk-GLBDBJOK.js → chunk-NKOG3XAV.js} +199 -304
- package/dist/hooks/{chunk-ZXNE6NY3.js → chunk-O4LL4HTI.js} +2 -7
- package/dist/hooks/{chunk-XPLP27WA.js → chunk-OIZUHPJI.js} +5 -27
- package/dist/hooks/{chunk-EIFCAJRB.js → chunk-UD24EAIL.js} +2546 -1636
- package/dist/hooks/codex-hook-adapter.js +10 -11
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +15 -34
- package/dist/hooks/inputs.json +279 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +23 -16
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +188 -509
- package/dist/josh.js +166 -225
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +412 -64
- package/eslint/rules/promise.js +5 -0
- package/package.json +13 -8
- package/prompts/collaboration-workflow/file-edits.md +6 -53
- 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 +4 -4
- package/prompts/collaboration-workflow/rule-delivery.md +5 -36
- package/prompts/collaboration-workflow/shell-body.md +7 -9
- package/prompts/collaboration-workflow/turn-batching.md +21 -37
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +36 -36
- 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 +12 -4
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +2 -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 +15 -25
- 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 +32 -22
- package/scripts/backlog/backlog-offer-cli.ts +0 -5
- package/scripts/backlog/backlog-plan-cli.ts +6 -8
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +34 -17
- package/scripts/backlog/backlog-rank.ts +106 -0
- 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 +47 -31
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +92 -11
- 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 +11 -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 +8 -9
- 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 +13 -4
- 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 +20 -30
- 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 +37 -0
- 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 +32 -30
- 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-command.ts +1 -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-execa-error.ts +6 -1
- package/scripts/git/git-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +24 -6
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push-transport.ts +12 -69
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-spawn.ts +79 -3
- package/scripts/git/git-ssh-keepalive.ts +74 -0
- 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 +4 -2
- 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-cli.ts +15 -0
- package/scripts/hooks/format-edited-file.ts +4 -9
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard-cli.ts +21 -0
- package/scripts/hooks/pretool-guard.ts +36 -19
- 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 +8 -2
- package/scripts/init/start-plan.ts +18 -5
- package/scripts/init/start-setup-pr.ts +52 -25
- package/scripts/init/start-steps.ts +42 -9
- package/scripts/init/start.ts +40 -10
- 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 +37 -8
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +19 -3
- 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 +20 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/issue/issue-rank.ts +89 -0
- 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 -102
- 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 +10 -3
- 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 +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-child-marker.ts +16 -2
- package/scripts/lane/lane-cli.ts +33 -18
- 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/lane-report.ts +10 -4
- 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-plan.ts +185 -0
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -3
- package/scripts/propagate/propagate-steps.ts +19 -6
- package/scripts/propagate/propagate-targets.ts +13 -6
- package/scripts/propagate/propagate.ts +60 -46
- 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 +1 -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 +48 -16
- package/scripts/review/review-brief-cli.ts +72 -8
- package/scripts/review/review-brief.ts +67 -9
- 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 +6 -2
- 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 +1 -2
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/issue-fold.ts +1 -2
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-carry-conflict.ts +1 -2
- package/scripts/rules/lane-park.ts +14 -8
- 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/pre-gate-cut.ts +2 -2
- 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 +24 -8
- 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 +143 -0
- 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 +3 -3
- package/scripts/run/run-progress.ts +22 -10
- 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 +27 -77
- 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 +87 -0
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +23 -30
- package/scripts/run/run-ship-review.ts +20 -0
- package/scripts/run/run-ship-scoped.ts +45 -0
- package/scripts/run/run-ship-stage.ts +5 -1
- package/scripts/run/run-ship-steps.ts +105 -0
- package/scripts/run/run-ship.ts +2 -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 +4 -5
- package/scripts/run/run-wake-describe.ts +19 -1
- 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 +2 -3
- 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 +97 -0
- 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 +5 -4
- package/scripts/version/version-remote.ts +28 -14
- 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
|
@@ -3,8 +3,8 @@ import { homedir, tmpdir } from 'node:os'
|
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
5
5
|
import { agent_event, type AgentEventState } from '#scripts/agent/agent-event'
|
|
6
|
-
import { git_gh_issue_read } from '#scripts/
|
|
7
|
-
import { ALREADY_DONE_LABEL, NEEDS_DECISION_LABEL } from '#scripts/
|
|
6
|
+
import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
|
|
7
|
+
import { ALREADY_DONE_LABEL, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
8
8
|
import { issue_state } from '#scripts/issue/issue-state'
|
|
9
9
|
import { PLATFORM_TEMP_ROOT } from '#scripts/josh/platform-temporary'
|
|
10
10
|
import { run_hold } from './run-hold'
|
|
@@ -401,7 +401,6 @@ const run_liveness = {
|
|
|
401
401
|
decide,
|
|
402
402
|
describe_agent_state,
|
|
403
403
|
read_child_settled,
|
|
404
|
-
read_agent_state,
|
|
405
404
|
read_output_frozen,
|
|
406
405
|
sample_output,
|
|
407
406
|
to_safe_path,
|
|
@@ -5,6 +5,7 @@ import { api_outage } from '#scripts/agent/api-outage'
|
|
|
5
5
|
import { CONTEXT_CUT_THRESHOLD } from '#scripts/cost-runtime/context-cut-threshold'
|
|
6
6
|
import { issue_closing_pr } from '#scripts/issue/issue-closing-pr'
|
|
7
7
|
import { issue_state_cli } from '#scripts/issue/issue-state-cli'
|
|
8
|
+
import { lane_handoff } from '#scripts/lane/lane-handoff'
|
|
8
9
|
import { run_carry, type CarryOwner, type RunCarry } from './run-carry'
|
|
9
10
|
import { run_ending } from './run-ending'
|
|
10
11
|
import { run_event_stream } from './run-event-stream'
|
|
@@ -12,8 +13,6 @@ import { run_event_stream_emit } from './run-event-stream-emit'
|
|
|
12
13
|
import { run_issue_number } from './run-issue-number'
|
|
13
14
|
import { run_merge, type ChildOutcome, type EndingSignals } from './run-merge'
|
|
14
15
|
import { run_merge_steps, type MergeContext } from './run-merge-steps'
|
|
15
|
-
import { run_ship_detach } from './run-ship-detach'
|
|
16
|
-
import { run_ship_probe } from './run-ship-probe'
|
|
17
16
|
|
|
18
17
|
// `josh run:merge <N>` — one composite command for a `backlogrun` merge event (joshuafolkken/kit#2024).
|
|
19
18
|
// The parent's context is the largest and its per-turn cost the highest, and the event was two turns:
|
|
@@ -316,7 +315,10 @@ async function on_cut(ctx: MergeContext): Promise<MergeVerdict> {
|
|
|
316
315
|
|
|
317
316
|
// A child that parked itself: nothing is counted, but the park is written to the stream as a failed
|
|
318
317
|
// child's is, so a reader restoring the run from its events sees the child settled (joshuafolkken/kit#2508).
|
|
318
|
+
// Its `in-progress` is dropped as a failed child's is: left on, it outlived the `needs-decision` a
|
|
319
|
+
// person later lifted, and a `run:solo` child then held the whole backlog (joshuafolkken/kit#3017).
|
|
319
320
|
async function on_parked(ctx: MergeContext): Promise<MergeVerdict> {
|
|
321
|
+
await run_merge_steps.remove_in_progress(ctx.child)
|
|
320
322
|
await run_event_stream_emit.emit(run_event_stream.EVENT_KIND.PARK, `#${ctx.child} parked`)
|
|
321
323
|
|
|
322
324
|
return emit(await run_merge_steps.ask_next(ctx), SUCCESS_EXIT_CODE)
|
|
@@ -355,18 +357,10 @@ const HANDLERS: Readonly<Record<ChildOutcome, (ctx: MergeContext) => Promise<Mer
|
|
|
355
357
|
shipping: on_shipping,
|
|
356
358
|
}
|
|
357
359
|
|
|
358
|
-
async function is_ship_running(child: string): Promise<boolean> {
|
|
359
|
-
const repository = await run_ship_probe.repository_directory()
|
|
360
|
-
|
|
361
|
-
return (
|
|
362
|
-
repository !== undefined && run_ship_detach.read_result(repository, child)?.result === 'running'
|
|
363
|
-
)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
360
|
// The whole merge event for one returned child, in-process: read its state, classify it, and run the
|
|
367
361
|
// handler. The CLI prints the token; `backlog:drive` branches on the outcome (joshuafolkken/kit#2508).
|
|
368
362
|
async function merge_child(ctx: MergeContext): Promise<MergeResult> {
|
|
369
|
-
if (
|
|
363
|
+
if (lane_handoff.is_ship_running(ctx.child, process.cwd())) {
|
|
370
364
|
return { outcome: 'shipping', ...(await on_shipping()) }
|
|
371
365
|
}
|
|
372
366
|
|
|
@@ -405,8 +399,6 @@ const run_merge_cli = {
|
|
|
405
399
|
RESUMED_TOKEN,
|
|
406
400
|
RETRY_TOKEN,
|
|
407
401
|
STOP_TOKEN,
|
|
408
|
-
USAGE,
|
|
409
|
-
main,
|
|
410
402
|
merge_child,
|
|
411
403
|
parse,
|
|
412
404
|
run,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
-
import { git_followup_issue_close } from '#scripts/
|
|
4
|
-
import { git_gh_issue_write } from '#scripts/
|
|
5
|
-
import { git_stash } from '#scripts/git/git-stash'
|
|
6
|
-
import { IN_PROGRESS_LABEL, NEEDS_DECISION_LABEL } from '#scripts/
|
|
3
|
+
import { git_followup_issue_close } from '#scripts/followup/git-followup-issue-close'
|
|
4
|
+
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
5
|
+
import { git_stash } from '#scripts/git/stash/git-stash'
|
|
6
|
+
import { IN_PROGRESS_LABEL, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
7
7
|
import { josh_command, type JoshResult } from '#scripts/josh/josh-run'
|
|
8
8
|
import { lane_close } from '#scripts/lane/lane-close'
|
|
9
9
|
import { lane_reap } from '#scripts/lane/lane-reap'
|
|
@@ -347,7 +347,6 @@ async function ask_next(ctx: MergeContext): Promise<string> {
|
|
|
347
347
|
|
|
348
348
|
const run_merge_steps = {
|
|
349
349
|
CUT_RELAUNCH_CAUSE,
|
|
350
|
-
apply_carry,
|
|
351
350
|
ask_next,
|
|
352
351
|
do_failed,
|
|
353
352
|
do_merged,
|
|
@@ -355,6 +354,7 @@ const run_merge_steps = {
|
|
|
355
354
|
has_resumable_cut,
|
|
356
355
|
is_over_budget,
|
|
357
356
|
refused_carry,
|
|
357
|
+
remove_in_progress,
|
|
358
358
|
resume_cut,
|
|
359
359
|
}
|
|
360
360
|
|
package/scripts/run/run-merge.ts
CHANGED
|
@@ -41,7 +41,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
41
41
|
process.exitCode = await run(argv)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const run_next_cli = {
|
|
44
|
+
const run_next_cli = { run }
|
|
45
45
|
|
|
46
46
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
47
47
|
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { CONTEXT_CUT_THRESHOLD } from '#scripts/cost-runtime/context-cut-threshold'
|
|
2
|
+
import { cost_cli, type CostVerdict } from '#scripts/cost-runtime/cost-cli'
|
|
3
|
+
import { cost_format } from '#scripts/cost-runtime/cost-format'
|
|
4
|
+
import { cost_verdict } from '#scripts/cost-runtime/cost-verdict'
|
|
5
|
+
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
6
|
+
import { implementation_cut_verdict } from '#scripts/rules/implementation-cut-verdict'
|
|
7
|
+
import { run_carry, type RunCarry } from './run-carry'
|
|
8
|
+
import { run_headless } from './run-headless'
|
|
9
|
+
import { run_watcher_hook } from './run-watcher-hook'
|
|
10
|
+
|
|
11
|
+
// The `backlogrun` parent's hand-off, delivered at the call it binds on (joshuafolkken/kit#2947).
|
|
12
|
+
//
|
|
13
|
+
// **The parent's hand-off was asked only at a merge, and the context grew between merges.** The
|
|
14
|
+
// orchestrator never implements, yet on 2026-10-02 parent 259fb6d5 sent 111 of its 170 requests past
|
|
15
|
+
// the shared threshold, peaking at 207,081 tokens: `pnpm josh cost --cut` is read after each child's
|
|
16
|
+
// merge (`backlogrun-progress.md` → "The hand-off"), and a long wait or a lane-failure investigation
|
|
17
|
+
// between two merges is exactly where it went unread. This is the lesson `implementation-cut.ts` records
|
|
18
|
+
// for a lane child, one session up — a check carried as a step is taken late, a `PreToolUse` refusal is
|
|
19
|
+
// taken at the next call.
|
|
20
|
+
//
|
|
21
|
+
// **The same statistic and the same threshold, never a second measurement.** The verdict is
|
|
22
|
+
// `cost_cli.session_verdict` — what `pnpm josh cost --cut` prints — read through the implementation cut's
|
|
23
|
+
// short reuse window so a burst of calls is priced once.
|
|
24
|
+
//
|
|
25
|
+
// **It is async and composed after the synchronous guards, like the watcher guard.** Telling the parent
|
|
26
|
+
// apart reads the carry record through `run_headless.driving_carry`, which is asynchronous; reusing it is
|
|
27
|
+
// what keeps a second, synchronous spelling of the parent test from existing.
|
|
28
|
+
|
|
29
|
+
const SWITCH_ENV_KEY = 'JOSH_PARENT_CUT_GUARD'
|
|
30
|
+
const STAMP_PREFIX = 'josh-parent-cut-guard-'
|
|
31
|
+
|
|
32
|
+
// **One refusal, then a quiet window long enough to finish the hand-off in.** The hand-off is several
|
|
33
|
+
// calls — `lane:list`, `lane:output`, `run:carry --cut`, `run:wake`, the progress comment — and a guard
|
|
34
|
+
// refusing each of them would wedge the very procedure it asks for. A parent that could not cut (a lane
|
|
35
|
+
// nobody can poll) is asked again once the window has passed, which is the "next opportunity" the merge
|
|
36
|
+
// seam used to be.
|
|
37
|
+
const QUIET_WINDOW_MS = 600_000
|
|
38
|
+
|
|
39
|
+
// What the decision has to know about the world, passed in so it is testable without a carry record or
|
|
40
|
+
// a session transcript on disk.
|
|
41
|
+
interface ParentCutState {
|
|
42
|
+
carry: () => Promise<RunCarry | undefined>
|
|
43
|
+
verdict: () => CostVerdict
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function current_state(): ParentCutState {
|
|
47
|
+
return {
|
|
48
|
+
carry: async (): Promise<RunCarry | undefined> => await run_headless.driving_carry(),
|
|
49
|
+
verdict: (): CostVerdict =>
|
|
50
|
+
implementation_cut_verdict.reused_verdict(() => cost_cli.session_verdict()),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const THRESHOLD_TEXT = `${cost_format.format_tokens(CONTEXT_CUT_THRESHOLD)}-token`
|
|
55
|
+
|
|
56
|
+
const PARENT_CUT_REASON =
|
|
57
|
+
'⛔ backlogrun parent hand-off: this session drives a `backlogrun` (it owns the live carry record) and ' +
|
|
58
|
+
`its recent-context cost has crossed the shared ${THRESHOLD_TEXT} threshold between merges, so every ` +
|
|
59
|
+
'later request re-reads the accumulated context (joshuafolkken/kit#2947). Take the hand-off now rather ' +
|
|
60
|
+
'than at the next merge: follow `.claude/skills/workflow-commands/backlogrun-progress.md` → "The ' +
|
|
61
|
+
'hand-off" from its `over` branch — open no new lane and take no new child, read `pnpm josh lane:list`, ' +
|
|
62
|
+
'make sure every lane in flight records an output path, then run `pnpm josh run:carry --cut --owner ' +
|
|
63
|
+
'"$PPID"` and, unless it answers `capped`, `pnpm josh run:wake`, post the progress comment and end the ' +
|
|
64
|
+
'turn. A lane nobody can poll means the cut does not happen; carry on and this asks again later. ' +
|
|
65
|
+
'Reissue this call when the hand-off is done or cannot be taken — the guard stays quiet for a while ' +
|
|
66
|
+
'after it refuses, so the hand-off calls themselves are not refused.'
|
|
67
|
+
|
|
68
|
+
// Neither an uncapped parent's own record nor a measured `over` is optional: a capped record has no cut
|
|
69
|
+
// left to take (`run:carry --cut` answers `capped`), and an unmeasurable session is left alone here —
|
|
70
|
+
// refusing every call of a session that cannot be priced would wedge it, while the merge-seam check
|
|
71
|
+
// still takes `over`'s branch for it.
|
|
72
|
+
async function is_due(state: ParentCutState): Promise<boolean> {
|
|
73
|
+
const carry = await state.carry()
|
|
74
|
+
|
|
75
|
+
if (carry === undefined || run_carry.is_at_cut_cap(carry)) return false
|
|
76
|
+
|
|
77
|
+
return state.verdict() === cost_verdict.OVER_VERDICT
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function is_quiet(target: string, now_ms: number): boolean {
|
|
81
|
+
const last_ms = hook_decision.create_refusal_stamp(STAMP_PREFIX).last_ms(target)
|
|
82
|
+
|
|
83
|
+
return last_ms !== hook_decision.NEVER_MS && now_ms - last_ms < QUIET_WINDOW_MS
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// The quiet window is read before the carry record and the transcript price, so a refused parent's
|
|
87
|
+
// following calls cost one small file read each.
|
|
88
|
+
async function refusal_for(
|
|
89
|
+
transcript: string,
|
|
90
|
+
now_ms: number,
|
|
91
|
+
state: ParentCutState,
|
|
92
|
+
): Promise<string | undefined> {
|
|
93
|
+
const stamp = hook_decision.create_refusal_stamp(STAMP_PREFIX)
|
|
94
|
+
const target = stamp.path(transcript)
|
|
95
|
+
|
|
96
|
+
if (is_quiet(target, now_ms) || !(await is_due(state))) return undefined
|
|
97
|
+
|
|
98
|
+
return stamp.record(target, now_ms) ? PARENT_CUT_REASON : undefined
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// A delegated unit's call names the *parent's* transcript and runs under the parent's process, so the
|
|
102
|
+
// carry record reads as owned here; only `agent_id` tells it apart (`hook-decision.ts`). Refusing it
|
|
103
|
+
// would hand the unit a hand-off it cannot take and spend the parent's quiet window on it.
|
|
104
|
+
function is_unit_call(raw_payload: string): boolean {
|
|
105
|
+
try {
|
|
106
|
+
return (hook_decision.parse_hook_payload(raw_payload)?.agent_id ?? '') !== ''
|
|
107
|
+
} catch {
|
|
108
|
+
return false
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function is_exempt(raw_payload: string): boolean {
|
|
113
|
+
return !hook_decision.is_switch_enabled(SWITCH_ENV_KEY) || is_unit_call(raw_payload)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The deny reason for a call a `backlogrun` parent makes past the shared threshold, or `undefined` when
|
|
118
|
+
* the call proceeds — a lane child, a delegated unit, a person's session, a handed-off or capped
|
|
119
|
+
* record, an `under` or unmeasurable verdict, or a call inside the quiet window after a refusal.
|
|
120
|
+
*/
|
|
121
|
+
async function parent_cut_reason(
|
|
122
|
+
raw_payload: string,
|
|
123
|
+
now_ms: number = Date.now(),
|
|
124
|
+
state: ParentCutState = current_state(),
|
|
125
|
+
): Promise<string | undefined> {
|
|
126
|
+
if (is_exempt(raw_payload)) return undefined
|
|
127
|
+
|
|
128
|
+
const transcript = run_watcher_hook.transcript_of(raw_payload)
|
|
129
|
+
|
|
130
|
+
if (transcript === undefined) return undefined
|
|
131
|
+
|
|
132
|
+
return await refusal_for(transcript, now_ms, state)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const run_parent_cut_hook = {
|
|
136
|
+
PARENT_CUT_REASON,
|
|
137
|
+
QUIET_WINDOW_MS,
|
|
138
|
+
SWITCH_ENV_KEY,
|
|
139
|
+
parent_cut_reason,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export type { ParentCutState }
|
|
143
|
+
export { run_parent_cut_hook }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { git_gh_pr_read } from '#scripts/gh/git-gh-pr-read'
|
|
1
2
|
import { git_command } from '#scripts/git/git-command'
|
|
2
|
-
import { git_gh_pr_read } from '#scripts/git/git-gh-pr-read'
|
|
3
3
|
import { lane_registry, type LaneInfo } from '#scripts/lane/lane-registry'
|
|
4
4
|
import { z } from 'zod'
|
|
5
5
|
import { run_hold } from './run-hold'
|
|
@@ -89,7 +89,7 @@ const STASH_LABEL_PREFIX = 'run:hold reclaimed before #'
|
|
|
89
89
|
// so the shape it may take is pinned beside the interpolation rather than only in the CLI that
|
|
90
90
|
// happens to be today's single caller. `run:liveness` interpolates it the same way, so the pattern
|
|
91
91
|
// and the refusal live in one module both read (joshuafolkken/kit#1485).
|
|
92
|
-
const {
|
|
92
|
+
const { require_issue_number } = run_issue_number
|
|
93
93
|
const UNREADABLE_PR_MESSAGE = 'The pull request could not be read for branch '
|
|
94
94
|
|
|
95
95
|
function needs_reclaim(tree: TreeState): boolean {
|
|
@@ -385,15 +385,8 @@ async function check(issue: string): Promise<PreflightDecision> {
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
const run_preflight = {
|
|
388
|
-
CLEAN_ADVICE,
|
|
389
|
-
CLEAN_REASON,
|
|
390
388
|
CLEAN_VERDICT,
|
|
391
|
-
ISSUE_NUMBER_PATTERN,
|
|
392
|
-
PARK_ADVICE,
|
|
393
|
-
PARK_VERDICT,
|
|
394
|
-
RECLAIM_VERDICT,
|
|
395
389
|
RESUME_ADVICE,
|
|
396
|
-
RESUME_VERDICT,
|
|
397
390
|
MERGED_PR,
|
|
398
391
|
STASH_LABEL_PREFIX,
|
|
399
392
|
check,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { git_stash } from '#scripts/git/git-stash'
|
|
3
|
+
import { git_stash } from '#scripts/git/stash/git-stash'
|
|
4
4
|
import { issue_read_cli, type BlockRead } from '#scripts/issue/issue-read-cli'
|
|
5
5
|
import { issue_state_cli, type StateRead } from '#scripts/issue/issue-state-cli'
|
|
6
6
|
import { lane_child_marker } from '#scripts/lane/lane-child-marker'
|
|
@@ -150,7 +150,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
150
150
|
// `gather` and `to_parts` are exported so `run:next` reads the same state from the same three reads
|
|
151
151
|
// rather than growing a second copy of the gather (joshuafolkken/kit#2188) — `run:next` is the
|
|
152
152
|
// consumer of `run:prep` the epic #2166 wanted.
|
|
153
|
-
const run_prep_cli = {
|
|
153
|
+
const run_prep_cli = { gather, parse_number, run, to_parts }
|
|
154
154
|
|
|
155
155
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
156
156
|
|
|
@@ -159,7 +159,7 @@ async function locate(text: string): Promise<string> {
|
|
|
159
159
|
return format_locations(located)
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
const run_prep_locate = { extract_targets,
|
|
162
|
+
const run_prep_locate = { extract_targets, locate, parse_hits }
|
|
163
163
|
|
|
164
164
|
export type { Hit, Located }
|
|
165
165
|
export { run_prep_locate }
|
|
@@ -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
|
|
|
@@ -347,10 +347,13 @@ async function run_ticks(
|
|
|
347
347
|
let loop = seed_loop(target, started_ms)
|
|
348
348
|
|
|
349
349
|
while (Date.now() - started_ms < options.max_ms && !run_progress_clock.is_life_ended(life)) {
|
|
350
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
350
351
|
await sleep(options.tick_ms)
|
|
351
352
|
run_progress_clock.ping_life(life)
|
|
353
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
352
354
|
loop = await step(options, target, loop)
|
|
353
355
|
|
|
356
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
354
357
|
const exit = await wait_exit(loop, wait)
|
|
355
358
|
|
|
356
359
|
if (exit !== undefined) return exit
|
|
@@ -491,27 +494,21 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
491
494
|
}
|
|
492
495
|
|
|
493
496
|
const run_progress_cli = {
|
|
494
|
-
DECLINE_RETRY_SECONDS,
|
|
495
497
|
DEFAULT_MAX_HOURS,
|
|
496
498
|
DISABLED_NOTICE,
|
|
497
499
|
FAILED_TICK_PREFIX,
|
|
498
500
|
FRESH_LOOP,
|
|
499
501
|
IDLE_NOTICE,
|
|
500
502
|
LANE_CHILD_NOTICE,
|
|
501
|
-
MARKED_NOTICE,
|
|
502
503
|
REPO_UNRESOLVED_NOTICE,
|
|
503
|
-
TICK_SECONDS,
|
|
504
504
|
UNREADABLE_NOTICE,
|
|
505
505
|
USAGE,
|
|
506
506
|
WAIT_EXPIRED_NOTICE,
|
|
507
|
-
main,
|
|
508
507
|
read_arguments: run_progress_args.read_arguments,
|
|
509
|
-
report_decline,
|
|
510
508
|
run,
|
|
511
509
|
step,
|
|
512
510
|
to_interval_ms: run_progress_args.to_interval_ms,
|
|
513
511
|
to_max_ms: run_progress_args.to_max_ms,
|
|
514
|
-
to_options,
|
|
515
512
|
wait_once,
|
|
516
513
|
}
|
|
517
514
|
|
|
@@ -1,6 +1,5 @@
|
|
|
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 { execaSync } from 'execa'
|
|
4
3
|
import { z } from 'zod'
|
|
5
4
|
|
|
6
5
|
// The report clock `josh run:progress` keeps, in the one form both of its readers can use
|
|
@@ -16,9 +15,10 @@ import { z } from 'zod'
|
|
|
16
15
|
//
|
|
17
16
|
// **The key is the work tree's own git directory**, the way `run_hold` keys its record: two lanes of
|
|
18
17
|
// 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
|
-
//
|
|
18
|
+
// synchronous twin is `git_common_directory.own()`, which asks the same two lines
|
|
19
|
+
// `git_command.git_directories` reads and takes the first — so the two spellings cannot name different
|
|
20
|
+
// files. A git read that fails or times out answers `undefined`, which reads as "no clock here" and
|
|
21
|
+
// lets the call through.
|
|
22
22
|
|
|
23
23
|
const PROGRESS_PREFIX = 'josh-run-progress-'
|
|
24
24
|
// The watcher's own liveness record, kept apart from the report clock above: that one says *when* the
|
|
@@ -55,14 +55,6 @@ const MS_PER_MINUTE = 60_000
|
|
|
55
55
|
const LOG_STALE_MINUTES = 90
|
|
56
56
|
const LOG_STALE_MS = LOG_STALE_MINUTES * MS_PER_MINUTE
|
|
57
57
|
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
58
|
|
|
67
59
|
// `line` is the last heartbeat the watcher printed, kept verbatim beside the clock so a reader that
|
|
68
60
|
// cannot see the watcher's transcript — a person checking a woken headless `backlogrun` through
|
|
@@ -259,25 +251,8 @@ function end_life(target: string): void {
|
|
|
259
251
|
stamp_file.remove_stamp(target)
|
|
260
252
|
}
|
|
261
253
|
|
|
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
254
|
function stamp_target_sync(): string | undefined {
|
|
280
|
-
const directory =
|
|
255
|
+
const directory = git_common_directory.own()
|
|
281
256
|
|
|
282
257
|
return directory === undefined ? undefined : stamp_target_of(directory)
|
|
283
258
|
}
|
|
@@ -299,8 +274,6 @@ const run_progress_clock = {
|
|
|
299
274
|
LIFE_PREFIX,
|
|
300
275
|
LOG_KEEP,
|
|
301
276
|
LOG_STALE_MS,
|
|
302
|
-
PROGRESS_PREFIX,
|
|
303
|
-
append_line,
|
|
304
277
|
begin_life,
|
|
305
278
|
end_life,
|
|
306
279
|
is_life_ended,
|
|
@@ -314,7 +287,6 @@ const run_progress_clock = {
|
|
|
314
287
|
read_last_report,
|
|
315
288
|
read_last_report_sync,
|
|
316
289
|
stamp_target_of,
|
|
317
|
-
stamp_target_sync,
|
|
318
290
|
}
|
|
319
291
|
|
|
320
292
|
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
|
|
|
@@ -78,7 +78,7 @@ async function to_child(issue: OpenIssueData): Promise<ChildObservation> {
|
|
|
78
78
|
const number = String(issue.number)
|
|
79
79
|
const child = await run_preflight.read_child_state(number)
|
|
80
80
|
|
|
81
|
-
return { issue: number, labels: to_labels(issue), pr_state: child.pr_state }
|
|
81
|
+
return { issue: number, title: issue.title, labels: to_labels(issue), pr_state: child.pr_state }
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
async function read_children(repo: string): Promise<ReadonlyArray<ChildObservation> | undefined> {
|
|
@@ -171,6 +171,7 @@ async function read_observations(request: ObservationRequest): Promise<Observati
|
|
|
171
171
|
if (children.length === 0 && !(await has_run_started(lanes))) return IDLE_READ
|
|
172
172
|
|
|
173
173
|
const observations: Observations = {
|
|
174
|
+
repo: request.repo,
|
|
174
175
|
children,
|
|
175
176
|
lanes,
|
|
176
177
|
load_average: loadavg()[FIRST_LOAD_AVERAGE] ?? 0,
|
|
@@ -181,7 +182,6 @@ async function read_observations(request: ObservationRequest): Promise<Observati
|
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
const run_progress_read = {
|
|
184
|
-
PROGRESS_PREFIX,
|
|
185
185
|
has_run_started,
|
|
186
186
|
live_target,
|
|
187
187
|
log_target,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { issue_cite, type IssueCiter } from '#scripts/issue/issue-cite'
|
|
2
|
+
|
|
1
3
|
// `josh run:progress` — the one line an unattended run prints when it has gone quiet, and the clock
|
|
2
4
|
// that decides when that is (joshuafolkken/kit#1520).
|
|
3
5
|
//
|
|
@@ -56,6 +58,9 @@ const DEFAULT_INTERVAL_MS = DEFAULT_INTERVAL_MINUTES * MS_PER_MINUTE
|
|
|
56
58
|
// a second spelling of it — `none` / `open` / `merged` / `closed`.
|
|
57
59
|
interface ChildObservation {
|
|
58
60
|
issue: string
|
|
61
|
+
// Kept from the `in-progress` listing the child was read from, so the line cites it in full
|
|
62
|
+
// (joshuafolkken/kit#2943) without a read per child.
|
|
63
|
+
title: string
|
|
59
64
|
labels: ReadonlyArray<string>
|
|
60
65
|
pr_state: string
|
|
61
66
|
}
|
|
@@ -66,6 +71,8 @@ interface LaneObservation {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
interface Observations {
|
|
74
|
+
// `owner/repo`, the repository the listing was read from — what every printed issue links into.
|
|
75
|
+
repo: string
|
|
69
76
|
children: ReadonlyArray<ChildObservation>
|
|
70
77
|
lanes: ReadonlyArray<LaneObservation>
|
|
71
78
|
load_average: number
|
|
@@ -195,26 +202,32 @@ function next_state(
|
|
|
195
202
|
return { key, unchanged_since_ms: now_ms }
|
|
196
203
|
}
|
|
197
204
|
|
|
198
|
-
|
|
205
|
+
// The issue leads as a citation rather than a bare `#N` (joshuafolkken/kit#2943): the parent relays these
|
|
206
|
+
// lines verbatim, and a bare number copied into a reply is what the Stop guard sends back.
|
|
207
|
+
function format_child(child: ChildObservation, cite: IssueCiter): string {
|
|
199
208
|
const labels = child.labels.length > 0 ? child.labels.join(',') : '(no labels)'
|
|
200
209
|
|
|
201
|
-
return
|
|
210
|
+
return `${cite(child.issue)} ${labels} PR:${child.pr_state}`
|
|
202
211
|
}
|
|
203
212
|
|
|
204
213
|
// An empty set is the pre-label stage, said as such rather than left as a blank slot between the
|
|
205
214
|
// separators (joshuafolkken/kit#1900). After that change a `read_observations` result carries no
|
|
206
215
|
// children exactly when a run has started and none has reached `in-progress` yet, so this is the one
|
|
207
216
|
// place the two cases are told apart on the line.
|
|
208
|
-
function format_children(children: ReadonlyArray<ChildObservation
|
|
217
|
+
function format_children(children: ReadonlyArray<ChildObservation>, repo: string): string {
|
|
209
218
|
if (children.length === 0) return NO_CHILD_YET
|
|
219
|
+
const cite = issue_cite.citer(repo, new Map(children.map((child) => [child.issue, child.title])))
|
|
210
220
|
|
|
211
|
-
return children.map((child) => format_child(child)).join(' · ')
|
|
221
|
+
return children.map((child) => format_child(child, cite)).join(' · ')
|
|
212
222
|
}
|
|
213
223
|
|
|
214
|
-
|
|
224
|
+
// A lane is linked without its title: a lane in flight is a child the line above already cited in full,
|
|
225
|
+
// so repeating the title here would only lengthen the line.
|
|
226
|
+
function format_lanes(lanes: ReadonlyArray<LaneObservation>, repo: string): string {
|
|
215
227
|
if (lanes.length === 0) return NO_LANES
|
|
228
|
+
const cite = issue_cite.citer(repo, new Map())
|
|
216
229
|
|
|
217
|
-
return lanes.map((lane) => `${lane.issue}:${lane.state}`).join(' ')
|
|
230
|
+
return lanes.map((lane) => `${cite(lane.issue)}:${lane.state}`).join(' ')
|
|
218
231
|
}
|
|
219
232
|
|
|
220
233
|
// Absent is said, never filled in. A run started without a transcript path prints `unread` here, which
|
|
@@ -244,7 +257,7 @@ interface LineTiming {
|
|
|
244
257
|
* this is that same move for one value.
|
|
245
258
|
*
|
|
246
259
|
* **It is a schedule rather than an observation, and the two conditions on it are said in prose**
|
|
247
|
-
* (`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
|
|
248
261
|
* real report arriving first restarts the clock through `--mark` and supersedes it. The line printing
|
|
249
262
|
* it is itself a report, so the clock starts at this observation.
|
|
250
263
|
*/
|
|
@@ -303,8 +316,8 @@ function format_line(observations: Observations, timing: LineTiming): string {
|
|
|
303
316
|
observed_at: format_observed_at(timing.now_ms),
|
|
304
317
|
quiet: format_minutes(timing.now_ms - timing.quiet_since_ms),
|
|
305
318
|
unchanged: format_minutes(timing.now_ms - timing.unchanged_since_ms),
|
|
306
|
-
children: format_children(observations.children),
|
|
307
|
-
lanes: format_lanes(observations.lanes),
|
|
319
|
+
children: format_children(observations.children, observations.repo),
|
|
320
|
+
lanes: format_lanes(observations.lanes, observations.repo),
|
|
308
321
|
load: observations.load_average.toFixed(1),
|
|
309
322
|
record: format_record(observations.record_age_ms),
|
|
310
323
|
next: format_next_report(timing.now_ms, timing.interval_ms),
|
|
@@ -354,7 +367,6 @@ const run_progress = {
|
|
|
354
367
|
format_line,
|
|
355
368
|
format_next_line,
|
|
356
369
|
format_next_report,
|
|
357
|
-
format_record,
|
|
358
370
|
format_report,
|
|
359
371
|
is_due,
|
|
360
372
|
minutes_from,
|