@joshuafolkken/kit 1.1784.0 → 1.2116.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/reviewer-verification.md +19 -0
- package/.claude/agents/reviewer.md +19 -0
- package/.claude/settings.json +5 -6
- package/.claude/skills/dependency-update/SKILL.md +9 -10
- package/.claude/skills/workflow-commands/SKILL.md +6 -6
- package/.claude/skills/workflow-commands/background-commands.md +8 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +41 -32
- package/.claude/skills/workflow-commands/delegation.md +6 -6
- package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +7 -5
- package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +9 -4
- package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -2
- package/.claude/skills/workflow-commands/observation-filing.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
- package/.claude/skills/workflow-commands/prerequisite.md +3 -2
- package/.claude/skills/workflow-commands/retrospective.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +7 -5
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-pnpm/action.yml +9 -16
- package/.github/dependabot.yml +16 -0
- package/.github/workflows/auto-tag.yml +45 -0
- package/.github/workflows/ci.yml +155 -15
- package/.github/workflows/dependabot-auto-merge.yml +63 -4
- package/.github/workflows/production.yml +8 -0
- package/.github/workflows/publish.yml +60 -45
- package/.vscode/settings.json +19 -0
- package/CLAUDE.md +5 -12
- package/SECURITY.md +2 -2
- package/dist/CLAUDE.md +5 -12
- package/dist/commands/document-read-cli.js +2 -1
- package/dist/commands/document-section-main.js +2 -1
- package/dist/commands/read-set-cli.js +194 -134
- package/dist/commands/run-prep-main.js +9694 -10173
- package/dist/commands/run-step-cli.js +22138 -18285
- package/dist/hooks/audit-provision.js +23 -5
- package/dist/hooks/chunk-3GKE653K.js +6204 -0
- package/dist/hooks/chunk-45CJJOO7.js +1243 -0
- package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
- package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
- package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
- package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
- package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
- package/dist/hooks/chunk-VVNYJWEI.js +30 -0
- package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
- package/dist/hooks/codex-hook-adapter.js +8 -8
- package/dist/hooks/format-edited.js +4 -5
- package/dist/hooks/inputs.json +386 -360
- package/dist/hooks/pretool-guard.js +7 -6
- package/dist/hooks/session-lang.js +101 -258
- package/dist/hooks/stop-guard.js +1744 -2576
- package/dist/josh.js +7133 -6368
- package/dist/version/index.js +161 -1
- package/eslint/rules/comment-why-only.js +108 -0
- package/package.json +16 -9
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +14 -11
- package/prompts/collaboration-workflow/issue-citation.md +0 -4
- package/prompts/collaboration-workflow/issue-template.md +40 -21
- package/prompts/collaboration-workflow/lane-instructions.md +3 -1
- package/prompts/collaboration-workflow/measurement.md +8 -1
- package/prompts/collaboration-workflow/operating-rules.md +11 -2
- package/prompts/collaboration-workflow/output-bounds.md +6 -2
- package/prompts/collaboration-workflow/plan-comment.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/residency.md +3 -2
- package/prompts/collaboration-workflow/rule-delivery.md +13 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +3 -1
- package/prompts/review-rubric.md +8 -0
- package/prompts/review.md +31 -22
- package/prompts/testing-guide.md +1 -0
- package/scripts/agent/agent-argv.ts +14 -16
- package/scripts/agent/agent-provider.ts +138 -0
- package/scripts/agent/agent-role-profile.ts +108 -156
- package/scripts/agent/agent-safe-text.ts +20 -5
- package/scripts/agent/api-usage-limit.ts +65 -0
- package/scripts/agent/claude-agent-argv.ts +19 -9
- package/scripts/agent/codex-agent-argv.ts +118 -22
- package/scripts/agent/usage-limit-reset.ts +179 -0
- package/scripts/auth/claude-token-output.ts +2 -2
- package/scripts/auto-ok/auto-ok-author.ts +53 -0
- package/scripts/auto-ok/auto-ok-cli.ts +20 -9
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +6 -1
- package/scripts/backlog/backlog-drive-hold.ts +3 -3
- package/scripts/backlog/backlog-drive-idle.ts +10 -0
- package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
- package/scripts/backlog/backlog-drive-launch.ts +8 -2
- package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
- package/scripts/backlog/backlog-drive-named.ts +28 -7
- package/scripts/backlog/backlog-drive-paused.ts +5 -4
- package/scripts/backlog/backlog-drive-restore.ts +11 -3
- package/scripts/backlog/backlog-drive.ts +21 -60
- package/scripts/backlog/backlog-gate-scope.ts +61 -0
- package/scripts/backlog/backlog-measure-close.ts +112 -0
- package/scripts/backlog/backlog-next.ts +39 -49
- package/scripts/backlog/backlog-occupied.ts +2 -2
- package/scripts/backlog/backlog-overlap.ts +42 -8
- package/scripts/backlog/backlog-plan-cli.ts +4 -1
- package/scripts/backlog/backlog-plan-comment.ts +81 -0
- package/scripts/backlog/backlog-plan-read.ts +19 -6
- package/scripts/backlog/backlog-pool.ts +50 -12
- package/scripts/backlog/backlog-rank.ts +60 -13
- package/scripts/backlog/backlog-stalled-detect.ts +2 -1
- package/scripts/backlog/backlog-waves.ts +17 -2
- package/scripts/backlog/backlogrun-launch.ts +7 -4
- package/scripts/cost-runtime/context-cut-payback.ts +27 -25
- package/scripts/cost-runtime/cost-cli.ts +37 -16
- package/scripts/cost-runtime/cost-pricing.ts +9 -0
- package/scripts/cost-runtime/cost-verdict.ts +4 -1
- package/scripts/delegation/delegation-policy.ts +2 -2
- package/scripts/delegation/duplicate-read-guard.ts +1 -0
- package/scripts/delegation/investigation-guard.ts +14 -2
- package/scripts/delegation/investigation-reads.ts +45 -23
- package/scripts/dependabot/dependabot-cooldown.ts +3 -2
- package/scripts/discovery/repo-party.ts +80 -20
- package/scripts/discovery/session-owner-pin.ts +51 -0
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/command-reference-line-budget.ts +42 -0
- package/scripts/document/document-byte-budget.ts +17 -7
- package/scripts/document/document-checks.ts +20 -0
- package/scripts/document/document-ratchet-check.ts +101 -0
- package/scripts/document/document-section.ts +1 -0
- package/scripts/document/entry-read-budget.ts +7 -3
- package/scripts/document/issue-citation-budget.ts +94 -0
- package/scripts/epic/epic-cli-argv.ts +2 -2
- package/scripts/epic/epic-fetch.ts +4 -2
- package/scripts/epic/epic-graph.ts +7 -2
- package/scripts/epic/epic-issue.ts +3 -1
- package/scripts/epic/epic-rank.ts +5 -0
- package/scripts/exports/unused-members-check.ts +62 -0
- package/scripts/exports/unused-members-cli.ts +6 -51
- package/scripts/followup/followup-ci-path.ts +67 -0
- package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
- package/scripts/followup/followup-coderabbit-wait.ts +13 -10
- package/scripts/followup/followup-failed-tests.ts +160 -0
- package/scripts/followup/followup-job-needs.ts +100 -0
- package/scripts/followup/followup-job-rerun.ts +303 -0
- package/scripts/followup/followup-main-move.ts +113 -0
- package/scripts/followup/git-followup-finish.ts +43 -11
- package/scripts/followup/git-followup-pending.ts +3 -3
- package/scripts/followup/git-followup-stages.ts +41 -11
- package/scripts/followup/git-pr-followup-checks.ts +55 -16
- package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
- package/scripts/followup/git-pr-followup.ts +62 -27
- package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
- package/scripts/gate/busy-average.ts +34 -2
- package/scripts/gate/check-related-pinned.ts +43 -0
- package/scripts/gate/check-related-reuse.ts +64 -0
- package/scripts/gate/check-related-section.ts +57 -0
- package/scripts/gate/check-related-unplanned.ts +34 -0
- package/scripts/gate/check-related.ts +265 -0
- package/scripts/gate/command-memory.ts +1 -1
- package/scripts/gate/core-admission.ts +24 -6
- package/scripts/gate/core-budget-timing.ts +20 -6
- package/scripts/gate/core-budget.ts +40 -11
- package/scripts/gate/core-wait-record.ts +3 -2
- package/scripts/gate/core-wait.ts +25 -2
- package/scripts/gate/core-weights.ts +15 -7
- package/scripts/gate/gate-labels.ts +46 -0
- package/scripts/gate/gate-ledger.ts +14 -6
- package/scripts/gate/gate-plan.ts +103 -58
- package/scripts/gate/gate-report.ts +9 -7
- package/scripts/gate/gate-run-steps.ts +26 -3
- package/scripts/gate/gate-skip.ts +45 -6
- package/scripts/gate/gate-static-group.ts +60 -0
- package/scripts/gate/gate-steps.ts +2 -1
- package/scripts/gate/gate-tree.ts +4 -2
- package/scripts/gate/hook-gate-reuse.ts +19 -2
- package/scripts/gate/metrics-totals.ts +59 -0
- package/scripts/gate/scoped-green.ts +68 -15
- package/scripts/gate/since-green.ts +14 -6
- package/scripts/gate/structural-checks.ts +96 -0
- package/scripts/gate/verification-gate.ts +51 -16
- package/scripts/gate/verification-inputs.ts +21 -6
- package/scripts/gate/verification-tail.ts +52 -0
- package/scripts/gh/gh-author-association.ts +23 -2
- package/scripts/gh/git-ai-review-scan.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +12 -3
- package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
- package/scripts/gh/git-gh-exec.ts +32 -2
- package/scripts/gh/git-gh-issue-read.ts +4 -2
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +8 -2
- package/scripts/gh/git-gh-issue.ts +12 -5
- package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
- package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
- package/scripts/gh/git-gh-pr-read.ts +74 -13
- package/scripts/gh/git-gh-pr-rest.ts +3 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
- package/scripts/gh/git-gh-pr-too-large.ts +20 -0
- package/scripts/gh/git-gh-pr.ts +21 -7
- package/scripts/gh/git-gh-retry.ts +141 -0
- package/scripts/gh/git-pr-ai-review.ts +15 -6
- package/scripts/gh/git-pr-checks-eval.ts +3 -0
- package/scripts/gh/git-pr-checks.ts +5 -5
- package/scripts/git/base-tree.ts +30 -0
- package/scripts/git/change-base.ts +4 -10
- package/scripts/git/changed-paths-sync.ts +63 -0
- package/scripts/git/changed-paths.ts +16 -1
- package/scripts/git/git-common-directory.ts +11 -1
- package/scripts/git/git-diff-reads.ts +66 -20
- package/scripts/git/git-error.ts +9 -2
- package/scripts/git/git-schemas.ts +13 -0
- package/scripts/git/git-worktree.ts +13 -0
- package/scripts/git/gone-branch.ts +4 -1
- package/scripts/git/main-merge-budget-conflict.ts +89 -0
- package/scripts/git/main-merge-guard.ts +55 -18
- package/scripts/git/main-merge-regenerate.ts +59 -25
- package/scripts/git/main-merge.ts +53 -5
- package/scripts/git/no-base-checkout.ts +127 -0
- package/scripts/git/stash/git-stash.ts +11 -2
- package/scripts/git/stash/stash-push-cli.ts +10 -0
- package/scripts/hooks/batch-guard.ts +40 -21
- package/scripts/hooks/edited-cspell.ts +37 -11
- package/scripts/hooks/format-edited-file.ts +22 -2
- package/scripts/hooks/lane-plan-guard.ts +50 -0
- package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
- package/scripts/hooks/pre-commit-lint.ts +14 -1
- package/scripts/hooks/pre-push-related-switch.ts +10 -0
- package/scripts/hooks/pre-push-unit.ts +76 -10
- package/scripts/hooks/pretool-guard.ts +2 -0
- package/scripts/hooks/reserved-run.ts +14 -1
- package/scripts/hooks/run-hook.sh +23 -8
- package/scripts/hooks/step-zero-notice.ts +6 -1
- package/scripts/hooks/stop-actions.ts +3 -15
- package/scripts/hooks/stop-guard.ts +7 -6
- package/scripts/init/distributed-paths.ts +1 -0
- package/scripts/init/hook-command-rewrite.ts +5 -1
- package/scripts/init/hook-launch.ts +4 -2
- package/scripts/issue/aggregation-split.ts +52 -0
- package/scripts/issue/defect-origin-line.ts +19 -1
- package/scripts/issue/defect-rate-cli.ts +5 -102
- package/scripts/issue/defect-report.ts +4 -4
- package/scripts/issue/effect-audit-cli.ts +178 -0
- package/scripts/issue/effect-audit.ts +185 -0
- package/scripts/issue/expected-effect-lint.ts +64 -9
- package/scripts/issue/git-next-issues.ts +5 -0
- package/scripts/issue/issue-body-or-comment.ts +38 -4
- package/scripts/issue/issue-cite-cli.ts +1 -3
- package/scripts/issue/issue-classification.ts +1 -0
- package/scripts/issue/issue-closing-pr.ts +8 -1
- package/scripts/issue/issue-evidence-exit.ts +4 -2
- package/scripts/issue/issue-file-cap.ts +58 -0
- package/scripts/issue/issue-file-cli.ts +111 -38
- package/scripts/issue/issue-file-deferral.ts +52 -0
- package/scripts/issue/issue-file-fold.ts +29 -10
- package/scripts/issue/issue-file-interrupt.ts +85 -0
- package/scripts/issue/issue-file-lane-hint.ts +30 -0
- package/scripts/issue/issue-file.ts +43 -6
- package/scripts/issue/issue-labels.ts +19 -2
- package/scripts/issue/issue-lint-cli.ts +27 -2
- package/scripts/issue/issue-measured-cli.ts +13 -35
- package/scripts/issue/issue-measured-close.ts +58 -0
- package/scripts/issue/issue-not-before-label.ts +2 -2
- package/scripts/issue/issue-not-before.ts +4 -1
- package/scripts/issue/issue-priority-cli.ts +60 -0
- package/scripts/issue/issue-priority-raise.ts +55 -0
- package/scripts/issue/issue-priority.ts +174 -43
- package/scripts/issue/issue-rank.ts +21 -4
- package/scripts/issue/issue-read-cli.ts +32 -6
- package/scripts/issue/issue-read.ts +37 -12
- package/scripts/issue/issue-sample-gate.ts +95 -74
- package/scripts/issue/issue-sample-prime.ts +127 -0
- package/scripts/issue/issue-sample-required.ts +57 -0
- package/scripts/issue/issue-sample-source.ts +12 -11
- package/scripts/issue/issue-search.ts +124 -0
- package/scripts/issue/issue-state.ts +13 -1
- package/scripts/issue/issue-template-section.ts +43 -0
- package/scripts/issue/issue-watch-diff.ts +31 -1
- package/scripts/issue/issue-watch-hook.ts +11 -2
- package/scripts/issue/issue-watch.ts +55 -12
- package/scripts/issue/markdown-section.ts +1 -0
- package/scripts/issue/measure-declaration.ts +121 -0
- package/scripts/issue/measure-rerun-cli.ts +7 -70
- package/scripts/issue/plan-consumers-section.ts +22 -1
- package/scripts/issue/reproduction-measure.ts +3 -1
- package/scripts/issue/size-estimate.ts +90 -0
- package/scripts/issue/trusted-measure.ts +84 -0
- package/scripts/josh/command-usage.ts +3 -2
- package/scripts/josh/durable-state-migrate.ts +105 -0
- package/scripts/josh/durable-state.ts +112 -0
- package/scripts/josh/josh-aliases.ts +95 -0
- package/scripts/josh/josh-command-map.ts +1 -82
- package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
- package/scripts/josh/josh-commands-ai.ts +5 -5
- package/scripts/josh/josh-commands-development.ts +59 -58
- package/scripts/josh/josh-commands-issue-write.ts +23 -4
- package/scripts/josh/josh-commands-issue.ts +32 -0
- package/scripts/josh/josh-commands-lane.ts +87 -4
- package/scripts/josh/josh-commands-lint.ts +16 -3
- package/scripts/josh/josh-commands-maintenance.ts +15 -0
- package/scripts/josh/josh-commands-review.ts +41 -6
- package/scripts/josh/josh-commands-ship.ts +56 -8
- package/scripts/josh/josh-commands-test-check.ts +80 -0
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/josh-environment-file.ts +43 -3
- package/scripts/josh/josh-in-process.ts +2 -2
- package/scripts/josh/josh-logic.ts +5 -3
- package/scripts/josh/josh-run.ts +19 -1
- package/scripts/josh/run-record-path.ts +15 -0
- package/scripts/josh/stamp-file.ts +11 -2
- package/scripts/lane/lane-adopt-cli.ts +98 -0
- package/scripts/lane/lane-adopt.ts +208 -0
- package/scripts/lane/lane-await.ts +5 -8
- package/scripts/lane/lane-baseline.ts +123 -0
- package/scripts/lane/lane-breakdown-cli.ts +64 -0
- package/scripts/lane/lane-breakdown-implement.ts +170 -0
- package/scripts/lane/lane-breakdown-laps.ts +107 -0
- package/scripts/lane/lane-breakdown-pinned.ts +76 -0
- package/scripts/lane/lane-breakdown-text.ts +145 -0
- package/scripts/lane/lane-breakdown.ts +239 -0
- package/scripts/lane/lane-check-stats.ts +29 -8
- package/scripts/lane/lane-child-invocation.ts +9 -2
- package/scripts/lane/lane-child-mark-keys.ts +12 -0
- package/scripts/lane/lane-child-marker.ts +20 -1
- package/scripts/lane/lane-ci-path-stats.ts +73 -0
- package/scripts/lane/lane-claim-stats.ts +84 -0
- package/scripts/lane/lane-close.ts +8 -3
- package/scripts/lane/lane-dispatch-log.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +2 -2
- package/scripts/lane/lane-gap-stats.ts +7 -6
- package/scripts/lane/lane-guard-policy.ts +7 -1
- package/scripts/lane/lane-implement-stats.ts +207 -0
- package/scripts/lane/lane-implement-subagents.ts +90 -0
- package/scripts/lane/lane-investigation-switch.ts +16 -0
- package/scripts/lane/lane-ledger-kind.ts +31 -0
- package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
- package/scripts/lane/lane-ledger-schema.ts +119 -36
- package/scripts/lane/lane-ledger-write.ts +257 -0
- package/scripts/lane/lane-ledger.ts +31 -177
- package/scripts/lane/lane-load.ts +1 -1
- package/scripts/lane/lane-measure-cli.ts +176 -59
- package/scripts/lane/lane-net-read.ts +44 -0
- package/scripts/lane/lane-net-time.ts +212 -0
- package/scripts/lane/lane-open.ts +16 -7
- package/scripts/lane/lane-output.ts +2 -4
- package/scripts/lane/lane-overrun-prompt.ts +147 -0
- package/scripts/lane/lane-overrun.ts +274 -0
- package/scripts/lane/lane-paths.ts +24 -1
- package/scripts/lane/lane-pause-cli.ts +4 -1
- package/scripts/lane/lane-paused-spans.ts +97 -0
- package/scripts/lane/lane-plan-check.ts +207 -0
- package/scripts/lane/lane-plan-cli.ts +41 -0
- package/scripts/lane/lane-plan.ts +144 -0
- package/scripts/lane/lane-registry.ts +14 -1
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-round-one-stats.ts +51 -0
- package/scripts/lane/lane-sampler.ts +23 -4
- package/scripts/lane/lane-session-action.ts +93 -18
- package/scripts/lane/lane-session-broker.ts +49 -21
- package/scripts/lane/lane-session-reread-main.ts +14 -0
- package/scripts/lane/lane-session-reread.ts +51 -0
- package/scripts/lane/lane-ship-lap-stats.ts +74 -0
- package/scripts/lane/lane-sleep.ts +58 -0
- package/scripts/lane/lane-spent.ts +1 -1
- package/scripts/lane/lane-split-stats.ts +28 -0
- package/scripts/lane/lane-stage-stats.ts +13 -1
- package/scripts/lane/lane-state.ts +41 -9
- package/scripts/lane/lane-stats-tables.ts +58 -0
- package/scripts/lane/lane-stats.ts +21 -5
- package/scripts/lane/lane-stop-stats.ts +51 -19
- package/scripts/lane/lane-tail-stats.ts +32 -0
- package/scripts/lane/lane-transcript-calls.ts +67 -10
- package/scripts/lane/lane-transcript-stats.ts +44 -12
- package/scripts/lane/lane-value-cell.ts +72 -0
- package/scripts/lane/lane-value.ts +118 -0
- package/scripts/lane/lane-withdraw-closed.ts +124 -0
- package/scripts/lane/lane-withdraw.ts +108 -31
- package/scripts/lane/lane-yield.ts +85 -0
- package/scripts/lane/openai-lane-ship.ts +12 -11
- package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
- package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
- package/scripts/lane/openai-lane-supervisor.ts +5 -4
- package/scripts/lib/poll.ts +38 -9
- package/scripts/lib/settled-together.ts +10 -0
- package/scripts/lib/shell-quote.ts +21 -0
- package/scripts/lib/token-shape.ts +111 -0
- package/scripts/lint/eslint-daemon-sources.ts +79 -0
- package/scripts/lint/eslint-daemon.ts +45 -6
- package/scripts/lint/eslint-warm-cli.ts +7 -0
- package/scripts/lint/eslint-warm.ts +66 -0
- package/scripts/lint/import-graph.ts +141 -11
- package/scripts/lint/lint-gate-scope.ts +2 -2
- package/scripts/lint/lint-parallel.ts +54 -6
- package/scripts/lint/lint-related.ts +154 -33
- package/scripts/lint/rename-cli.ts +179 -0
- package/scripts/lint/rename-identifier.ts +192 -0
- package/scripts/lint/type-only-imports.ts +58 -0
- package/scripts/notify/telegram-notify.ts +12 -3
- package/scripts/observations/observation-record.ts +42 -16
- package/scripts/observations/observations-flush.ts +32 -9
- package/scripts/overrides/overrides-check.ts +9 -1
- package/scripts/release/release-approval-prune.ts +7 -1
- package/scripts/repo/required-checks-logic.ts +4 -1
- package/scripts/repo/ruleset-check.ts +4 -3
- package/scripts/report/markdown-shape.ts +28 -0
- package/scripts/report/report-format-reference.ts +15 -1
- package/scripts/report/report-labels.ts +12 -1
- package/scripts/report/report-lint-child-summary.ts +94 -0
- package/scripts/report/report-lint-cli.ts +26 -7
- package/scripts/report/report-lint.ts +2 -20
- package/scripts/review/prose-stale-cli.ts +88 -0
- package/scripts/review/prose-stale-scan.ts +152 -0
- package/scripts/review/review-attest.ts +73 -23
- package/scripts/review/review-brief-cli.ts +68 -19
- package/scripts/review/review-brief-paths.ts +22 -0
- package/scripts/review/review-brief.ts +14 -7
- package/scripts/review/review-comment-carry.ts +47 -0
- package/scripts/review/review-comment-round.ts +85 -22
- package/scripts/review/review-finding-ledger.ts +109 -7
- package/scripts/review/review-finding-text.ts +43 -0
- package/scripts/review/review-interaction.ts +11 -0
- package/scripts/review/review-lane-handover.ts +68 -0
- package/scripts/review/review-lint-cli.ts +57 -0
- package/scripts/review/review-lint-findings.ts +92 -0
- package/scripts/review/review-lint-sections.ts +80 -0
- package/scripts/review/review-lint.ts +221 -0
- package/scripts/review/review-prior-findings.ts +102 -0
- package/scripts/review/review-readers-scan.ts +4 -2
- package/scripts/review/review-record-cli.ts +177 -54
- package/scripts/review/review-record-code-round.ts +55 -0
- package/scripts/review/review-record-comment.ts +60 -0
- package/scripts/review/review-record-interaction.ts +35 -0
- package/scripts/review/review-record-pinned.ts +108 -0
- package/scripts/review/review-record.ts +25 -1
- package/scripts/review/review-reviewed-tree.ts +307 -0
- package/scripts/review/review-round-one-closure.ts +62 -0
- package/scripts/review/review-round-reuse.ts +106 -0
- package/scripts/review/review-round2-cli.ts +91 -29
- package/scripts/review/review-round2-skip-comment.ts +55 -0
- package/scripts/review/review-round2.ts +24 -8
- package/scripts/review/review-stamps.ts +7 -3
- package/scripts/review/review-stop-log.ts +20 -6
- package/scripts/review/review-stops-cli.ts +2 -1
- package/scripts/review/review-submit-cli.ts +101 -0
- package/scripts/rules/agent-model.ts +1 -1
- package/scripts/rules/bash-triggers.ts +3 -3
- package/scripts/rules/concise-reply.ts +88 -0
- package/scripts/rules/credential-body.ts +77 -0
- package/scripts/rules/decision-oracle.ts +1 -1
- package/scripts/rules/delivered-rules.ts +36 -17
- package/scripts/rules/destructive-command.ts +3 -11
- package/scripts/rules/direct-issue-comment.ts +34 -12
- package/scripts/rules/direct-issue-read.ts +191 -0
- package/scripts/rules/direct-pr-create.ts +4 -24
- package/scripts/rules/early-heartbeat.ts +2 -0
- package/scripts/rules/edit-tool.ts +27 -0
- package/scripts/rules/file-edit-rows.ts +17 -0
- package/scripts/rules/file-rewrite.ts +146 -0
- package/scripts/rules/firing-point.ts +3 -2
- package/scripts/rules/gh-api.ts +128 -7
- package/scripts/rules/gh-repo-selector.ts +84 -0
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/guard-remedy.ts +14 -5
- package/scripts/rules/implementation-cut.ts +61 -28
- package/scripts/rules/investigator-foreground.ts +231 -0
- package/scripts/rules/issue-citation.ts +15 -60
- package/scripts/rules/issue-comments.ts +9 -4
- package/scripts/rules/josh-git-bare.ts +1 -1
- package/scripts/rules/lane-background.ts +41 -13
- package/scripts/rules/lane-direct-tool.ts +107 -9
- package/scripts/rules/lane-interactive-ask.ts +4 -1
- package/scripts/rules/lane-park.ts +4 -2
- package/scripts/rules/lane-spilled-read.ts +90 -0
- package/scripts/rules/lane-split-park.ts +1 -1
- package/scripts/rules/lane-switch-main.ts +4 -4
- package/scripts/rules/last-prompt.ts +20 -47
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/permission-guards.ts +5 -1
- package/scripts/rules/piped-verification-shapes.ts +110 -0
- package/scripts/rules/piped-verification.ts +67 -17
- package/scripts/rules/poll-loop.ts +72 -9
- package/scripts/rules/pr-merge.ts +5 -5
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +88 -24
- package/scripts/rules/reply-language.ts +3 -17
- package/scripts/rules/reply-prose.ts +34 -0
- package/scripts/rules/repo-admin.ts +132 -0
- package/scripts/rules/reviewer-foreground.ts +88 -0
- package/scripts/rules/round-one-check-related.ts +120 -0
- package/scripts/rules/rule-body-guard.ts +5 -15
- package/scripts/rules/rule-value-cache.ts +53 -5
- package/scripts/rules/rule-value-candidates.ts +84 -0
- package/scripts/rules/rule-value-cli.ts +59 -11
- package/scripts/rules/rule-value.ts +17 -4
- package/scripts/rules/run-tail-rule.ts +1 -1
- package/scripts/rules/sed-in-place.ts +196 -0
- package/scripts/rules/shell-segments.ts +10 -2
- package/scripts/rules/stop-rule-rows.ts +1 -13
- package/scripts/rules/stop-rules.ts +33 -58
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +110 -23
- package/scripts/rules/timed-rerun.ts +1 -1
- package/scripts/rules/turn-filings.ts +90 -0
- package/scripts/rules/worktree-guard.ts +22 -7
- package/scripts/run/board/run-board-ending-reason.ts +6 -2
- package/scripts/run/board/run-board-fit.ts +24 -1
- package/scripts/run/board/run-board-found.ts +134 -0
- package/scripts/run/board/run-board-header.ts +8 -0
- package/scripts/run/board/run-board-labels.ts +11 -1
- package/scripts/run/board/run-board-lane-time.ts +1 -0
- package/scripts/run/board/run-board-link.ts +15 -2
- package/scripts/run/board/run-board-notes.ts +7 -1
- package/scripts/run/board/run-board-operation.ts +4 -2
- package/scripts/run/board/run-board-phase.ts +2 -5
- package/scripts/run/board/run-board-plan.ts +1 -1
- package/scripts/run/board/run-board-read.ts +46 -1
- package/scripts/run/board/run-board-reason.ts +20 -8
- package/scripts/run/board/run-board-render-checks.ts +3 -2
- package/scripts/run/board/run-board-render-drawn.ts +11 -0
- package/scripts/run/board/run-board-render-found.ts +157 -0
- package/scripts/run/board/run-board-render-lead.ts +9 -0
- package/scripts/run/board/run-board-render-legend.ts +19 -0
- package/scripts/run/board/run-board-render-tail.ts +1 -1
- package/scripts/run/board/run-board-render.ts +82 -18
- package/scripts/run/board/run-board-spin.ts +1 -3
- package/scripts/run/board/run-board-status.ts +2 -0
- package/scripts/run/board/run-board-tick.ts +39 -10
- package/scripts/run/carry/run-carry-ended.ts +3 -2
- package/scripts/run/carry/run-carry.ts +3 -2
- package/scripts/run/cut/run-cut-cli.ts +33 -133
- package/scripts/run/cut/run-cut-digest.ts +152 -0
- package/scripts/run/cut/run-cut-handoff.ts +52 -8
- package/scripts/run/cut/run-cut-report.ts +24 -3
- package/scripts/run/cut/run-cut-resume.ts +129 -0
- package/scripts/run/cut/run-cut-review.ts +105 -0
- package/scripts/run/cut/run-cut.ts +18 -7
- package/scripts/run/detached-launch.ts +1 -1
- package/scripts/run/entry/run-entry-cli.ts +88 -19
- package/scripts/run/entry/run-entry-spill.ts +83 -0
- package/scripts/run/entry/run-entry-stop.ts +5 -1
- package/scripts/run/entry/run-entry-trust.ts +91 -0
- package/scripts/run/event/run-event-baseline.ts +56 -0
- package/scripts/run/event/run-event-filed.ts +9 -3
- package/scripts/run/event/run-event-overrun.ts +197 -0
- package/scripts/run/event/run-event-render.ts +4 -0
- package/scripts/run/event/run-event-stream.ts +25 -3
- package/scripts/run/hold/run-stop-notify.ts +3 -8
- package/scripts/run/merge/run-merge-cap.ts +57 -0
- package/scripts/run/merge/run-merge-cli.ts +66 -23
- package/scripts/run/merge/run-merge-outcome.ts +2 -0
- package/scripts/run/merge/run-merge-ship.ts +13 -3
- package/scripts/run/merge/run-merge-signals.ts +40 -23
- package/scripts/run/merge/run-merge-steps.ts +56 -36
- package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
- package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
- package/scripts/run/merge/run-merge.ts +41 -14
- package/scripts/run/review/run-review-cli.ts +306 -20
- package/scripts/run/review/run-review-early-push.ts +121 -0
- package/scripts/run/review/run-review-join-read.ts +94 -0
- package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
- package/scripts/run/review/run-review-pinned-join.ts +216 -0
- package/scripts/run/review/run-review-pinned-steps.ts +383 -0
- package/scripts/run/review/run-review-pinned-tree.ts +37 -0
- package/scripts/run/review/run-review-pinned.ts +53 -0
- package/scripts/run/review/run-review-steps.ts +70 -34
- package/scripts/run/review/run-review.ts +26 -6
- package/scripts/run/run-parent-cut-hook.ts +3 -4
- package/scripts/run/run-prep.ts +1 -0
- package/scripts/run/run-stage-read.ts +2 -6
- package/scripts/run/run-step-cli.ts +17 -5
- package/scripts/run/run-step-lane-plan.ts +27 -0
- package/scripts/run/run-step-section.ts +26 -7
- package/scripts/run/run-step.ts +5 -2
- package/scripts/run/ship/run-ship-args.ts +19 -0
- package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
- package/scripts/run/ship/run-ship-cli.ts +131 -39
- package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
- package/scripts/run/ship/run-ship-detach.ts +10 -4
- package/scripts/run/ship/run-ship-handover.ts +106 -0
- package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
- package/scripts/run/ship/run-ship-lap.ts +63 -0
- package/scripts/run/ship/run-ship-next.ts +27 -26
- package/scripts/run/ship/run-ship-overlap.ts +8 -3
- package/scripts/run/ship/run-ship-place.ts +9 -2
- package/scripts/run/ship/run-ship-planned.ts +92 -0
- package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
- package/scripts/run/ship/run-ship-preflight.ts +16 -4
- package/scripts/run/ship/run-ship-probe.ts +23 -9
- package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
- package/scripts/run/ship/run-ship-relaunch.ts +51 -0
- package/scripts/run/ship/run-ship-return.ts +103 -29
- package/scripts/run/ship/run-ship-review-reason.ts +24 -0
- package/scripts/run/ship/run-ship-review-steps.ts +230 -59
- package/scripts/run/ship/run-ship-review.ts +171 -51
- package/scripts/run/ship/run-ship-reviewer.ts +138 -42
- package/scripts/run/ship/run-ship-scoped.ts +39 -10
- package/scripts/run/ship/run-ship-stage.ts +49 -13
- package/scripts/run/ship/run-ship-steps.ts +24 -4
- package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
- package/scripts/run/ship/run-ship-stop-context.ts +50 -13
- package/scripts/run/ship/run-ship-sync.ts +171 -30
- package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
- package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
- package/scripts/run/ship/run-ship-waiter.ts +114 -0
- package/scripts/run/ship/run-ship.ts +16 -2
- package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
- package/scripts/run/wake/run-wake-cli.ts +6 -113
- package/scripts/run/wake/run-wake-code.ts +53 -11
- package/scripts/run/wake/run-wake-driver.ts +5 -3
- package/scripts/run/wake/run-wake-finish.ts +137 -0
- package/scripts/run/wake/run-wake-loop.ts +5 -3
- package/scripts/run/wake/run-wake-ports.ts +11 -3
- package/scripts/run/wake/run-wake-session.ts +2 -0
- package/scripts/run/wake/run-wake.ts +3 -2
- package/scripts/safe-chain/ci-installer-pin.ts +49 -8
- package/scripts/safe-chain/project-config.ts +3 -2
- package/scripts/security/secretlint-scan.ts +42 -9
- package/scripts/security/security-audit-provision-main.ts +9 -1
- package/scripts/security/security-audit-provision.ts +1 -1
- package/scripts/security/security-audit.ts +21 -1
- package/scripts/security/sonar-file.ts +10 -5
- package/scripts/split/split-assess.ts +12 -3
- package/scripts/split/split-early-notice.ts +116 -0
- package/scripts/split/split-measure.ts +20 -2
- package/scripts/split/split-resolution.ts +107 -0
- package/scripts/test/direct-importers.ts +185 -0
- package/scripts/test/pure-files-entries.ts +83 -0
- package/scripts/test/related-heavy-tests.ts +81 -0
- package/scripts/test/test-no-base.ts +88 -0
- package/scripts/test/test-pinned-cache-logic.ts +363 -0
- package/scripts/test/test-pinned-cache.ts +337 -0
- package/scripts/test/test-pinned-emit.ts +49 -0
- package/scripts/test/test-pinned-functions.ts +116 -0
- package/scripts/test/test-pinned-ledger.ts +80 -0
- package/scripts/test/test-pinned-logic.ts +208 -20
- package/scripts/test/test-pinned-main.ts +84 -18
- package/scripts/test/test-pinned-pool.ts +73 -0
- package/scripts/test/test-pinned-probe.ts +254 -0
- package/scripts/test/test-pinned-prune-logic.ts +118 -0
- package/scripts/test/test-pinned-reach.ts +194 -0
- package/scripts/test/test-pinned-record.ts +196 -0
- package/scripts/test/test-pinned-rewire.ts +148 -0
- package/scripts/test/test-pinned-spawn.ts +81 -0
- package/scripts/test/test-pinned-stage.ts +70 -0
- package/scripts/test/test-pinned.ts +258 -47
- package/scripts/test/test-reach-cli.ts +61 -0
- package/scripts/test/test-read-map.ts +35 -11
- package/scripts/test/test-read-recording.ts +17 -5
- package/scripts/test/test-read-trace.ts +26 -8
- package/scripts/test/test-red-logic.ts +46 -7
- package/scripts/test/test-red.ts +34 -14
- package/scripts/test/test-related-claim.ts +37 -0
- package/scripts/test/test-related-main.ts +4 -1
- package/scripts/test/test-related-moved.ts +91 -0
- package/scripts/test/test-related-record.ts +43 -23
- package/scripts/test/test-related-scope.ts +99 -34
- package/scripts/test/test-related-synced.ts +135 -0
- package/scripts/test/test-related-touched.ts +84 -0
- package/scripts/test/test-related.ts +167 -83
- package/scripts/test/test-unit-guard.ts +28 -5
- package/scripts/test/unit-durations.ts +41 -0
- package/scripts/test/unit-worker-share.ts +5 -4
- package/scripts/test/vitest-cache-directory.ts +19 -0
- package/scripts/test/vitest-cli-excludes.ts +14 -0
- package/scripts/test/vitest-failure-summary.ts +111 -0
- package/scripts/test/whole-suite-files.ts +12 -1
- package/scripts/time-runtime/time-batch-guard.ts +42 -4
- package/scripts/time-runtime/time-bundle-call.ts +1 -1
- package/scripts/time-runtime/time-bundles.ts +36 -5
- package/scripts/time-runtime/time-markers.ts +2 -2
- package/scripts/time-runtime/time-search-call.ts +38 -0
- package/scripts/time-runtime/time-shell.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +17 -5
- package/scripts/version/development-engines-verdict.ts +124 -0
- package/scripts/version/latest-corepack.ts +2 -0
- package/templates/gitignore +2 -0
- package/templates/workflows/ci.yml +41 -0
- package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
- package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
- package/dist/hooks/chunk-TUIFS5E7.js +0 -72
- package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
- package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
- package/scripts/rules/filing-cap.ts +0 -139
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { repo_party } from '#scripts/discovery/repo-party'
|
|
2
2
|
import { bash_triggers } from './bash-triggers'
|
|
3
3
|
import { gh_api } from './gh-api'
|
|
4
|
+
import { gh_repo_selector } from './gh-repo-selector'
|
|
5
|
+
import { git_argv } from './git-argv'
|
|
6
|
+
import { pr_merge } from './pr-merge'
|
|
7
|
+
import { repo_admin } from './repo-admin'
|
|
4
8
|
import { shell_segments } from './shell-segments'
|
|
5
9
|
|
|
6
10
|
// The trigger and the delivered text behind the `third-party-write` row of `delivered-rules.ts`.
|
|
@@ -70,44 +74,126 @@ function candidates_at(
|
|
|
70
74
|
return has_moved ? unreadable_candidates : resolve_placeholder_owners
|
|
71
75
|
}
|
|
72
76
|
|
|
73
|
-
//
|
|
74
|
-
//
|
|
77
|
+
// A merge or an administration write is refused by its own row whoever owns the target, and one
|
|
78
|
+
// refusal is what a PreToolUse hook carries — so the two readings this row added for
|
|
79
|
+
// joshuafolkken/kit#4659 leave those to the row that names them. Asked only of a candidate, so an
|
|
80
|
+
// ordinary shell line pays nothing for it.
|
|
81
|
+
function is_claimed_by_narrower_row(command: string): boolean {
|
|
82
|
+
return pr_merge.is_pr_merge(command) || repo_admin.is_repo_admin_write(command)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// **A GraphQL mutation names no repository this guard can read** (joshuafolkken/kit#4659): its target
|
|
86
|
+
// is a node id inside the body, so it is refused whoever owns the session — the disposition
|
|
87
|
+
// `pr-merge.ts` takes for a GraphQL body it cannot read, which that row already refuses for a body
|
|
88
|
+
// read from a file or computed by the shell. A query passes. The keyword is looked for in the whole
|
|
89
|
+
// line, because the segment cut ignores quotes and a multi-line query splits across it. A query field
|
|
90
|
+
// the shell expands (`query="$Q"`, or the whole argument quoted: `"query=$Q"`) hides its keyword the
|
|
91
|
+
// same way, so it is refused as a mutation; a single-quoted `query='query($o: String!) {…}'` is
|
|
92
|
+
// literal and still read. A body read from a file is `pr-merge.ts`'s, which refuses it already.
|
|
93
|
+
const GRAPHQL_MUTATION = /\bmutation\b/u
|
|
94
|
+
const EXPANDED_QUERY = /^(?:-[fF])?"?query=(?!')[\s\S]*\$/u
|
|
95
|
+
|
|
96
|
+
function is_hidden_or_mutation(command: string, args: ReadonlyArray<string>): boolean {
|
|
97
|
+
return GRAPHQL_MUTATION.test(command) || args.some((argument) => EXPANDED_QUERY.test(argument))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// The arguments of a `gh api` GraphQL call, or `undefined` when the segment is not one.
|
|
101
|
+
function graphql_args(segment: string): ReadonlyArray<string> | undefined {
|
|
102
|
+
const call = git_argv.program_of(segment)
|
|
103
|
+
|
|
104
|
+
if (call === undefined || !gh_api.is_gh_api(segment)) return undefined
|
|
105
|
+
|
|
106
|
+
return pr_merge.is_graphql_call(call.name, call.args) ? call.args : undefined
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function is_graphql_mutation(command: string, segment: string): boolean {
|
|
110
|
+
const args = graphql_args(segment)
|
|
111
|
+
|
|
112
|
+
if (args === undefined) return false
|
|
113
|
+
|
|
114
|
+
return is_hidden_or_mutation(command, args) && !is_claimed_by_narrower_row(command)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// **A `gh <group> <action> -R <owner>/<repo>` write is judged by its selector** (kit#4659).
|
|
118
|
+
// A selector whose owner cannot be read (`-R "$REPO"`) is refused, like an unreadable placeholder
|
|
119
|
+
// candidate: it is a repository `gh` really writes to.
|
|
120
|
+
function is_third_party_selector_write(
|
|
121
|
+
command: string,
|
|
122
|
+
segments: ReadonlyArray<string>,
|
|
123
|
+
index: number,
|
|
124
|
+
session_owner: string | undefined,
|
|
125
|
+
): boolean {
|
|
126
|
+
const selectors = gh_repo_selector.write_selectors(segments, index)
|
|
127
|
+
const is_third_party = selectors.some((selector) => {
|
|
128
|
+
const owner = repo_party.selector_owner(selector)
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
owner === undefined || repo_party.classify(session_owner, owner) === repo_party.THIRD_PARTY
|
|
132
|
+
)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return is_third_party && !is_claimed_by_narrower_row(command)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function is_owner_dependent_write(segments: ReadonlyArray<string>, index: number): boolean {
|
|
139
|
+
const segment = segments[index] ?? ''
|
|
140
|
+
|
|
141
|
+
if (gh_api.is_gh_api(segment)) return gh_api.is_write(segment)
|
|
142
|
+
|
|
143
|
+
return gh_repo_selector.write_selectors(segments, index).length > 0
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function writes_to_third_party_owner(
|
|
147
|
+
command: string,
|
|
148
|
+
segments: ReadonlyArray<string>,
|
|
149
|
+
resolve_owner: () => string | undefined,
|
|
150
|
+
resolve_placeholder_owners: () => Array<string | undefined>,
|
|
151
|
+
): boolean {
|
|
152
|
+
if (segments.every((_segment, index) => !is_owner_dependent_write(segments, index))) return false
|
|
153
|
+
|
|
154
|
+
const session_owner = resolve_owner()
|
|
155
|
+
|
|
156
|
+
return segments.some(
|
|
157
|
+
(segment, index) =>
|
|
158
|
+
is_third_party_selector_write(command, segments, index, session_owner) ||
|
|
159
|
+
is_third_party_write_segment(
|
|
160
|
+
segment,
|
|
161
|
+
session_owner,
|
|
162
|
+
candidates_at(segments, index, resolve_placeholder_owners),
|
|
163
|
+
),
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// The session owner is read only when a segment is actually a repository write — so an ordinary shell
|
|
168
|
+
// line, and every read, pays nothing for the local config read. `resolve_owner` and
|
|
75
169
|
// `resolve_placeholder_owners` are injected so the suite fixes the owners without touching the real
|
|
76
170
|
// remotes, the way `file-body.ts` injects `has_file`. Each segment is judged on its own, so a `gh api`
|
|
77
171
|
// write quoted inside another command's argument is read as the write it is not, exactly as every
|
|
78
|
-
// other trigger here reads its own.
|
|
172
|
+
// other trigger here reads its own. The cut is by program — a pipe and a background `&` cut too, a
|
|
173
|
+
// quoted one does not — after joining backslash-continued lines, so `echo hi | gh pr comment …` and a
|
|
174
|
+
// `gh api graphql \⏎ -f query=…` are each read as the one `gh` call they launch.
|
|
79
175
|
function writes_third_party(
|
|
80
176
|
command: string,
|
|
81
177
|
resolve_owner: () => string | undefined = repo_party.current_owner,
|
|
82
178
|
resolve_placeholder_owners: () => Array<string | undefined> = repo_party.placeholder_owners,
|
|
83
179
|
): boolean {
|
|
84
|
-
const segments = shell_segments.
|
|
85
|
-
|
|
86
|
-
(segment) => gh_api.is_gh_api(segment) && gh_api.is_write(segment),
|
|
180
|
+
const segments = shell_segments.quote_aware_commands_of(
|
|
181
|
+
shell_segments.joined_continuations(command),
|
|
87
182
|
)
|
|
88
183
|
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
const session_owner = resolve_owner()
|
|
184
|
+
if (segments.some((segment) => is_graphql_mutation(command, segment))) return true
|
|
92
185
|
|
|
93
|
-
return
|
|
94
|
-
is_third_party_write_segment(
|
|
95
|
-
segment,
|
|
96
|
-
session_owner,
|
|
97
|
-
candidates_at(segments, index, resolve_placeholder_owners),
|
|
98
|
-
),
|
|
99
|
-
)
|
|
186
|
+
return writes_to_third_party_owner(command, segments, resolve_owner, resolve_placeholder_owners)
|
|
100
187
|
}
|
|
101
188
|
|
|
102
189
|
// The instruction in the shape a refusal can carry: what the command does, why it is Tier C, and what
|
|
103
190
|
// to do instead. The command that computes the party is handed over, because the whole point of this
|
|
104
191
|
// Issue is that the test is computed rather than judged.
|
|
105
192
|
const THIRD_PARTY_WRITE_REASON =
|
|
106
|
-
|
|
107
|
-
'
|
|
108
|
-
'
|
|
109
|
-
'
|
|
110
|
-
'(`prompts/collaboration-workflow/upstream-interrupt.md`).'
|
|
193
|
+
"⛔ third-party write: this `gh` call writes to another owner's repository, or one it cannot " +
|
|
194
|
+
'read (a GraphQL mutation, an unreadable `-R`) — Tier C. Check `pnpm josh repo:party ' +
|
|
195
|
+
'<owner/repo>`; first-party, use a REST `repos/<owner>/<repo>` path. Else record it on our ' +
|
|
196
|
+
'Issue and draft it for a person to post. Fires on every occurrence (`upstream-interrupt.md`).'
|
|
111
197
|
|
|
112
198
|
// `decide` returns true so it refuses every occurrence; it declares no `keeps` — not writing to
|
|
113
199
|
// another owner's tracker is the absence of a call, not a call, so the row is reported unmeasured
|
|
@@ -121,8 +207,9 @@ const ROW = {
|
|
|
121
207
|
title: 'Third-party write',
|
|
122
208
|
topic: '`upstream-interrupt.md`',
|
|
123
209
|
fires:
|
|
124
|
-
'a `gh api` write (field flag or a write method) to a repository whose owner is not this session. Every occurrence',
|
|
125
|
-
quiet:
|
|
210
|
+
'a `gh api` write (field flag or a write method) or a `gh <group> <action>` write selected by `-R` / `GH_REPO` to a repository whose owner is not this session, or a `gh api graphql` call whose line names `mutation` or whose query the shell expands, outside the merge and administration rows. Every occurrence',
|
|
211
|
+
quiet:
|
|
212
|
+
'a read, a GraphQL query, or a first-party owner (pinned at session start, `pnpm josh repo:party`)',
|
|
126
213
|
},
|
|
127
214
|
}
|
|
128
215
|
|
|
@@ -12,7 +12,7 @@ import { shell_segments } from './shell-segments'
|
|
|
12
12
|
//
|
|
13
13
|
// **Once per run.** The rule allows one re-run when the record cannot answer, so the reissue goes
|
|
14
14
|
// through. On that reissue `lane-direct-tool` still refuses a lane child's `time`-prefixed heavy tool
|
|
15
|
-
// (`git_argv` skips the timer) and points it at `pnpm josh reserved-run`, the overlap
|
|
15
|
+
// (`git_argv` skips the timer), never wrapping it, and points it at `pnpm josh reserved-run`, the overlap
|
|
16
16
|
// `delivered-rules.ts` admits. A `hyperfine "<command>"` carries the tool inside a quoted argument,
|
|
17
17
|
// which `lane-direct-tool` does not read, so in a lane that reissue is not budgeted.
|
|
18
18
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
2
|
+
import { time_transcript_line, type Block } from '#scripts/time-runtime/time-transcript-line'
|
|
3
|
+
import { bash_triggers } from './bash-triggers'
|
|
4
|
+
import { tail_commands } from './tail-commands'
|
|
5
|
+
|
|
6
|
+
// The filings a turn made, read off the session transcript for the `Stop` hook's offer to file
|
|
7
|
+
// (`stop-guard.ts`). **No new predicate**: the filing is `bash_triggers.is_issue_filing`, reused
|
|
8
|
+
// verbatim. The filing cap is not this count — it is `issue:file`'s own step, per originating work item
|
|
9
|
+
// (`scripts/issue/issue-file-cap.ts`, joshuafolkken/kit#4750).
|
|
10
|
+
//
|
|
11
|
+
// **A guard-refused filing does not count.** Claude Code writes a denied call to the transcript as a
|
|
12
|
+
// `tool_use` block with an errored `tool_result` — the same exclusion `investigation-reads.ts` makes
|
|
13
|
+
// for a refused read. **Nor does one `issue:file` held itself**: a lint problem or an unacknowledged
|
|
14
|
+
// duplicate exits non-zero having filed nothing. The filing is counted only where its result did not
|
|
15
|
+
// fail.
|
|
16
|
+
|
|
17
|
+
interface TailFilings {
|
|
18
|
+
// The `tool_use` id of every filing on the tail.
|
|
19
|
+
filing_ids: Array<string>
|
|
20
|
+
// The id of every result that came back as a failure — a guard refusal, or `issue:file` holding the
|
|
21
|
+
// filing itself (a lint problem, an unacknowledged duplicate), which files nothing either.
|
|
22
|
+
failures: Set<string>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function is_filing_use(block: Block): boolean {
|
|
26
|
+
if (!tail_commands.is_bash_use(block)) return false
|
|
27
|
+
|
|
28
|
+
return bash_triggers.is_issue_filing(time_shell.bash_command(block.input))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function collect_block(block: Block, found: TailFilings): void {
|
|
32
|
+
if (block.result_id !== '' && block.is_error === true) found.failures.add(block.result_id)
|
|
33
|
+
if (is_filing_use(block)) found.filing_ids.push(block.id)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function collect_line(line: string, found: TailFilings): void {
|
|
37
|
+
const parsed = time_transcript_line.parse_line(line)
|
|
38
|
+
|
|
39
|
+
if (parsed === undefined) return
|
|
40
|
+
|
|
41
|
+
for (const block of parsed.blocks) collect_block(block, found)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function scan_tail(tail: string): TailFilings {
|
|
45
|
+
const found: TailFilings = { filing_ids: [], failures: new Set<string>() }
|
|
46
|
+
|
|
47
|
+
for (const line of tail.split('\n')) collect_line(line, found)
|
|
48
|
+
|
|
49
|
+
return found
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// How many Issues the tail filed, counting only filings whose result did not fail.
|
|
53
|
+
function filing_count(tail: string): number {
|
|
54
|
+
const { filing_ids, failures } = scan_tail(tail)
|
|
55
|
+
|
|
56
|
+
return filing_ids.filter((id) => !failures.has(id)).length
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// A person's prompt: a `user` line carrying no tool result. Tool results ride `user` lines too, so the
|
|
60
|
+
// absence of one is what marks the line as typed rather than returned.
|
|
61
|
+
function is_prompt_line(line: string): boolean {
|
|
62
|
+
const parsed = time_transcript_line.parse_line(line)
|
|
63
|
+
|
|
64
|
+
if (parsed?.type !== 'user') return false
|
|
65
|
+
|
|
66
|
+
return parsed.blocks.every((block) => block.result_id === '')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// The tail from the last prompt on, so a filing an earlier turn made does not answer for this one.
|
|
70
|
+
// A tail with no prompt on it is returned whole.
|
|
71
|
+
function current_turn(tail: string): string {
|
|
72
|
+
const lines = tail.split('\n')
|
|
73
|
+
const start = lines.findLastIndex((line) => is_prompt_line(line))
|
|
74
|
+
|
|
75
|
+
return lines.slice(Math.max(start, 0)).join('\n')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// How many Issues this turn has filed — `filing_count` read over `current_turn`.
|
|
79
|
+
function turn_filing_count(tail: string): number {
|
|
80
|
+
return filing_count(current_turn(tail))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const turn_filings = {
|
|
84
|
+
current_turn,
|
|
85
|
+
filing_count,
|
|
86
|
+
is_prompt_line,
|
|
87
|
+
turn_filing_count,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { turn_filings }
|
|
@@ -25,6 +25,14 @@ import { shell_segments } from './shell-segments'
|
|
|
25
25
|
// stash with `git stash apply`, and the lane parked on how to apply it instead of popping by message;
|
|
26
26
|
// the reason now says the substitution is the run's own to make (joshuafolkken/kit#3648).
|
|
27
27
|
//
|
|
28
|
+
// **The refusal names the way back for a single file.** A lane that refused `git checkout -- <file>`
|
|
29
|
+
// reverted its own edit by hand with `Edit` and left a line behind, so a green record landed on the
|
|
30
|
+
// wrong tree (joshuafolkken/kit#4988). The named restore writes HEAD's bytes over that one file, carries
|
|
31
|
+
// no body inline (`file-edits.md`), and no row refuses it. It reverses the file's unstaged diff, so a
|
|
32
|
+
// staged change (the user's) stays, `<path>` is read from the shell's directory like any pathspec,
|
|
33
|
+
// nothing is emptied before git runs (a `git show HEAD:<path> > <path>` redirect is), and an untracked
|
|
34
|
+
// path has no diff to reverse.
|
|
35
|
+
//
|
|
28
36
|
// **It fires on every occurrence**, for the reason `git-force.ts` does: discarding the working tree is
|
|
29
37
|
// destructive each time it is issued.
|
|
30
38
|
|
|
@@ -122,33 +130,40 @@ function is_unauthorized_worktree_change(command: string): boolean {
|
|
|
122
130
|
return shell_segments.commands_of(command).some((segment) => is_unauthorized_segment(segment))
|
|
123
131
|
}
|
|
124
132
|
|
|
125
|
-
// The instruction in the shape a refusal can carry:
|
|
126
|
-
//
|
|
127
|
-
//
|
|
133
|
+
// The instruction in the shape a refusal can carry: the authorized route — for one file, the restore,
|
|
134
|
+
// limited to this run's own edit (another's uncommitted change is never discarded); for a stash, the
|
|
135
|
+
// message form that is allowed. The refused command is the caller's own, so it is not listed back.
|
|
136
|
+
// The `headline:` opening is what `time-transcript-line.ts` names the guard by. `pnpm josh git` and
|
|
137
|
+
// `pnpm josh stash:pop` are invisible to this trigger, so a run that uses them is never refused.
|
|
138
|
+
const SINGLE_FILE_RESTORE = 'git diff -- <path> | git apply -R'
|
|
128
139
|
const WORKTREE_MUTATION_REASON =
|
|
129
|
-
|
|
130
|
-
|
|
140
|
+
"⛔ unauthorized working-tree change: undo only this run's edit: " +
|
|
141
|
+
`\`${SINGLE_FILE_RESTORE}\`. A documented flow stashes with ` +
|
|
142
|
+
'`pnpm josh stash:push "<message>"`; a handed-over ' +
|
|
131
143
|
'stash is `pnpm josh stash:pop "<message>"`; record the substitution on the Issue (Tier A) unless ' +
|
|
132
144
|
'the plan says why the owner keeps the stash: then stop and confirm. It fires on every occurrence ' +
|
|
133
145
|
'(`operating-rules.md`).'
|
|
146
|
+
// The opening before joshuafolkken/kit#4988, so `rule-value.ts` still credits a refusal it delivered.
|
|
147
|
+
const FORMER_OPENING = '⛔ unauthorized working-tree change: `git checkout --`, `git restore`'
|
|
134
148
|
|
|
135
149
|
const ROW = {
|
|
136
150
|
id: 'worktree-mutation',
|
|
137
151
|
is_trigger: bash_triggers.on_bash_command(is_unauthorized_worktree_change),
|
|
138
152
|
reason: WORKTREE_MUTATION_REASON,
|
|
153
|
+
former_reasons: [FORMER_OPENING],
|
|
139
154
|
decide: (): boolean => true,
|
|
140
155
|
about: {
|
|
141
156
|
title: 'Unauthorized work-tree mutation',
|
|
142
157
|
topic: '`operating-rules.md`',
|
|
143
158
|
fires:
|
|
144
159
|
'`git checkout -- <path>` / `git restore <path>` / forced `git clean -f` / an unauthorized `git stash` (bare, push without a message, positional pop). Every occurrence',
|
|
145
|
-
quiet:
|
|
146
|
-
'`git stash push -m`, `git stash list`, `pnpm josh git`, `pnpm josh stash:push`, `pnpm josh stash:pop`',
|
|
160
|
+
quiet: `\`git stash push -m\`, \`git stash list\`, \`pnpm josh git\`, \`pnpm josh stash:push\`, \`pnpm josh stash:pop\`, \`${SINGLE_FILE_RESTORE}\``,
|
|
147
161
|
},
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
const worktree_guard = {
|
|
151
165
|
ROW,
|
|
166
|
+
SINGLE_FILE_RESTORE,
|
|
152
167
|
WORKTREE_MUTATION_REASON,
|
|
153
168
|
is_unauthorized_worktree_change,
|
|
154
169
|
touches_worktree,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { lane_withdraw } from '#scripts/lane/lane-withdraw'
|
|
1
2
|
import { run_event_scope } from '#scripts/run/event/run-event-scope'
|
|
2
3
|
import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
|
|
3
4
|
import { run_stalled } from '#scripts/run/park/run-stalled'
|
|
@@ -10,8 +11,11 @@ const KIND = run_event_stream.EVENT_KIND
|
|
|
10
11
|
// waiting park does not name its issue twice.
|
|
11
12
|
const PARK_PREFIX = /^#\d+ (?:parked\s*)?/u
|
|
12
13
|
const PARENTHESES = /^\((?<inner>.*)\)$/u
|
|
13
|
-
// `#<N> withdrawn by
|
|
14
|
-
const WITHDRAW_PREFIX =
|
|
14
|
+
// `#<N> withdrawn by <who>: <reason>` — every withdrawer `lane-withdraw.ts` names.
|
|
15
|
+
const WITHDRAW_PREFIX = new RegExp(
|
|
16
|
+
String.raw`^#\d+ withdrawn by (?:${lane_withdraw.WITHDRAWER_NAMES.join('|')}):\s*`,
|
|
17
|
+
'u',
|
|
18
|
+
)
|
|
15
19
|
|
|
16
20
|
// `#<N> parked (needs-decision)` reads as the reason `needs-decision`; a bare park has none.
|
|
17
21
|
function park_reason(event: RunEvent): string {
|
|
@@ -107,9 +107,32 @@ const NO_CUT: Cut = {
|
|
|
107
107
|
rows: new Set(),
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// A line of printable ASCII alone takes a column a character, so `string-width` is spared it.
|
|
111
|
+
const PRINTABLE_ASCII = /^[ -~]*$/u
|
|
112
|
+
|
|
113
|
+
// The widths measured so far. A fit weighs a frame for every cut of its order, each repeating most of
|
|
114
|
+
// the last one's lines, and the next redraw draws nearly the same lines and cells again, so each is
|
|
115
|
+
// measured once (joshuafolkken/kit#5185). Let go whole once it holds `WIDTHS_KEPT`, so a long-running
|
|
116
|
+
// board does not keep every line it stopped drawing.
|
|
117
|
+
const WIDTHS_KEPT = 10_000
|
|
118
|
+
const widths = new Map<string, number>()
|
|
119
|
+
|
|
120
|
+
function measured(plain: string): number {
|
|
121
|
+
return PRINTABLE_ASCII.test(plain) ? plain.length : string_width(plain)
|
|
122
|
+
}
|
|
123
|
+
|
|
110
124
|
// The columns a line takes on screen: its color escapes take none, an emoji two.
|
|
111
125
|
function width_of(line: string): number {
|
|
112
|
-
|
|
126
|
+
const known = widths.get(line)
|
|
127
|
+
|
|
128
|
+
if (known !== undefined) return known
|
|
129
|
+
if (widths.size >= WIDTHS_KEPT) widths.clear()
|
|
130
|
+
|
|
131
|
+
const width = measured(stripVTControlCharacters(line))
|
|
132
|
+
|
|
133
|
+
widths.set(line, width)
|
|
134
|
+
|
|
135
|
+
return width
|
|
113
136
|
}
|
|
114
137
|
|
|
115
138
|
function height_of(line: string, columns: number): number {
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { process_identity } from '#scripts/josh/process-identity'
|
|
2
|
+
import { lane_process_table, type TableRead } from '#scripts/lane/lane-process-table'
|
|
3
|
+
import { run_event_filed } from '#scripts/run/event/run-event-filed'
|
|
4
|
+
import {
|
|
5
|
+
run_event_overrun,
|
|
6
|
+
type Longest,
|
|
7
|
+
type OverrunNote,
|
|
8
|
+
} from '#scripts/run/event/run-event-overrun'
|
|
9
|
+
import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
|
|
10
|
+
|
|
11
|
+
// What a done row says after its time (joshuafolkken/kit#4772, joshuafolkken/kit#4818): the Issues
|
|
12
|
+
// filed during its child's work, its lane's net minutes and what its overrun investigation came to —
|
|
13
|
+
// read off the stream's `filed` events and the overrun notes (`run-event-overrun.ts`). The child's own
|
|
14
|
+
// filings and the investigation's are kept apart by the event's recorded mark (joshuafolkken/kit#4880).
|
|
15
|
+
|
|
16
|
+
interface Found {
|
|
17
|
+
// Each filing of the child's own session as `header.link` takes it: `4768`, or `owner/repo#12` for
|
|
18
|
+
// one filed elsewhere. An event with no overrun mark is the child's.
|
|
19
|
+
filed: ReadonlyArray<string>
|
|
20
|
+
// Each filing of the lane's overrun investigation, read off its mark (joshuafolkken/kit#4880).
|
|
21
|
+
overrun_filed: ReadonlyArray<string>
|
|
22
|
+
// The lane's net minutes, from the notes; `undefined` where none said them.
|
|
23
|
+
minutes: number | undefined
|
|
24
|
+
// The child's latest overrun note.
|
|
25
|
+
overrun: OverrunNote | undefined
|
|
26
|
+
// The longest stage the overrun's start note carried (joshuafolkken/kit#4995), kept past its end note.
|
|
27
|
+
longest: Longest | undefined
|
|
28
|
+
// The latest note is the investigation's start and its session is alive; `undefined` where its start
|
|
29
|
+
// token could not be read, so neither its life nor its death is known.
|
|
30
|
+
is_investigating: boolean | undefined
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// By the child's number.
|
|
34
|
+
type FoundOf = ReadonlyMap<number, Found>
|
|
35
|
+
|
|
36
|
+
// Whether the process a start note names — its pid and start token — is still there, one this reader
|
|
37
|
+
// may not signal included, `undefined` where the note carries no start token; injected, so a test never
|
|
38
|
+
// probes one.
|
|
39
|
+
type IsLive = (pid: number, start: string | undefined) => boolean | undefined
|
|
40
|
+
|
|
41
|
+
const KIND = run_event_stream.EVENT_KIND
|
|
42
|
+
const NONE: Found = {
|
|
43
|
+
filed: [],
|
|
44
|
+
overrun_filed: [],
|
|
45
|
+
minutes: undefined,
|
|
46
|
+
overrun: undefined,
|
|
47
|
+
longest: undefined,
|
|
48
|
+
is_investigating: false,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// The child a filing was found during, the reference the board draws, and whether the overrun filed it.
|
|
52
|
+
type FiledEntry = readonly [number, string, boolean]
|
|
53
|
+
|
|
54
|
+
function filed_entry(event: RunEvent): ReadonlyArray<FiledEntry> {
|
|
55
|
+
const filed = event.kind === KIND.FILED ? run_event_filed.parse(event.text) : undefined
|
|
56
|
+
|
|
57
|
+
if (filed?.found_during === undefined) return []
|
|
58
|
+
|
|
59
|
+
return [
|
|
60
|
+
[Number(filed.found_during), filed.reference.replace(/^#/u, ''), filed.is_overrun === true],
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function with_filed(known: Found, reference: string, is_overrun: boolean): Found {
|
|
65
|
+
if (is_overrun) return { ...known, overrun_filed: [...known.overrun_filed, reference] }
|
|
66
|
+
|
|
67
|
+
return { ...known, filed: [...known.filed, reference] }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function overrun_note(event: RunEvent): OverrunNote | undefined {
|
|
71
|
+
return event.kind === KIND.NOTE ? run_event_overrun.parse(event.text) : undefined
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// The minutes a note carries, else the ones an earlier note did: an end note carries none.
|
|
75
|
+
function minutes_of(note: OverrunNote, known: number | undefined): number | undefined {
|
|
76
|
+
return 'minutes' in note ? (note.minutes ?? known) : known
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// A session that died before its end note turns no spinner, nor does a later process given its pid.
|
|
80
|
+
function noted(found: Found, note: OverrunNote, is_live: IsLive): Found {
|
|
81
|
+
return {
|
|
82
|
+
...found,
|
|
83
|
+
minutes: minutes_of(note, found.minutes),
|
|
84
|
+
overrun: note,
|
|
85
|
+
longest: note.kind === 'started' ? note.longest : found.longest,
|
|
86
|
+
is_investigating: note.kind === 'started' ? is_live(note.pid, note.start) : false,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function add_filed(found: Map<number, Found>, events: ReadonlyArray<RunEvent>): void {
|
|
91
|
+
const entries = events.flatMap((event) => filed_entry(event))
|
|
92
|
+
|
|
93
|
+
for (const [issue, reference, is_overrun] of entries) {
|
|
94
|
+
found.set(issue, with_filed(found.get(issue) ?? NONE, reference, is_overrun))
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Each child's latest overrun note decides what its row says.
|
|
99
|
+
function add_overrun(
|
|
100
|
+
found: Map<number, Found>,
|
|
101
|
+
events: ReadonlyArray<RunEvent>,
|
|
102
|
+
is_live: IsLive,
|
|
103
|
+
): void {
|
|
104
|
+
const notes = events.flatMap((event) => overrun_note(event) ?? [])
|
|
105
|
+
|
|
106
|
+
for (const note of notes) {
|
|
107
|
+
found.set(note.issue, noted(found.get(note.issue) ?? NONE, note, is_live))
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function found_of(events: ReadonlyArray<RunEvent>, is_live: IsLive): FoundOf {
|
|
112
|
+
const found = new Map<number, Found>()
|
|
113
|
+
|
|
114
|
+
add_filed(found, events)
|
|
115
|
+
add_overrun(found, events, is_live)
|
|
116
|
+
|
|
117
|
+
return found
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// The board's own probe, each start time answered from the read's own `ps` snapshot, so neither the
|
|
121
|
+
// read nor a redraw runs a `ps` of its own per note (joshuafolkken/kit#4263). The pid alone reads a
|
|
122
|
+
// later process given that pid as the session, so the start token decides; a note without one — a
|
|
123
|
+
// platform that could not read it — is known dead only once its pid is gone.
|
|
124
|
+
async function live_in(table: TableRead | undefined): Promise<IsLive> {
|
|
125
|
+
const rows = table === undefined ? undefined : await table()
|
|
126
|
+
const read = lane_process_table.start_reader(rows ?? [])
|
|
127
|
+
|
|
128
|
+
return (pid, start) => process_identity.is_present_process(pid, start, read)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const run_board_found = { found_of, live_in }
|
|
132
|
+
|
|
133
|
+
export { run_board_found }
|
|
134
|
+
export type { Found, FoundOf, IsLive }
|
|
@@ -3,6 +3,7 @@ import type { BudgetWait } from '#scripts/gate/core-wait'
|
|
|
3
3
|
import { MS_PER_MINUTE } from '#scripts/lib/timeouts'
|
|
4
4
|
import { run_board_estimate } from './run-board-estimate'
|
|
5
5
|
import { run_board_fit } from './run-board-fit'
|
|
6
|
+
import type { FoundOf } from './run-board-found'
|
|
6
7
|
import { run_board_fresh } from './run-board-fresh'
|
|
7
8
|
import { run_board_labels } from './run-board-labels'
|
|
8
9
|
import { run_board_layout, type BoardLayout, type BoardRow } from './run-board-layout'
|
|
@@ -92,6 +93,11 @@ interface BoardHeader {
|
|
|
92
93
|
usual?: UsualTimes | undefined
|
|
93
94
|
// How many lanes the run may hold at once, which the estimated finish stacks the waiting children on.
|
|
94
95
|
lane_limit?: number | undefined
|
|
96
|
+
// What each done row says after its time (`run-board-found.ts`); none where nothing was read.
|
|
97
|
+
found?: FoundOf | undefined
|
|
98
|
+
// Whether `JOSH_LANE_INVESTIGATION` is on; off, a merged row hides its minutes and investigation
|
|
99
|
+
// (joshuafolkken/kit#5132, joshuafolkken/kit#5194).
|
|
100
|
+
is_investigation_on: boolean
|
|
95
101
|
// The spinner's frame a running run and a running row turn, `undefined` where the output is not a
|
|
96
102
|
// terminal and they draw their still icons.
|
|
97
103
|
spinner: string | undefined
|
|
@@ -101,6 +107,8 @@ interface BoardHeader {
|
|
|
101
107
|
// An issue reference as the board draws it — `3450` or `owner/repo#12` — made a link where the
|
|
102
108
|
// terminal opens one.
|
|
103
109
|
link: (reference: string) => string
|
|
110
|
+
// A pull request's number, made a link to it where the terminal opens one (joshuafolkken/kit#4625).
|
|
111
|
+
pull_link: (number: number) => string
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
interface BoardCounts {
|
|
@@ -62,6 +62,7 @@ const WORDS = {
|
|
|
62
62
|
named: 'named order',
|
|
63
63
|
held: 'held by triage',
|
|
64
64
|
headroom: 'memory headroom',
|
|
65
|
+
usage_limit: 'usage limit',
|
|
65
66
|
untriaged: 'untriaged',
|
|
66
67
|
solo: 'runs alone',
|
|
67
68
|
solo_ahead: 'behind solo',
|
|
@@ -95,6 +96,7 @@ const WORDS = {
|
|
|
95
96
|
park: 'park',
|
|
96
97
|
note: 'note',
|
|
97
98
|
found_during: ' (found during {n})',
|
|
99
|
+
overrun: 'overrun investigation',
|
|
98
100
|
// What the run is doing now, where no stage of its own says it.
|
|
99
101
|
watching: 'watching',
|
|
100
102
|
pool_empty: 'pool empty',
|
|
@@ -188,6 +190,10 @@ const NOTES_ICON = '📌'
|
|
|
188
190
|
// A plan row the run filed leads its title with it, in place of a findings line naming it again
|
|
189
191
|
// (joshuafolkken/kit#4099).
|
|
190
192
|
const FILED_RUN_MARK = '✚'
|
|
193
|
+
// A merged row whose overrun investigation is running ends on it where no spinner turns
|
|
194
|
+
// (joshuafolkken/kit#4772), and leads its result once it ended (joshuafolkken/kit#4818): the
|
|
195
|
+
// investigate phase's own icon, for the same work.
|
|
196
|
+
const OVERRUN_MARK = PHASE_ICONS.investigate
|
|
191
197
|
const NOTE_ICONS: Readonly<Record<BoardNote['kind'], string>> = {
|
|
192
198
|
filed: '🆕',
|
|
193
199
|
park: STATE_ICONS.parked,
|
|
@@ -252,8 +258,10 @@ const STAGE_ICONS: Readonly<Partial<Record<string, string>>> = {
|
|
|
252
258
|
// running issue holds, 📋 the declared order, ✋ a pool held for a judgment, ❓ an issue nobody has
|
|
253
259
|
// judged, 🧍 a `run:solo` issue waiting for the running lanes, 🙅 a row behind it (#4294; 🚧 is a
|
|
254
260
|
// held check's) and 🔒 a row a running `run:solo` issue holds (#4391), chosen on the same rule as
|
|
255
|
-
// every row icon
|
|
261
|
+
// every row icon, and 🪫 the account's Claude usage limit until it resets (#4796). The rest are the
|
|
262
|
+
// board's own, shared rather than copied.
|
|
256
263
|
const WAIT_ICONS = {
|
|
264
|
+
usage_limit: '🪫',
|
|
257
265
|
path: '📂',
|
|
258
266
|
named: '📋',
|
|
259
267
|
held: '✋',
|
|
@@ -280,6 +288,7 @@ const WAIT_WORDS: ReadonlyArray<readonly [icon: string, word: keyof Words]> = [
|
|
|
280
288
|
[WAIT_ICONS.solo, 'solo'],
|
|
281
289
|
[WAIT_ICONS.solo_ahead, 'solo_ahead'],
|
|
282
290
|
[WAIT_ICONS.solo_running, 'solo_running'],
|
|
291
|
+
[WAIT_ICONS.usage_limit, 'usage_limit'],
|
|
283
292
|
[WAIT_ICONS.memory, 'headroom'],
|
|
284
293
|
[WAIT_ICONS.untriaged, 'untriaged'],
|
|
285
294
|
[WAIT_ICONS.blocker, 'waits'],
|
|
@@ -366,6 +375,7 @@ const run_board_labels = {
|
|
|
366
375
|
NOTES_ICON,
|
|
367
376
|
NOTE_ICONS,
|
|
368
377
|
NOW_ICONS,
|
|
378
|
+
OVERRUN_MARK,
|
|
369
379
|
PHASE_ICONS,
|
|
370
380
|
PHASE_WORDS,
|
|
371
381
|
SPINNER_INTERVAL_MS,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// The issue numbers on `run:board` open their GitHub issue: each is wrapped in
|
|
2
2
|
// an OSC 8 terminal hyperlink, so VSCode's terminal opens it on Cmd+click while the visible text stays
|
|
3
3
|
// the number. A reference is drawn the way the plan names it — `3450` for this repository's issue,
|
|
4
|
-
// `owner/repo#12` for one elsewhere — and links to the repository it names.
|
|
4
|
+
// `owner/repo#12` for one elsewhere — and links to the repository it names. A followup row's pull
|
|
5
|
+
// request number opens its pull request the same way (joshuafolkken/kit#4625).
|
|
5
6
|
//
|
|
6
7
|
// The columns are padded on the text before it is linked: the escape draws nothing, but `padEnd`
|
|
7
8
|
// counts it. Whether a terminal gets the escape at all is the `link` port's answer.
|
|
@@ -18,6 +19,11 @@ function issue_url(reference: string, repo: string): string {
|
|
|
18
19
|
return `${GITHUB_URL_PREFIX}${target}/issues/${number}`
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
// A pull request of `repo` (joshuafolkken/kit#4625).
|
|
23
|
+
function pull_url(number: number, repo: string): string {
|
|
24
|
+
return `${GITHUB_URL_PREFIX}${repo}/pull/${String(number)}`
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
// A board with no plan read yet knows no repository, so its references stay plain text.
|
|
22
28
|
function linker(repo: string | undefined, link: Link): (reference: string) => string {
|
|
23
29
|
if (repo === undefined) return (reference) => reference
|
|
@@ -25,7 +31,14 @@ function linker(repo: string | undefined, link: Link): (reference: string) => st
|
|
|
25
31
|
return (reference) => link(reference, issue_url(reference, repo))
|
|
26
32
|
}
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
// A pull request's number linked to it, plain text on the same rule as `linker`.
|
|
35
|
+
function pull_linker(repo: string | undefined, link: Link): (number: number) => string {
|
|
36
|
+
if (repo === undefined) return String
|
|
37
|
+
|
|
38
|
+
return (number) => link(String(number), pull_url(number, repo))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const run_board_link = { issue_url, linker, pull_linker, pull_url }
|
|
29
42
|
|
|
30
43
|
export { run_board_link }
|
|
31
44
|
export type { Link }
|