@joshuafolkken/kit 1.1035.0 → 1.1094.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +9 -8
- package/.claude/skills/epic-commands/SKILL.md +5 -7
- package/.claude/skills/verify-ui/SKILL.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +21 -13
- package/.claude/skills/workflow-commands/background-commands.md +5 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -3
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -7
- package/.claude/skills/workflow-commands/backlogrun-park.md +6 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +31 -37
- package/.claude/skills/workflow-commands/backlogrun-steps.md +25 -25
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +6 -4
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +3 -3
- package/.claude/skills/workflow-commands/followup.md +7 -3
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/fullrun.md +3 -2
- package/.claude/skills/workflow-commands/halfrun.md +16 -19
- package/.claude/skills/workflow-commands/issue-comments.md +2 -2
- package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +9 -4
- package/.claude/skills/workflow-commands/latest-gate.md +1 -1
- package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +44 -89
- package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -36
- package/.claude/skills/workflow-commands/prerequisite.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +36 -0
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +24 -4
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/auto-tag.yml +21 -0
- package/.github/workflows/ci.yml +26 -128
- package/.github/workflows/pr-classification.yml +5 -41
- package/.github/workflows/publish.yml +42 -48
- package/.github/workflows/sonar-qube.yml +37 -4
- package/AGENTS.md +12 -2
- package/CLAUDE.md +15 -16
- package/GEMINI.md +14 -2
- package/README.md +59 -18
- package/SECURITY.md +36 -6
- package/cspell/index.yaml +2 -1
- package/dist/CLAUDE.md +15 -16
- package/dist/config-merge/index.js +15 -3
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-Y27M6A7X.js → chunk-3C4YCCEF.js} +5 -13
- package/dist/hooks/{chunk-D67KVGGY.js → chunk-7ZPFAVR7.js} +17 -88
- package/dist/hooks/{chunk-HOYJU5RM.js → chunk-E54KGFEQ.js} +11 -4
- package/dist/hooks/{chunk-KG6PZD72.js → chunk-IL27YTPH.js} +2 -2
- package/dist/hooks/{chunk-GJT4BNVE.js → chunk-KHWHKJOM.js} +3 -3
- package/dist/hooks/{chunk-HU66PWWL.js → chunk-M2XDCUKD.js} +1076 -509
- package/dist/hooks/{chunk-GLBDBJOK.js → chunk-NKOG3XAV.js} +199 -304
- package/dist/hooks/{chunk-ZXNE6NY3.js → chunk-O4LL4HTI.js} +2 -7
- package/dist/hooks/{chunk-XPLP27WA.js → chunk-OIZUHPJI.js} +5 -27
- package/dist/hooks/{chunk-EIFCAJRB.js → chunk-UD24EAIL.js} +2546 -1636
- package/dist/hooks/codex-hook-adapter.js +10 -11
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +15 -34
- package/dist/hooks/inputs.json +279 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +23 -16
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +188 -509
- package/dist/josh.js +166 -225
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +412 -64
- package/eslint/rules/promise.js +5 -0
- package/package.json +13 -8
- package/prompts/collaboration-workflow/file-edits.md +6 -53
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/operating-rules.md +4 -4
- package/prompts/collaboration-workflow/overview.md +13 -1
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +4 -4
- package/prompts/collaboration-workflow/rule-delivery.md +5 -36
- package/prompts/collaboration-workflow/shell-body.md +7 -9
- package/prompts/collaboration-workflow/turn-batching.md +21 -37
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +36 -36
- package/prompts/collaboration-workflow.md +5 -8
- package/prompts/review-rubric.md +1 -1
- package/prompts/review.md +3 -3
- package/prompts/sonar-hotspot-handling.md +12 -4
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +2 -2
- package/scripts/adopt/adopt.ts +0 -2
- package/scripts/agent/agent-argv.ts +0 -2
- package/scripts/agent/agent-diagnostics.ts +1 -1
- package/scripts/agent/agent-role-profile.ts +0 -7
- package/scripts/agent/claude-agent-argv.ts +0 -2
- package/scripts/agent/codex-agent-argv.ts +1 -1
- package/scripts/agent/codex-hooks.ts +92 -0
- package/scripts/agent/interactive-ask.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +15 -25
- package/scripts/backlog/backlog-budget.ts +0 -2
- package/scripts/backlog/backlog-defect-priority.ts +2 -2
- package/scripts/backlog/backlog-drive-cli.ts +10 -8
- package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
- package/scripts/backlog/backlog-drive-named.ts +2 -1
- package/scripts/backlog/backlog-drive.ts +76 -16
- package/scripts/backlog/backlog-named.ts +0 -3
- package/scripts/backlog/backlog-next.ts +32 -22
- package/scripts/backlog/backlog-offer-cli.ts +0 -5
- package/scripts/backlog/backlog-plan-cli.ts +6 -8
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +34 -17
- package/scripts/backlog/backlog-rank.ts +106 -0
- package/scripts/backlog/backlog-ready.ts +19 -3
- package/scripts/backlog/backlog-scope.ts +1 -3
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +0 -1
- package/scripts/backlog/backlog-waves.ts +47 -31
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +92 -11
- package/scripts/build/hook-bundle-stamp.ts +111 -0
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +1 -1
- package/scripts/ci/composite-actions.ts +30 -0
- package/scripts/ci/pr-classification.ts +3 -3
- package/scripts/claude/workflow-destination.ts +10 -1
- package/scripts/clone/clone-fingerprint.ts +0 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/json-format.ts +0 -1
- package/scripts/config-merge/patch-yaml-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +2 -9
- package/scripts/cost-runtime/cost-attribute.ts +0 -1
- package/scripts/cost-runtime/cost-cli.ts +0 -3
- package/scripts/cost-runtime/cost-corpus.ts +0 -2
- package/scripts/cost-runtime/cost-format.ts +0 -3
- package/scripts/cost-runtime/cost-pricing.ts +0 -1
- package/scripts/cost-runtime/cost-tokens.ts +0 -1
- package/scripts/delegation/delegation-cli.ts +1 -1
- package/scripts/delegation/delegation-policy.ts +11 -1
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +0 -2
- package/scripts/delegation/investigation-reads.ts +1 -164
- package/scripts/discovery/repo-map-logic.ts +0 -1
- package/scripts/discovery/repo-party-cli.ts +1 -1
- package/scripts/doctor/doctor-consumer.ts +4 -6
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/document-byte-budget.ts +8 -9
- package/scripts/document/document-byte-check.ts +0 -1
- package/scripts/document/document-read-cli.ts +0 -2
- package/scripts/document/document-section-cli.ts +1 -1
- package/scripts/document/document-section.ts +0 -3
- package/scripts/document/edit-files-cli.ts +0 -1
- package/scripts/document/entry-read-budget.ts +13 -4
- package/scripts/document/lane-child-read-set.ts +1 -6
- package/scripts/document/read-files-cli.ts +0 -4
- package/scripts/document/read-set-cli.ts +0 -2
- package/scripts/document/read-set-point-of-use.ts +1 -0
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +1 -1
- package/scripts/epic/epic-add.ts +1 -1
- package/scripts/epic/epic-audit-cli.ts +1 -4
- package/scripts/epic/epic-audit-orphans.ts +1 -3
- package/scripts/epic/epic-audit-rationale.ts +0 -1
- package/scripts/epic/epic-audit-report.ts +0 -2
- package/scripts/epic/epic-audit.ts +5 -4
- package/scripts/epic/epic-bundle-cli.ts +1 -1
- package/scripts/epic/epic-bundle-evidence.ts +0 -1
- package/scripts/epic/epic-bundle-referenced.ts +1 -5
- package/scripts/epic/epic-bundle.ts +0 -4
- package/scripts/epic/epic-busy.ts +4 -5
- package/scripts/epic/epic-candidate-confirm.ts +0 -5
- package/scripts/epic/epic-classify.ts +2 -2
- package/scripts/epic/epic-cli-argv.ts +0 -1
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +5 -2
- package/scripts/epic/epic-cross-repo.ts +2 -4
- package/scripts/epic/epic-decision.ts +0 -1
- package/scripts/epic/epic-fetch.ts +2 -2
- package/scripts/epic/epic-index.ts +2 -3
- package/scripts/epic/epic-issue.ts +1 -15
- package/scripts/epic/epic-lane-offer.ts +20 -30
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +1 -3
- package/scripts/epic/epic-next-views.ts +0 -1
- package/scripts/epic/epic-next.ts +1 -10
- package/scripts/epic/epic-parse.ts +0 -1
- package/scripts/epic/epic-promote.ts +0 -9
- package/scripts/epic/epic-rank.ts +37 -0
- package/scripts/epic/epic-read.ts +1 -2
- package/scripts/epic/epic-reconcile.ts +1 -1
- package/scripts/epic/epic-reference.ts +1 -13
- package/scripts/epic/epic-relation-recheck.ts +1 -1
- package/scripts/epic/epic-relations.ts +1 -1
- package/scripts/epic/epic-remove.ts +1 -1
- package/scripts/epic/epic-report.ts +0 -1
- package/scripts/epic/epic-run.ts +2 -3
- package/scripts/epic/epic-shape.ts +1 -1
- package/scripts/epic/epic-solo-stale.ts +107 -0
- package/scripts/epic/epic-solo.ts +32 -30
- package/scripts/epic/epic-triage.ts +1 -1
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/epic/epic.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +53 -0
- package/scripts/{git → followup}/followup-issue-number.ts +1 -6
- package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
- package/scripts/{git → followup}/git-followup-finish.ts +1 -3
- package/scripts/{git → followup}/git-followup-flush.ts +2 -2
- package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
- package/scripts/{git → followup}/git-followup-label.ts +4 -4
- package/scripts/followup/git-followup-merged.ts +112 -0
- package/scripts/{git → followup}/git-followup-pending.ts +1 -1
- package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
- package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
- package/scripts/{git → followup}/git-pr-followup.ts +53 -16
- package/scripts/gate/core-budget.ts +3 -9
- package/scripts/gate/gate-plan.ts +7 -4
- package/scripts/gate/gate-report.ts +0 -6
- package/scripts/gate/gate-tree.ts +1 -1
- package/scripts/gate/pre-commit-type-check.ts +0 -6
- package/scripts/gate/project-checks.ts +7 -8
- package/scripts/gate/scoped-green.ts +0 -1
- package/scripts/gate/type-check-step.ts +1 -1
- package/scripts/gate/verification-gate.ts +0 -2
- package/scripts/gh/fix-gh-packages.ts +15 -12
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
- package/scripts/{git → gh}/git-gh-check.ts +2 -1
- package/scripts/{git → gh}/git-gh-exec.ts +1 -1
- package/scripts/{git → gh}/git-gh-failure.ts +1 -1
- package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
- package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
- package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
- package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
- package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
- package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
- package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
- package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
- package/scripts/{git → gh}/git-gh-pr.ts +3 -1
- package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
- package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
- package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
- package/scripts/{git → gh}/git-pr-checks.ts +2 -1
- package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
- package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
- package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
- package/scripts/{git → gh}/git-pr.ts +3 -3
- package/scripts/git/changed-file-scope.ts +0 -1
- package/scripts/git/git-branch.ts +3 -6
- package/scripts/git/git-command.ts +1 -1
- package/scripts/git/git-commit.ts +1 -1
- package/scripts/git/git-common-directory.ts +80 -24
- package/scripts/git/git-error.ts +66 -9
- package/scripts/git/git-execa-error.ts +6 -1
- package/scripts/git/git-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +24 -6
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push-transport.ts +12 -69
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-spawn.ts +79 -3
- package/scripts/git/git-ssh-keepalive.ts +74 -0
- package/scripts/git/git-staging.ts +1 -0
- package/scripts/git/git-status.ts +1 -1
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/gone-branch.ts +4 -2
- package/scripts/git/listing-cutoff.ts +1 -1
- package/scripts/git/main-merge.ts +1 -1
- package/scripts/git/main-sync.ts +19 -1
- package/scripts/git/parse-json-array.ts +0 -3
- package/scripts/git/repository-lock.ts +16 -16
- package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
- package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
- package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
- package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
- package/scripts/hooks/codex-hook-adapter.ts +0 -1
- package/scripts/hooks/edited-cspell.ts +1 -1
- package/scripts/hooks/format-edited-cli.ts +15 -0
- package/scripts/hooks/format-edited-file.ts +4 -9
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard-cli.ts +21 -0
- package/scripts/hooks/pretool-guard.ts +36 -19
- package/scripts/hooks/reserved-run.ts +1 -1
- package/scripts/hooks/step-zero-notice.ts +76 -0
- package/scripts/hooks/stop-guard.ts +47 -21
- package/scripts/init/claude-plugin-config.ts +4 -5
- package/scripts/init/hook-command-rewrite.ts +16 -8
- package/scripts/init/hook-launch.ts +41 -15
- package/scripts/init/init-basic.ts +2 -5
- package/scripts/init/init-logic.ts +7 -0
- package/scripts/init/init.ts +0 -3
- package/scripts/init/project-profile.ts +6 -11
- package/scripts/init/start-exec.ts +8 -2
- package/scripts/init/start-plan.ts +18 -5
- package/scripts/init/start-setup-pr.ts +52 -25
- package/scripts/init/start-steps.ts +42 -9
- package/scripts/init/start.ts +40 -10
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +3 -3
- package/scripts/issue/defect-rate.ts +1 -2
- package/scripts/{git → issue}/git-next-issues.ts +37 -8
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +19 -3
- package/scripts/issue/issue-classification.ts +1 -9
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +2 -2
- package/scripts/issue/issue-file-cli.ts +5 -5
- package/scripts/issue/issue-file.ts +2 -2
- package/scripts/issue/issue-fold-cli.ts +1 -1
- package/scripts/issue/issue-fold-existing-cli.ts +1 -1
- package/scripts/{git → issue}/issue-labels.ts +20 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/issue/issue-rank.ts +89 -0
- package/scripts/issue/issue-read-cli.ts +8 -47
- package/scripts/issue/issue-read.ts +0 -2
- package/scripts/issue/issue-report-failures.ts +80 -0
- package/scripts/issue/issue-scout-cli.ts +1 -7
- package/scripts/issue/issue-scout-closed.ts +2 -2
- package/scripts/issue/issue-scout.ts +0 -2
- package/scripts/issue/issue-state-cli.ts +5 -46
- package/scripts/issue/issue-state.ts +1 -5
- package/scripts/issue/markdown-section.ts +1 -1
- package/scripts/issue/measure-rerun-cli.ts +1 -1
- package/scripts/issue/reproduction-measure.ts +1 -1
- package/scripts/josh/cli-body.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +0 -3
- package/scripts/josh/josh-command-map.ts +2 -102
- package/scripts/josh/josh-commands-ai.ts +9 -102
- package/scripts/josh/josh-commands-backlog.ts +5 -1
- package/scripts/josh/josh-commands-development.ts +10 -3
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/josh/josh-commands-maintenance.ts +7 -0
- package/scripts/josh/josh-commands-project.ts +7 -1
- package/scripts/josh/josh-commands-run.ts +114 -0
- package/scripts/josh/josh-commands-versioning.ts +8 -0
- package/scripts/josh/josh-commands-workflow.ts +2 -2
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +3 -6
- package/scripts/lane/lane-capacity.ts +6 -3
- package/scripts/lane/lane-child-invocation.ts +20 -7
- package/scripts/lane/lane-child-marker.ts +16 -2
- package/scripts/lane/lane-cli.ts +33 -18
- package/scripts/lane/lane-close.ts +1 -3
- package/scripts/lane/lane-dispatch.ts +3 -4
- package/scripts/lane/lane-environment.ts +0 -9
- package/scripts/lane/lane-handoff.ts +38 -0
- package/scripts/lane/lane-launch-cli.ts +21 -11
- package/scripts/lane/lane-open.ts +0 -3
- package/scripts/lane/lane-output.ts +0 -1
- package/scripts/lane/lane-registry.ts +9 -0
- package/scripts/lane/lane-report.ts +10 -4
- package/scripts/lane/openai-lane-ship.ts +2 -0
- package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
- package/scripts/lane/openai-lane-supervisor.ts +6 -4
- package/scripts/lane/openai-review-broker.ts +3 -0
- package/scripts/lib/bounded-pool.ts +1 -0
- package/scripts/lib/json-value.ts +5 -4
- package/scripts/lib/poll.ts +3 -1
- package/scripts/lib/timed-fetch.ts +15 -0
- package/scripts/lib/timeouts.ts +13 -0
- package/scripts/{yaml → lib}/yaml-document.ts +3 -1
- package/scripts/{bytes → lines}/bytes-command.ts +0 -2
- package/scripts/lines/lines-command.ts +0 -1
- package/scripts/lint/lint-related-scope.ts +0 -1
- package/scripts/lint/lint-related.ts +1 -1
- package/scripts/{git → notify}/telegram-notify.ts +2 -2
- package/scripts/{git → notify}/telegram-test.ts +4 -4
- package/scripts/observations/observation-ledger-home.ts +0 -1
- package/scripts/observations/observation-ledger-line.ts +0 -1
- package/scripts/observations/observation-ledger-migrate.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +3 -3
- package/scripts/observations/observations-flush.ts +2 -2
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/package/package-scout-cli.ts +2 -7
- package/scripts/package/package-scout.ts +0 -2
- package/scripts/propagate/propagate-git-failure.ts +0 -1
- package/scripts/propagate/propagate-git.ts +0 -2
- package/scripts/propagate/propagate-plan.ts +185 -0
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -3
- package/scripts/propagate/propagate-steps.ts +19 -6
- package/scripts/propagate/propagate-targets.ts +13 -6
- package/scripts/propagate/propagate.ts +60 -46
- package/scripts/refactor/import-graph.ts +0 -1
- package/scripts/refactor/refactor-lint.ts +0 -2
- package/scripts/refactor/refactor-scan.ts +0 -1
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +1 -2
- package/scripts/registry-migration/migrate.ts +19 -9
- package/scripts/release/github-release-cli.ts +8 -6
- package/scripts/release/github-release-environment.ts +46 -0
- package/scripts/release/github-release.ts +151 -94
- package/scripts/release/release-history.ts +0 -1
- package/scripts/release/release-plan.ts +0 -1
- package/scripts/release/release-publish.ts +2 -3
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- package/scripts/repo/auto-merge-setting-logic.ts +1 -4
- package/scripts/repo/repo-setting.ts +1 -1
- package/scripts/repo/repository-labels.ts +3 -3
- package/scripts/repo/required-checks-logic.ts +206 -0
- package/scripts/repo/required-checks-report.ts +71 -0
- package/scripts/repo/ruleset-check-cli.ts +53 -0
- package/scripts/repo/ruleset-check.ts +147 -0
- package/scripts/report/report-lint-cli.ts +0 -4
- package/scripts/review/disposition-cli.ts +1 -1
- package/scripts/review/live-evidence.ts +1 -1
- package/scripts/review/review-attest-cli.ts +0 -6
- package/scripts/review/review-attest.ts +48 -16
- package/scripts/review/review-brief-cli.ts +72 -8
- package/scripts/review/review-brief.ts +67 -9
- package/scripts/review/review-diff-parts.ts +89 -0
- package/scripts/review/review-diff-write.ts +97 -0
- package/scripts/review/review-finding-ledger.ts +0 -1
- package/scripts/review/review-record-cli.ts +1 -1
- package/scripts/review/review-record.ts +0 -1
- package/scripts/review/review-round2-cli.ts +1 -1
- package/scripts/review/review-stamps.ts +6 -2
- package/scripts/review/review-tree.ts +14 -2
- package/scripts/rules/decision-oracle-stage.ts +18 -0
- package/scripts/rules/decision-oracle.ts +10 -7
- package/scripts/rules/delivered-rules.ts +9 -1
- package/scripts/rules/destructive-command.ts +119 -0
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/file-body.ts +0 -3
- package/scripts/rules/filing-cap.ts +0 -2
- package/scripts/rules/gh-api.ts +7 -2
- package/scripts/rules/git-argv.ts +18 -7
- package/scripts/rules/git-force.ts +0 -2
- package/scripts/rules/implementation-cut.ts +1 -2
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/issue-fold.ts +1 -2
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-carry-conflict.ts +1 -2
- package/scripts/rules/lane-park.ts +14 -8
- package/scripts/rules/last-prompt.ts +1 -0
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +0 -3
- package/scripts/rules/permission-guards.ts +14 -0
- package/scripts/rules/pre-gate-cut.ts +2 -2
- package/scripts/rules/protected-files.ts +74 -0
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +0 -3
- package/scripts/rules/rule-value-cli.ts +0 -1
- package/scripts/rules/shell-body-trigger.ts +0 -1
- package/scripts/rules/shell-segments.ts +0 -1
- package/scripts/rules/stop-rules.ts +13 -5
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +0 -1
- package/scripts/rules/worktree-guard.ts +26 -9
- package/scripts/run/run-carry-cli.ts +0 -2
- package/scripts/run/run-carry-stash.ts +2 -2
- package/scripts/run/run-carry-streak.ts +1 -1
- package/scripts/run/run-cut-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +1 -1
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +101 -24
- package/scripts/run/run-entry.ts +0 -1
- package/scripts/run/run-event-cli.ts +0 -2
- package/scripts/run/run-event-follow.ts +1 -0
- package/scripts/run/run-event-render.ts +1 -1
- package/scripts/run/run-event-scope.ts +53 -4
- package/scripts/run/run-event-stream.ts +0 -3
- package/scripts/run/run-event-watch.ts +1 -0
- package/scripts/run/run-halfrun-resume.ts +20 -7
- package/scripts/run/run-headless.ts +24 -8
- package/scripts/run/run-hold-cli.ts +33 -10
- package/scripts/run/run-hold.ts +25 -5
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +1 -1
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +5 -13
- package/scripts/run/run-merge-steps.ts +5 -5
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-next-cli.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +143 -0
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +2 -2
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-cli.ts +4 -7
- package/scripts/run/run-progress-clock.ts +6 -34
- package/scripts/run/run-progress-config.ts +0 -4
- package/scripts/run/run-progress-read.ts +3 -3
- package/scripts/run/run-progress.ts +22 -10
- package/scripts/run/run-prrun-resume.ts +117 -0
- package/scripts/run/run-report-cli.ts +1 -2
- package/scripts/run/run-report.ts +0 -1
- package/scripts/run/run-retrospective.ts +1 -1
- package/scripts/run/run-review-cli.ts +0 -3
- package/scripts/run/run-review-steps.ts +2 -0
- package/scripts/run/run-review.ts +0 -2
- package/scripts/run/run-ship-cli.ts +27 -77
- package/scripts/run/run-ship-detach.ts +1 -0
- package/scripts/run/run-ship-next.ts +106 -0
- package/scripts/run/run-ship-preflight.ts +87 -0
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +23 -30
- package/scripts/run/run-ship-review.ts +20 -0
- package/scripts/run/run-ship-scoped.ts +45 -0
- package/scripts/run/run-ship-stage.ts +5 -1
- package/scripts/run/run-ship-steps.ts +105 -0
- package/scripts/run/run-ship.ts +2 -1
- package/scripts/run/run-stage-read.ts +62 -0
- package/scripts/run/run-stage.ts +160 -0
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +21 -14
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stop-notify.ts +1 -3
- package/scripts/run/run-stranded-cli.ts +0 -4
- package/scripts/run/run-stranded-detect.ts +2 -2
- package/scripts/run/run-tail-cli.ts +17 -11
- package/scripts/run/run-tail.ts +2 -0
- package/scripts/run/run-tidy-lanes.ts +2 -1
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +4 -5
- package/scripts/run/run-wake-describe.ts +19 -1
- package/scripts/run/run-wake-loop.ts +2 -2
- package/scripts/run/run-wake.ts +2 -4
- package/scripts/run/run-watcher-guard-cli.ts +0 -4
- package/scripts/run/run-watcher-guard.ts +9 -7
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- package/scripts/safe-chain/project-config.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +0 -1
- package/scripts/security/security-audit-provision.ts +3 -2
- package/scripts/security/security-audit.ts +0 -1
- package/scripts/security/security-updates-logic.ts +0 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
- package/scripts/sonar/sonar-hotspots.ts +0 -1
- package/scripts/sonar/sonar-new-code-cli.ts +150 -0
- package/scripts/sonar/sonar-new-code.ts +79 -0
- package/scripts/sonar/sonar-project.ts +97 -0
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +2 -5
- package/scripts/sync/managed-config-scope-cli.ts +1 -1
- package/scripts/sync/skill-migration.ts +0 -1
- package/scripts/sync/sync-hook-safety.ts +2 -3
- package/scripts/sync/sync.ts +1 -8
- package/scripts/sync/template-source-logic.ts +0 -1
- package/scripts/sync/workflow-pin-logic.ts +16 -28
- package/scripts/test/test-declared-logic.ts +0 -1
- package/scripts/test/test-declared.ts +0 -2
- package/scripts/test/test-red-commit.ts +2 -2
- package/scripts/test/test-red.ts +14 -7
- package/scripts/test/test-type-logic.ts +1 -1
- package/scripts/test/unit-worker-share.ts +7 -16
- package/scripts/time-runtime/time-batch-guard.ts +1 -2
- package/scripts/time-runtime/time-bundle-call.ts +2 -3
- package/scripts/time-runtime/time-bundles.ts +0 -4
- package/scripts/time-runtime/time-density-hook.ts +0 -2
- package/scripts/time-runtime/time-followup-stage.ts +1 -1
- package/scripts/time-runtime/time-format.ts +0 -73
- package/scripts/time-runtime/time-round-trips.ts +0 -4
- package/scripts/time-runtime/time-single-check.ts +1 -1
- package/scripts/time-runtime/time-spans.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +1 -2
- package/scripts/ui/ui-routes-cli.ts +0 -5
- package/scripts/ui/ui-routes.ts +0 -5
- package/scripts/version/effective-upstream.ts +2 -2
- package/scripts/version/latest-corepack.ts +7 -9
- package/scripts/version/latest-scope-cli.ts +0 -2
- package/scripts/version/latest-update.ts +0 -2
- package/scripts/version/npm-registry.ts +97 -0
- package/scripts/version/publishable-range-check.ts +1 -1
- package/scripts/version/release-hold.ts +0 -4
- package/scripts/version/running-binary.ts +2 -2
- package/scripts/version/version-check-logic.ts +0 -2
- package/scripts/version/version-commands.ts +5 -4
- package/scripts/version/version-remote.ts +28 -14
- package/scripts/version/version-targets.ts +4 -4
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/dependabot-auto-merge.yml +5 -3
- package/templates/workflows/github-release.yml +81 -0
- package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
- package/prompts/collaboration-workflow/epic-audit.md +0 -5
- package/prompts/collaboration-workflow/epic-bundle.md +0 -5
- package/scripts/init/plugin-install-hint.ts +0 -47
- package/scripts/version/parse-json.ts +0 -13
- /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
- /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
- /package/scripts/{git → gh}/git-gh-command.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
- /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
- /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
- /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
- /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
- /package/scripts/{git → gh}/git-pr-error.ts +0 -0
- /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
- /package/scripts/{git → gh}/github-issue-url.ts +0 -0
- /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
- /package/scripts/{git → issue}/issue-reference.ts +0 -0
- /package/scripts/{git → lib}/animation-helpers.ts +0 -0
- /package/scripts/{git → lib}/git-animation.ts +0 -0
- /package/scripts/{git → notify}/git-notify.ts +0 -0
- /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
|
@@ -2,15 +2,23 @@
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { fileURLToPath } from 'node:url'
|
|
4
4
|
import { agent_role_profile, type AgentProfile } from '#scripts/agent/agent-role-profile'
|
|
5
|
+
import { bash_output_cap_reader } from '#scripts/document/bash-output-cap'
|
|
5
6
|
import { scoped_green } from '#scripts/gate/scoped-green'
|
|
6
7
|
import { change_base } from '#scripts/git/change-base'
|
|
7
8
|
import { changed_paths } from '#scripts/git/changed-paths'
|
|
8
9
|
import { git_command } from '#scripts/git/git-command'
|
|
10
|
+
import { PROJECT_ROOT } from '#scripts/init/init-paths'
|
|
11
|
+
import type { FileMapStamp } from '#scripts/josh/file-map-stamp'
|
|
9
12
|
import { find_package_directory } from '#scripts/josh/josh-logic'
|
|
10
13
|
import { path_decision } from '#scripts/josh/path-decision'
|
|
14
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
15
|
+
import { openai_review_broker } from '#scripts/lane/openai-review-broker'
|
|
16
|
+
import { run_ship_review } from '#scripts/run/run-ship-review'
|
|
11
17
|
import { review_attest } from './review-attest'
|
|
12
18
|
import { review_brief } from './review-brief'
|
|
13
19
|
import { review_checkout, type ReviewCheckout } from './review-checkout'
|
|
20
|
+
import type { DiffParts } from './review-diff-parts'
|
|
21
|
+
import { review_diff_write } from './review-diff-write'
|
|
14
22
|
import { review_level, type ReviewLevel } from './review-level'
|
|
15
23
|
import { review_stamps } from './review-stamps'
|
|
16
24
|
import { review_tree } from './review-tree'
|
|
@@ -134,13 +142,54 @@ function record_round_one(
|
|
|
134
142
|
// failed to record would hand the review a command that cannot succeed and the run a check that
|
|
135
143
|
// answers `not-required` — the guard gone, silently, which is the shape this whole record exists to
|
|
136
144
|
// remove.
|
|
137
|
-
|
|
145
|
+
//
|
|
146
|
+
// **Whether this is a resume is read first** (joshuafolkken/kit#2945): `record_target` drops the
|
|
147
|
+
// previous nonce's records, so asked afterwards the finished review would always read as absent. The
|
|
148
|
+
// findings file is the ship's, keyed on `PROJECT_ROOT` as the ship keys it; a review run outside the
|
|
149
|
+
// ship writes none, so it never reads as a resume and keeps the whole change.
|
|
150
|
+
//
|
|
151
|
+
// **The narrowing is measured from the tree that review was briefed on**, and only when that record
|
|
152
|
+
// was written by the brief the pointer names: one left by an earlier brief is not the tree the
|
|
153
|
+
// finished review read, so the resume reads the whole change instead.
|
|
154
|
+
function attested_tree(checkout: ReviewCheckout): FileMapStamp | undefined {
|
|
155
|
+
const { findings } = openai_review_broker.review_paths(PROJECT_ROOT)
|
|
156
|
+
const briefed = review_stamps.briefed_stamp.read()
|
|
157
|
+
|
|
158
|
+
if (briefed === undefined || !review_attest.is_briefed_since(briefed.taken_at, checkout.root)) {
|
|
159
|
+
return undefined
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const is_clean =
|
|
163
|
+
review_attest.is_reviewed_on(checkout, findings, checkout.root) &&
|
|
164
|
+
run_ship_review.is_clean_round_one(stamp_file.read_stamp_text(findings))
|
|
165
|
+
|
|
166
|
+
return is_clean ? briefed : undefined
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function open_contract(): Promise<{
|
|
170
|
+
checkout: ReviewCheckout
|
|
171
|
+
nonce: string
|
|
172
|
+
resumed_from: FileMapStamp | undefined
|
|
173
|
+
}> {
|
|
138
174
|
const checkout = await review_checkout.read_checkout()
|
|
175
|
+
const resumed_from = attested_tree(checkout)
|
|
139
176
|
|
|
140
177
|
// Keyed on the root git just answered with, never on `process.cwd()`: the check made before the
|
|
141
178
|
// merge asks git the same question, and the two hash different keys the moment one of them runs
|
|
142
179
|
// from a subdirectory — a mismatch that would drop the guard with nothing printed.
|
|
143
|
-
return { checkout, nonce: review_attest.record_target(checkout, checkout.root) }
|
|
180
|
+
return { checkout, nonce: review_attest.record_target(checkout, checkout.root), resumed_from }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Retaken on every round-1 brief, after the pointer it pairs with (joshuafolkken/kit#2945). Swallowed:
|
|
184
|
+
// a record that failed to write predates the next pointer, so the resume widens rather than narrows.
|
|
185
|
+
function record_briefed(round: number, tree: Record<string, string>, base?: string): void {
|
|
186
|
+
if (round !== FIRST_ROUND) return
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
review_stamps.briefed_stamp.write(tree, undefined, base)
|
|
190
|
+
} catch {
|
|
191
|
+
/* no record widens the resume rather than narrowing it */
|
|
192
|
+
}
|
|
144
193
|
}
|
|
145
194
|
|
|
146
195
|
interface ComposeRequest {
|
|
@@ -151,8 +200,26 @@ interface ComposeRequest {
|
|
|
151
200
|
profile: AgentProfile
|
|
152
201
|
}
|
|
153
202
|
|
|
203
|
+
// **Swallowed, and the brief keeps its target line** (joshuafolkken/kit#2963): parts that could not be
|
|
204
|
+
// written leave the reviewer the whole `git diff` to read, which costs truncated output rather than
|
|
205
|
+
// scope — the direction every failure here falls.
|
|
206
|
+
async function read_diff(
|
|
207
|
+
root: string,
|
|
208
|
+
base: string,
|
|
209
|
+
paths: ReadonlyArray<string>,
|
|
210
|
+
): Promise<{ parts: DiffParts; cap: number } | undefined> {
|
|
211
|
+
const cap = bash_output_cap_reader.bash_output_cap(root)
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
return { parts: await review_diff_write.write_parts({ root, base, paths, cap }), cap }
|
|
215
|
+
} catch {
|
|
216
|
+
return undefined
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
154
220
|
async function compose_brief(request: ComposeRequest): Promise<string> {
|
|
155
221
|
const { round, paths, tree, base, profile } = request
|
|
222
|
+
const contract = await open_contract()
|
|
156
223
|
const stamps = {
|
|
157
224
|
gate: review_stamps.gate_stamp.read(),
|
|
158
225
|
in_flight: review_stamps.in_flight_stamp.read(),
|
|
@@ -172,7 +239,8 @@ async function compose_brief(request: ComposeRequest): Promise<string> {
|
|
|
172
239
|
// the map is stored against is the same one the brief printed (joshuafolkken/kit#1537).
|
|
173
240
|
base,
|
|
174
241
|
rubric_path: RUBRIC_PATH,
|
|
175
|
-
...
|
|
242
|
+
...contract,
|
|
243
|
+
diff: await read_diff(contract.checkout.root, base, paths),
|
|
176
244
|
})
|
|
177
245
|
}
|
|
178
246
|
|
|
@@ -252,6 +320,7 @@ async function run_review(round: number, reading: ChangeReading): Promise<number
|
|
|
252
320
|
if (resolved.kind === 'rejected') return report_error(resolved.note)
|
|
253
321
|
console.info(await compose_brief({ round, paths, tree, base, profile: resolved.profile }))
|
|
254
322
|
record_round_one(round, tree, commit)
|
|
323
|
+
record_briefed(round, tree, commit)
|
|
255
324
|
|
|
256
325
|
return 0
|
|
257
326
|
}
|
|
@@ -274,15 +343,10 @@ const review_brief_cli = {
|
|
|
274
343
|
FIRST_ROUND,
|
|
275
344
|
format_reason,
|
|
276
345
|
KEPT_NOTE_PREFIX,
|
|
277
|
-
kept_note,
|
|
278
|
-
LEVEL_ONLY_FLAG,
|
|
279
|
-
main,
|
|
280
346
|
parse_round,
|
|
281
347
|
record_round_one,
|
|
282
348
|
report_error,
|
|
283
349
|
run,
|
|
284
|
-
run_level,
|
|
285
|
-
USAGE,
|
|
286
350
|
}
|
|
287
351
|
|
|
288
352
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { agent_role_profile, type AgentProfile } from '#scripts/agent/agent-role-profile'
|
|
2
2
|
import { file_map_stamp, type FileMapStamp } from '#scripts/josh/file-map-stamp'
|
|
3
3
|
import { review_checkout, type ReviewCheckout } from './review-checkout'
|
|
4
|
+
import { review_diff_parts, type DiffParts } from './review-diff-parts'
|
|
4
5
|
|
|
5
6
|
// The text `josh review:brief` prints — the `/code-review` invocation, composed from what the run
|
|
6
7
|
// already knows (joshuafolkken/kit#1241).
|
|
@@ -56,7 +57,7 @@ function attest_line(nonce: string): string {
|
|
|
56
57
|
const RUBRIC_RELATIVE_PATH = 'prompts/review-rubric.md'
|
|
57
58
|
|
|
58
59
|
function rubric_line(rubric_path: string): string {
|
|
59
|
-
return `Rubric: read \`${rubric_path}\` first
|
|
60
|
+
return `Rubric: read \`${rubric_path}\` first, with the Read tool rather than \`cat\` — it is larger than the Bash output cap, so a Bash print comes back truncated (joshuafolkken/kit#2963) — and apply it: it is the severity tests, the round output format, the nine categories and the stop conditions this review is scored against. You do not carry them otherwise, so a review that skips it is scored on the wrong rules.`
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
function checkout_block(checkout: ReviewCheckout, nonce: string): string {
|
|
@@ -357,6 +358,39 @@ function round_two_block(
|
|
|
357
358
|
return narrow_block(scope.recorded_at, scope, root, base)
|
|
358
359
|
}
|
|
359
360
|
|
|
361
|
+
// **A resumed round 1 reads what changed since the attested review, reusing round 2's reconciliation**
|
|
362
|
+
// (joshuafolkken/kit#2945). A ship that stopped and was re-issued briefed the whole change again, so
|
|
363
|
+
// the reviewer re-read every file the attested review had just read. The scope is the comparison round
|
|
364
|
+
// 2 makes, measured from the tree that review was briefed on. Every reading that cannot narrow falls back to the whole
|
|
365
|
+
// change: no record, a moved base, or an empty target. An empty target is included because a resumed
|
|
366
|
+
// review that read nothing would report a clean verdict over the one already recorded.
|
|
367
|
+
const RESUMED_HEADING =
|
|
368
|
+
'Resumed round 1 — a review of this branch was already attested, so this pass reads only what changed since the tree it read.'
|
|
369
|
+
|
|
370
|
+
const RESUMED_QUESTION =
|
|
371
|
+
'Review these files in full against the rubric — they are the only code this pass has not already read.'
|
|
372
|
+
|
|
373
|
+
function resumed_target(
|
|
374
|
+
snapshot: FileMapStamp | undefined,
|
|
375
|
+
tree: Record<string, string>,
|
|
376
|
+
root: string,
|
|
377
|
+
base: string,
|
|
378
|
+
): string {
|
|
379
|
+
const scope = round_two_scope(snapshot, tree, base)
|
|
380
|
+
|
|
381
|
+
if (scope.recorded_at === undefined || scope.target.length === 0) {
|
|
382
|
+
return whole_change_target(root, base)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return [
|
|
386
|
+
RESUMED_HEADING,
|
|
387
|
+
`The attested review read the tree recorded at ${scope.recorded_at}.`,
|
|
388
|
+
`Target: only these files, which changed since that tree:\n${format_paths(root, scope.target)}`,
|
|
389
|
+
...reconciliation(root, base, scope),
|
|
390
|
+
RESUMED_QUESTION,
|
|
391
|
+
].join('\n')
|
|
392
|
+
}
|
|
393
|
+
|
|
360
394
|
interface BriefStamps {
|
|
361
395
|
gate: FileMapStamp | undefined
|
|
362
396
|
in_flight: FileMapStamp | undefined
|
|
@@ -377,20 +411,48 @@ interface BriefInput {
|
|
|
377
411
|
// The rubric's absolute path, resolved by the caller against the kit package rather than the review
|
|
378
412
|
// checkout, so it resolves in a consumer that ships no `prompts/` of its own (joshuafolkken/kit#2402).
|
|
379
413
|
rubric_path: string
|
|
414
|
+
// The tree a finished, clean review of this branch was briefed on, so round 1 is a resume
|
|
415
|
+
// (joshuafolkken/kit#2945). Absent, round 1 reads the whole change.
|
|
416
|
+
resumed_from?: FileMapStamp | undefined
|
|
417
|
+
// The change written as parts under the Bash output cap (joshuafolkken/kit#2963). Absent when the
|
|
418
|
+
// write failed, and the target line alone then names the change.
|
|
419
|
+
diff?: { parts: DiffParts; cap: number } | undefined
|
|
380
420
|
}
|
|
381
421
|
|
|
382
422
|
const SECOND_ROUND = 2
|
|
383
423
|
|
|
424
|
+
function round_one_target(input: BriefInput): string {
|
|
425
|
+
const { root } = input.checkout
|
|
426
|
+
|
|
427
|
+
if (input.resumed_from === undefined) return whole_change_target(root, input.base)
|
|
428
|
+
|
|
429
|
+
return resumed_target(input.resumed_from, input.tree, root, input.base)
|
|
430
|
+
}
|
|
431
|
+
|
|
384
432
|
function target_block(input: BriefInput): string {
|
|
385
|
-
if (input.round < SECOND_ROUND) return
|
|
433
|
+
if (input.round < SECOND_ROUND) return round_one_target(input)
|
|
386
434
|
|
|
387
435
|
return round_two_block(input.stamps.round_one, input.tree, input.checkout.root, input.base)
|
|
388
436
|
}
|
|
389
437
|
|
|
438
|
+
// **Only beside a whole-change target** (joshuafolkken/kit#2963): each part is a path's diff against
|
|
439
|
+
// the base, so beside a narrowed round 2 or a resumed round 1 the list would hand the reviewer the
|
|
440
|
+
// code that narrowing exists to keep out of scope. Decided by the target actually printed, not by
|
|
441
|
+
// the round: every round that cannot narrow widens through `whole_change_target`, and that round
|
|
442
|
+
// needs the parts as much as a first one does.
|
|
443
|
+
function diff_block(input: BriefInput, target: string): ReadonlyArray<string> {
|
|
444
|
+
const is_whole_change = target.includes(whole_change_target(input.checkout.root, input.base))
|
|
445
|
+
|
|
446
|
+
if (!is_whole_change || input.diff === undefined) return []
|
|
447
|
+
|
|
448
|
+
return ['', review_diff_parts.reading_block(input.diff.parts, input.diff.cap)]
|
|
449
|
+
}
|
|
450
|
+
|
|
390
451
|
// The level alone on the first line, because the level-only mode's contract — a caller reading the
|
|
391
452
|
// answer with `$(...)` — is the one thing a brief must not break.
|
|
392
453
|
function compose(input: BriefInput): string {
|
|
393
454
|
const profile = input.profile ?? agent_role_profile.DEFAULT_PROFILES.reviewer
|
|
455
|
+
const target = target_block(input)
|
|
394
456
|
|
|
395
457
|
return [
|
|
396
458
|
input.level,
|
|
@@ -404,28 +466,24 @@ function compose(input: BriefInput): string {
|
|
|
404
466
|
gate_line(input.stamps, input.tree, input.base),
|
|
405
467
|
TEST_COMMAND_LINE,
|
|
406
468
|
'',
|
|
407
|
-
|
|
469
|
+
target,
|
|
470
|
+
...diff_block(input, target),
|
|
408
471
|
].join('\n')
|
|
409
472
|
}
|
|
410
473
|
|
|
411
474
|
const review_brief = {
|
|
412
475
|
attest_line,
|
|
413
476
|
BASE_MOVED_PREFIX,
|
|
414
|
-
base_moved_line,
|
|
415
477
|
carried_line,
|
|
416
|
-
checkout_block,
|
|
417
478
|
checkout_warning,
|
|
418
479
|
compose,
|
|
419
480
|
dropped_line,
|
|
420
481
|
EMPTY_DELTA_LINE,
|
|
421
482
|
gate_line,
|
|
422
|
-
|
|
423
|
-
in_flight_line,
|
|
424
|
-
live_marker,
|
|
483
|
+
RESUMED_HEADING,
|
|
425
484
|
matching_stamp,
|
|
426
485
|
no_snapshot_line,
|
|
427
486
|
NOTHING_LEFT_LINE,
|
|
428
|
-
NOT_VERIFIED_LINE,
|
|
429
487
|
rubric_line,
|
|
430
488
|
RUBRIC_RELATIVE_PATH,
|
|
431
489
|
ROUND_TWO_HEADING,
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// The change handed to the reviewer as files no larger than the Bash output cap
|
|
2
|
+
// (joshuafolkken/kit#2963). The brief used to name the whole change as one `git diff` and the rubric
|
|
3
|
+
// as one path, and the forked reviewer printed both through Bash: every print past
|
|
4
|
+
// `BASH_MAX_OUTPUT_LENGTH` came back as a truncated preview plus a saved file it then re-read, and both
|
|
5
|
+
// stayed in the cached prefix of every later request — 120 overflows and 68 re-reads in one review.
|
|
6
|
+
//
|
|
7
|
+
// **The diff is split, not shortened.** Each changed path gets its own parts, every part fits under the
|
|
8
|
+
// cap, and the parts of one path concatenate back to exactly its diff — so the scope a review covers
|
|
9
|
+
// is the one `git diff` lists, and only the size of a single read changes.
|
|
10
|
+
|
|
11
|
+
// A map from each changed path to the absolute part files that carry its diff, in order.
|
|
12
|
+
type DiffParts = Readonly<Record<string, ReadonlyArray<string>>>
|
|
13
|
+
|
|
14
|
+
const LINE_BREAK = '\n'
|
|
15
|
+
|
|
16
|
+
// A line longer than the budget is cut by characters: a minified file or a lockfile line would
|
|
17
|
+
// otherwise produce one part past the cap, which is the read this module exists to remove.
|
|
18
|
+
function cut_line(line: string, budget: number): Array<string> {
|
|
19
|
+
const pieces: Array<string> = []
|
|
20
|
+
|
|
21
|
+
for (let start = 0; start < line.length; start += budget) {
|
|
22
|
+
pieces.push(line.slice(start, start + budget))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return pieces
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function pieces_of(text: string, budget: number): Array<string> {
|
|
29
|
+
return text.split(/(?<=\n)/u).flatMap((line) => cut_line(line, budget))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Line-preserving where a line fits, so a part ends on a line boundary and a reader never sees a hunk
|
|
33
|
+
// cut mid-line unless that one line is itself over the budget.
|
|
34
|
+
function is_full(current: string, piece: string, budget: number): boolean {
|
|
35
|
+
return current.length > 0 && current.length + piece.length > budget
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function split_text(text: string, budget: number): Array<string> {
|
|
39
|
+
const parts: Array<string> = []
|
|
40
|
+
let current = ''
|
|
41
|
+
|
|
42
|
+
for (const piece of pieces_of(text, budget)) {
|
|
43
|
+
if (is_full(current, piece, budget)) {
|
|
44
|
+
parts.push(current)
|
|
45
|
+
current = ''
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
current += piece
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return current.length > 0 ? [...parts, current] : parts
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function part_header(relative: string, index: number, count: number): string {
|
|
55
|
+
return `# ${relative} — part ${String(index + 1)} of ${String(count)}${LINE_BREAK}`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// The header is counted inside the cap, so the file a reader opens — header included — is what fits.
|
|
59
|
+
// The count in the header is the final one, so it is sized against the widest header it can carry.
|
|
60
|
+
function part_texts(relative: string, diff: string, cap: number): Array<string> {
|
|
61
|
+
const budget = Math.max(1, cap - part_header(relative, diff.length, diff.length).length)
|
|
62
|
+
const bodies = split_text(diff, budget)
|
|
63
|
+
|
|
64
|
+
return bodies.map((body, index) => `${part_header(relative, index, bodies.length)}${body}`)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function body_of(part: string): string {
|
|
68
|
+
return part.slice(part.indexOf(LINE_BREAK) + 1)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function part_list(parts: DiffParts): string {
|
|
72
|
+
return Object.entries(parts)
|
|
73
|
+
.flatMap(([relative, files]) => [` ${relative}`, ...files.map((file) => ` ${file}`)])
|
|
74
|
+
.join(LINE_BREAK)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// **The read instruction names the tool as well as the files.** A part under the cap would survive a
|
|
78
|
+
// `cat`, but the Read tool is the one read that is never truncated, and naming it keeps the reviewer
|
|
79
|
+
// from reaching back for the whole `git diff` the target line defines the change by.
|
|
80
|
+
function reading_block(parts: DiffParts, cap: number): string {
|
|
81
|
+
return [
|
|
82
|
+
`Reading the diff: Bash output is cut at ${String(cap)} characters, so the change is written below as one or more parts per path, each under that cap, and together exactly the diff. Read the parts of every path you review with the Read tool. Do not print the diff, or any file this brief names, through Bash (\`git diff\`, \`cat\`).`,
|
|
83
|
+
part_list(parts),
|
|
84
|
+
].join(LINE_BREAK)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const review_diff_parts = { body_of, part_texts, reading_block, split_text }
|
|
88
|
+
|
|
89
|
+
export { review_diff_parts, type DiffParts }
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { git_spawn } from '#scripts/git/git-spawn'
|
|
4
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
5
|
+
import { review_diff_parts, type DiffParts } from './review-diff-parts'
|
|
6
|
+
|
|
7
|
+
// Writes the change as the parts `review-diff-parts.ts` cuts it into (joshuafolkken/kit#2963).
|
|
8
|
+
//
|
|
9
|
+
// **One diff per path, read the way the target line defines the change** — `git -C <root> diff
|
|
10
|
+
// <base> -- <path>` for a tracked path, and the file's own content for an untracked one, which no
|
|
11
|
+
// `git diff` lists. The parts are written to the temp directory keyed per checkout, the same place the
|
|
12
|
+
// brief's other records live, and the directory is replaced on every brief so a part from an earlier
|
|
13
|
+
// tree is never offered beside this one's.
|
|
14
|
+
|
|
15
|
+
const DIRECTORY_PREFIX = 'josh-review-diff-'
|
|
16
|
+
const DIRECTORY_MODE = 0o700
|
|
17
|
+
const FILE_MODE = 0o600
|
|
18
|
+
const PART_SUFFIX = '.diff'
|
|
19
|
+
const INDEX_WIDTH = 3
|
|
20
|
+
const NUL = '\0'
|
|
21
|
+
const SLUG_SEPARATOR = '__'
|
|
22
|
+
|
|
23
|
+
function untracked_text(root: string, relative: string): string {
|
|
24
|
+
try {
|
|
25
|
+
const content = readFileSync(path.join(root, relative), 'utf8')
|
|
26
|
+
|
|
27
|
+
if (content.includes(NUL)) return `untracked binary file ${relative}, not shown\n`
|
|
28
|
+
|
|
29
|
+
return `untracked file ${relative}, shown whole:\n${content}`
|
|
30
|
+
} catch {
|
|
31
|
+
return `${relative} is listed by the change but holds no diff and no file\n`
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function path_diff(root: string, base: string, relative: string): Promise<string> {
|
|
36
|
+
const diff = await git_spawn.read(['-C', root, 'diff', '--no-color', base, '--', relative])
|
|
37
|
+
|
|
38
|
+
return diff.length > 0 ? diff : untracked_text(root, relative)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function part_name(position: number, relative: string, index: number): string {
|
|
42
|
+
const prefix = String(position).padStart(INDEX_WIDTH, '0')
|
|
43
|
+
|
|
44
|
+
return `${prefix}-${relative.split('/').join(SLUG_SEPARATOR)}-${String(index + 1)}${PART_SUFFIX}`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface PathText {
|
|
48
|
+
relative: string
|
|
49
|
+
text: string
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function write_path(
|
|
53
|
+
directory: string,
|
|
54
|
+
position: number,
|
|
55
|
+
entry: PathText,
|
|
56
|
+
cap: number,
|
|
57
|
+
): Array<string> {
|
|
58
|
+
return review_diff_parts.part_texts(entry.relative, entry.text, cap).map((part, index) => {
|
|
59
|
+
const file = path.join(directory, part_name(position, entry.relative, index))
|
|
60
|
+
|
|
61
|
+
writeFileSync(file, part, { flag: 'wx', mode: FILE_MODE })
|
|
62
|
+
|
|
63
|
+
return file
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function fresh_directory(root: string): string {
|
|
68
|
+
const directory = stamp_file.stamp_path(DIRECTORY_PREFIX, root, '')
|
|
69
|
+
|
|
70
|
+
rmSync(directory, { recursive: true, force: true })
|
|
71
|
+
mkdirSync(directory, { mode: DIRECTORY_MODE })
|
|
72
|
+
|
|
73
|
+
return directory
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface DiffRequest {
|
|
77
|
+
root: string
|
|
78
|
+
base: string
|
|
79
|
+
paths: ReadonlyArray<string>
|
|
80
|
+
cap: number
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function write_parts(request: DiffRequest, directory?: string): Promise<DiffParts> {
|
|
84
|
+
const { root, base, paths, cap } = request
|
|
85
|
+
const texts = await Promise.all(
|
|
86
|
+
paths.map(async (relative) => ({ relative, text: await path_diff(root, base, relative) })),
|
|
87
|
+
)
|
|
88
|
+
const target = directory ?? fresh_directory(root)
|
|
89
|
+
|
|
90
|
+
return Object.fromEntries(
|
|
91
|
+
texts.map((entry, position) => [entry.relative, write_path(target, position, entry, cap)]),
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const review_diff_write = { path_diff, write_parts }
|
|
96
|
+
|
|
97
|
+
export { review_diff_write }
|
|
@@ -186,7 +186,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
186
186
|
process.exitCode = await run(argv, new Date())
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
const review_record_cli = {
|
|
189
|
+
const review_record_cli = { build_lines, parse_finding, run }
|
|
190
190
|
|
|
191
191
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
192
192
|
|
|
@@ -77,7 +77,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
77
77
|
process.exitCode = await run(argv)
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
const review_round2_cli = { CLOSED_FLAG,
|
|
80
|
+
const review_round2_cli = { CLOSED_FLAG, parse_options, run }
|
|
81
81
|
|
|
82
82
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
83
83
|
|
|
@@ -59,10 +59,15 @@ const TEST_RELATED_PREFIX = 'josh-test-related-stamp-'
|
|
|
59
59
|
const GATE_PREFIX = 'josh-gate-stamp-'
|
|
60
60
|
const IN_FLIGHT_PREFIX = 'josh-gate-running-'
|
|
61
61
|
const ROUND_ONE_PREFIX = 'josh-review-round1-'
|
|
62
|
+
const BRIEFED_PREFIX = 'josh-review-briefed-'
|
|
62
63
|
|
|
63
64
|
const gate_stamp: FileMapStampAccess = file_map_stamp.create(GATE_PREFIX, PROJECT_ROOT)
|
|
64
65
|
const in_flight_stamp: FileMapStampAccess = file_map_stamp.create(IN_FLIGHT_PREFIX, PROJECT_ROOT)
|
|
65
66
|
const round_one_stamp: FileMapStampAccess = file_map_stamp.create(ROUND_ONE_PREFIX, PROJECT_ROOT)
|
|
67
|
+
// **The tree the latest round-1 brief handed out, retaken on every brief** (joshuafolkken/kit#2945).
|
|
68
|
+
// The round-1 snapshot is kept from the first brief of a run, so it is not the tree a later review
|
|
69
|
+
// read — a resume narrowed against it would skip a file put back to that older content.
|
|
70
|
+
const briefed_stamp: FileMapStampAccess = file_map_stamp.create(BRIEFED_PREFIX, PROJECT_ROOT)
|
|
66
71
|
const lint_related_stamp: FileMapStampAccess = file_map_stamp.create(
|
|
67
72
|
LINT_RELATED_PREFIX,
|
|
68
73
|
PROJECT_ROOT,
|
|
@@ -97,16 +102,15 @@ function clear_round_one(target?: string): void {
|
|
|
97
102
|
}
|
|
98
103
|
|
|
99
104
|
const review_stamps = {
|
|
105
|
+
briefed_stamp,
|
|
100
106
|
clear_round_one,
|
|
101
107
|
GATE_PREFIX,
|
|
102
108
|
gate_stamp,
|
|
103
109
|
IN_FLIGHT_PREFIX,
|
|
104
110
|
in_flight_stamp,
|
|
105
|
-
LINT_RELATED_PREFIX,
|
|
106
111
|
lint_related_stamp,
|
|
107
112
|
ROUND_ONE_PREFIX,
|
|
108
113
|
round_one_stamp,
|
|
109
|
-
TEST_RELATED_PREFIX,
|
|
110
114
|
test_related_stamp,
|
|
111
115
|
}
|
|
112
116
|
|
|
@@ -3,6 +3,7 @@ import path from 'node:path'
|
|
|
3
3
|
import { changed_paths } from '#scripts/git/changed-paths'
|
|
4
4
|
import { git_command } from '#scripts/git/git-command'
|
|
5
5
|
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
6
|
+
import { observation_ledger } from '#scripts/observations/observation-ledger'
|
|
6
7
|
|
|
7
8
|
// The tree `josh review:brief` records: every path the change touches, and the digest of its content
|
|
8
9
|
// (joshuafolkken/kit#1241).
|
|
@@ -30,8 +31,18 @@ function digest_of(root: string, relative: string): string {
|
|
|
30
31
|
|
|
31
32
|
// Sorted so two readings of one tree produce the same record byte for byte, which is what lets a
|
|
32
33
|
// stored stamp be compared against a fresh reading without a normalization step in between.
|
|
34
|
+
//
|
|
35
|
+
// **The observation ledger is left out of the map**, for the reason `hook-gate-reuse.ts` drops it from
|
|
36
|
+
// the status it reads: it is no code any check runs (joshuafolkken/kit#1756). Kept in, a review's line
|
|
37
|
+
// appended after the gate moved the map, so the ledger commit `pnpm josh followup` pushes carried a
|
|
38
|
+
// tree the record no longer matched — the pre-push hook re-ran the whole unit suite inside the push's
|
|
39
|
+
// 120-second budget, the timed-out push was retried over the still-running suite, and the commit's
|
|
40
|
+
// undo then moved the tree under both (joshuafolkken/kit#2998). Filtered here, every reader of the map
|
|
41
|
+
// — the gate's record, both hooks, the brief and the round-2 fix delta — agrees on it.
|
|
33
42
|
function tree_of(root: string, paths: ReadonlyArray<string>): Record<string, string> {
|
|
34
|
-
const sorted =
|
|
43
|
+
const sorted = paths
|
|
44
|
+
.filter((relative) => !observation_ledger.is_ledger_path(relative))
|
|
45
|
+
.toSorted((left, right) => left.localeCompare(right))
|
|
35
46
|
|
|
36
47
|
return Object.fromEntries(sorted.map((relative) => [relative, digest_of(root, relative)]))
|
|
37
48
|
}
|
|
@@ -43,6 +54,7 @@ function tree_of(root: string, paths: ReadonlyArray<string>): Record<string, str
|
|
|
43
54
|
// say the gate had verified an arbitrarily edited tree, and `--round 2` would report an empty fix
|
|
44
55
|
// delta. **A defect that answers "all clear" is the one shape this record cannot take**, which is why
|
|
45
56
|
// the root is resolved rather than assumed (measured from `scripts/`: 18 of 25 entries `absent`).
|
|
57
|
+
// The observation ledger is dropped inside `tree_of`, above (joshuafolkken/kit#3017).
|
|
46
58
|
async function read_changed_tree(
|
|
47
59
|
paths?: ReadonlyArray<string>,
|
|
48
60
|
root?: string,
|
|
@@ -53,6 +65,6 @@ async function read_changed_tree(
|
|
|
53
65
|
)
|
|
54
66
|
}
|
|
55
67
|
|
|
56
|
-
const review_tree = { ABSENT_DIGEST,
|
|
68
|
+
const review_tree = { ABSENT_DIGEST, read_changed_tree, tree_of }
|
|
57
69
|
|
|
58
70
|
export { review_tree }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { run_stage } from '#scripts/run/run-stage'
|
|
2
|
+
import type { DecisionOracle } from './decision-oracle'
|
|
3
|
+
|
|
4
|
+
// The stage-ladder oracle (joshuafolkken/kit#3042), kept beside the enumeration rather than inside it
|
|
5
|
+
// because `decision-oracle.ts` sits at its file-size limit. Where a run on an issue starts — and whether
|
|
6
|
+
// the command typed has already been reached — is computed by `run:entry` from the issue and the tree's
|
|
7
|
+
// hold, so the skill's stage table points at the command rather than re-deciding it in prose. The
|
|
8
|
+
// vocabulary is `run_stage`'s own start tokens, never a second copy.
|
|
9
|
+
const RUN_ENTRY_ORACLE: DecisionOracle = {
|
|
10
|
+
name: 'run:entry',
|
|
11
|
+
decision:
|
|
12
|
+
'Where a run on an issue starts, and whether the typed command has already been reached',
|
|
13
|
+
args: '<N> [--to kickoff|halfrun|prrun|fullrun]',
|
|
14
|
+
vocabulary: run_stage.START_TOKENS,
|
|
15
|
+
single_source: '.claude/skills/workflow-commands/SKILL.md → §2k',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { RUN_ENTRY_ORACLE }
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// not by prose. Single source: `prompts/collaboration-workflow/residency.md` → question 0.
|
|
7
7
|
//
|
|
8
8
|
// Anything not on this list is answered by prose or by a hook-delivered rule, never by a command.
|
|
9
|
+
import { RUN_ENTRY_ORACLE } from './decision-oracle-stage'
|
|
9
10
|
|
|
10
11
|
// Paths that appear in more than one entry's `single_source` field.
|
|
11
12
|
const CHAIN_RULE_MD = '.claude/skills/workflow-commands/chain-rule.md'
|
|
@@ -22,11 +23,11 @@ const BACKLOGRUN_MD = '.claude/skills/workflow-commands/backlogrun.md'
|
|
|
22
23
|
// now has its verdict contract only in this reference. That makes it the single source and the section
|
|
23
24
|
// a reader is routed to, in the same `file.md → \`josh <command>\`` form the `epic:reconcile` and
|
|
24
25
|
// `lane:list` entries already use. joshuafolkken/kit#2254.
|
|
25
|
-
const RUN_MERGE_REFERENCE = 'docs/josh-commands.md → `josh run:merge`'
|
|
26
|
-
const EPIC_NEXT_REFERENCE = 'docs/josh-commands.md → `josh epic:next`'
|
|
27
|
-
const BACKLOG_BUDGET_REFERENCE = 'docs/josh-commands.md → `josh backlog:budget`'
|
|
28
|
-
const RUN_LIVENESS_REFERENCE = 'docs/josh-commands.md → `josh run:liveness`'
|
|
29
|
-
const AUTO_OK_NEXT_REFERENCE = 'docs/josh-commands.md → `josh auto-ok:next`'
|
|
26
|
+
const RUN_MERGE_REFERENCE = 'docs/josh-commands-automation.md → `josh run:merge`'
|
|
27
|
+
const EPIC_NEXT_REFERENCE = 'docs/josh-commands-automation.md → `josh epic:next`'
|
|
28
|
+
const BACKLOG_BUDGET_REFERENCE = 'docs/josh-commands-automation.md → `josh backlog:budget`'
|
|
29
|
+
const RUN_LIVENESS_REFERENCE = 'docs/josh-commands-automation.md → `josh run:liveness`'
|
|
30
|
+
const AUTO_OK_NEXT_REFERENCE = 'docs/josh-commands-automation.md → `josh auto-ok:next`'
|
|
30
31
|
|
|
31
32
|
// Command used by two separate oracle entries (run:cut:resume and run:cut:gate).
|
|
32
33
|
const RUN_CUT_CMD = 'run:cut'
|
|
@@ -311,7 +312,7 @@ const DECISION_ORACLES: ReadonlyArray<DecisionOracle> = [
|
|
|
311
312
|
"Whether an epic's declaration matches its recorded relations, and the repair when it does not",
|
|
312
313
|
args: '--reconcile <E>',
|
|
313
314
|
vocabulary: [RECONCILED, NOTHING_TO_RECONCILE],
|
|
314
|
-
single_source: 'docs/josh-commands.md → `josh epic --reconcile`',
|
|
315
|
+
single_source: 'docs/josh-commands-automation.md → `josh epic --reconcile`',
|
|
315
316
|
},
|
|
316
317
|
{
|
|
317
318
|
name: 'lane:list',
|
|
@@ -319,8 +320,9 @@ const DECISION_ORACLES: ReadonlyArray<DecisionOracle> = [
|
|
|
319
320
|
'Whether each in-progress issue holds a live lane, and the two-directional difference',
|
|
320
321
|
args: '',
|
|
321
322
|
vocabulary: [LIVE, STOPPED, UNKNOWN],
|
|
322
|
-
single_source: 'docs/josh-commands.md → The `in-progress` / lane difference',
|
|
323
|
+
single_source: 'docs/josh-commands-automation.md → The `in-progress` / lane difference',
|
|
323
324
|
},
|
|
325
|
+
RUN_ENTRY_ORACLE,
|
|
324
326
|
]
|
|
325
327
|
|
|
326
328
|
// Returns the command name for an oracle entry. When `command` is omitted from the entry,
|
|
@@ -339,4 +341,5 @@ const decision_oracle = {
|
|
|
339
341
|
get_command,
|
|
340
342
|
}
|
|
341
343
|
|
|
344
|
+
export type { DecisionOracle }
|
|
342
345
|
export { decision_oracle }
|