@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
|
@@ -2,16 +2,19 @@ import path from 'node:path'
|
|
|
2
2
|
import { cost_blocks } from '#scripts/cost-runtime/cost-blocks'
|
|
3
3
|
import { cost_transcript } from '#scripts/cost-runtime/cost-transcript'
|
|
4
4
|
import { capped_print_part } from '#scripts/document/capped-print-part'
|
|
5
|
+
import { changed_paths_sync } from '#scripts/git/changed-paths-sync'
|
|
5
6
|
import { hook_decision, type GuardRun } from '#scripts/josh/hook-decision'
|
|
6
7
|
import { time_batch_guard, type GuardedCall } from '#scripts/time-runtime/time-batch-guard'
|
|
7
8
|
import { time_bundle_call } from '#scripts/time-runtime/time-bundle-call'
|
|
9
|
+
import { time_search_call } from '#scripts/time-runtime/time-search-call'
|
|
8
10
|
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
9
11
|
import { time_spans, type Span } from '#scripts/time-runtime/time-spans'
|
|
10
12
|
import { delegation_policy } from './delegation-policy'
|
|
11
13
|
|
|
12
14
|
// How many files a run has read and not edited since its last delegated unit, counted off the
|
|
13
15
|
// transcript rather than left to the agent's memory, so the threshold fires again on a second
|
|
14
|
-
// accumulation. A delegation clears the set; a read adds to it; an edit exempts its file
|
|
16
|
+
// accumulation. A delegation clears the set; a read adds to it; an edit exempts its file, as does
|
|
17
|
+
// the branch's own change since its merge base, which an earlier session of the run wrote.
|
|
15
18
|
|
|
16
19
|
const READ_TOOLS: ReadonlySet<string> = new Set(['Read'])
|
|
17
20
|
// Both spellings of the subagent tool are in use: `Task` (published) and `Agent` (this harness).
|
|
@@ -32,12 +35,6 @@ const CONTENT_READ_LABELS: ReadonlySet<string> = new Set(
|
|
|
32
35
|
CONTENT_READ_COMMANDS.map((command) => time_shell.bash_label(command)),
|
|
33
36
|
)
|
|
34
37
|
|
|
35
|
-
// A search carries no file text but costs a turn, so searches count in turns: parallel ones count once.
|
|
36
|
-
const SEARCH_COMMANDS: ReadonlyArray<string> = ['fd', 'find', 'grep', 'rg']
|
|
37
|
-
const SEARCH_LABELS: ReadonlySet<string> = new Set(
|
|
38
|
-
SEARCH_COMMANDS.map((command) => time_shell.bash_label(command)),
|
|
39
|
-
)
|
|
40
|
-
|
|
41
38
|
const { INVESTIGATOR_AGENT } = delegation_policy
|
|
42
39
|
|
|
43
40
|
// The deny reason is the only text that reaches the model, so it names the count, command and return shape.
|
|
@@ -55,7 +52,8 @@ interface ReadTally {
|
|
|
55
52
|
// The search-side `pending` / `pending_since`, reset by a delegation or a successful write.
|
|
56
53
|
searches: number
|
|
57
54
|
searches_since: number
|
|
58
|
-
// Files successfully edited in the window; a read of one stays in the main
|
|
55
|
+
// Files successfully edited in the window or changed on the branch; a read of one stays in the main
|
|
56
|
+
// line, so it never counts.
|
|
59
57
|
edited: ReadonlySet<string>
|
|
60
58
|
}
|
|
61
59
|
|
|
@@ -187,10 +185,6 @@ interface Accumulation {
|
|
|
187
185
|
searches: Map<string, number>
|
|
188
186
|
}
|
|
189
187
|
|
|
190
|
-
function is_read_only_search(span: Span): boolean {
|
|
191
|
-
return SEARCH_LABELS.has(span.label) && span.is_bundleable && !span.may_write
|
|
192
|
-
}
|
|
193
|
-
|
|
194
188
|
// A span with no message id is a turn of its own, as in every other turn counter.
|
|
195
189
|
function search_turn_key(searches: ReadonlyMap<string, number>, span: Span): string {
|
|
196
190
|
if (span.message_id !== time_spans.NO_MESSAGE_ID) return span.message_id
|
|
@@ -209,19 +203,27 @@ function apply_search(searches: Map<string, number>, span: Span): void {
|
|
|
209
203
|
|
|
210
204
|
const turn = search_turn_key(searches, span)
|
|
211
205
|
|
|
212
|
-
|
|
206
|
+
// A search carries no file text but costs a turn, so searches count in turns: parallel ones count once.
|
|
207
|
+
if (time_search_call.is_read_only_search(span) && !searches.has(turn)) {
|
|
208
|
+
searches.set(turn, span.ended_ms)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// A refused dispatch (`investigator-foreground`, `agent-model`) ran no unit, so it resets nothing.
|
|
213
|
+
function is_delegation(span: Span): boolean {
|
|
214
|
+
return DELEGATION_TOOLS.has(span.label) && !is_failed_outcome(span)
|
|
213
215
|
}
|
|
214
216
|
|
|
215
217
|
function apply_span(accumulation: Accumulation, span: Span, edited: ReadonlySet<string>): void {
|
|
216
|
-
if (
|
|
218
|
+
if (is_failed_outcome(span)) return
|
|
219
|
+
|
|
220
|
+
if (is_delegation(span)) {
|
|
217
221
|
accumulation.pending.clear()
|
|
218
222
|
accumulation.searches.clear()
|
|
219
223
|
|
|
220
224
|
return
|
|
221
225
|
}
|
|
222
226
|
|
|
223
|
-
if (is_failed_outcome(span)) return
|
|
224
|
-
|
|
225
227
|
apply_search(accumulation.searches, span)
|
|
226
228
|
|
|
227
229
|
if (!is_content_read(span.label)) return
|
|
@@ -232,7 +234,7 @@ function apply_span(accumulation: Accumulation, span: Span, edited: ReadonlySet<
|
|
|
232
234
|
}
|
|
233
235
|
|
|
234
236
|
function last_delegation_ms(spans: ReadonlyArray<Span>): number {
|
|
235
|
-
return delegation_instant(spans.findLast((span) =>
|
|
237
|
+
return delegation_instant(spans.findLast((span) => is_delegation(span)))
|
|
236
238
|
}
|
|
237
239
|
|
|
238
240
|
// The window is the tail the hook read; the set clears at every delegation, so the tail suffices.
|
|
@@ -240,9 +242,15 @@ function pending_after(pending: ReadonlyMap<string, number>, since_ms: number):
|
|
|
240
242
|
return [...pending.values()].filter((at_ms) => at_ms > since_ms).length
|
|
241
243
|
}
|
|
242
244
|
|
|
243
|
-
|
|
245
|
+
// `branch_files` (repository-relative) are the branch's own change since its merge base: an earlier
|
|
246
|
+
// session of this run wrote them, and a resumed session's transcript holds none of those writes.
|
|
247
|
+
function tally_of(
|
|
248
|
+
text: string,
|
|
249
|
+
since_ms: number = hook_decision.NEVER_MS,
|
|
250
|
+
branch_files: ReadonlyArray<string> = [],
|
|
251
|
+
): ReadTally {
|
|
244
252
|
const { spans, started_ms } = time_spans.parse_timeline(text)
|
|
245
|
-
const edited = edited_files(spans)
|
|
253
|
+
const edited = new Set([...edited_files(spans), ...subject_targets(branch_files)])
|
|
246
254
|
const accumulation: Accumulation = { pending: new Map(), searches: new Map() }
|
|
247
255
|
|
|
248
256
|
for (const span of spans) apply_span(accumulation, span, edited)
|
|
@@ -313,7 +321,9 @@ function is_read_only_command(call: GuardedCall, labels: ReadonlySet<string>): b
|
|
|
313
321
|
|
|
314
322
|
// A search is refusable without a subject target: a bare-directory sweep is what this count is for.
|
|
315
323
|
function is_search_call(call: GuardedCall): boolean {
|
|
316
|
-
return
|
|
324
|
+
return time_search_call.is_read_only_search(
|
|
325
|
+
time_spans.to_tool_call(call.name, call.input, time_spans.NO_MESSAGE_ID),
|
|
326
|
+
)
|
|
317
327
|
}
|
|
318
328
|
|
|
319
329
|
// This guard counts reading, so a `Bash` line that also writes is never refused, and neither is a call
|
|
@@ -335,6 +345,20 @@ function is_growing_past_threshold(tally: ReadTally, call: GuardedCall): boolean
|
|
|
335
345
|
return projected_count(tally.pending, call, tally.edited) > tally.pending.length
|
|
336
346
|
}
|
|
337
347
|
|
|
348
|
+
function is_blocking(tally: ReadTally, call: GuardedCall, refused_at_ms: number): boolean {
|
|
349
|
+
return is_growing_past_threshold(tally, call) && is_rearmed(tally, refused_at_ms)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// The branch diff is a git read, so it is asked only of a call the transcript alone would refuse; more
|
|
353
|
+
// edited files can only lower the counts, so a call that passes without it passes with it.
|
|
354
|
+
function is_blocking_past_branch(text: string, call: GuardedCall, refused_at_ms: number): boolean {
|
|
355
|
+
if (!is_blocking(tally_of(text, refused_at_ms), call, refused_at_ms)) return false
|
|
356
|
+
|
|
357
|
+
const branch_files = changed_paths_sync.read_changed_paths()
|
|
358
|
+
|
|
359
|
+
return is_blocking(tally_of(text, refused_at_ms, branch_files), call, refused_at_ms)
|
|
360
|
+
}
|
|
361
|
+
|
|
338
362
|
function should_block(
|
|
339
363
|
text: string,
|
|
340
364
|
call: GuardedCall,
|
|
@@ -344,9 +368,7 @@ function should_block(
|
|
|
344
368
|
// A delegated unit is never refused: the remedy — send the reading to a unit — does not exist inside one.
|
|
345
369
|
if (!is_refusable_call(call) || is_unit_run(run)) return false
|
|
346
370
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return is_growing_past_threshold(tally, call) && is_rearmed(tally, refused_at_ms)
|
|
371
|
+
return is_blocking_past_branch(text, call, refused_at_ms)
|
|
350
372
|
}
|
|
351
373
|
|
|
352
374
|
const investigation_reads = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { existsSync, readFileSync
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
+
import { file_content } from '#scripts/sync/file-content'
|
|
3
4
|
import {
|
|
4
5
|
DEFAULT_RELEASE_AGE_MINUTES,
|
|
5
6
|
release_window,
|
|
@@ -184,7 +185,7 @@ function sync_dependabot_cooldown(root: string): boolean {
|
|
|
184
185
|
const existing = readFileSync(config_path, 'utf8')
|
|
185
186
|
const merged = merge_cooldown(existing, release_window.read_release_window(root))
|
|
186
187
|
if (merged === existing) return false
|
|
187
|
-
|
|
188
|
+
file_content.write_contained(config_path, merged)
|
|
188
189
|
|
|
189
190
|
return true
|
|
190
191
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { repo_discovery } from './repo-discovery'
|
|
2
|
-
import { repo_origin } from './repo-origin'
|
|
2
|
+
import { repo_origin, type RepoIdentity } from './repo-origin'
|
|
3
|
+
import { session_owner_pin } from './session-owner-pin'
|
|
3
4
|
|
|
4
5
|
// **First-party vs third-party, computed rather than judged**. `CLAUDE.md`
|
|
5
6
|
// and `upstream-interrupt.md` both declared the test mechanical — owner equality between the target
|
|
@@ -32,45 +33,100 @@ function classify(session_owner: string | undefined, target: string | undefined)
|
|
|
32
33
|
// The owner half of a `owner/repo` argument, parsed through the remote-URL reader so a `.git` suffix
|
|
33
34
|
// and a malformed form (one segment, three segments) are handled by the one place that already knows
|
|
34
35
|
// them rather than by a second split here.
|
|
36
|
+
function parse_owner_repo(owner_repo: string): RepoIdentity | undefined {
|
|
37
|
+
return repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${owner_repo}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
function target_owner(owner_repo: string): string | undefined {
|
|
36
|
-
return
|
|
41
|
+
return parse_owner_repo(owner_repo)?.owner
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
// The owner of the repository the session runs in
|
|
40
|
-
// and no authenticated CLI, so the guard that consults it
|
|
44
|
+
// The owner of the repository the session runs in: the one pinned at session start, else read
|
|
45
|
+
// locally from its `origin` — no network call and no authenticated CLI, so the guard that consults it
|
|
46
|
+
// stays synchronous. The pin is what keeps a mid-session remote rewrite from changing the answer
|
|
47
|
+
// (`session-owner-pin.ts`).
|
|
41
48
|
function current_owner(repository_path: string = process.cwd()): string | undefined {
|
|
42
|
-
return
|
|
49
|
+
return (
|
|
50
|
+
session_owner_pin.pinned(repository_path) ??
|
|
51
|
+
repo_discovery.resolve_current_owner(repository_path)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The repository a `[HOST/]OWNER/REPO` selector names — `GH_REPO`, or `gh`'s `-R` / `--repo` value —
|
|
56
|
+
// read from its last two segments so an optional host prefix is skipped.
|
|
57
|
+
function selector_repository(selector: string): RepoIdentity | undefined {
|
|
58
|
+
return parse_owner_repo(selector.split('/').slice(-GH_REPO_PATH_SEGMENTS).join('/'))
|
|
43
59
|
}
|
|
44
60
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return [target_owner(gh_repo.split('/').slice(-GH_REPO_PATH_SEGMENTS).join('/'))]
|
|
61
|
+
function selector_owner(selector: string): string | undefined {
|
|
62
|
+
return selector_repository(selector)?.owner
|
|
48
63
|
}
|
|
49
64
|
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
function
|
|
65
|
+
// Every remote the work tree declares. A remote that cannot be read stays in the set as `undefined`
|
|
66
|
+
// rather than being dropped: an SSH host alias (`git@github-work:o/r.git`) is one `gh` translates to
|
|
67
|
+
// github.com and may pick, so dropping it would hide the repository `gh` writes to.
|
|
68
|
+
function remote_repositories(repository_path: string): Array<RepoIdentity | undefined> {
|
|
54
69
|
return repo_discovery
|
|
55
70
|
.read_remote_urls(repository_path)
|
|
56
|
-
.map((url) => repo_origin.parse_origin_url(url)
|
|
71
|
+
.map((url) => repo_origin.parse_origin_url(url))
|
|
57
72
|
}
|
|
58
73
|
|
|
59
|
-
// Every
|
|
74
|
+
// Every repository `gh` could expand the `{owner}/{repo}` placeholders to. `GH_REPO`
|
|
60
75
|
// (`[HOST/]OWNER/REPO`) overrides the remotes outright; otherwise `gh` picks its base repository among
|
|
61
76
|
// the GitHub remotes — `upstream` ahead of `origin`, or a `gh repo set-default` choice — so in a fork
|
|
62
|
-
// checkout it can expand to the upstream
|
|
77
|
+
// checkout it can expand to the upstream repository. Answering the whole candidate set rather than
|
|
63
78
|
// re-implementing that pick keeps the caller safe whichever remote `gh` chooses. An `undefined` entry
|
|
64
|
-
// is a candidate
|
|
79
|
+
// is a candidate that could not be read, which the caller must not assume is first-party.
|
|
80
|
+
function placeholder_repositories(
|
|
81
|
+
repository_path: string,
|
|
82
|
+
environment: NodeJS.ProcessEnv,
|
|
83
|
+
): Array<RepoIdentity | undefined> {
|
|
84
|
+
const gh_repo = environment[GH_REPO_ENV_KEY]
|
|
85
|
+
|
|
86
|
+
return gh_repo === undefined || gh_repo === ''
|
|
87
|
+
? remote_repositories(repository_path)
|
|
88
|
+
: [selector_repository(gh_repo)]
|
|
89
|
+
}
|
|
90
|
+
|
|
65
91
|
function placeholder_owners(
|
|
66
92
|
repository_path: string = process.cwd(),
|
|
67
93
|
environment: NodeJS.ProcessEnv = process.env,
|
|
68
94
|
): Array<string | undefined> {
|
|
69
|
-
|
|
95
|
+
return placeholder_repositories(repository_path, environment).map((identity) => identity?.owner)
|
|
96
|
+
}
|
|
70
97
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
98
|
+
// Two spellings of one repository, compared case-insensitively as GitHub resolves them.
|
|
99
|
+
function is_same_repository(left: RepoIdentity | undefined, right: RepoIdentity): boolean {
|
|
100
|
+
if (left === undefined || classify(left.owner, right.owner) !== FIRST_PARTY) return false
|
|
101
|
+
|
|
102
|
+
return left.repo.toLowerCase() === right.repo.toLowerCase()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// The one repository every candidate names, or nothing when there is none, one is unreadable, or two
|
|
106
|
+
// differ — a fork checkout whose `upstream` `gh` may pick ahead of `origin`.
|
|
107
|
+
function sole_repository(
|
|
108
|
+
candidates: ReadonlyArray<RepoIdentity | undefined>,
|
|
109
|
+
): RepoIdentity | undefined {
|
|
110
|
+
const [first, ...rest] = candidates
|
|
111
|
+
if (first === undefined) return undefined
|
|
112
|
+
|
|
113
|
+
return rest.every((candidate) => is_same_repository(candidate, first)) ? first : undefined
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// The checkout's own repository: the one `{owner}/{repo}` expands to — where `josh issue:comment`
|
|
117
|
+
// posts. Nothing unless that is one repository whichever candidate `gh` picks, so a spelled-out
|
|
118
|
+
// repository is never read as the one `issue:comment` reaches when it might not be
|
|
119
|
+
// (joshuafolkken/kit#4737).
|
|
120
|
+
function current_repository(
|
|
121
|
+
repository_path: string = process.cwd(),
|
|
122
|
+
environment: NodeJS.ProcessEnv = process.env,
|
|
123
|
+
): RepoIdentity | undefined {
|
|
124
|
+
return sole_repository(placeholder_repositories(repository_path, environment))
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Whether `target` is the checkout's own repository `current_repository` answered.
|
|
128
|
+
function is_own_repository(target: RepoIdentity, own: RepoIdentity | undefined): boolean {
|
|
129
|
+
return is_same_repository(own, target)
|
|
74
130
|
}
|
|
75
131
|
|
|
76
132
|
const repo_party = {
|
|
@@ -79,7 +135,11 @@ const repo_party = {
|
|
|
79
135
|
UNKNOWN,
|
|
80
136
|
classify,
|
|
81
137
|
current_owner,
|
|
138
|
+
current_repository,
|
|
139
|
+
is_own_repository,
|
|
82
140
|
placeholder_owners,
|
|
141
|
+
selector_owner,
|
|
142
|
+
sole_repository,
|
|
83
143
|
target_owner,
|
|
84
144
|
}
|
|
85
145
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
2
|
+
import { repo_discovery } from './repo-discovery'
|
|
3
|
+
|
|
4
|
+
// **The session's owner, fixed when the session starts** (joshuafolkken/kit#4659). The first-party
|
|
5
|
+
// test compares a target's owner with the session's, and the session's was read from `origin` on
|
|
6
|
+
// every call — so `git remote set-url origin https://github.com/<other>/x` mid-session made another
|
|
7
|
+
// owner first-party. The session-start hook records the owner once; `repo_party.current_owner`
|
|
8
|
+
// answers the record ahead of the live remote. Only the session's owner is pinned: the `{owner}`
|
|
9
|
+
// placeholder candidates and a selector-less `gh` write still resolve against the live remotes.
|
|
10
|
+
//
|
|
11
|
+
// **Written by the process the session start already runs** (`audit-provision --session-start`), so
|
|
12
|
+
// pinning adds no spawn to the launch, and read as one local file by the hooks that already run — no
|
|
13
|
+
// network call. A checkout with no record (a session the hook did not start) falls back to `origin`.
|
|
14
|
+
//
|
|
15
|
+
// **Per checkout, replaced at every session start.** The record is the stamp `stamp-file.ts` keeps in
|
|
16
|
+
// the temp directory, keyed on the account and the checkout path; a checkout whose origin owner
|
|
17
|
+
// cannot be read at start leaves no record rather than a stale one. A command run outside a session
|
|
18
|
+
// reads the last session's record for that path, which the next session start replaces.
|
|
19
|
+
|
|
20
|
+
const PIN_PREFIX = 'josh-session-owner-'
|
|
21
|
+
const PIN_SUFFIX = '.txt'
|
|
22
|
+
|
|
23
|
+
function pin_path(repository_path: string): string {
|
|
24
|
+
return stamp_file.stamp_path(PIN_PREFIX, repository_path, PIN_SUFFIX)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Records the checkout's `origin` owner for the session about to run. Never throws: this runs at
|
|
28
|
+
// session start beside the scanner provisioning, and an unwritable temp directory only costs the pin.
|
|
29
|
+
function pin(repository_path: string = process.cwd()): string | undefined {
|
|
30
|
+
const owner = repo_discovery.resolve_current_owner(repository_path)
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
if (owner === undefined) stamp_file.remove_stamp(pin_path(repository_path))
|
|
34
|
+
else stamp_file.write_text_stamp(pin_path(repository_path), owner)
|
|
35
|
+
} catch {
|
|
36
|
+
return undefined
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return owner
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// The owner recorded at session start, or `undefined` when the checkout holds no readable record.
|
|
43
|
+
function pinned(repository_path: string = process.cwd()): string | undefined {
|
|
44
|
+
const text = stamp_file.read_stamp_text(pin_path(repository_path))?.trim()
|
|
45
|
+
|
|
46
|
+
return text === '' ? undefined : text
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const session_owner_pin = { pin, pin_path, pinned }
|
|
50
|
+
|
|
51
|
+
export { session_owner_pin }
|
|
@@ -68,6 +68,6 @@ function capped_print(text: string, label: string, root: string = process.cwd())
|
|
|
68
68
|
console.info(listing(text, budget, write_parts(label, text, budget)))
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const capped_output = { HEADROOM_CHARS, capped_print }
|
|
71
|
+
const capped_output = { HEADROOM_CHARS, capped_print, output_budget }
|
|
72
72
|
|
|
73
73
|
export { capped_output }
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// The long-line ceiling of the command reference — one source for `command-reference.test.ts` and the
|
|
2
|
+
// fast `josh lint:related` path (`document-ratchet-check.ts`), so the two can never hold different
|
|
3
|
+
// lines. A reference entry is a short summary; the why behind it lives in the page's maintainer
|
|
4
|
+
// rationale file. The pages once carried 137 lines over 400 characters (joshuafolkken/kit#3868); the
|
|
5
|
+
// ceiling is a ratchet at the long lines left after condensing them, so lowering it is the only way
|
|
6
|
+
// it moves.
|
|
7
|
+
|
|
8
|
+
// The only files under `docs/` an agent is routed to read — the four command references; the rest of
|
|
9
|
+
// `docs/` is reference a human browses, so the byte budget (`document/document-byte-budget.ts`)
|
|
10
|
+
// covers these alone.
|
|
11
|
+
const COMMAND_REFERENCE_DOCS: ReadonlyArray<string> = [
|
|
12
|
+
'docs/josh-commands.md',
|
|
13
|
+
'docs/josh-commands-automation.md',
|
|
14
|
+
'docs/josh-commands-run.md',
|
|
15
|
+
'docs/josh-commands-backlog.md',
|
|
16
|
+
]
|
|
17
|
+
const LONG_LINE_CHARACTERS = 400
|
|
18
|
+
const MAX_LONG_LINES = 3
|
|
19
|
+
|
|
20
|
+
// The lines over the length limit across every page handed in — the ceiling holds the pages
|
|
21
|
+
// together, so one page's cut makes room in another.
|
|
22
|
+
function long_line_count(texts: ReadonlyArray<string>): number {
|
|
23
|
+
return texts
|
|
24
|
+
.flatMap((text) => text.split('\n'))
|
|
25
|
+
.filter((line) => line.length > LONG_LINE_CHARACTERS).length
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// The failure for a count over the ceiling, or undefined at or under it.
|
|
29
|
+
function long_line_violation(count: number): string | undefined {
|
|
30
|
+
if (count <= MAX_LONG_LINES) return undefined
|
|
31
|
+
|
|
32
|
+
return `the command reference (${COMMAND_REFERENCE_DOCS.join(', ')}) has ${count.toString()} lines over ${LONG_LINE_CHARACTERS.toString()} characters, over its ceiling of ${MAX_LONG_LINES.toString()}. Shorten the entry — the why belongs in the page's maintainer rationale file.`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const command_reference_line_budget = {
|
|
36
|
+
COMMAND_REFERENCE_DOCS,
|
|
37
|
+
long_line_count,
|
|
38
|
+
long_line_violation,
|
|
39
|
+
MAX_LONG_LINES,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { command_reference_line_budget }
|
|
@@ -73,10 +73,18 @@ const DOCUMENT_BYTE_BUDGET: ReadonlyArray<DocumentBudget> = [
|
|
|
73
73
|
{ path: '.claude/skills/workflow-commands/prerequisite.md', bytes: 8192 },
|
|
74
74
|
{ path: '.claude/skills/workflow-commands/target-repository.md', bytes: 4096 },
|
|
75
75
|
{ path: '.claude/skills/workflow-commands/working-tree-hold.md', bytes: 8192 },
|
|
76
|
-
|
|
77
|
-
{ path: 'docs/josh-commands-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
// `command:derive`'s usage section (joshuafolkken/kit#4970) crossed the 45056 block.
|
|
77
|
+
{ path: 'docs/josh-commands-automation.md', bytes: 49_152 },
|
|
78
|
+
// The carried `--unpinned-ok` record (joshuafolkken/kit#4775) crossed the 73728 block.
|
|
79
|
+
// `run:merge`'s withdrawn child (joshuafolkken/kit#4916) crossed the 77824 block.
|
|
80
|
+
// `lane:plan --probe` and the entry probe (joshuafolkken/kit#5211) crossed the 81920 block.
|
|
81
|
+
{ path: 'docs/josh-commands-run.md', bytes: 86_016 },
|
|
82
|
+
// `josh effect:audit` (joshuafolkken/kit#4958) and `issue:priority`'s usage section (joshuafolkken/kit#4960) crossed the 57344 block;
|
|
83
|
+
// `josh prose:stale` (joshuafolkken/kit#5287) crossed the 61440 block.
|
|
84
|
+
{ path: 'docs/josh-commands-backlog.md', bytes: 65_536 },
|
|
85
|
+
// `run:merge` withdrawing a lane closed without a merge (joshuafolkken/kit#4916) crossed the 53248 block;
|
|
86
|
+
// `gate --static-group` (joshuafolkken/kit#5215) crossed the 57344 block.
|
|
87
|
+
{ path: 'docs/josh-commands.md', bytes: 61_440 },
|
|
80
88
|
{ path: 'docs/labels-and-run-states.md', bytes: 8192 },
|
|
81
89
|
{ path: 'prompts/coding-standards.md', bytes: 4096 },
|
|
82
90
|
{ path: 'prompts/collaboration-workflow.md', bytes: 4096 },
|
|
@@ -84,8 +92,9 @@ const DOCUMENT_BYTE_BUDGET: ReadonlyArray<DocumentBudget> = [
|
|
|
84
92
|
{ path: 'prompts/collaboration-workflow/gh-rest.md', bytes: 4096 },
|
|
85
93
|
{ path: 'prompts/collaboration-workflow/glossary.md', bytes: 4096 },
|
|
86
94
|
{ path: 'prompts/collaboration-workflow/issue-citation.md', bytes: 4096 },
|
|
87
|
-
// The priority declaration and its criteria (joshuafolkken/kit#4383) crossed the 8192 block
|
|
88
|
-
|
|
95
|
+
// The priority declaration and its criteria (joshuafolkken/kit#4383) crossed the 8192 block; the
|
|
96
|
+
// causing-lane declaration and criteria F / G (joshuafolkken/kit#4749) crossed the 12288 one.
|
|
97
|
+
{ path: 'prompts/collaboration-workflow/issue-template.md', bytes: 16_384 },
|
|
89
98
|
{ path: 'prompts/collaboration-workflow/lane-instructions.md', bytes: 4096 },
|
|
90
99
|
{ path: 'prompts/collaboration-workflow/measurement.md', bytes: 4096 },
|
|
91
100
|
{ path: 'prompts/collaboration-workflow/operating-rules.md', bytes: 8192 },
|
|
@@ -103,7 +112,8 @@ const DOCUMENT_BYTE_BUDGET: ReadonlyArray<DocumentBudget> = [
|
|
|
103
112
|
{ path: 'prompts/collaboration-workflow/wip-cap.md', bytes: 8192 },
|
|
104
113
|
{ path: 'prompts/refactoring.md', bytes: 8192 },
|
|
105
114
|
{ path: 'prompts/review-rubric.md', bytes: 12_288 },
|
|
106
|
-
|
|
115
|
+
// Self-check 2's `josh prose:stale` pointer (joshuafolkken/kit#5287) crossed the 12288 block.
|
|
116
|
+
{ path: 'prompts/review.md', bytes: 16_384 },
|
|
107
117
|
{ path: 'prompts/sonar-hotspot-handling.md', bytes: 8192 },
|
|
108
118
|
{ path: 'prompts/testing-guide.md', bytes: 12_288 },
|
|
109
119
|
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { document_byte_check } from './document-byte-check'
|
|
2
|
+
import { document_ratchet_check } from './document-ratchet-check'
|
|
3
|
+
|
|
4
|
+
// The document checks `josh lint:related` brings forward from the gate's tests, as one call: the
|
|
5
|
+
// byte ceilings (`document-byte-check.ts`) and the ratchets (`document-ratchet-check.ts`). Both run
|
|
6
|
+
// every time, so one edit reports every ceiling it broke in one pass rather than one per run.
|
|
7
|
+
|
|
8
|
+
const CHECKS = [document_byte_check, document_ratchet_check]
|
|
9
|
+
|
|
10
|
+
function check_files(root: string, absolute_files: ReadonlyArray<string>): number {
|
|
11
|
+
return Math.max(...CHECKS.map((check) => check.check_files(root, absolute_files)))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function check_all(root: string): number {
|
|
15
|
+
return Math.max(...CHECKS.map((check) => check.check_all(root)))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const document_checks = { check_all, check_files }
|
|
19
|
+
|
|
20
|
+
export { document_checks }
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { project_checks } from '#scripts/gate/project-checks'
|
|
4
|
+
import { command_reference_line_budget } from './command-reference-line-budget'
|
|
5
|
+
import { issue_citation_budget } from './issue-citation-budget'
|
|
6
|
+
|
|
7
|
+
// The two document ratchets the gate's tests hold — the command reference's long-line ceiling
|
|
8
|
+
// (`command-reference.test.ts`) and each agent-read document's issue-citation count
|
|
9
|
+
// (`issue-citation-budget.test.ts`) — made reachable on the fast between-edits path beside
|
|
10
|
+
// `document-byte-check.ts`, so a documentation edit that breaks either surfaces in seconds rather
|
|
11
|
+
// than in a minutes-long `check:related` (joshuafolkken/kit#4986). The ceilings, the counting and the
|
|
12
|
+
// messages are the budget modules' alone; this adds none of its own.
|
|
13
|
+
//
|
|
14
|
+
// It reads no change of its own: `lint:related` hands in the files it already resolved. The citation
|
|
15
|
+
// check holds the documents the budget records; a document with no entry, and the whole-list checks
|
|
16
|
+
// (a stale or a zero entry), stay with the gate's test, which knows the agent-read set.
|
|
17
|
+
//
|
|
18
|
+
// Both ratchets are kit's: the budget records kit's paths, and a consumer's own file at one of them
|
|
19
|
+
// holds its own count, so a consumer root is checked by neither.
|
|
20
|
+
|
|
21
|
+
const LABEL = 'document ratchet'
|
|
22
|
+
|
|
23
|
+
function read_text(absolute_path: string): string | undefined {
|
|
24
|
+
return existsSync(absolute_path) ? readFileSync(absolute_path, 'utf8') : undefined
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// The long-line failure across the whole command reference, which the ceiling holds together.
|
|
28
|
+
function long_line_message(root: string): string | undefined {
|
|
29
|
+
const texts = command_reference_line_budget.COMMAND_REFERENCE_DOCS.map((relative_path) =>
|
|
30
|
+
read_text(path.join(root, relative_path)),
|
|
31
|
+
).filter((text): text is string => text !== undefined)
|
|
32
|
+
|
|
33
|
+
return command_reference_line_budget.long_line_violation(
|
|
34
|
+
command_reference_line_budget.long_line_count(texts),
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function touches_command_reference(root: string, absolute_files: ReadonlyArray<string>): boolean {
|
|
39
|
+
const references = new Set(command_reference_line_budget.COMMAND_REFERENCE_DOCS)
|
|
40
|
+
|
|
41
|
+
return absolute_files.some((absolute_path) => references.has(path.relative(root, absolute_path)))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// The citation failure for one file the budget records, or undefined when it holds its count, has no
|
|
45
|
+
// entry, or is gone from the tree.
|
|
46
|
+
function citation_message(root: string, absolute_path: string): string | undefined {
|
|
47
|
+
const relative_path = path.relative(root, absolute_path)
|
|
48
|
+
const recorded = issue_citation_budget.recorded_citations_for(relative_path)
|
|
49
|
+
const text = read_text(absolute_path)
|
|
50
|
+
if (recorded === 0 || text === undefined) return undefined
|
|
51
|
+
|
|
52
|
+
const current = issue_citation_budget.count_citations(text)
|
|
53
|
+
|
|
54
|
+
return issue_citation_budget.citation_violation(relative_path, current, recorded)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function citation_messages(
|
|
58
|
+
root: string,
|
|
59
|
+
absolute_files: ReadonlyArray<string>,
|
|
60
|
+
): ReadonlyArray<string> {
|
|
61
|
+
return absolute_files
|
|
62
|
+
.map((absolute_path) => citation_message(root, absolute_path))
|
|
63
|
+
.filter((message): message is string => message !== undefined)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Prints one labelled line per failure and answers non-zero, or stays silent and answers zero.
|
|
67
|
+
function report(messages: ReadonlyArray<string | undefined>): number {
|
|
68
|
+
const lines = messages
|
|
69
|
+
.filter((message): message is string => message !== undefined)
|
|
70
|
+
.map((message) => `${LABEL}: ${message}`)
|
|
71
|
+
if (lines.length === 0) return 0
|
|
72
|
+
|
|
73
|
+
process.stdout.write(`${lines.join('\n')}\n`)
|
|
74
|
+
|
|
75
|
+
return 1
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// The check over a resolved change: the long-line ceiling when it touches a command reference page,
|
|
79
|
+
// and the citation count of every changed file the budget records. An unrelated change reads nothing.
|
|
80
|
+
function check_files(root: string, absolute_files: ReadonlyArray<string>): number {
|
|
81
|
+
if (!project_checks.is_kit_repository(root)) return 0
|
|
82
|
+
const long_line = touches_command_reference(root, absolute_files)
|
|
83
|
+
? long_line_message(root)
|
|
84
|
+
: undefined
|
|
85
|
+
|
|
86
|
+
return report([long_line, ...citation_messages(root, absolute_files)])
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// The whole-tree fallback: the long-line ceiling and every recorded document, a superset of any change.
|
|
90
|
+
function check_all(root: string): number {
|
|
91
|
+
if (!project_checks.is_kit_repository(root)) return 0
|
|
92
|
+
const absolute_files = issue_citation_budget.ISSUE_CITATION_BUDGET.map((entry) =>
|
|
93
|
+
path.join(root, entry.path),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
return report([long_line_message(root), ...citation_messages(root, absolute_files)])
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const document_ratchet_check = { check_all, check_files }
|
|
100
|
+
|
|
101
|
+
export { document_ratchet_check }
|
|
@@ -34,6 +34,9 @@ const { block_ceiling } = document_byte_budget
|
|
|
34
34
|
const { LANE_CHILD } = lane_child_read_set
|
|
35
35
|
const { BACKLOGRUN } = backlogrun_parent_read_set
|
|
36
36
|
const NOTHING = 0
|
|
37
|
+
// The command that re-measures every entry total in seconds, named by the over-budget message so a
|
|
38
|
+
// trim is checked without re-running the whole lint or gate.
|
|
39
|
+
const RECHECK_COMMAND = 'pnpm josh bytes'
|
|
37
40
|
|
|
38
41
|
interface EntryBudget {
|
|
39
42
|
entry: string
|
|
@@ -46,8 +49,8 @@ interface EntryBudget {
|
|
|
46
49
|
const ENTRY_READ_BUDGET: ReadonlyArray<EntryBudget> = [
|
|
47
50
|
{ entry: 'kickoff', bytes: 36_864 },
|
|
48
51
|
{ entry: 'fullrun', bytes: 53_248 },
|
|
49
|
-
{ entry: 'halfrun', bytes:
|
|
50
|
-
{ entry: 'prrun', bytes:
|
|
52
|
+
{ entry: 'halfrun', bytes: 45_056 },
|
|
53
|
+
{ entry: 'prrun', bytes: 57_344 },
|
|
51
54
|
{ entry: 'backlogrun', bytes: 81_920 },
|
|
52
55
|
{ entry: LANE_CHILD, bytes: 45_056 },
|
|
53
56
|
]
|
|
@@ -95,7 +98,7 @@ function over_budget_message(entry: string, current_bytes: number, recorded_byte
|
|
|
95
98
|
const next = block_ceiling(current_bytes).toString()
|
|
96
99
|
const raise_hint = `raise its recorded size to ${next} in scripts/document/entry-read-budget.ts so the reason shows in the PR diff`
|
|
97
100
|
|
|
98
|
-
return `entry ${entry} reads ${current_bytes.toString()} bytes, over its ${recorded_bytes.toString()}-byte ceiling. Trim what it reads, or ${raise_hint}
|
|
101
|
+
return `entry ${entry} reads ${current_bytes.toString()} bytes, over its ${recorded_bytes.toString()}-byte ceiling. Trim what it reads, or ${raise_hint}. Recheck with \`${RECHECK_COMMAND}\`.`
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
// The stale-ratchet message: a recorded ceiling more than a block above the entry's actual total was
|
|
@@ -113,6 +116,7 @@ function stale_budget_message(
|
|
|
113
116
|
|
|
114
117
|
const entry_read_budget = {
|
|
115
118
|
ENTRY_READ_BUDGET,
|
|
119
|
+
RECHECK_COMMAND,
|
|
116
120
|
entry_total_bytes,
|
|
117
121
|
over_budget_message,
|
|
118
122
|
recorded_bytes_for,
|