@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,20 +1,47 @@
|
|
|
1
|
-
import { lstatSync, mkdirSync } from 'node:fs'
|
|
1
|
+
import { existsSync, lstatSync, mkdirSync, readdirSync, realpathSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { git_common_directory } from '#scripts/git/git-common-directory'
|
|
4
|
+
import { durable_state } from '#scripts/josh/durable-state'
|
|
4
5
|
import { OBSERVATION_LEDGER_DIRECTORY } from '#scripts/observations/observation-ledger'
|
|
5
6
|
import { agent_role_profile, type AgentProfile } from './agent-role-profile'
|
|
6
7
|
|
|
7
8
|
const AGENT_COMMAND = 'codex'
|
|
8
|
-
const AGENT_FLAGS: ReadonlyArray<string> = ['exec'
|
|
9
|
+
const AGENT_FLAGS: ReadonlyArray<string> = ['exec']
|
|
9
10
|
const MODEL_FLAG = '--model'
|
|
10
11
|
const CONFIG_FLAG = '-c'
|
|
11
12
|
const JSON_FLAG = '--json'
|
|
12
|
-
const NETWORK_CONFIG = 'sandbox_workspace_write.network_access=true'
|
|
13
13
|
const SQLITE_CACHE_PATH = ['node_modules', '.cache', 'josh', 'openai']
|
|
14
14
|
const EPHEMERAL_FLAG = '--ephemeral'
|
|
15
|
-
const ADD_DIRECTORY_FLAG = '--add-dir'
|
|
16
15
|
const GIT_DIRECTORY = '.git'
|
|
17
16
|
const LEDGER_DIRECTORY = path.dirname(OBSERVATION_LEDGER_DIRECTORY)
|
|
17
|
+
const WORKTREE_REGISTRY = 'worktrees'
|
|
18
|
+
const READ = 'read'
|
|
19
|
+
const WRITE = 'write'
|
|
20
|
+
|
|
21
|
+
// The sandbox is a Codex permission profile, not `--sandbox workspace-write` with `--add-dir` roots
|
|
22
|
+
// (joshuafolkken/kit#4653). It reads the whole disk and writes the work tree, the temp directories, the
|
|
23
|
+
// network and the common git directory — whose root a ref deletion needs: `git branch -d` and
|
|
24
|
+
// `git stash drop` rewrite `packed-refs` through `packed-refs.lock` there.
|
|
25
|
+
const PERMISSION_PROFILE = 'josh_lane'
|
|
26
|
+
const PROFILE_CONFIG = `default_permissions="${PERMISSION_PROFILE}"`
|
|
27
|
+
const NETWORK_CONFIG = `permissions.${PERMISSION_PROFILE}.network.enabled=true`
|
|
28
|
+
const FILESYSTEM_KEY = `permissions.${PERMISSION_PROFILE}.filesystem`
|
|
29
|
+
const BASE_GRANTS: ReadonlyArray<Grant> = [
|
|
30
|
+
[':root', READ],
|
|
31
|
+
[':workspace_roots', WRITE],
|
|
32
|
+
[':slash_tmp', WRITE],
|
|
33
|
+
[':tmpdir', WRITE],
|
|
34
|
+
]
|
|
35
|
+
// What git runs or follows to another directory stays read-only, so the sandbox cannot plant code that
|
|
36
|
+
// runs outside it the next time anything runs git: `hooks/` and `config`, and the `commondir` and
|
|
37
|
+
// `config.worktree` that would point a git directory at a planted one. An exact read-only path also
|
|
38
|
+
// refuses creating, renaming and deleting it (measured on codex-cli 0.156.1).
|
|
39
|
+
const PINNED_WORKTREE_ENTRIES: ReadonlyArray<string> = ['commondir', 'config.worktree']
|
|
40
|
+
const PINNED_ENTRIES: ReadonlyArray<string> = ['hooks', 'config', ...PINNED_WORKTREE_ENTRIES]
|
|
41
|
+
// Each registered work tree's git directory is pinned the same way; one registered after launch — a
|
|
42
|
+
// later lane, or the detached tree `josh test:red` and `josh metrics` add (`base-tree.ts`) — is not.
|
|
43
|
+
|
|
44
|
+
type Grant = readonly [string, string]
|
|
18
45
|
|
|
19
46
|
interface CodexArgv {
|
|
20
47
|
command: string
|
|
@@ -34,20 +61,49 @@ function persistence_arguments(profile: AgentProfile): ReadonlyArray<string> {
|
|
|
34
61
|
return profile.role === agent_role_profile.WORKER ? [] : [EPHEMERAL_FLAG]
|
|
35
62
|
}
|
|
36
63
|
|
|
37
|
-
|
|
64
|
+
// A granted directory is created up front — it would otherwise be created in a directory the sandbox
|
|
65
|
+
// cannot write — and refused when it is not a real directory, so a symlink cannot widen the grant.
|
|
66
|
+
function ensure_writable_directory(directory: string, mode?: number): void {
|
|
38
67
|
const current = lstatSync(directory, { throwIfNoEntry: false })
|
|
39
68
|
|
|
40
|
-
if (current === undefined) mkdirSync(directory, { recursive: true })
|
|
69
|
+
if (current === undefined) mkdirSync(directory, { recursive: true, mode })
|
|
41
70
|
else if (!current.isDirectory() || current.isSymbolicLink()) {
|
|
42
|
-
throw new Error(`
|
|
71
|
+
throw new Error(`Writable root must be a real directory: ${directory}`)
|
|
43
72
|
}
|
|
44
73
|
}
|
|
45
74
|
|
|
75
|
+
function pinned(directory: string, entries: ReadonlyArray<string>): ReadonlyArray<Grant> {
|
|
76
|
+
return entries.map((entry) => [path.join(directory, entry), READ])
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function registered_worktrees(common_directory: string): ReadonlyArray<string> {
|
|
80
|
+
const registry = path.join(common_directory, WORKTREE_REGISTRY)
|
|
81
|
+
if (!existsSync(registry)) return []
|
|
82
|
+
|
|
83
|
+
return readdirSync(registry, { withFileTypes: true })
|
|
84
|
+
.filter((entry) => entry.isDirectory())
|
|
85
|
+
.map((entry) => path.join(registry, entry.name))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Real paths, since the sandbox matches resolved paths: a `.git` reached through a symlink is granted
|
|
89
|
+
// where it lives, and an entry of it that is a symlink is not followed out of it.
|
|
90
|
+
function git_grants(common_directory: string | undefined): ReadonlyArray<Grant> {
|
|
91
|
+
if (common_directory === undefined) return []
|
|
92
|
+
|
|
93
|
+
const root = realpathSync(common_directory)
|
|
94
|
+
|
|
95
|
+
return [
|
|
96
|
+
[root, WRITE],
|
|
97
|
+
...pinned(root, PINNED_ENTRIES),
|
|
98
|
+
...registered_worktrees(root).flatMap((worktree) => pinned(worktree, PINNED_WORKTREE_ENTRIES)),
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
|
|
46
102
|
// Only the ledger's parent directory is writable outside a lane, never the primary checkout root.
|
|
47
|
-
function
|
|
103
|
+
function ledger_grants(
|
|
48
104
|
common_directory: string | undefined,
|
|
49
105
|
profile: AgentProfile,
|
|
50
|
-
): ReadonlyArray<
|
|
106
|
+
): ReadonlyArray<Grant> {
|
|
51
107
|
if (
|
|
52
108
|
common_directory === undefined ||
|
|
53
109
|
profile.role !== agent_role_profile.WORKER ||
|
|
@@ -56,27 +112,68 @@ function ledger_arguments(
|
|
|
56
112
|
return []
|
|
57
113
|
}
|
|
58
114
|
|
|
59
|
-
const
|
|
115
|
+
const ledger = path.join(path.dirname(common_directory), LEDGER_DIRECTORY)
|
|
116
|
+
|
|
117
|
+
ensure_writable_directory(ledger)
|
|
60
118
|
|
|
61
|
-
|
|
119
|
+
return [[realpathSync(ledger), WRITE]]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// An inline TOML table; a JSON string is a valid TOML basic string.
|
|
123
|
+
function filesystem_config(grants: ReadonlyArray<Grant>): string {
|
|
124
|
+
const pairs = grants.map(
|
|
125
|
+
([target, access]) => `${JSON.stringify(target)}=${JSON.stringify(access)}`,
|
|
126
|
+
)
|
|
62
127
|
|
|
63
|
-
return
|
|
128
|
+
return `${FILESYSTEM_KEY}={${pairs.join(',')}}`
|
|
64
129
|
}
|
|
65
130
|
|
|
66
|
-
|
|
131
|
+
// A `backlogrun` parent runs in the primary checkout, where no common git directory grant is given,
|
|
132
|
+
// so the run-state directory its lanes write through that grant is granted on its own — without it the
|
|
133
|
+
// parent's records would fall back to the temp root, apart from its lanes'.
|
|
134
|
+
function state_grants(cwd: string): ReadonlyArray<Grant> {
|
|
135
|
+
const repository = git_common_directory.repository(cwd)
|
|
136
|
+
if (repository === undefined) return []
|
|
137
|
+
|
|
138
|
+
const state = durable_state.root_for(repository)
|
|
139
|
+
|
|
140
|
+
ensure_writable_directory(state, durable_state.STATE_DIRECTORY_MODE)
|
|
141
|
+
|
|
142
|
+
return [[realpathSync(state), WRITE]]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function lane_grants(cwd: string | undefined, profile: AgentProfile): ReadonlyArray<Grant> {
|
|
146
|
+
if (cwd === undefined) return []
|
|
147
|
+
|
|
67
148
|
const common_directory = git_common_directory.resolve(cwd)
|
|
68
|
-
|
|
69
|
-
|
|
149
|
+
|
|
150
|
+
if (common_directory === undefined) return state_grants(cwd)
|
|
151
|
+
|
|
152
|
+
return [...git_grants(common_directory), ...ledger_grants(common_directory, profile)]
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function permission_arguments(
|
|
156
|
+
cwd: string | undefined,
|
|
157
|
+
profile: AgentProfile,
|
|
158
|
+
): ReadonlyArray<string> {
|
|
159
|
+
const grants = [...BASE_GRANTS, ...lane_grants(cwd, profile)]
|
|
70
160
|
|
|
71
161
|
return [
|
|
72
162
|
CONFIG_FLAG,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
163
|
+
PROFILE_CONFIG,
|
|
164
|
+
CONFIG_FLAG,
|
|
165
|
+
filesystem_config(grants),
|
|
166
|
+
CONFIG_FLAG,
|
|
167
|
+
NETWORK_CONFIG,
|
|
77
168
|
]
|
|
78
169
|
}
|
|
79
170
|
|
|
171
|
+
function lane_arguments(cwd: string | undefined, profile: AgentProfile): ReadonlyArray<string> {
|
|
172
|
+
if (cwd === undefined) return []
|
|
173
|
+
|
|
174
|
+
return [CONFIG_FLAG, sqlite_config(cwd), ...persistence_arguments(profile)]
|
|
175
|
+
}
|
|
176
|
+
|
|
80
177
|
function build(invocation: string, profile: AgentProfile, cwd?: string): CodexArgv {
|
|
81
178
|
return {
|
|
82
179
|
command: AGENT_COMMAND,
|
|
@@ -86,9 +183,8 @@ function build(invocation: string, profile: AgentProfile, cwd?: string): CodexAr
|
|
|
86
183
|
profile.model,
|
|
87
184
|
CONFIG_FLAG,
|
|
88
185
|
effort_config(profile),
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
...(cwd === undefined ? [] : lane_arguments(cwd, profile)),
|
|
186
|
+
...permission_arguments(cwd, profile),
|
|
187
|
+
...lane_arguments(cwd, profile),
|
|
92
188
|
JSON_FLAG,
|
|
93
189
|
invocation,
|
|
94
190
|
],
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// When a Claude usage limit resets, read off the harness's own limit sentence (joshuafolkken/kit#4745):
|
|
2
|
+
// `resets 10am (Asia/Tokyo)`, `resets 3:30pm (America/New_York)`, `resets Oct 25, 10am (Asia/Tokyo)`, or
|
|
3
|
+
// the older `Claude AI usage limit reached|<epoch seconds>`. The wall clock is turned into an instant in
|
|
4
|
+
// its named zone with the platform's `Intl`, so no time-zone table is kept here. A sentence that names
|
|
5
|
+
// no readable time, or an unknown zone, answers `undefined` — the caller re-checks on an interval.
|
|
6
|
+
|
|
7
|
+
const RESET_PATTERN = /resets (?<when>[^(]*)\((?<zone>[^)]*)\)/iu
|
|
8
|
+
const TIME_PATTERN = /\b(?<hour>\d{1,2})(?::(?<minute>\d{2}))? ?(?<meridiem>am|pm)\b/iu
|
|
9
|
+
const DATE_PATTERN = /\b(?<month>[a-z]+)\.? (?<day>\d{1,2})\b/iu
|
|
10
|
+
const MONTH_PREFIX = 3
|
|
11
|
+
const EPOCH_PATTERN = /\|(?<epoch>\d{10})\b/u
|
|
12
|
+
const MONTHS = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
|
|
13
|
+
const MS_PER_SECOND = 1000
|
|
14
|
+
const MS_PER_MINUTE = 60_000
|
|
15
|
+
const HALF_YEAR_MS = 15_778_800_000
|
|
16
|
+
const HOURS_PER_HALF_DAY = 12
|
|
17
|
+
const PM = 'pm'
|
|
18
|
+
const NOT_FOUND = -1
|
|
19
|
+
|
|
20
|
+
interface ZoneFields {
|
|
21
|
+
year: number
|
|
22
|
+
month: number
|
|
23
|
+
day: number
|
|
24
|
+
hour: number
|
|
25
|
+
minute: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface WallClock {
|
|
29
|
+
// The named date, where the sentence carries one — a weekly limit's reset can be days away.
|
|
30
|
+
date: Pick<ZoneFields, 'month' | 'day'> | undefined
|
|
31
|
+
hour: number
|
|
32
|
+
minute: number
|
|
33
|
+
zone: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type Groups = Readonly<Record<string, string | undefined>>
|
|
37
|
+
|
|
38
|
+
function epoch_ms(text: string): number | undefined {
|
|
39
|
+
const epoch = EPOCH_PATTERN.exec(text)?.groups?.['epoch']
|
|
40
|
+
|
|
41
|
+
return epoch === undefined ? undefined : Number(epoch) * MS_PER_SECOND
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// A word that is no month's name — `resets at 10am` — names no date.
|
|
45
|
+
function dated(groups: Groups): WallClock['date'] {
|
|
46
|
+
const month = MONTHS.indexOf(String(groups['month']).slice(0, MONTH_PREFIX).toLowerCase())
|
|
47
|
+
|
|
48
|
+
return month === NOT_FOUND ? undefined : { month, day: Number(groups['day']) }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function date_of(when: string): WallClock['date'] {
|
|
52
|
+
const groups = DATE_PATTERN.exec(when)?.groups
|
|
53
|
+
|
|
54
|
+
return groups === undefined ? undefined : dated(groups)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function hour_of(time: Groups): number {
|
|
58
|
+
const half = time['meridiem']?.toLowerCase() === PM ? HOURS_PER_HALF_DAY : 0
|
|
59
|
+
|
|
60
|
+
return (Number(time['hour']) % HOURS_PER_HALF_DAY) + half
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function wall_of(when: string, zone: string): WallClock | undefined {
|
|
64
|
+
const time = TIME_PATTERN.exec(when)?.groups
|
|
65
|
+
|
|
66
|
+
if (time === undefined) return undefined
|
|
67
|
+
|
|
68
|
+
return { date: date_of(when), hour: hour_of(time), minute: Number(time['minute'] ?? 0), zone }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function zone_format(zone: string): Intl.DateTimeFormat {
|
|
72
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
73
|
+
timeZone: zone,
|
|
74
|
+
hourCycle: 'h23',
|
|
75
|
+
year: 'numeric',
|
|
76
|
+
month: 'numeric',
|
|
77
|
+
day: 'numeric',
|
|
78
|
+
hour: 'numeric',
|
|
79
|
+
minute: 'numeric',
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// The wall clock the zone reads at an instant. Throws `RangeError` on a zone `Intl` does not know.
|
|
84
|
+
function zone_fields(at_ms: number, zone: string): ZoneFields {
|
|
85
|
+
const parts = zone_format(zone).formatToParts(at_ms)
|
|
86
|
+
const read = new Map(parts.map((part) => [part.type, Number(part.value)]))
|
|
87
|
+
|
|
88
|
+
function field(type: Intl.DateTimeFormatPartTypes): number {
|
|
89
|
+
return read.get(type) ?? 0
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
year: field('year'),
|
|
94
|
+
month: field('month') - 1,
|
|
95
|
+
day: field('day'),
|
|
96
|
+
hour: field('hour'),
|
|
97
|
+
minute: field('minute'),
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function utc_of(fields: ZoneFields): number {
|
|
102
|
+
return Date.UTC(fields.year, fields.month, fields.day, fields.hour, fields.minute)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// How far the zone's wall clock runs ahead of UTC at an instant, to the minute.
|
|
106
|
+
function offset_ms(at_ms: number, zone: string): number {
|
|
107
|
+
return utc_of(zone_fields(at_ms, zone)) - (at_ms - (at_ms % MS_PER_MINUTE))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// The instant the zone's wall clock reads `fields`, the offset read again at the first guess so a
|
|
111
|
+
// daylight-saving change between the two is followed.
|
|
112
|
+
function instant_of(fields: ZoneFields, zone: string): number {
|
|
113
|
+
const guess = utc_of(fields)
|
|
114
|
+
|
|
115
|
+
return guess - offset_ms(guess - offset_ms(guess, zone), zone)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// The years to move a named date in this year by so it lies within half a year of `now_ms`: a January
|
|
119
|
+
// date read in December is next year's, a December date read in January last year's.
|
|
120
|
+
function year_shift(at_ms: number, now_ms: number): number {
|
|
121
|
+
if (now_ms - at_ms > HALF_YEAR_MS) return 1
|
|
122
|
+
|
|
123
|
+
return at_ms - now_ms > HALF_YEAR_MS ? -1 : 0
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// A named date's nearest occurrence. One just past stays past, for the caller's re-check.
|
|
127
|
+
function dated_instant(fields: ZoneFields, zone: string, now_ms: number): number {
|
|
128
|
+
const at_ms = instant_of(fields, zone)
|
|
129
|
+
const shift = year_shift(at_ms, now_ms)
|
|
130
|
+
|
|
131
|
+
return shift === 0 ? at_ms : instant_of({ ...fields, year: fields.year + shift }, zone)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// An undated hour's next occurrence: today's, else the next day's.
|
|
135
|
+
function undated_instant(fields: ZoneFields, zone: string, now_ms: number): number {
|
|
136
|
+
const at_ms = instant_of(fields, zone)
|
|
137
|
+
|
|
138
|
+
return at_ms > now_ms ? at_ms : instant_of({ ...fields, day: fields.day + 1 }, zone)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function next_instant(wall: WallClock, now_ms: number): number {
|
|
142
|
+
const today = zone_fields(now_ms, wall.zone)
|
|
143
|
+
const fields = { ...today, ...wall.date, hour: wall.hour, minute: wall.minute }
|
|
144
|
+
|
|
145
|
+
if (wall.date === undefined) return undated_instant(fields, wall.zone, now_ms)
|
|
146
|
+
|
|
147
|
+
return dated_instant(fields, wall.zone, now_ms)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function wall_in(text: string): WallClock | undefined {
|
|
151
|
+
const groups = RESET_PATTERN.exec(text)?.groups
|
|
152
|
+
|
|
153
|
+
if (groups === undefined) return undefined
|
|
154
|
+
|
|
155
|
+
return wall_of(String(groups['when']), String(groups['zone']).trim())
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// A zone `Intl` does not know reads as no time.
|
|
159
|
+
function known_instant(wall: WallClock, now_ms: number): number | undefined {
|
|
160
|
+
try {
|
|
161
|
+
return next_instant(wall, now_ms)
|
|
162
|
+
} catch {
|
|
163
|
+
return undefined
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function clock_ms(text: string, now_ms: number): number | undefined {
|
|
168
|
+
const wall = wall_in(text)
|
|
169
|
+
|
|
170
|
+
return wall === undefined ? undefined : known_instant(wall, now_ms)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function reset_ms(text: string, now_ms: number): number | undefined {
|
|
174
|
+
return epoch_ms(text) ?? clock_ms(text, now_ms)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const usage_limit_reset = { reset_ms }
|
|
178
|
+
|
|
179
|
+
export { usage_limit_reset }
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { stripVTControlCharacters } from 'node:util'
|
|
2
|
+
import { token_shape } from '#scripts/lib/token-shape'
|
|
2
3
|
|
|
3
4
|
// What `claude setup-token` printed, split into the token and the text that may be shown: the token
|
|
4
5
|
// is replaced, so it reaches neither the screen nor a log.
|
|
5
6
|
|
|
6
|
-
const REDACTED =
|
|
7
|
+
const { REDACTED, ANTHROPIC_OAUTH_TOKEN: TOKEN_PATTERN } = token_shape
|
|
7
8
|
const TOKEN_START = 'sk-ant-oat'
|
|
8
|
-
const TOKEN_PATTERN = /sk-ant-oat\d+-[\w-]+/u
|
|
9
9
|
const EVERY_TOKEN_PATTERN = new RegExp(TOKEN_PATTERN.source, 'gu')
|
|
10
10
|
// A narrow terminal wraps the token onto lines of its own characters alone, so a continuation is a
|
|
11
11
|
// whole such line and the prose after the token never joins it.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { epic_graph, type EpicChild } from '#scripts/epic/epic-graph'
|
|
2
|
+
import { gh_author_association } from '#scripts/gh/gh-author-association'
|
|
3
|
+
import type { OpenIssueData } from '#scripts/git/git-schemas'
|
|
4
|
+
|
|
5
|
+
// Whether an unattended run may act on an opted-in issue's body. The run takes that body as its
|
|
6
|
+
// specification, and on a public repository anyone can file an issue — the `auto-ok` a person applied
|
|
7
|
+
// says nothing about a body its author rewrote after the label. So only an issue whose author has
|
|
8
|
+
// write access is runnable, and a lookup that failed is not trust; the rest wait on a person.
|
|
9
|
+
|
|
10
|
+
async function with_trust(issue: OpenIssueData): Promise<OpenIssueData> {
|
|
11
|
+
const author = gh_author_association.author_of(issue)
|
|
12
|
+
|
|
13
|
+
return { ...issue, author_trusted: await gh_author_association.is_trusted(author) }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function with_author_trust(
|
|
17
|
+
issues: ReadonlyArray<OpenIssueData>,
|
|
18
|
+
): Promise<Array<OpenIssueData>> {
|
|
19
|
+
return await Promise.all(issues.map(async (issue) => await with_trust(issue)))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function is_author_trusted(issue: OpenIssueData): boolean {
|
|
23
|
+
return issue.author_trusted === true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// An epic child's body is run just the same, so the same rule holds for it (joshuafolkken/kit#4633).
|
|
27
|
+
// The write-access lookup asks *this* repository's collaborators, which says nothing about access to
|
|
28
|
+
// another one — so a child elsewhere is asked with no login, which `trust_of` answers for `OWNER` alone.
|
|
29
|
+
async function is_child_trusted(child: EpicChild, repo: string): Promise<boolean> {
|
|
30
|
+
const author = gh_author_association.author_of(child)
|
|
31
|
+
|
|
32
|
+
return await gh_author_association.is_trusted(
|
|
33
|
+
child.repo === repo ? author : { ...author, login: undefined },
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The keys of the open children whose author is not trusted — a child read without author fields
|
|
38
|
+
// among them, since an unknown author is not a trusted one.
|
|
39
|
+
async function untrusted_child_keys(
|
|
40
|
+
children: ReadonlyArray<EpicChild>,
|
|
41
|
+
repo: string,
|
|
42
|
+
): Promise<ReadonlySet<string>> {
|
|
43
|
+
const open = children.filter((child) => child.state === 'OPEN')
|
|
44
|
+
const trusted = await Promise.all(open.map(async (child) => await is_child_trusted(child, repo)))
|
|
45
|
+
|
|
46
|
+
const untrusted = open.filter((_, index) => trusted[index] !== true)
|
|
47
|
+
|
|
48
|
+
return new Set(untrusted.map((child) => epic_graph.key_of(child)))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const auto_ok_author = { is_author_trusted, untrusted_child_keys, with_author_trust }
|
|
52
|
+
|
|
53
|
+
export { auto_ok_author }
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { auto_ok_author } from '#scripts/auto-ok/auto-ok-author'
|
|
1
2
|
import { epic_bundle_gaps } from '#scripts/epic/epic-bundle-gaps'
|
|
2
3
|
import { epic_index, type FetchedEpics } from '#scripts/epic/epic-index'
|
|
3
4
|
import { epic_issue } from '#scripts/epic/epic-issue'
|
|
@@ -9,7 +10,7 @@ import { read_json_listing } from '#scripts/git/parse-json-array'
|
|
|
9
10
|
import { git_next_issues } from '#scripts/issue/git-next-issues'
|
|
10
11
|
import { AUTO_OK_LABEL } from '#scripts/issue/issue-labels'
|
|
11
12
|
import { issue_not_before } from '#scripts/issue/issue-not-before'
|
|
12
|
-
import {
|
|
13
|
+
import { issue_sample_prime } from '#scripts/issue/issue-sample-prime'
|
|
13
14
|
import { session_cite } from '#scripts/issue/session-cite'
|
|
14
15
|
|
|
15
16
|
// `josh auto-ok:next` — which issue outside the epic an unattended run picks up next.
|
|
@@ -211,9 +212,13 @@ async function fetch_opted_in(): Promise<OptedInRead> {
|
|
|
211
212
|
|
|
212
213
|
const read = json === undefined ? await classify_failed_read() : parse_listing(json, is_capped)
|
|
213
214
|
|
|
214
|
-
if (read.kind
|
|
215
|
+
if (read.kind !== 'read') return read
|
|
215
216
|
|
|
216
|
-
|
|
217
|
+
const issues = await auto_ok_author.with_author_trust(read.issues)
|
|
218
|
+
|
|
219
|
+
await issue_sample_prime.prime(issues.map((issue) => issue.body))
|
|
220
|
+
|
|
221
|
+
return { ...read, issues }
|
|
217
222
|
}
|
|
218
223
|
|
|
219
224
|
// Whether every issue this one declares as a blocker has closed. `blockedBy` is the same native
|
|
@@ -330,6 +335,16 @@ async function fetch_tracking(count: number): Promise<TrackingRead> {
|
|
|
330
335
|
// by the native `blockedBy` relations `is_unblocked` already refuses to run past.
|
|
331
336
|
// `tracked` is the narrowed set `epic_index.withheld_children` builds, not
|
|
332
337
|
// every tracked child; this function only applies it.
|
|
338
|
+
// What the issue itself must hold: an author with write access (`auto-ok-author.ts`), every blocker
|
|
339
|
+
// closed, and its declared start date reached.
|
|
340
|
+
function is_ready(issue: OpenIssueData, now: number): boolean {
|
|
341
|
+
return (
|
|
342
|
+
auto_ok_author.is_author_trusted(issue) &&
|
|
343
|
+
is_unblocked(issue) &&
|
|
344
|
+
issue_not_before.is_due(issue.body, now)
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
|
|
333
348
|
function is_runnable(
|
|
334
349
|
issue: OpenIssueData,
|
|
335
350
|
tracked: ReadonlyMap<number, number>,
|
|
@@ -338,11 +353,7 @@ function is_runnable(
|
|
|
338
353
|
): boolean {
|
|
339
354
|
if (tracked.has(issue.number)) return false
|
|
340
355
|
|
|
341
|
-
return (
|
|
342
|
-
is_unblocked(issue) &&
|
|
343
|
-
!exclude.includes(issue.number) &&
|
|
344
|
-
issue_not_before.is_due(issue.body, now)
|
|
345
|
-
)
|
|
356
|
+
return !exclude.includes(issue.number) && is_ready(issue, now)
|
|
346
357
|
}
|
|
347
358
|
|
|
348
359
|
function pick_next(
|
|
@@ -359,7 +370,7 @@ function pick_next(
|
|
|
359
370
|
function none_reason(count: number): string {
|
|
360
371
|
if (count === 0) return NONE_OPTED_IN_MESSAGE
|
|
361
372
|
|
|
362
|
-
return `All ${String(count)} open \`${AUTO_OK_LABEL}\` issue(s) are excluded — tracked by an opted-in epic, an epic itself, already in progress, parked, blocked by an open issue, not due until its start time, or the one just merged.`
|
|
373
|
+
return `All ${String(count)} open \`${AUTO_OK_LABEL}\` issue(s) are excluded — tracked by an opted-in epic, an epic itself, already in progress, parked, filed by an author without write access (waiting on a person), blocked by an open issue, not due until its start time, or the one just merged.`
|
|
363
374
|
}
|
|
364
375
|
|
|
365
376
|
// Said only when the cap actually bit, and worded from the answer rather than before it: the one run
|
|
@@ -15,7 +15,7 @@ const UNMEASURED_MESSAGE =
|
|
|
15
15
|
const KIND_RANK: Readonly<Record<IssueKind, number>> = { defect: 0, other: 1, mechanism: 2 }
|
|
16
16
|
|
|
17
17
|
function above_message(measured: DefectRate): string {
|
|
18
|
-
return `The defect rate ${defect_rate.rate_text(measured)} is above its baseline ${String(defect_rate.BASELINE_RATE)}, so defects are offered first and new mechanisms last.`
|
|
18
|
+
return `The defect rate ${defect_rate.rate_text(measured)} is above its baseline ${String(defect_rate.BASELINE_RATE)}, so among issues the ranking keys tie, defects are offered first and new mechanisms last.`
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// The body the listing already carried, else one read for it (joshuafolkken/kit#4550). An unreadable
|
|
@@ -14,6 +14,7 @@ import { run_carry, type RunCarry } from '#scripts/run/carry/run-carry'
|
|
|
14
14
|
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
15
15
|
import type { MergeResult } from '#scripts/run/merge/run-merge-cli'
|
|
16
16
|
import { run_merge_driver } from '#scripts/run/merge/run-merge-driver'
|
|
17
|
+
import { run_merge_usage_limit } from '#scripts/run/merge/run-merge-usage-limit'
|
|
17
18
|
import { z } from 'zod'
|
|
18
19
|
import { backlog_budget } from './backlog-budget'
|
|
19
20
|
import {
|
|
@@ -203,12 +204,16 @@ function reporters(holds: HoldRecorder): Pick<LoopPorts, 'hold' | 'idle' | 'paus
|
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
// What a launch is weighed against: the free lanes, a kept lane, and the memory for one more.
|
|
206
|
-
function room_ports(): Pick<
|
|
207
|
+
function room_ports(): Pick<
|
|
208
|
+
LoopPorts,
|
|
209
|
+
'free_lanes' | 'has_lane' | 'limit_room' | 'memory_held' | 'usage_limited'
|
|
210
|
+
> {
|
|
207
211
|
return {
|
|
208
212
|
free_lanes: backlog_ready.drive_free_lane_count,
|
|
209
213
|
limit_room: backlog_ready.drive_limit_room,
|
|
210
214
|
has_lane: backlog_drive_seats.has_kept_lane,
|
|
211
215
|
memory_held: backlog_drive_memory.gauge(),
|
|
216
|
+
usage_limited: async () => await run_merge_usage_limit.is_held(Date.now()),
|
|
212
217
|
}
|
|
213
218
|
}
|
|
214
219
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { lane_ledger_write } from '#scripts/lane/lane-ledger-write'
|
|
2
2
|
import type { DriveEnd, DrivePorts, DriveState, OfferRead, PassResult } from './backlog-drive'
|
|
3
3
|
import { backlog_ready } from './backlog-ready'
|
|
4
4
|
|
|
@@ -104,7 +104,7 @@ async function free_count(
|
|
|
104
104
|
|
|
105
105
|
async function release(ledger: HoldLedger): Promise<void> {
|
|
106
106
|
ledger.is_open = false
|
|
107
|
-
await
|
|
107
|
+
await lane_ledger_write.record_released()
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
async function release_open(ledger: HoldLedger): Promise<void> {
|
|
@@ -134,7 +134,7 @@ async function record(
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
ledger.is_open = true
|
|
137
|
-
await
|
|
137
|
+
await lane_ledger_write.record_held({ reason: draft.reason, waiting: draft.waiting })
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// The production `hold` port and the driver's end, sharing whether a hold is open. Best-effort like
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { auto_ok_author } from '#scripts/auto-ok/auto-ok-author'
|
|
1
2
|
import { auto_ok_cli } from '#scripts/auto-ok/auto-ok-cli'
|
|
2
3
|
import type { OpenIssueData } from '#scripts/git/git-schemas'
|
|
3
4
|
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
@@ -21,6 +22,7 @@ const WATCH_VERDICT = 'watch'
|
|
|
21
22
|
const BLOCKED_ANSWER = 'blocked'
|
|
22
23
|
const DECISION_HEADING = `Waiting on a decision (${NEEDS_DECISION_LABEL}):`
|
|
23
24
|
const STALLED_HEADING = `Stalled mechanically (${RUN_STALLED_LABEL}):`
|
|
25
|
+
const UNTRUSTED_HEADING = 'Waiting on a person to vouch for the body (author without write access):'
|
|
24
26
|
const IDLE_HEAD = 'No child running and nothing left to dispatch.'
|
|
25
27
|
const IDLE_RECOVERY =
|
|
26
28
|
'Decide the parked issues, fix and release the stalled ones, or start the next run with `backlogrun`.'
|
|
@@ -70,6 +72,13 @@ function labelled_lines(issues: ReadonlyArray<OpenIssueData>, label: string): Ar
|
|
|
70
72
|
.map((issue) => cited(issue))
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
// `backlog:next` holds these for a person exactly as it does a parked one (joshuafolkken/kit#4633).
|
|
76
|
+
function untrusted_lines(issues: ReadonlyArray<OpenIssueData>): Array<string> {
|
|
77
|
+
return issues
|
|
78
|
+
.filter((issue) => !auto_ok_author.is_author_trusted(issue))
|
|
79
|
+
.map((issue) => cited(issue))
|
|
80
|
+
}
|
|
81
|
+
|
|
73
82
|
function dated_lines(issues: ReadonlyArray<OpenIssueData>, now_ms: number): Array<string> {
|
|
74
83
|
const lines: Array<string> = []
|
|
75
84
|
|
|
@@ -92,6 +101,7 @@ function remaining_lines(reading: IdleReading): Array<string> {
|
|
|
92
101
|
const lines = [
|
|
93
102
|
...section(DECISION_HEADING, labelled_lines(reading.issues, NEEDS_DECISION_LABEL)),
|
|
94
103
|
...section(STALLED_HEADING, labelled_lines(reading.issues, RUN_STALLED_LABEL)),
|
|
104
|
+
...section(UNTRUSTED_HEADING, untrusted_lines(reading.issues)),
|
|
95
105
|
...section('Waiting on a date:', dated_lines(reading.issues, reading.now_ms)),
|
|
96
106
|
]
|
|
97
107
|
|