@joshuafolkken/kit 1.1784.0 → 1.2114.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 +59 -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 +415 -389
- 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 +15 -8
- 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,4 +1,7 @@
|
|
|
1
|
+
import { gh_author_association, type AuthorFields } from '#scripts/gh/gh-author-association'
|
|
1
2
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
3
|
+
import { parse_json_object_or_undefined } from '#scripts/git/parse-json-array'
|
|
4
|
+
import { z } from 'zod'
|
|
2
5
|
|
|
3
6
|
// One text written to an issue: **into the body when the body is blank, as a comment otherwise.**
|
|
4
7
|
// Two writers make this decision — `followup`'s completion notice and `issue:plan`'s plan — and a copy
|
|
@@ -6,6 +9,11 @@ import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
|
6
9
|
//
|
|
7
10
|
// A body that could not be read is not blank: overwriting a body nobody saw could erase a person's
|
|
8
11
|
// text, so an unreadable body falls to a comment, which loses nothing.
|
|
12
|
+
//
|
|
13
|
+
// **A blank body filed by an author without write access is not written into either**
|
|
14
|
+
// (joshuafolkken/kit#4663). Readers judge a body by the issue's author, not by who last edited it, so
|
|
15
|
+
// a trusted `kickoff` plan written there would read as untrusted text, and `run:entry` — which waits
|
|
16
|
+
// for a trusted comment on such an issue — would never see the plan it waits for.
|
|
9
17
|
|
|
10
18
|
type Destination = 'body' | 'comment'
|
|
11
19
|
|
|
@@ -14,15 +22,41 @@ interface PostOutcome {
|
|
|
14
22
|
url: string
|
|
15
23
|
}
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
const BODY_FIELDS = `body,${gh_author_association.AUTHOR_FIELDS}`
|
|
26
|
+
|
|
27
|
+
const body_schema = z.looseObject({
|
|
28
|
+
body: z.string().nullish(),
|
|
29
|
+
...gh_author_association.author_fields_schema,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
function is_blank_body(body: string | null | undefined): boolean {
|
|
18
33
|
return body?.trim().length === 0
|
|
19
34
|
}
|
|
20
35
|
|
|
36
|
+
// The write-access lookup asks *this* repository's collaborators, which says nothing about access to
|
|
37
|
+
// another one — so an issue elsewhere is asked with no login, which `trust_of` answers for `OWNER`
|
|
38
|
+
// alone (the rule `auto-ok-author.ts` applies to an epic child in another repository).
|
|
39
|
+
async function is_author_trusted(row: AuthorFields, repo?: string): Promise<boolean> {
|
|
40
|
+
const author = gh_author_association.author_of(row)
|
|
41
|
+
|
|
42
|
+
return await gh_author_association.is_trusted(
|
|
43
|
+
repo === undefined ? author : { ...author, login: undefined },
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Whether the body is blank *and* its author has write access — a failed read is neither.
|
|
48
|
+
async function is_writable_body(issue_number: string, repo?: string): Promise<boolean> {
|
|
49
|
+
const json = await git_gh_command.issue_view_json(issue_number, BODY_FIELDS, repo)
|
|
50
|
+
const parsed = json === undefined ? undefined : parse_json_object_or_undefined(json, body_schema)
|
|
51
|
+
|
|
52
|
+
if (parsed === undefined || !is_blank_body(parsed.body ?? '')) return false
|
|
53
|
+
|
|
54
|
+
return await is_author_trusted(parsed, repo)
|
|
55
|
+
}
|
|
56
|
+
|
|
21
57
|
// `repo` (`owner/name`) addresses an issue in another repository; left out, the checkout's own.
|
|
22
58
|
async function post(issue_number: string, text: string, repo?: string): Promise<PostOutcome> {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (is_blank_body(current_body)) {
|
|
59
|
+
if (await is_writable_body(issue_number, repo)) {
|
|
26
60
|
const url = await git_gh_command.issue_edit_body(issue_number, text, repo)
|
|
27
61
|
|
|
28
62
|
return { destination: 'body', url }
|
|
@@ -129,8 +129,7 @@ function read_targets(args: ReadonlyArray<string>): ReadonlyArray<CiteTarget> |
|
|
|
129
129
|
return parse_targets(parsed.positionals, parsed.values.repo)
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// The lines `issue:cite` prints for `args`,
|
|
133
|
-
// (`stop-actions.ts`). `undefined` for a line nobody can read.
|
|
132
|
+
// The lines `issue:cite` prints for `args`, or `undefined` for a line nobody can read.
|
|
134
133
|
async function cite(args: ReadonlyArray<string>): Promise<CiteReport | undefined> {
|
|
135
134
|
const targets = read_targets(args)
|
|
136
135
|
if (targets === undefined) return undefined
|
|
@@ -159,7 +158,6 @@ async function run(args: ReadonlyArray<string>): Promise<number> {
|
|
|
159
158
|
|
|
160
159
|
const issue_cite_cli = {
|
|
161
160
|
USAGE,
|
|
162
|
-
cite,
|
|
163
161
|
parse_targets,
|
|
164
162
|
run,
|
|
165
163
|
}
|
|
@@ -56,6 +56,7 @@ function problems(body: string): ReadonlyArray<string> {
|
|
|
56
56
|
bug_classification_problem(body),
|
|
57
57
|
label_conflict(body),
|
|
58
58
|
defect_origin_line.problem(body),
|
|
59
|
+
defect_origin_line.reproduction_problem(body),
|
|
59
60
|
]
|
|
60
61
|
|
|
61
62
|
return found.filter((problem) => problem !== undefined)
|
|
@@ -88,6 +88,13 @@ async function read_closing_pr(issue: string): Promise<string | undefined> {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
// The closing pull request's number, read off the URL `read_closing_pr` answers.
|
|
92
|
+
async function read_closing_number(issue: number): Promise<number | undefined> {
|
|
93
|
+
const url = await read_closing_pr(String(issue))
|
|
94
|
+
|
|
95
|
+
return url === undefined ? undefined : Number(url.slice(url.lastIndexOf('/') + 1))
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const issue_closing_pr = { read_closing_number, read_closing_pr }
|
|
92
99
|
|
|
93
100
|
export { issue_closing_pr }
|
|
@@ -94,7 +94,9 @@ async function run(argv: ReadonlyArray<string>, exit: EvidenceExit): Promise<num
|
|
|
94
94
|
: FAILURE_EXIT_CODE
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
// The writes alone, for evidence composed in process — `backlog:drive`'s measured close
|
|
98
|
+
// (`backlog-measure-close.ts`), which holds no tree of the issue's, so there is nothing to release.
|
|
99
|
+
const issue_evidence_exit = { run, write: write_exit }
|
|
98
100
|
|
|
99
|
-
export type { EvidenceExit }
|
|
101
|
+
export type { EvidenceExit, EvidenceRequest }
|
|
100
102
|
export { issue_evidence_exit }
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { run_hold_member } from '#scripts/run/hold/run-hold-member'
|
|
2
|
+
import { issue_file_fold } from './issue-file-fold'
|
|
3
|
+
import { session_cite } from './session-cite'
|
|
4
|
+
|
|
5
|
+
// The automatic-filing cap, asked by `josh issue:file` itself as the fold and the WIP cap are.
|
|
6
|
+
//
|
|
7
|
+
// **Ten filings per originating work item, refused at the eleventh** (joshuafolkken/kit#4750). The
|
|
8
|
+
// origin is the fold's finder — the `--found-during` the filing names, else the lane child's mark, else
|
|
9
|
+
// the Issue the checkout's branch names — so a lane's filings, a long lane the parent investigated and
|
|
10
|
+
// the Issue a prerequisite came out of are each their own count. The count is the origin's `filed`
|
|
11
|
+
// events on the repository's event stream, read whole, so it outlives a session cut; a transcript tail
|
|
12
|
+
// counted every origin a long session touched against one ceiling and forgot each filing once it
|
|
13
|
+
// scrolled out (joshuafolkken/kit#2119).
|
|
14
|
+
//
|
|
15
|
+
// **Only a run's filings are automatic**: the cap holds in a run's session — a lane child or the
|
|
16
|
+
// hold's owner — and counts the filings marked as a run's, so a person filing from their own session
|
|
17
|
+
// is the further Issue the refusal leaves to them. **A filing with no origin counts against the
|
|
18
|
+
// invocation running** — the carry record's scope the fold reads for it too — so a retrospective's or a
|
|
19
|
+
// parent's own filings share one count per run. **A failed filing never counts**: `issue:file` appends
|
|
20
|
+
// its `filed` event only once the Issue exists.
|
|
21
|
+
|
|
22
|
+
const FILING_CAP = 10
|
|
23
|
+
|
|
24
|
+
// How many Issues the origin has already filed from a run.
|
|
25
|
+
async function prior_count(origin: string | undefined): Promise<number> {
|
|
26
|
+
const events = await issue_file_fold.events_of(origin)
|
|
27
|
+
|
|
28
|
+
return issue_file_fold.finder_filings(events, origin).filter((filed) => filed.is_run === true)
|
|
29
|
+
.length
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function owner_of(origin: string | undefined): string {
|
|
33
|
+
return origin === undefined ? 'this run (no originating Issue)' : session_cite.issue(origin)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function reason_of(origin: string | undefined): string {
|
|
37
|
+
return (
|
|
38
|
+
`✖ filing cap: ${owner_of(origin)} has already filed ${String(FILING_CAP)} Issues, the ceiling ` +
|
|
39
|
+
"per originating work item. Stop filing and report; a further Issue is a person's to file from " +
|
|
40
|
+
'their own session (`.claude/skills/workflow-commands/prerequisite.md`).'
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Whether the filing may go on: `false`, with the reason printed, once a run's filing finds its
|
|
45
|
+
// origin's count at the cap — this filing would be the eleventh.
|
|
46
|
+
async function is_cap_clear(named: string | undefined): Promise<boolean> {
|
|
47
|
+
if (!(await run_hold_member.is_run_member())) return true
|
|
48
|
+
const origin = await issue_file_fold.finder(named)
|
|
49
|
+
|
|
50
|
+
if ((await prior_count(origin)) < FILING_CAP) return true
|
|
51
|
+
console.error(reason_of(origin))
|
|
52
|
+
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const issue_file_cap = { FILING_CAP, is_cap_clear, reason_of }
|
|
57
|
+
|
|
58
|
+
export { issue_file_cap }
|
|
@@ -8,6 +8,7 @@ import { git_gh_exec } from '#scripts/gh/git-gh-exec'
|
|
|
8
8
|
import { git_gh_issue_list, MAX_SCANNED } from '#scripts/gh/git-gh-issue-list'
|
|
9
9
|
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
10
10
|
import { github_issue_url } from '#scripts/gh/github-issue-url'
|
|
11
|
+
import { lane_child_marker } from '#scripts/lane/lane-child-marker'
|
|
11
12
|
import { error_text } from '#scripts/lib/error-message'
|
|
12
13
|
import type { PollOptions } from '#scripts/lib/poll'
|
|
13
14
|
import { repository_labels } from '#scripts/repo/repository-labels'
|
|
@@ -15,37 +16,48 @@ import { run_event_filed } from '#scripts/run/event/run-event-filed'
|
|
|
15
16
|
import { run_event_stream } from '#scripts/run/event/run-event-stream'
|
|
16
17
|
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
17
18
|
import { run_hold_member } from '#scripts/run/hold/run-hold-member'
|
|
19
|
+
import { split_resolution } from '#scripts/split/split-resolution'
|
|
18
20
|
import { issue_auto_ok } from './issue-auto-ok'
|
|
19
21
|
import { issue_cite } from './issue-cite'
|
|
20
22
|
import { issue_file, type FileArguments } from './issue-file'
|
|
23
|
+
import { issue_file_cap } from './issue-file-cap'
|
|
24
|
+
import { issue_file_deferral } from './issue-file-deferral'
|
|
21
25
|
import { issue_file_fold } from './issue-file-fold'
|
|
26
|
+
import { issue_file_interrupt } from './issue-file-interrupt'
|
|
27
|
+
import { issue_file_lane_hint } from './issue-file-lane-hint'
|
|
22
28
|
import { issue_lint_cli } from './issue-lint-cli'
|
|
23
29
|
import { issue_priority } from './issue-priority'
|
|
24
30
|
import { issue_release_cli } from './issue-release-cli'
|
|
31
|
+
import { issue_sample_required } from './issue-sample-required'
|
|
25
32
|
import { issue_sample_source } from './issue-sample-source'
|
|
26
33
|
import { issue_scout_cli } from './issue-scout-cli'
|
|
27
34
|
import { issue_wip } from './issue-wip'
|
|
35
|
+
import { size_estimate } from './size-estimate'
|
|
28
36
|
|
|
29
37
|
// `josh issue:file "<title>" --body-file <path> [--route <route>] [--label <name>]…
|
|
30
|
-
// [--repo <owner/repo>] [--distinct <N,…>] [--over-cap] [--no-auto-ok]
|
|
31
|
-
// with every filing step run
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
// the
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
+
// [--repo <owner/repo>] [--distinct <N,…>] [--found-during <N>] [--over-cap] [--no-auto-ok]
|
|
39
|
+
// [--release] [--blocks-finder]` — file an Issue with every filing step run: the third-party refusal,
|
|
40
|
+
// the filing cap per origin and the fold question against the run's earlier filings, each ending the
|
|
41
|
+
// filing on its own; then, each tier printing every refusal of its own at once, the local checks —
|
|
42
|
+
// the body lint, the size estimate against the split guide, the start condition a measurement
|
|
43
|
+
// follow-up owes, the `## Origin` check for another repository, the `auto-ok` decision with the run
|
|
44
|
+
// label it owes; once those pass, the start condition read as a pull request and the WIP cap count;
|
|
45
|
+
// once those pass, the duplicate scout; then the missing workflow labels created, the create call
|
|
46
|
+
// carrying every label, a blocking interrupt's finder recorded as blocked by it, the release link on
|
|
47
|
+
// `--release`, and `epic:bundle`.
|
|
38
48
|
// A direct `gh api …/issues` filing is refused by the `direct-filing` delivered rule and pointed here.
|
|
39
49
|
|
|
40
50
|
const SUCCESS_EXIT_CODE = 0
|
|
41
51
|
const FAILURE_EXIT_CODE = 1
|
|
42
52
|
const ARGV_OFFSET = 2
|
|
43
53
|
const USAGE =
|
|
44
|
-
'Usage: josh issue:file "<title>" --body-file <path> [--route <tier-a|split|interrupt|review-cap>] [--label <name>]… [--repo <owner/repo>] [--distinct <N,…>] [--over-cap] [--no-auto-ok] [--release]'
|
|
54
|
+
'Usage: josh issue:file "<title>" --body-file <path> [--route <tier-a|split|interrupt|review-cap>] [--label <name>]… [--repo <owner/repo>] [--distinct <N,…>] [--found-during <N>] [--over-cap] [--no-auto-ok] [--release] [--blocks-finder]'
|
|
45
55
|
const UNKNOWN_REPO_MESSAGE =
|
|
46
56
|
'Could not read this repository from `git remote`, so the filing has no repository to compare against — check `gh auth status`.'
|
|
47
57
|
const THIRD_PARTY_MESSAGE =
|
|
48
58
|
'✖ third-party target: a tracker we do not own is Tier C — draft the Issue for a person to post instead (`CLAUDE.md` → "Third-party repositories are Tier C").'
|
|
59
|
+
const UNKNOWN_PARTY_MESSAGE =
|
|
60
|
+
'✖ unknown party: the owner of this session or of the target could not be read (`git remote` / `--repo`), so the target is not known to be ours — check `pnpm josh repo:party`.'
|
|
49
61
|
// `GH_REPO` is the variable `gh` reads `{owner}/{repo}` from, so setting it points every listing the
|
|
50
62
|
// scout and `epic:bundle` make at the target repository rather than at this checkout.
|
|
51
63
|
const GH_REPO_VARIABLE = 'GH_REPO'
|
|
@@ -68,18 +80,22 @@ async function read_body(path: string): Promise<string | undefined> {
|
|
|
68
80
|
}
|
|
69
81
|
}
|
|
70
82
|
|
|
71
|
-
|
|
83
|
+
// An owner that cannot be read is refused like a third party — stricter than the `third-party-write`
|
|
84
|
+
// hook, which stays silent on `unknown`: a filing is admitted only when the target is known to be ours.
|
|
85
|
+
function party_refusal(target: string): string | undefined {
|
|
72
86
|
const party = repo_party.classify(repo_party.current_owner(), repo_party.target_owner(target))
|
|
73
87
|
|
|
74
|
-
|
|
88
|
+
if (party === repo_party.FIRST_PARTY) return undefined
|
|
89
|
+
|
|
90
|
+
return party === repo_party.THIRD_PARTY ? THIRD_PARTY_MESSAGE : UNKNOWN_PARTY_MESSAGE
|
|
75
91
|
}
|
|
76
92
|
|
|
77
|
-
// Every refusal the
|
|
78
|
-
// the filing may go on to the scout.
|
|
93
|
+
// Every refusal the body and the arguments carry, read locally — `[]` when the body is admitted.
|
|
79
94
|
function refusals_of(filing: Filing): ReadonlyArray<string> {
|
|
80
|
-
if (is_third_party(filing.target)) return [THIRD_PARTY_MESSAGE]
|
|
81
95
|
const problems = [
|
|
82
96
|
...issue_lint_cli.problems(filing.body),
|
|
97
|
+
size_estimate.guide_problem(filing.body, filing.args.route),
|
|
98
|
+
issue_sample_required.problem(filing.body),
|
|
83
99
|
issue_auto_ok.declaration_problem(filing.body),
|
|
84
100
|
issue_priority.problem(filing.body, filing.args.labels),
|
|
85
101
|
issue_file.origin_problem(filing.body, filing.target, filing.current),
|
|
@@ -143,7 +159,8 @@ async function is_scout_clear(filing: Filing): Promise<boolean> {
|
|
|
143
159
|
|
|
144
160
|
if (outcome === undefined) return false
|
|
145
161
|
console.info(outcome.report)
|
|
146
|
-
const
|
|
162
|
+
const answered = issue_file.acknowledged(filing.args, filing.target, filing.current)
|
|
163
|
+
const open = issue_file.unacknowledged(outcome.candidates, answered)
|
|
147
164
|
|
|
148
165
|
if (open.length > 0) console.error(unacknowledged_message(open))
|
|
149
166
|
|
|
@@ -151,8 +168,8 @@ async function is_scout_clear(filing: Filing): Promise<boolean> {
|
|
|
151
168
|
}
|
|
152
169
|
|
|
153
170
|
// Every label the create call carries, or `undefined` when an `auto-ok` filing names neither run label.
|
|
154
|
-
//
|
|
155
|
-
//
|
|
171
|
+
// The decision reads the labels the body's declarations add, so a declared breaking change is excluded
|
|
172
|
+
// like its label.
|
|
156
173
|
function labels_of(filing: Filing): ReadonlyArray<string> | undefined {
|
|
157
174
|
const auto_ok = issue_auto_ok.decide({
|
|
158
175
|
is_opted_out: filing.args.is_auto_ok_opted_out,
|
|
@@ -229,33 +246,60 @@ async function place(url: string, target: string): Promise<void> {
|
|
|
229
246
|
|
|
230
247
|
// Every filing lands on the run's event stream: this is the one filing path, so
|
|
231
248
|
// one append here reaches `run:board` from every route. A filing outside a run lands too, unmarked as
|
|
232
|
-
// the run's (`run_hold_member`), and the board counts only the marked ones;
|
|
233
|
-
// as every emit is.
|
|
249
|
+
// the run's (`run_hold_member`), and the board counts only the marked ones; a lane's overrun
|
|
250
|
+
// investigation marks its own, which the board draws after 🔍; the append is best-effort, as every emit is.
|
|
251
|
+
async function emit_filed(
|
|
252
|
+
reference: string,
|
|
253
|
+
filing: Filing,
|
|
254
|
+
labels: ReadonlyArray<string>,
|
|
255
|
+
found_during: string | undefined,
|
|
256
|
+
): Promise<void> {
|
|
257
|
+
const kind = run_event_filed.kind_of(labels)
|
|
258
|
+
const is_run = await run_hold_member.is_run_member()
|
|
259
|
+
const is_overrun = lane_child_marker.is_overrun()
|
|
260
|
+
const { title } = filing.args
|
|
261
|
+
const text = run_event_filed.text_of({ reference, kind, title, found_during, is_run, is_overrun })
|
|
262
|
+
|
|
263
|
+
await run_event_stream_emit.emit(run_event_stream.EVENT_KIND.FILED, text)
|
|
264
|
+
}
|
|
265
|
+
|
|
234
266
|
async function record(url: string, filing: Filing, labels: ReadonlyArray<string>): Promise<void> {
|
|
235
267
|
const number = String(issue_number_of(url))
|
|
236
268
|
const reference = issue_cite.plain(
|
|
237
269
|
number,
|
|
238
270
|
issue_file_fold.reference_prefix(filing.target, filing.current),
|
|
239
271
|
)
|
|
240
|
-
const found_during = await issue_file_fold.finder()
|
|
241
|
-
const kind = run_event_filed.kind_of(labels)
|
|
242
|
-
const is_run = await run_hold_member.is_run_member()
|
|
243
|
-
const { title } = filing.args
|
|
244
|
-
const text = run_event_filed.text_of({ reference, kind, title, found_during, is_run })
|
|
272
|
+
const found_during = await issue_file_fold.finder(filing.args.found_during)
|
|
245
273
|
|
|
246
|
-
await
|
|
274
|
+
await emit_filed(reference, filing, labels, found_during)
|
|
275
|
+
await issue_file_deferral.note_finder({
|
|
276
|
+
found_during: filing.args.found_during,
|
|
277
|
+
reference,
|
|
278
|
+
title: filing.args.title,
|
|
279
|
+
current: filing.current,
|
|
280
|
+
})
|
|
281
|
+
await split_resolution.record_child({ route: filing.args.route, found_during, child: reference })
|
|
282
|
+
await issue_file_interrupt.block_finder({
|
|
283
|
+
route: filing.args.route,
|
|
284
|
+
is_blocking_finder: filing.args.is_blocking_finder,
|
|
285
|
+
found_during,
|
|
286
|
+
blocker: issue_number_of(url),
|
|
287
|
+
is_here: issue_file.is_same_repository(filing.target, filing.current),
|
|
288
|
+
})
|
|
247
289
|
}
|
|
248
290
|
|
|
249
|
-
function is_admitted(filing: Filing): boolean {
|
|
291
|
+
async function is_admitted(filing: Filing): Promise<boolean> {
|
|
250
292
|
const refusals = refusals_of(filing)
|
|
251
293
|
|
|
252
294
|
if (refusals.length === 0) return true
|
|
253
|
-
|
|
295
|
+
const hint = await issue_file_lane_hint.lines_of(filing.args.found_during, filing.body)
|
|
296
|
+
|
|
297
|
+
console.error([...refusals, ...hint].join('\n'))
|
|
254
298
|
|
|
255
299
|
return false
|
|
256
300
|
}
|
|
257
301
|
|
|
258
|
-
// The start condition's citation read against GitHub
|
|
302
|
+
// The start condition's citation read against GitHub.
|
|
259
303
|
async function is_source_clear(filing: Filing): Promise<boolean> {
|
|
260
304
|
const is_here = issue_file.is_same_repository(filing.target, filing.current)
|
|
261
305
|
const problem = await issue_sample_source.problem(
|
|
@@ -281,23 +325,46 @@ async function send(filing: Filing, labels: ReadonlyArray<string>): Promise<numb
|
|
|
281
325
|
return SUCCESS_EXIT_CODE
|
|
282
326
|
}
|
|
283
327
|
|
|
284
|
-
// The holds that
|
|
285
|
-
// stream
|
|
286
|
-
async function
|
|
328
|
+
// The holds that end the filing whatever the body says, read first: the filing cap reads the local
|
|
329
|
+
// event stream, the fold the stream and diff.
|
|
330
|
+
async function is_run_clear(filing: Filing): Promise<boolean> {
|
|
287
331
|
const prefix = issue_file_fold.reference_prefix(filing.target, filing.current)
|
|
288
332
|
|
|
289
|
-
|
|
333
|
+
return (
|
|
334
|
+
(await issue_file_cap.is_cap_clear(filing.args.found_during)) &&
|
|
335
|
+
(await issue_file_fold.is_fold_clear(prefix, filing.args))
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Every step the caller answers from the body and the arguments, cheapest first, each tier's refusals
|
|
340
|
+
// printed at once and fixed in one reissue: the local checks (the body's own refusals and the run
|
|
341
|
+
// label) before anything asks GitHub, then the start condition's citation and the WIP count, then the
|
|
342
|
+
// duplicate scout's search, run only once nothing else refuses. The labels, or `undefined` when any refused.
|
|
343
|
+
async function labels_in_one_pass(filing: Filing): Promise<ReadonlyArray<string> | undefined> {
|
|
344
|
+
const is_body_clear = await is_admitted(filing)
|
|
345
|
+
const labels = labels_of(filing)
|
|
346
|
+
|
|
347
|
+
if (!is_body_clear || labels === undefined) return undefined
|
|
348
|
+
const verdicts = [await is_source_clear(filing), await is_wip_clear(filing)]
|
|
290
349
|
|
|
291
|
-
|
|
350
|
+
if (!verdicts.every(Boolean)) return undefined
|
|
351
|
+
|
|
352
|
+
return (await is_scout_clear(filing)) ? labels : undefined
|
|
292
353
|
}
|
|
293
354
|
|
|
294
355
|
async function file(filing: Filing): Promise<number> {
|
|
295
|
-
|
|
296
|
-
const labels = labels_of(filing)
|
|
356
|
+
const party_problem = party_refusal(filing.target)
|
|
297
357
|
|
|
298
|
-
if (
|
|
358
|
+
if (party_problem !== undefined) {
|
|
359
|
+
console.error(party_problem)
|
|
299
360
|
|
|
300
|
-
|
|
361
|
+
return FAILURE_EXIT_CODE
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (!(await is_run_clear(filing))) return FAILURE_EXIT_CODE
|
|
365
|
+
const labels = await labels_in_one_pass(filing)
|
|
366
|
+
|
|
367
|
+
return labels === undefined ? FAILURE_EXIT_CODE : await send(filing, labels)
|
|
301
368
|
}
|
|
302
369
|
|
|
303
370
|
async function filing_of(args: FileArguments): Promise<Filing | string> {
|
|
@@ -336,7 +403,13 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
336
403
|
process.exitCode = await run(argv)
|
|
337
404
|
}
|
|
338
405
|
|
|
339
|
-
const issue_file_cli = {
|
|
406
|
+
const issue_file_cli = {
|
|
407
|
+
FRESH_ISSUE_POLL,
|
|
408
|
+
THIRD_PARTY_MESSAGE,
|
|
409
|
+
UNKNOWN_PARTY_MESSAGE,
|
|
410
|
+
record,
|
|
411
|
+
run,
|
|
412
|
+
}
|
|
340
413
|
|
|
341
414
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
342
415
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
2
|
+
import { shell_quote } from '#scripts/lib/shell-quote'
|
|
3
|
+
import { session_cite } from './session-cite'
|
|
4
|
+
|
|
5
|
+
// What `josh issue:file --found-during <N>` leaves on #N: one comment, `NOTE_PREFIX <filed> <title>`, so
|
|
6
|
+
// the deferral is read wherever #N is read. The run event alone reached neither `issue:read <N>` nor the
|
|
7
|
+
// ship reviewer's brief, so the reviewer raised the deferred gap again as a Medium and the ship
|
|
8
|
+
// stopped on scope the lane had already filed away (joshuafolkken/kit#4821). `review-rubric.md` →
|
|
9
|
+
// "Stop conditions" is the rule that reads the note.
|
|
10
|
+
//
|
|
11
|
+
// Only a finder the filing names is noted — a finder inferred from the lane mark or the branch is the
|
|
12
|
+
// run's, not a declared deferral. The finder is an Issue in this repository, so the comment is posted
|
|
13
|
+
// to `current` even when `GH_REPO` points the filing's listings at another target. The Issue already
|
|
14
|
+
// exists, so a failed comment is reported rather than failed, for the reason `issue-file-cli.ts` →
|
|
15
|
+
// `place` gives.
|
|
16
|
+
|
|
17
|
+
const NOTE_PREFIX = '先送り:'
|
|
18
|
+
|
|
19
|
+
interface Deferral {
|
|
20
|
+
found_during: string | undefined
|
|
21
|
+
reference: string
|
|
22
|
+
title: string
|
|
23
|
+
current: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function note_of(deferral: Deferral): string {
|
|
27
|
+
return `${NOTE_PREFIX} ${deferral.reference} ${deferral.title}`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function failure_line(finder: number, note: string): string {
|
|
31
|
+
const rerun = `pnpm josh issue:comment ${String(finder)} --body ${shell_quote.single_quoted(note)}`
|
|
32
|
+
|
|
33
|
+
return `⚠ the deferral note did not reach ${session_cite.issue(finder)} — run \`${rerun}\`.`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function note_finder(deferral: Deferral): Promise<void> {
|
|
37
|
+
const finder = Number(deferral.found_during)
|
|
38
|
+
|
|
39
|
+
if (!Number.isSafeInteger(finder) || finder <= 0) return
|
|
40
|
+
const note = note_of(deferral)
|
|
41
|
+
const is_noted = await git_gh_issue_write.issue_try_comment(
|
|
42
|
+
String(finder),
|
|
43
|
+
note,
|
|
44
|
+
deferral.current,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if (!is_noted) console.error(failure_line(finder, note))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const issue_file_deferral = { NOTE_PREFIX, note_finder }
|
|
51
|
+
|
|
52
|
+
export { issue_file_deferral }
|
|
@@ -28,6 +28,7 @@ const CLOSED_STATE = 'CLOSED'
|
|
|
28
28
|
interface FoldArguments {
|
|
29
29
|
route: string | undefined
|
|
30
30
|
distinct: ReadonlyArray<number>
|
|
31
|
+
found_during: string | undefined
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
function number_of(reference: string): number {
|
|
@@ -55,10 +56,12 @@ async function branch_issue(): Promise<number | undefined> {
|
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
// Whose work turned the finding up: the
|
|
59
|
-
// so a person's `fullrun` on `3423-x` is one finder across
|
|
60
|
-
// checkout on no Issue's branch — a `backlogrun` parent on
|
|
61
|
-
|
|
59
|
+
// Whose work turned the finding up: the `--found-during` the filing named, else the lane child's mark,
|
|
60
|
+
// else the Issue the checkout's branch names, so a person's `fullrun` on `3423-x` is one finder across
|
|
61
|
+
// its filings just as a lane child is. A checkout on no Issue's branch — a `backlogrun` parent on
|
|
62
|
+
// `main` — has none unless the filing names one.
|
|
63
|
+
async function finder(named?: string): Promise<string | undefined> {
|
|
64
|
+
if (named !== undefined) return named
|
|
62
65
|
const marked = lane_child_marker.marked_issue()
|
|
63
66
|
|
|
64
67
|
if (marked !== undefined) return marked
|
|
@@ -76,6 +79,17 @@ async function events_of(found_during: string | undefined): Promise<ReadonlyArra
|
|
|
76
79
|
return await run_event_stream_emit.all_events()
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
// The finder's filings on the events, in every repository.
|
|
83
|
+
function finder_filings(
|
|
84
|
+
events: ReadonlyArray<RunEvent>,
|
|
85
|
+
found_during: string | undefined,
|
|
86
|
+
): ReadonlyArray<Filed> {
|
|
87
|
+
return events
|
|
88
|
+
.filter((event) => event.kind === run_event_stream.EVENT_KIND.FILED)
|
|
89
|
+
.flatMap((event) => run_event_filed.parse(event.text) ?? [])
|
|
90
|
+
.filter((filed) => filed.found_during === found_during)
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
// This run's earlier filings by the same finder — so a parallel lane's filing is never what this one
|
|
80
94
|
// folds into — in the repository this filing targets. One the caller named in `--distinct` has been
|
|
81
95
|
// declared a separate deliverable and is left out, the same declaration the scout's candidates take.
|
|
@@ -85,10 +99,8 @@ function prior_filings(
|
|
|
85
99
|
prefix: string,
|
|
86
100
|
distinct: ReadonlyArray<number>,
|
|
87
101
|
): ReadonlyArray<Filed> {
|
|
88
|
-
return events
|
|
89
|
-
.filter((
|
|
90
|
-
.flatMap((event) => run_event_filed.parse(event.text) ?? [])
|
|
91
|
-
.filter((filed) => filed.found_during === found_during && prefix_of(filed.reference) === prefix)
|
|
102
|
+
return finder_filings(events, found_during)
|
|
103
|
+
.filter((filed) => prefix_of(filed.reference) === prefix)
|
|
92
104
|
.filter((filed) => !distinct.includes(number_of(filed.reference)))
|
|
93
105
|
}
|
|
94
106
|
|
|
@@ -136,7 +148,7 @@ function held_message(priors: ReadonlyArray<Filed>): string {
|
|
|
136
148
|
// exempt, as it is from the WIP cap: the split assessment already decided it is a separate deliverable.
|
|
137
149
|
async function is_fold_clear(prefix: string, args: FoldArguments): Promise<boolean> {
|
|
138
150
|
if (args.route === SPLIT_ROUTE_LABEL) return true
|
|
139
|
-
const found_during = await finder()
|
|
151
|
+
const found_during = await finder(args.found_during)
|
|
140
152
|
const filings = prior_filings(await events_of(found_during), found_during, prefix, args.distinct)
|
|
141
153
|
const priors = await open_filings(filings, prefix)
|
|
142
154
|
|
|
@@ -150,6 +162,13 @@ async function is_fold_clear(prefix: string, args: FoldArguments): Promise<boole
|
|
|
150
162
|
return verdict !== issue_fold.FOLD
|
|
151
163
|
}
|
|
152
164
|
|
|
153
|
-
const issue_file_fold = {
|
|
165
|
+
const issue_file_fold = {
|
|
166
|
+
events_of,
|
|
167
|
+
finder,
|
|
168
|
+
finder_filings,
|
|
169
|
+
is_fold_clear,
|
|
170
|
+
prior_filings,
|
|
171
|
+
reference_prefix,
|
|
172
|
+
}
|
|
154
173
|
|
|
155
174
|
export { issue_file_fold }
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { epic_relations } from '#scripts/epic/epic-relations'
|
|
2
|
+
import { git_gh_api_path } from '#scripts/gh/git-gh-api-path'
|
|
3
|
+
import { INTERRUPT_ROUTE_LABEL } from './issue-labels'
|
|
4
|
+
import { session_cite } from './session-cite'
|
|
5
|
+
|
|
6
|
+
// What `josh issue:file` just filed on `--route interrupt --blocks-finder`: the Issue whose work turned
|
|
7
|
+
// the defect up is recorded as blocked by it, in the same command as the filing — so a session that
|
|
8
|
+
// dies after the filing still leaves the dispatch a relation that keeps the finder back until the
|
|
9
|
+
// interrupt lands (`upstream-interrupt.md` → the run-machinery case). An interrupt that blocks nobody
|
|
10
|
+
// (`wip-cap.md` → the three conditions) omits the flag, since a relation there is a false dependency.
|
|
11
|
+
// Written through the relation path epic creation and `epic --add` use, and only for a filing in this
|
|
12
|
+
// repository: the relation write resolves both numbers here.
|
|
13
|
+
//
|
|
14
|
+
// The Issue already exists, so a failed write is reported rather than failed, for the reason
|
|
15
|
+
// `issue-file-cli.ts` → `place` gives.
|
|
16
|
+
|
|
17
|
+
interface InterruptFiling {
|
|
18
|
+
route: string | undefined
|
|
19
|
+
is_blocking_finder: boolean
|
|
20
|
+
found_during: string | undefined
|
|
21
|
+
blocker: number
|
|
22
|
+
is_here: boolean
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function is_issue_number(value: number): boolean {
|
|
26
|
+
return Number.isSafeInteger(value) && value > 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function finder_of(filing: InterruptFiling): number | undefined {
|
|
30
|
+
if (filing.route !== INTERRUPT_ROUTE_LABEL || !filing.is_here) return undefined
|
|
31
|
+
const finder = Number(filing.found_during)
|
|
32
|
+
|
|
33
|
+
return is_issue_number(finder) ? finder : undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// An explicit `--blocks-finder` that records nothing is said, so the caller does not read the
|
|
37
|
+
// silence as a recorded relation and leave the finder dispatchable.
|
|
38
|
+
function ignored_line(filing: InterruptFiling): string {
|
|
39
|
+
const reason =
|
|
40
|
+
filing.route === INTERRUPT_ROUTE_LABEL
|
|
41
|
+
? 'no finder and filed Issue pair in this repository was read'
|
|
42
|
+
: 'it applies to `--route interrupt` only'
|
|
43
|
+
|
|
44
|
+
return `⚠ --blocks-finder recorded nothing: ${reason}.`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The re-run writes the one relation and nothing else — no epic placement and no chain splice, which
|
|
48
|
+
// would record dependencies the interrupt does not have.
|
|
49
|
+
function failure_line(blocked: number, blocker: number): string {
|
|
50
|
+
const path = git_gh_api_path.blocked_by_api_path(String(blocked))
|
|
51
|
+
const id = `$(gh api ${git_gh_api_path.issue_api_path(String(blocker))} --jq .id)`
|
|
52
|
+
const cited = `${session_cite.issue(blocked)} could not be recorded as blocked by ${session_cite.issue(blocker)}`
|
|
53
|
+
|
|
54
|
+
return `⚠ ${cited} — run \`gh api ${path} -F issue_id=${id}\`.`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function record(blocked: number, blocker: number): Promise<void> {
|
|
58
|
+
const links = [{ blocked, blocker }]
|
|
59
|
+
const failures = await epic_relations.apply_relations(links, 'record')
|
|
60
|
+
|
|
61
|
+
if (failures === 0) {
|
|
62
|
+
console.info(epic_relations.format_relation_report({ links, failures, action: 'record' }))
|
|
63
|
+
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.error(failure_line(blocked, blocker))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function block_finder(filing: InterruptFiling): Promise<void> {
|
|
71
|
+
if (!filing.is_blocking_finder) return
|
|
72
|
+
const blocked = finder_of(filing)
|
|
73
|
+
|
|
74
|
+
if (blocked === undefined || !is_issue_number(filing.blocker)) {
|
|
75
|
+
console.warn(ignored_line(filing))
|
|
76
|
+
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await record(blocked, filing.blocker)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const issue_file_interrupt = { block_finder }
|
|
84
|
+
|
|
85
|
+
export { issue_file_interrupt }
|