@joshuafolkken/kit 1.1514.0 → 1.1784.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/investigator.md +1 -1
- package/.claude/settings.json +5 -5
- package/.claude/skills/epic-commands/SKILL.md +26 -65
- package/.claude/skills/epic-commands/epic-bundle.md +3 -1
- package/.claude/skills/workflow-commands/SKILL.md +5 -5
- package/.claude/skills/workflow-commands/background-commands.md +5 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
- package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
- package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +13 -7
- package/.claude/skills/workflow-commands/delegation.md +6 -5
- package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
- package/.claude/skills/workflow-commands/followup.md +9 -31
- package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
- package/.claude/skills/workflow-commands/fullrun.md +2 -2
- package/.claude/skills/workflow-commands/halfrun.md +17 -25
- package/.claude/skills/workflow-commands/issue-comments.md +16 -12
- package/.claude/skills/workflow-commands/issue-scout.md +2 -2
- package/.claude/skills/workflow-commands/kickoff.md +24 -23
- package/.claude/skills/workflow-commands/latest-gate.md +7 -12
- package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
- package/.claude/skills/workflow-commands/observation-filing.md +4 -36
- package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
- package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
- package/.claude/skills/workflow-commands/prerequisite.md +10 -16
- package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +3 -7
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/split-assessment.md +13 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-node/action.yml +9 -0
- package/.github/actions/setup-pnpm/action.yml +1 -1
- package/.github/dependabot.yml +16 -0
- package/.github/release.yml +0 -2
- package/.github/workflows/ci.yml +120 -10
- package/.github/workflows/publish.yml +8 -1
- package/.github/workflows/sonar-qube.yml +1 -0
- package/.prettierignore +2 -0
- package/.vscode/tasks.json +1 -2
- package/CLAUDE.md +3 -7
- package/README.md +4 -2
- package/SECURITY.md +1 -1
- package/dist/CLAUDE.md +3 -7
- package/dist/commands/document-read-cli.js +882 -0
- package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
- package/dist/commands/read-set-cli.js +1867 -0
- package/dist/commands/run-prep-main.js +21653 -0
- package/dist/commands/run-step-cli.js +23880 -0
- package/dist/config-merge/index.js +5 -1
- package/dist/hooks/audit-provision.js +20 -35
- package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
- package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
- package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
- package/dist/hooks/{chunk-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
- package/dist/hooks/chunk-TUIFS5E7.js +72 -0
- package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
- package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
- package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
- package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
- package/dist/hooks/codex-hook-adapter.js +10 -22
- package/dist/hooks/format-edited.js +5 -6
- package/dist/hooks/inputs.json +443 -317
- package/dist/hooks/pretool-guard.js +7 -25
- package/dist/hooks/session-lang.js +44 -51
- package/dist/hooks/stop-guard.js +7716 -2187
- package/dist/josh.js +6002 -3583
- package/dist/self-sync-guard/index.js +74 -10
- package/dist/version/index.js +115 -406
- package/eslint/base.js +1 -1
- package/lefthook/base.yml +3 -1
- package/package.json +10 -48
- package/pnpm-workspace.yaml +4 -2
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +1 -7
- package/prompts/collaboration-workflow/issue-citation.md +1 -1
- package/prompts/collaboration-workflow/issue-template.md +33 -16
- package/prompts/collaboration-workflow/lane-instructions.md +1 -2
- package/prompts/collaboration-workflow/measurement.md +37 -0
- package/prompts/collaboration-workflow/operating-rules.md +4 -6
- package/prompts/collaboration-workflow/output-bounds.md +2 -7
- package/prompts/collaboration-workflow/plan-comment.md +3 -42
- package/prompts/collaboration-workflow/principles.md +5 -0
- package/prompts/collaboration-workflow/report-format.md +31 -60
- package/prompts/collaboration-workflow/residency.md +2 -2
- package/prompts/collaboration-workflow/shell-body.md +6 -16
- package/prompts/collaboration-workflow/turn-batching.md +0 -2
- package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
- package/prompts/collaboration-workflow/wip-cap.md +1 -1
- package/prompts/collaboration-workflow.md +3 -7
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +41 -21
- package/prompts/testing-guide.md +8 -43
- package/scripts/agent/agent-event.ts +15 -15
- package/scripts/agent/agent-exit-record.ts +13 -1
- package/scripts/agent/api-auth.ts +41 -0
- package/scripts/agent/api-outage.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +14 -16
- package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
- package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
- package/scripts/auto-ok/auto-ok-judge.ts +13 -2
- package/scripts/auto-ok/auto-ok-main.ts +17 -0
- package/scripts/backlog/backlog-arrival.ts +14 -3
- package/scripts/backlog/backlog-budget-cli.ts +7 -33
- package/scripts/backlog/backlog-budget-main.ts +16 -0
- package/scripts/backlog/backlog-budget.ts +2 -3
- package/scripts/backlog/backlog-defect-priority.ts +4 -3
- package/scripts/backlog/backlog-drive-adopt.ts +67 -0
- package/scripts/backlog/backlog-drive-args.ts +4 -5
- package/scripts/backlog/backlog-drive-cli.ts +113 -28
- package/scripts/backlog/backlog-drive-hold.ts +162 -0
- package/scripts/backlog/backlog-drive-idle.ts +151 -0
- package/scripts/backlog/backlog-drive-judge.ts +25 -0
- package/scripts/backlog/backlog-drive-memory.ts +126 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
- package/scripts/backlog/backlog-drive-named.ts +53 -6
- package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
- package/scripts/backlog/backlog-drive-paused.ts +169 -0
- package/scripts/backlog/backlog-drive-restore.ts +30 -7
- package/scripts/backlog/backlog-drive-seats.ts +18 -8
- package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
- package/scripts/backlog/backlog-drive.ts +79 -75
- package/scripts/backlog/backlog-next-main.ts +16 -0
- package/scripts/backlog/backlog-next-shared.ts +73 -0
- package/scripts/backlog/backlog-next.ts +48 -16
- package/scripts/backlog/backlog-occupied.ts +52 -39
- package/scripts/backlog/backlog-offer-cli.ts +6 -21
- package/scripts/backlog/backlog-offer-exclude.ts +15 -0
- package/scripts/backlog/backlog-offer-main.ts +12 -0
- package/scripts/backlog/backlog-offer.ts +36 -3
- package/scripts/backlog/backlog-overlap.ts +22 -4
- package/scripts/backlog/backlog-plan-read.ts +6 -2
- package/scripts/backlog/backlog-plan.ts +18 -4
- package/scripts/backlog/backlog-pool.ts +10 -10
- package/scripts/backlog/backlog-rank.ts +10 -2
- package/scripts/backlog/backlog-ready.ts +112 -30
- package/scripts/backlog/backlog-stalled-detect.ts +109 -36
- package/scripts/backlog/backlog-stalled.ts +52 -16
- package/scripts/backlog/backlog-wait-cause.ts +86 -0
- package/scripts/backlog/backlog-waves.ts +39 -13
- package/scripts/backlog/backlogrun-args.ts +19 -7
- package/scripts/backlog/backlogrun-cli.ts +19 -5
- package/scripts/backlog/backlogrun-launch.ts +6 -0
- package/scripts/backlog/backlogrun-restart.ts +97 -0
- package/scripts/backlog/backlogrun-stop.ts +79 -7
- package/scripts/behavior/behavior-cli.ts +2 -2
- package/scripts/behavior/behavior-rules.ts +47 -24
- package/scripts/build/build-bin.ts +2 -16
- package/scripts/build/build-claude-md.ts +0 -7
- package/scripts/build/build-commands.ts +0 -13
- package/scripts/build/build-hooks.ts +49 -48
- package/scripts/build/hook-bundle-stamp.ts +29 -11
- package/scripts/build/local-bin.ts +1 -1
- package/scripts/cases/cases-cli.ts +25 -13
- package/scripts/cases/cases-interaction-scan.ts +134 -0
- package/scripts/cases/cases-interaction.ts +183 -0
- package/scripts/cases/cases-logic.ts +39 -6
- package/scripts/ci/pr-classification-main.ts +18 -0
- package/scripts/ci/pr-classification.ts +10 -17
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/cost-runtime/cost-blocks.ts +22 -37
- package/scripts/cost-runtime/cost-cli.ts +31 -14
- package/scripts/cost-runtime/cost-main.ts +12 -0
- package/scripts/cost-runtime/cost-transcript.ts +1 -0
- package/scripts/delegation/delegation-policy.ts +17 -4
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/investigation-guard.ts +0 -8
- package/scripts/delegation/investigation-reads.ts +3 -4
- package/scripts/dependabot/dependabot-cooldown.ts +194 -0
- package/scripts/discovery/repo-discovery.ts +24 -6
- package/scripts/doctor/doctor-consumer.ts +2 -5
- package/scripts/document/document-byte-budget.ts +8 -6
- package/scripts/document/document-scan.ts +1 -1
- package/scripts/document/document-section-cli.ts +0 -8
- package/scripts/document/document-section-main.ts +12 -0
- package/scripts/epic/epic-audit-cli.ts +12 -6
- package/scripts/epic/epic-bundle-apply.ts +137 -0
- package/scripts/epic/epic-bundle-cli.ts +32 -121
- package/scripts/epic/epic-bundle-format.ts +116 -0
- package/scripts/epic/epic-bundle-main.ts +17 -0
- package/scripts/epic/epic-busy.ts +5 -12
- package/scripts/epic/epic-classify.ts +24 -15
- package/scripts/epic/epic-cli-argv.ts +31 -0
- package/scripts/epic/epic-cli-decide.ts +42 -0
- package/scripts/epic/epic-cli.ts +6 -38
- package/scripts/epic/epic-close.ts +112 -55
- package/scripts/epic/epic-cross-repo.ts +4 -7
- package/scripts/epic/epic-decide.ts +119 -0
- package/scripts/epic/epic-decision.ts +9 -0
- package/scripts/epic/epic-fetch.ts +4 -0
- package/scripts/epic/epic-graph.ts +2 -0
- package/scripts/epic/epic-issue.ts +5 -1
- package/scripts/epic/epic-label-age.ts +1 -1
- package/scripts/epic/epic-lane-offer.ts +39 -4
- package/scripts/epic/epic-next-main.ts +24 -0
- package/scripts/epic/epic-next.ts +6 -24
- package/scripts/epic/epic-outside-blocker.ts +6 -2
- package/scripts/epic/epic-parse.ts +9 -3
- package/scripts/epic/epic-read.ts +1 -0
- package/scripts/epic/epic-reconcile.ts +39 -0
- package/scripts/epic/epic-run.ts +10 -1
- package/scripts/epic/epic-solo.ts +50 -14
- package/scripts/epic/epic.ts +41 -7
- package/scripts/exports/unused-members-cli.ts +2 -2
- package/scripts/followup/followup-checks-event.ts +8 -3
- package/scripts/followup/followup-coderabbit-wait.ts +82 -0
- package/scripts/followup/followup-review-gates.ts +81 -0
- package/scripts/followup/git-followup-stages.ts +13 -3
- package/scripts/followup/git-followup-workflow.ts +19 -66
- package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
- package/scripts/followup/git-pr-followup.ts +36 -8
- package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
- package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
- package/scripts/gate/busy-average.ts +58 -0
- package/scripts/gate/check-cpu.ts +60 -0
- package/scripts/gate/check-inputs.ts +39 -95
- package/scripts/gate/check-reuse.ts +33 -54
- package/scripts/gate/command-memory.ts +192 -0
- package/scripts/gate/core-admission.ts +218 -28
- package/scripts/gate/core-budget-timing.ts +37 -0
- package/scripts/gate/core-budget.ts +80 -98
- package/scripts/gate/core-wait-record.ts +48 -0
- package/scripts/gate/core-wait.ts +37 -5
- package/scripts/gate/core-weights.ts +86 -0
- package/scripts/gate/free-cores.ts +27 -4
- package/scripts/gate/gate-ledger.ts +32 -4
- package/scripts/gate/gate-plan.ts +41 -34
- package/scripts/gate/gate-report.ts +14 -2
- package/scripts/gate/gate-run-steps.ts +53 -8
- package/scripts/gate/gate-skip.ts +12 -2
- package/scripts/gate/gate-steps.ts +12 -1
- package/scripts/gate/input-fingerprint.ts +42 -0
- package/scripts/gate/machine-capacity.ts +65 -31
- package/scripts/gate/moved-paths.ts +67 -0
- package/scripts/gate/project-checks.ts +5 -12
- package/scripts/gate/scoped-green.ts +12 -8
- package/scripts/gate/since-green.ts +62 -0
- package/scripts/gate/toolchain-inputs.ts +115 -0
- package/scripts/gate/verification-gate.ts +27 -24
- package/scripts/gate/verification-inputs.ts +250 -0
- package/scripts/gh/gh-author-association.ts +96 -9
- package/scripts/gh/git-ai-review-scan.ts +4 -2
- package/scripts/gh/git-gh-api-path.ts +15 -0
- package/scripts/gh/git-gh-branch-rules.ts +73 -0
- package/scripts/gh/git-gh-conditional.ts +5 -2
- package/scripts/gh/git-gh-issue-read.ts +5 -1
- package/scripts/gh/git-gh-issue-write.ts +67 -29
- package/scripts/gh/git-gh-issue.ts +7 -3
- package/scripts/gh/git-gh-poll-read.ts +89 -0
- package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
- package/scripts/gh/git-gh-pr-rest.ts +1 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
- package/scripts/gh/git-gh-pr.ts +27 -15
- package/scripts/gh/git-pr-checks-eval.ts +39 -7
- package/scripts/gh/git-pr-checks-parse.ts +39 -9
- package/scripts/gh/git-pr-merge-checked.ts +80 -0
- package/scripts/git/base-tree.ts +19 -2
- package/scripts/git/changed-file-scope.ts +6 -4
- package/scripts/git/changed-paths.ts +18 -1
- package/scripts/git/git-diff-reads.ts +27 -2
- package/scripts/git/git-grep-hits.ts +85 -0
- package/scripts/git/git-location-environment.ts +1 -1
- package/scripts/git/git-merge-conflicts.ts +83 -0
- package/scripts/git/git-preflight.ts +37 -12
- package/scripts/git/git-push-transport.ts +1 -2
- package/scripts/git/git-schemas.ts +17 -7
- package/scripts/git/git-spawn.ts +1 -2
- package/scripts/git/git-status.ts +4 -4
- package/scripts/git/main-merge-main.ts +12 -0
- package/scripts/git/main-merge-regenerate.ts +2 -2
- package/scripts/git/main-merge.ts +25 -9
- package/scripts/git/main-sync-main.ts +12 -0
- package/scripts/git/main-sync.ts +0 -9
- package/scripts/git/stash/git-stash.ts +27 -4
- package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
- package/scripts/git/stash/stash-pop-cli.ts +6 -12
- package/scripts/git/stash/stash-pop-main.ts +12 -0
- package/scripts/git/stash/stash-push-cli.ts +76 -0
- package/scripts/git/stash/stash-push-main.ts +12 -0
- package/scripts/hooks/batch-guard.ts +0 -8
- package/scripts/hooks/check-commit-message-main.ts +8 -0
- package/scripts/hooks/check-commit-message.ts +4 -7
- package/scripts/hooks/format-edited-file.ts +8 -24
- package/scripts/hooks/pre-commit-lint.ts +30 -3
- package/scripts/hooks/pre-push-unit.ts +4 -2
- package/scripts/hooks/pretool-guard-cli.ts +1 -8
- package/scripts/hooks/pretool-guard.ts +32 -19
- package/scripts/hooks/reserved-run.ts +67 -9
- package/scripts/hooks/run-hook.sh +13 -4
- package/scripts/hooks/shell-rules-notice.ts +37 -0
- package/scripts/hooks/stop-actions.ts +2 -21
- package/scripts/hooks/stop-guard.ts +13 -9
- package/scripts/init/hook-command-rewrite.ts +19 -5
- package/scripts/init/hook-launch.ts +15 -17
- package/scripts/init/init-actions.ts +0 -6
- package/scripts/init/init-ai-copy.ts +10 -36
- package/scripts/init/init-bootstrap.ts +9 -8
- package/scripts/init/init-dry-run-report.ts +1 -1
- package/scripts/init/init-dry-run.ts +1 -1
- package/scripts/init/init-file-action.ts +7 -9
- package/scripts/init/init-logic-json-merge.ts +2 -2
- package/scripts/init/init-logic-migrate.ts +9 -82
- package/scripts/init/init-logic.ts +3 -2
- package/scripts/init/init-main.ts +12 -0
- package/scripts/init/init.ts +5 -12
- package/scripts/init/kit-development-versions.ts +3 -7
- package/scripts/init/kit-written-paths.ts +2 -2
- package/scripts/init/project-profile.ts +5 -4
- package/scripts/init/tsconfig-preset-migration.ts +2 -1
- package/scripts/init/vscode-tasks.ts +1 -1
- package/scripts/issue/defect-origin-cli.ts +106 -0
- package/scripts/issue/defect-origin-line.ts +60 -0
- package/scripts/issue/defect-origin-main.ts +11 -0
- package/scripts/issue/defect-origin.ts +114 -0
- package/scripts/issue/defect-rate-cli.ts +34 -78
- package/scripts/issue/defect-rate.ts +0 -16
- package/scripts/issue/defect-report-cli.ts +128 -0
- package/scripts/issue/defect-report-format.ts +56 -0
- package/scripts/issue/defect-report-main.ts +11 -0
- package/scripts/issue/defect-report.ts +160 -0
- package/scripts/issue/expected-effect-lint.ts +1 -0
- package/scripts/issue/issue-already-done-cli.ts +62 -0
- package/scripts/issue/issue-body-or-comment.ts +40 -0
- package/scripts/issue/issue-cite-cli.ts +0 -9
- package/scripts/issue/issue-cite-main.ts +12 -0
- package/scripts/issue/issue-classification.ts +12 -7
- package/scripts/issue/issue-comment-cli.ts +10 -24
- package/scripts/issue/issue-comment-main.ts +12 -0
- package/scripts/issue/issue-evidence-exit.ts +100 -0
- package/scripts/issue/issue-file-cli.ts +29 -7
- package/scripts/issue/issue-file.ts +19 -19
- package/scripts/issue/issue-fold-cli.ts +2 -11
- package/scripts/issue/issue-fold-main.ts +12 -0
- package/scripts/issue/issue-labels.ts +81 -90
- package/scripts/issue/issue-lint-cli.ts +2 -10
- package/scripts/issue/issue-lint-main.ts +12 -0
- package/scripts/issue/issue-measured-cli.ts +56 -0
- package/scripts/issue/issue-merged.ts +19 -2
- package/scripts/issue/issue-not-before-label.ts +135 -0
- package/scripts/issue/issue-not-before.ts +111 -0
- package/scripts/issue/issue-number-shape.ts +15 -1
- package/scripts/issue/issue-park.ts +28 -0
- package/scripts/issue/issue-plan-cli.ts +151 -0
- package/scripts/issue/issue-priority.ts +151 -0
- package/scripts/issue/issue-rank.ts +7 -1
- package/scripts/issue/issue-read-cli.ts +3 -10
- package/scripts/issue/issue-read-main.ts +12 -0
- package/scripts/issue/issue-read.ts +29 -5
- package/scripts/issue/issue-release-cli.ts +0 -10
- package/scripts/issue/issue-release-main.ts +13 -0
- package/scripts/issue/issue-release.ts +7 -12
- package/scripts/issue/issue-sample-gate.ts +192 -0
- package/scripts/issue/issue-sample-source.ts +76 -0
- package/scripts/issue/issue-scout-cli.ts +0 -11
- package/scripts/issue/issue-scout-main.ts +14 -0
- package/scripts/issue/issue-state-cli.ts +0 -10
- package/scripts/issue/issue-state-main.ts +12 -0
- package/scripts/issue/issue-watch-diff.ts +56 -15
- package/scripts/issue/issue-watch.ts +2 -1
- package/scripts/issue/issue-wip.ts +2 -7
- package/scripts/issue/measure-rerun-cli.ts +13 -8
- package/scripts/issue/plan-consumers-cli.ts +39 -0
- package/scripts/issue/plan-consumers-main.ts +11 -0
- package/scripts/issue/plan-consumers-section.ts +55 -0
- package/scripts/issue/plan-consumers.ts +127 -0
- package/scripts/josh/agent-session-environment.ts +1 -1
- package/scripts/josh/command-usage.ts +15 -43
- package/scripts/josh/file-map-stamp.ts +49 -16
- package/scripts/josh/hook-decision.ts +32 -20
- package/scripts/josh/josh-command-map.ts +4 -1
- package/scripts/josh/josh-command-types.ts +12 -6
- package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
- package/scripts/josh/josh-commands-ai.ts +157 -158
- package/scripts/josh/josh-commands-backlog.ts +82 -16
- package/scripts/josh/josh-commands-clone.ts +1 -0
- package/scripts/josh/josh-commands-development.ts +111 -71
- package/scripts/josh/josh-commands-document.ts +43 -1
- package/scripts/josh/josh-commands-epic.ts +171 -0
- package/scripts/josh/josh-commands-hooks.ts +25 -2
- package/scripts/josh/josh-commands-issue-write.ts +181 -0
- package/scripts/josh/josh-commands-issue.ts +124 -24
- package/scripts/josh/josh-commands-lane.ts +103 -2
- package/scripts/josh/josh-commands-lint.ts +19 -8
- package/scripts/josh/josh-commands-maintenance.ts +112 -4
- package/scripts/josh/josh-commands-pause.ts +29 -0
- package/scripts/josh/josh-commands-progress.ts +87 -0
- package/scripts/josh/josh-commands-project.ts +138 -9
- package/scripts/josh/josh-commands-review.ts +124 -0
- package/scripts/josh/josh-commands-run.ts +211 -23
- package/scripts/josh/josh-commands-ship.ts +169 -0
- package/scripts/josh/josh-commands-split.ts +9 -0
- package/scripts/josh/josh-commands-versioning.ts +49 -2
- package/scripts/josh/josh-commands-workflow.ts +144 -6
- package/scripts/josh/josh-logic.ts +6 -13
- package/scripts/josh/package-directory.ts +2 -4
- package/scripts/josh/process-identity.ts +13 -4
- package/scripts/josh/session-language-cli.ts +4 -8
- package/scripts/josh/session-language-main.ts +13 -0
- package/scripts/josh/session-language.ts +6 -1
- package/scripts/josh/shared-cache.ts +90 -0
- package/scripts/josh/stamp-file.ts +9 -15
- package/scripts/lane/lane-await.ts +51 -12
- package/scripts/lane/lane-cache.ts +5 -30
- package/scripts/lane/lane-capacity.ts +14 -23
- package/scripts/lane/lane-check-stats.ts +62 -21
- package/scripts/lane/lane-child-invocation.ts +8 -0
- package/scripts/lane/lane-cli.ts +15 -5
- package/scripts/lane/lane-close.ts +86 -18
- package/scripts/lane/lane-core-wait-stats.ts +66 -0
- package/scripts/lane/lane-dispatch.ts +24 -3
- package/scripts/lane/lane-gap-stats.ts +156 -0
- package/scripts/lane/lane-handoff.ts +69 -1
- package/scripts/lane/lane-held-stats.ts +129 -0
- package/scripts/lane/lane-install.ts +4 -11
- package/scripts/lane/lane-launch-cli.ts +0 -9
- package/scripts/lane/lane-launch-main.ts +12 -0
- package/scripts/lane/lane-ledger-schema.ts +266 -0
- package/scripts/lane/lane-ledger.ts +92 -123
- package/scripts/lane/lane-limit-cli.ts +12 -1
- package/scripts/lane/lane-measure-cli.ts +57 -11
- package/scripts/lane/lane-open.ts +9 -1
- package/scripts/lane/lane-parked.ts +3 -3
- package/scripts/lane/lane-pause-cli.ts +130 -0
- package/scripts/lane/lane-pause.ts +158 -0
- package/scripts/lane/lane-process-table.ts +166 -0
- package/scripts/lane/lane-reap-settle.ts +124 -0
- package/scripts/lane/lane-reap.ts +50 -15
- package/scripts/lane/lane-registry.ts +24 -3
- package/scripts/lane/lane-residents.ts +162 -0
- package/scripts/lane/lane-restart.ts +22 -2
- package/scripts/lane/lane-round-two-stats.ts +49 -0
- package/scripts/lane/lane-sampler.ts +4 -0
- package/scripts/lane/lane-session-action.ts +19 -5
- package/scripts/lane/lane-session-broker.ts +102 -21
- package/scripts/lane/lane-snapshot-trace.ts +84 -0
- package/scripts/lane/lane-spans.ts +51 -0
- package/scripts/lane/lane-spent.ts +6 -3
- package/scripts/lane/lane-stage-stats.ts +7 -2
- package/scripts/lane/lane-state.ts +302 -0
- package/scripts/lane/lane-stats.ts +58 -4
- package/scripts/lane/lane-stop-stats.ts +113 -37
- package/scripts/lane/lane-test-related-stats.ts +127 -0
- package/scripts/lane/lane-transcript-calls.ts +145 -0
- package/scripts/lane/lane-transcript-stats.ts +168 -0
- package/scripts/lane/lane-vacant.ts +13 -3
- package/scripts/lane/lane-withdraw-cli.ts +5 -4
- package/scripts/lane/lane-withdraw.ts +50 -49
- package/scripts/lane/process-directories.ts +70 -0
- package/scripts/lane/process-lane-marks.ts +94 -0
- package/scripts/lib/atomic-write.ts +62 -0
- package/scripts/lib/buffered-process.ts +12 -5
- package/scripts/lib/cli-flags.ts +53 -0
- package/scripts/lib/figure-format.ts +63 -0
- package/scripts/lib/json-value.ts +9 -1
- package/scripts/lib/package-manifest.ts +35 -0
- package/scripts/lib/read-file.ts +3 -1
- package/scripts/lib/stamped-memo.ts +63 -0
- package/scripts/lib/stdout-on-stderr.ts +24 -0
- package/scripts/lib/timeouts.ts +9 -0
- package/scripts/lib/transcript-record.ts +91 -0
- package/scripts/lines/effective-limit.ts +1 -1
- package/scripts/lint/eslint-cache-dependencies.ts +145 -0
- package/scripts/lint/eslint-daemon.ts +265 -0
- package/scripts/lint/format.ts +11 -2
- package/scripts/lint/import-graph.ts +279 -0
- package/scripts/lint/lint-gate-scope.ts +102 -0
- package/scripts/lint/lint-parallel-main.ts +19 -0
- package/scripts/lint/lint-parallel.ts +62 -30
- package/scripts/lint/lint-related-scope.ts +30 -24
- package/scripts/lint/lint-related.ts +38 -6
- package/scripts/notify/confirmation-options.ts +1 -2
- package/scripts/notify/telegram-notify.ts +20 -20
- package/scripts/notify/telegram-test-logic.ts +0 -1
- package/scripts/notify/telegram-test-main.ts +8 -0
- package/scripts/notify/telegram-test.ts +2 -6
- package/scripts/observations/observation-ledger.ts +13 -0
- package/scripts/observations/observations-flush-landing.ts +5 -3
- package/scripts/observations/observations-flush.ts +6 -1
- package/scripts/overrides/overrides-check.ts +2 -5
- package/scripts/overrides/overrides-files.ts +2 -1
- package/scripts/overrides/overrides-logic.ts +3 -6
- package/scripts/package/verify-optional-eslint-install.ts +8 -6
- package/scripts/propagate/propagate-publish.ts +2 -7
- package/scripts/propagate/propagate-targets.ts +4 -12
- package/scripts/refactor/import-graph.ts +9 -7
- package/scripts/release/github-release-runs.ts +17 -6
- package/scripts/release/release-approval-prune.ts +18 -0
- package/scripts/release/release-history.ts +1 -3
- package/scripts/release/release-progress.ts +42 -22
- package/scripts/release/release-publish-run.ts +39 -0
- package/scripts/release/release-publish.ts +6 -6
- package/scripts/release/release-scope-cli.ts +0 -10
- package/scripts/release/release-scope-main.ts +12 -0
- package/scripts/repo/repo-setting.ts +3 -6
- package/scripts/repo/required-checks-logic.ts +6 -15
- package/scripts/report/report-format-reference.ts +2 -0
- package/scripts/report/report-labels.ts +155 -0
- package/scripts/report/report-lint-cli.ts +3 -0
- package/scripts/report/report-lint.ts +85 -110
- package/scripts/report/report-template-cli.ts +59 -0
- package/scripts/report/report-template.ts +112 -0
- package/scripts/review/acceptance-map.ts +1 -0
- package/scripts/review/removed-tests-check.ts +86 -0
- package/scripts/review/removed-tests.ts +149 -0
- package/scripts/review/review-brief-cli.ts +81 -15
- package/scripts/review/review-brief-main.ts +12 -0
- package/scripts/review/review-brief.ts +31 -3
- package/scripts/review/review-code-tree.ts +10 -6
- package/scripts/review/review-comment-round.ts +26 -8
- package/scripts/review/review-finding-ledger.ts +30 -15
- package/scripts/review/review-interaction.ts +94 -0
- package/scripts/review/review-readers-scan.ts +163 -0
- package/scripts/review/review-record-cli.ts +69 -30
- package/scripts/review/review-record-main.ts +12 -0
- package/scripts/review/review-round-one-blobs.ts +221 -0
- package/scripts/review/review-round2-cli.ts +49 -12
- package/scripts/review/review-round2.ts +80 -12
- package/scripts/review/review-stamps.ts +19 -1
- package/scripts/review/review-stop-log.ts +96 -0
- package/scripts/review/review-stops-cli.ts +85 -0
- package/scripts/review/review-tree.ts +6 -17
- package/scripts/review/review-untouched-readers.ts +146 -0
- package/scripts/review/test-titles.ts +118 -0
- package/scripts/rules/agent-model.ts +8 -0
- package/scripts/rules/bash-triggers.ts +46 -3
- package/scripts/rules/decision-oracle-batch.ts +9 -1
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/delivered-rules.ts +80 -2
- package/scripts/rules/destructive-command.ts +8 -1
- package/scripts/rules/direct-filing.ts +10 -2
- package/scripts/rules/direct-issue-comment.ts +117 -0
- package/scripts/rules/direct-pr-create.ts +69 -3
- package/scripts/rules/early-heartbeat.ts +2 -1
- package/scripts/rules/file-body.ts +7 -0
- package/scripts/rules/filing-cap.ts +7 -0
- package/scripts/rules/git-argv.ts +72 -14
- package/scripts/rules/git-force.ts +12 -2
- package/scripts/rules/guard-remedy.ts +4 -0
- package/scripts/rules/implementation-cut-verdict.ts +1 -1
- package/scripts/rules/implementation-cut.ts +11 -3
- package/scripts/rules/index-guard.ts +8 -1
- package/scripts/rules/issue-comments.ts +9 -1
- package/scripts/rules/josh-git-bare.ts +7 -0
- package/scripts/rules/lane-background.ts +67 -25
- package/scripts/rules/lane-carry-conflict.ts +6 -0
- package/scripts/rules/lane-direct-tool.ts +74 -0
- package/scripts/rules/lane-interactive-ask.ts +9 -2
- package/scripts/rules/lane-park.ts +45 -23
- package/scripts/rules/lane-split-park.ts +10 -2
- package/scripts/rules/lane-switch-main.ts +7 -0
- package/scripts/rules/oracle-consulted.ts +10 -0
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/permission-guards.ts +3 -0
- package/scripts/rules/piped-verification.ts +1 -1
- package/scripts/rules/poll-loop.ts +7 -0
- package/scripts/rules/pr-merge.ts +123 -0
- package/scripts/rules/protected-files.ts +32 -5
- package/scripts/rules/raw-field-body.ts +6 -0
- package/scripts/rules/rule-body-guard.ts +8 -0
- package/scripts/rules/rule-list.ts +9 -28
- package/scripts/rules/rule-value-cache.ts +4 -9
- package/scripts/rules/rule-value-cli.ts +51 -32
- package/scripts/rules/rule-value.ts +1 -1
- package/scripts/rules/shell-segments.ts +35 -0
- package/scripts/rules/stop-rule-rows.ts +64 -0
- package/scripts/rules/stop-rules.ts +3 -4
- package/scripts/rules/test-declared-commit.ts +11 -1
- package/scripts/rules/third-party-write.ts +7 -0
- package/scripts/rules/timed-rerun.ts +69 -0
- package/scripts/rules/worktree-guard.ts +13 -3
- package/scripts/run/board/run-board-app-name.ts +23 -0
- package/scripts/run/board/run-board-cli.ts +65 -32
- package/scripts/run/board/run-board-earlier.ts +94 -0
- package/scripts/run/board/run-board-ending-reason.ts +67 -0
- package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
- package/scripts/run/board/run-board-estimate.ts +98 -0
- package/scripts/run/board/run-board-fit.ts +153 -36
- package/scripts/run/board/run-board-fold.ts +123 -0
- package/scripts/run/board/run-board-fresh.ts +2 -2
- package/scripts/run/board/run-board-gather-live.ts +29 -0
- package/scripts/run/board/run-board-gather-thread.ts +189 -0
- package/scripts/run/board/run-board-gather-worker.ts +29 -0
- package/scripts/run/board/run-board-gather.ts +187 -0
- package/scripts/run/board/run-board-github.ts +118 -38
- package/scripts/run/board/run-board-header.ts +82 -20
- package/scripts/run/board/run-board-keys.ts +58 -0
- package/scripts/run/board/run-board-kind.ts +20 -6
- package/scripts/run/board/run-board-labels.ts +116 -71
- package/scripts/run/board/run-board-lane-state.ts +109 -0
- package/scripts/run/board/run-board-lane-time.ts +122 -0
- package/scripts/run/board/run-board-layout.ts +239 -60
- package/scripts/run/board/run-board-length.ts +52 -0
- package/scripts/run/board/run-board-machine.ts +8 -4
- package/scripts/run/board/run-board-main.ts +12 -0
- package/scripts/run/board/run-board-notes.ts +52 -31
- package/scripts/run/board/run-board-now.ts +1 -1
- package/scripts/run/board/run-board-operation.ts +15 -33
- package/scripts/run/board/run-board-phase.ts +1 -1
- package/scripts/run/board/run-board-plan-shared.ts +115 -0
- package/scripts/run/board/run-board-plan.ts +55 -3
- package/scripts/run/board/run-board-planning.ts +45 -0
- package/scripts/run/board/run-board-priority.ts +44 -0
- package/scripts/run/board/run-board-process-groups.ts +195 -0
- package/scripts/run/board/run-board-read.ts +151 -27
- package/scripts/run/board/run-board-reason.ts +235 -51
- package/scripts/run/board/run-board-released.ts +35 -0
- package/scripts/run/board/run-board-render-checks.ts +39 -5
- package/scripts/run/board/run-board-render-condition.ts +96 -0
- package/scripts/run/board/run-board-render-drawn.ts +67 -0
- package/scripts/run/board/run-board-render-foot.ts +59 -0
- package/scripts/run/board/run-board-render-icon.ts +35 -0
- package/scripts/run/board/run-board-render-lanes.ts +145 -0
- package/scripts/run/board/run-board-render-lead.ts +80 -0
- package/scripts/run/board/run-board-render-legend.ts +117 -48
- package/scripts/run/board/run-board-render-notes.ts +156 -29
- package/scripts/run/board/run-board-render-processes.ts +196 -0
- package/scripts/run/board/run-board-render-section.ts +119 -0
- package/scripts/run/board/run-board-render-slot.ts +3 -36
- package/scripts/run/board/run-board-render-tail.ts +115 -48
- package/scripts/run/board/run-board-render-time.ts +56 -0
- package/scripts/run/board/run-board-render-title.ts +117 -24
- package/scripts/run/board/run-board-render-waits.ts +104 -20
- package/scripts/run/board/run-board-render.ts +207 -265
- package/scripts/run/board/run-board-roots.ts +54 -0
- package/scripts/run/board/run-board-row-yield.ts +9 -4
- package/scripts/run/board/run-board-setup.ts +1 -12
- package/scripts/run/board/run-board-snapshot.ts +111 -0
- package/scripts/run/board/run-board-spin.ts +2 -2
- package/scripts/run/board/run-board-state.ts +22 -33
- package/scripts/run/board/run-board-status.ts +147 -71
- package/scripts/run/board/run-board-thanks-read.ts +2 -2
- package/scripts/run/board/run-board-tick.ts +122 -107
- package/scripts/run/board/run-board-usage-board.ts +78 -0
- package/scripts/run/board/run-board-usage-lanes.ts +113 -0
- package/scripts/run/board/run-board-usage-listing.ts +93 -0
- package/scripts/run/board/run-board-usage-read.ts +120 -150
- package/scripts/run/board/run-board-usage-rusage.ts +19 -7
- package/scripts/run/board/run-board-usage-text.ts +139 -51
- package/scripts/run/board/run-board-usage-top.ts +102 -0
- package/scripts/run/board/run-board-usage.ts +89 -72
- package/scripts/run/board/run-board-usual.ts +20 -9
- package/scripts/run/carry/run-carry-args.ts +4 -7
- package/scripts/run/carry/run-carry-conversation.ts +1 -1
- package/scripts/run/carry/run-carry.ts +9 -4
- package/scripts/run/cut/run-cut-handoff.ts +2 -2
- package/scripts/run/event/run-event-cli.ts +1 -5
- package/scripts/run/event/run-event-filed.ts +12 -6
- package/scripts/run/event/run-event-follow.ts +2 -3
- package/scripts/run/event/run-event-render.ts +6 -10
- package/scripts/run/event/run-event-scope.ts +2 -2
- package/scripts/run/event/run-event-stream-emit.ts +82 -22
- package/scripts/run/event/run-event-stream.ts +34 -8
- package/scripts/run/hold/run-hold-adopt.ts +65 -0
- package/scripts/run/hold/run-hold-cli.ts +93 -22
- package/scripts/run/hold/run-hold-main.ts +12 -0
- package/scripts/run/hold/run-hold-member.ts +37 -0
- package/scripts/run/hold/run-stop-notify.ts +183 -0
- package/scripts/run/merge/run-merge-auth.ts +31 -0
- package/scripts/run/merge/run-merge-cli.ts +62 -48
- package/scripts/run/merge/run-merge-close.ts +74 -0
- package/scripts/run/merge/run-merge-collect.ts +6 -13
- package/scripts/run/merge/run-merge-driver.ts +71 -0
- package/scripts/run/merge/run-merge-main.ts +12 -0
- package/scripts/run/merge/run-merge-outcome.ts +23 -0
- package/scripts/run/merge/run-merge-restart.ts +39 -0
- package/scripts/run/merge/run-merge-ship.ts +20 -4
- package/scripts/run/merge/run-merge-signals.ts +33 -9
- package/scripts/run/merge/run-merge-steps.ts +120 -85
- package/scripts/run/merge/run-merge.ts +38 -37
- package/scripts/run/park/run-park-cli.ts +91 -0
- package/scripts/run/park/run-park.ts +88 -0
- package/scripts/run/park/run-stalled.ts +68 -0
- package/scripts/run/pause/run-pause-cli.ts +73 -0
- package/scripts/run/pause/run-pause.ts +251 -0
- package/scripts/run/progress/run-progress-cli.ts +4 -12
- package/scripts/run/progress/run-progress-clock.ts +1 -1
- package/scripts/run/progress/run-progress-config.ts +6 -14
- package/scripts/run/progress/run-progress-main.ts +12 -0
- package/scripts/run/progress/run-progress.ts +1 -4
- package/scripts/run/review/run-review.ts +2 -1
- package/scripts/run/run-ending.ts +1 -0
- package/scripts/run/run-invocation.ts +5 -6
- package/scripts/run/run-liveness-cli.ts +6 -8
- package/scripts/run/run-liveness.ts +60 -29
- package/scripts/run/run-next.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +2 -2
- package/scripts/run/run-preflight.ts +18 -3
- package/scripts/run/run-prep-cli.ts +1 -10
- package/scripts/run/run-prep-locate.ts +7 -50
- package/scripts/run/run-prep-main.ts +12 -0
- package/scripts/run/run-prep.ts +6 -0
- package/scripts/run/run-report-cli.ts +101 -13
- package/scripts/run/run-report-handoff.ts +114 -0
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +13 -0
- package/scripts/run/run-watcher-guard-cli.ts +1 -1
- package/scripts/run/run-watcher-guard.ts +1 -1
- package/scripts/run/ship/run-ship-args.ts +121 -0
- package/scripts/run/ship/run-ship-body-draft.ts +110 -0
- package/scripts/run/ship/run-ship-cli.ts +63 -140
- package/scripts/run/ship/run-ship-detach.ts +19 -8
- package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
- package/scripts/run/ship/run-ship-next.ts +18 -2
- package/scripts/run/ship/run-ship-overlap.ts +42 -5
- package/scripts/run/ship/run-ship-place.ts +96 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +81 -24
- package/scripts/run/ship/run-ship-preflight.ts +137 -32
- package/scripts/run/ship/run-ship-probe.ts +11 -3
- package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
- package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
- package/scripts/run/ship/run-ship-return.ts +107 -23
- package/scripts/run/ship/run-ship-review-steps.ts +105 -151
- package/scripts/run/ship/run-ship-review.ts +73 -6
- package/scripts/run/ship/run-ship-reviewer.ts +207 -0
- package/scripts/run/ship/run-ship-stage.ts +55 -6
- package/scripts/run/ship/run-ship-steps.ts +46 -15
- package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
- package/scripts/run/ship/run-ship-stop-text.ts +11 -6
- package/scripts/run/ship/run-ship-sync.ts +43 -6
- package/scripts/run/ship/run-ship.ts +30 -2
- package/scripts/run/tidy/run-tidy-cli.ts +0 -4
- package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
- package/scripts/run/tidy/run-tidy-main.ts +8 -0
- package/scripts/run/wake/run-wake-cli.ts +119 -100
- package/scripts/run/wake/run-wake-code.ts +83 -0
- package/scripts/run/wake/run-wake-driver.ts +19 -8
- package/scripts/run/wake/run-wake-loop.ts +34 -3
- package/scripts/run/wake/run-wake-main.ts +13 -0
- package/scripts/run/wake/run-wake-ports.ts +90 -0
- package/scripts/run/wake/run-wake-takeover.ts +66 -0
- package/scripts/run/wake/run-wake.ts +2 -1
- package/scripts/safe-chain/pack-hook.ts +2 -2
- package/scripts/safe-chain/preinstall-command.ts +2 -1
- package/scripts/safe-chain/project-config.ts +3 -9
- package/scripts/security/security-audit-main.ts +8 -0
- package/scripts/security/security-audit-provision-logic.ts +0 -11
- package/scripts/security/security-audit-provision-main.ts +12 -0
- package/scripts/security/security-audit-provision.ts +11 -26
- package/scripts/security/security-audit.ts +6 -7
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
- package/scripts/split/split-assess-cli.ts +2 -2
- package/scripts/split/split-assess.ts +15 -0
- package/scripts/split/split-measure.ts +65 -0
- package/scripts/sync/claude-settings-merge.ts +8 -15
- package/scripts/sync/directory-copy-guard.ts +4 -9
- package/scripts/sync/file-content.ts +78 -8
- package/scripts/sync/sync-ai-files.ts +3 -5
- package/scripts/sync/sync-configs.ts +11 -23
- package/scripts/sync/sync-hook-safety.ts +4 -10
- package/scripts/sync/sync-main.ts +11 -0
- package/scripts/sync/sync.ts +25 -37
- package/scripts/test/test-declared-changed.ts +2 -2
- package/scripts/test/test-declared.ts +1 -1
- package/scripts/test/test-e2e-guard.ts +25 -1
- package/scripts/test/test-e2e-stamp.ts +38 -0
- package/scripts/test/test-pinned-logic.ts +145 -0
- package/scripts/test/test-pinned-main.ts +78 -0
- package/scripts/test/test-pinned.ts +100 -0
- package/scripts/test/test-read-map.ts +264 -0
- package/scripts/test/test-read-recording.ts +91 -0
- package/scripts/test/test-read-trace.ts +148 -0
- package/scripts/test/test-red-main.ts +12 -0
- package/scripts/test/test-red.ts +12 -30
- package/scripts/test/test-related-main.ts +18 -0
- package/scripts/test/test-related-record.ts +119 -0
- package/scripts/test/test-related-scope.ts +229 -43
- package/scripts/test/test-related.ts +300 -22
- package/scripts/test/test-unit-guard-main.ts +15 -0
- package/scripts/test/test-unit-guard.ts +42 -24
- package/scripts/test/unit-count-file.ts +37 -0
- package/scripts/test/unit-run-marker.ts +162 -0
- package/scripts/test/unit-setup-files.ts +51 -0
- package/scripts/test/unit-worker-share.ts +61 -149
- package/scripts/test/whole-suite-files.ts +63 -0
- package/scripts/time-runtime/time-background.ts +20 -2
- package/scripts/time-runtime/time-bundles.ts +4 -3
- package/scripts/time-runtime/time-density-hook.ts +8 -6
- package/scripts/time-runtime/time-followup-stage.ts +1 -3
- package/scripts/time-runtime/time-format.ts +5 -28
- package/scripts/time-runtime/time-markers.ts +10 -1
- package/scripts/time-runtime/time-shell.ts +97 -10
- package/scripts/time-runtime/time-transcript-line.ts +49 -62
- package/scripts/uninstall/uninstall.ts +1 -1
- package/scripts/version/bump-version-main.ts +12 -0
- package/scripts/version/bump-version.ts +25 -25
- package/scripts/version/effective-upstream.ts +6 -12
- package/scripts/version/latest-corepack.ts +17 -32
- package/scripts/version/latest-if-required-cli.ts +93 -0
- package/scripts/version/latest-lane-guard-main.ts +8 -0
- package/scripts/version/latest-lane-guard.ts +0 -4
- package/scripts/version/latest-scope-cli.ts +0 -9
- package/scripts/version/latest-scope-main.ts +12 -0
- package/scripts/version/latest-update.ts +5 -5
- package/scripts/version/npm-registry.ts +44 -6
- package/scripts/version/publishable-range-check.ts +5 -16
- package/scripts/version/release-age.ts +1 -1
- package/scripts/version/release-hold.ts +1 -1
- package/scripts/version/release-window.ts +38 -0
- package/scripts/version/running-binary.ts +1 -1
- package/scripts/version/safe-chain-version-update.ts +3 -8
- package/scripts/version/version-targets.ts +6 -28
- package/templates/dependabot.yml +29 -0
- package/templates/gitignore +4 -1
- package/templates/pnpm-workspace.basic.yaml +1 -1
- package/templates/sonar-project.properties +3 -2
- package/templates/workflows/ci.yml +12 -4
- package/templates/workflows/github-release.yml +4 -0
- package/tsconfig.sonar.json +1 -1
- package/.ncurc.json +0 -3
- package/dist/hooks/batch-guard.js +0 -29
- package/dist/hooks/chunk-4KKD2UTK.js +0 -66
- package/dist/hooks/chunk-6TS2JD6D.js +0 -237
- package/dist/hooks/chunk-7DSBJVFH.js +0 -50
- package/dist/hooks/chunk-A65Y4YOR.js +0 -79
- package/dist/hooks/chunk-CDY4NFQG.js +0 -15
- package/dist/hooks/chunk-EFXE6C37.js +0 -81
- package/dist/hooks/chunk-GP4IEC4O.js +0 -20
- package/dist/hooks/chunk-JP45SOCJ.js +0 -56
- package/dist/hooks/chunk-LAOV7NLM.js +0 -45
- package/dist/hooks/chunk-M4HGZV7U.js +0 -83
- package/dist/hooks/chunk-PF2NZL2A.js +0 -131
- package/dist/hooks/chunk-PTICX4OL.js +0 -358
- package/dist/hooks/chunk-RT27QRJW.js +0 -6247
- package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
- package/dist/hooks/chunk-UPUZF3AN.js +0 -279
- package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
- package/dist/hooks/duplicate-read-guard.js +0 -30
- package/dist/hooks/investigation-guard.js +0 -29
- package/scripts/backlog/backlog-stalled-cli.ts +0 -30
- package/scripts/cost-runtime/cost-format.ts +0 -29
- package/scripts/init/basic-path-migration.ts +0 -24
- package/scripts/issue/issue-backlinks-cli.ts +0 -93
- package/scripts/josh/josh-commands-guard.ts +0 -38
- package/scripts/josh/josh-usage-automation.ts +0 -121
- package/scripts/josh/josh-usage-backlog.ts +0 -180
- package/scripts/josh/josh-usage-developer.ts +0 -230
- package/scripts/josh/josh-usage-hooks.ts +0 -38
- package/scripts/josh/josh-usage-issue.ts +0 -205
- package/scripts/josh/josh-usage-review.ts +0 -101
- package/scripts/josh/josh-usage-run.ts +0 -252
- package/scripts/josh/josh-usage-session.ts +0 -238
- package/scripts/josh/josh-usage-workflow.ts +0 -212
- package/scripts/lint/cross-file-recheck.ts +0 -155
- package/scripts/registry-migration/migrate-logic.ts +0 -237
- package/scripts/registry-migration/migrate.ts +0 -292
- package/scripts/registry-migration/user-npmrc.ts +0 -15
- package/scripts/rules/rule-guard.ts +0 -23
- package/scripts/rules/rule-registry-rows.ts +0 -292
- package/scripts/rules/rule-registry.ts +0 -112
- package/scripts/run/run-stranded-cli.ts +0 -27
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { project_checks } from '#scripts/gate/project-checks'
|
|
2
|
+
import { changed_paths } from '#scripts/git/changed-paths'
|
|
3
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
4
|
+
import { observation_ledger_home } from '#scripts/observations/observation-ledger-home'
|
|
5
|
+
import { review_finding_ledger } from './review-finding-ledger'
|
|
6
|
+
|
|
7
|
+
// The interaction review — one adversarial pass after `/code-review`, over a change to the run
|
|
8
|
+
// tooling (joshuafolkken/kit#4276).
|
|
9
|
+
//
|
|
10
|
+
// **`/code-review` reads the diff for its own correctness, and the defects came from elsewhere**: most
|
|
11
|
+
// of them were a new mechanism meeting an existing one — a pause meeting the next run, a count meeting
|
|
12
|
+
// the per-second repaint. This pass is given one role, to find the existing features the change
|
|
13
|
+
// breaks, and is due only where those meetings happen: the four directories below, in the kit
|
|
14
|
+
// repository alone — a consumer's own `scripts/run/` is not kit's run tooling.
|
|
15
|
+
//
|
|
16
|
+
// **Its round is its own ledger line, `- ri:`**, so the merge gate tells it apart from `/code-review`'s
|
|
17
|
+
// and `josh followup` refuses a due change that has none. The verdicts mirror `review_record.check`'s:
|
|
18
|
+
// `not-required` covers both a change outside the directories and a checkout that keeps no ledger.
|
|
19
|
+
|
|
20
|
+
const TARGET_DIRECTORIES = ['scripts/run/', 'scripts/lane/', 'scripts/backlog/', 'scripts/hooks/']
|
|
21
|
+
|
|
22
|
+
const NOT_DUE_LINE =
|
|
23
|
+
'Interaction review not due: this is not the kit repository, or the change touches none of scripts/run/, scripts/lane/, scripts/backlog/ or scripts/hooks/.'
|
|
24
|
+
|
|
25
|
+
const ROLE_LINES = [
|
|
26
|
+
'## Interaction review',
|
|
27
|
+
'This pass is not a second `/code-review`: do not hunt for bugs inside the diff — the round before it did. Your role is to find three existing features this change breaks. Check only these three:',
|
|
28
|
+
'1. Every state, command, label, file or process this change adds or gives a new meaning to — who else reads or writes it? Search the repository outside the diff for each. Where the plan has a `### 影響を受ける既存の利用者` section, check it names them all.',
|
|
29
|
+
'2. Does each of those readers and writers still behave correctly when the new state or value reaches it (for example, a paused lane counted as running)?',
|
|
30
|
+
'3. Does the change add heavy or synchronous work to a path called repeatedly — every second, every Bash call, every edit?',
|
|
31
|
+
"Report each break with the reader's `file:line` and the change's, rated by the rubric's severities; it is disposed of by `prompts/review.md` → \"Interaction review\".",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
type InteractionStatus = 'ok' | 'missing' | 'not-required'
|
|
35
|
+
|
|
36
|
+
function due_paths(
|
|
37
|
+
paths: ReadonlyArray<string>,
|
|
38
|
+
checkout: string = process.cwd(),
|
|
39
|
+
): ReadonlyArray<string> {
|
|
40
|
+
if (!project_checks.is_kit_repository(checkout)) return []
|
|
41
|
+
|
|
42
|
+
return paths.filter((file) => TARGET_DIRECTORIES.some((directory) => file.startsWith(directory)))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function brief_block(targets: ReadonlyArray<string>): string {
|
|
46
|
+
const listed = targets.map((file) => `- ${file}`)
|
|
47
|
+
|
|
48
|
+
return [...ROLE_LINES, 'Changed in the run tooling:', ...listed].join('\n')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function status_of(
|
|
52
|
+
issue: number,
|
|
53
|
+
paths: ReadonlyArray<string>,
|
|
54
|
+
root: string = observation_ledger_home.ledger_root(),
|
|
55
|
+
): Promise<InteractionStatus> {
|
|
56
|
+
const content = due_paths(paths).length > 0 ? await observation_ledger_home.read(root) : undefined
|
|
57
|
+
|
|
58
|
+
if (content === undefined) return 'not-required'
|
|
59
|
+
|
|
60
|
+
return review_finding_ledger.has_issue_record(content, issue, 'interaction') ? 'ok' : 'missing'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The status over this checkout's change — the reading `review:brief` takes.
|
|
64
|
+
async function status(issue: number, root?: string): Promise<InteractionStatus> {
|
|
65
|
+
return await status_of(issue, await changed_paths.read_changed_paths(false), root)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const MISSING_REASON =
|
|
69
|
+
'This change touches the run tooling, and no interaction review is recorded for its issue — the pass that looks for the existing features a change breaks, which `/code-review` does not (joshuafolkken/kit#4276).'
|
|
70
|
+
|
|
71
|
+
const REMEDY =
|
|
72
|
+
'Run it from `pnpm josh review:brief --interaction`, then record it with `pnpm josh review:record --interaction --issue <N> [<category>:<severity>:<file> ...]` — a clean pass is a call with no findings — and reissue the merge.'
|
|
73
|
+
|
|
74
|
+
function refusal_message(issue: number): string {
|
|
75
|
+
return [MISSING_REASON, `Issue: ${session_cite.issue(issue)}`, REMEDY].join('\n')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// The merge gate's half: the refusal for a due change with no recorded pass, else `undefined`.
|
|
79
|
+
async function refusal(issue: number, root?: string): Promise<string | undefined> {
|
|
80
|
+
return (await status(issue, root)) === 'missing' ? refusal_message(issue) : undefined
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const review_interaction = {
|
|
84
|
+
brief_block,
|
|
85
|
+
due_paths,
|
|
86
|
+
NOT_DUE_LINE,
|
|
87
|
+
refusal,
|
|
88
|
+
refusal_message,
|
|
89
|
+
status,
|
|
90
|
+
status_of,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type { InteractionStatus }
|
|
94
|
+
export { review_interaction }
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// The exported names a diff edits, read from one file's `git diff -U0` and its new text
|
|
2
|
+
// (joshuafolkken/kit#4515). Pure: `review-untouched-readers.ts` reads the diff and searches each name.
|
|
3
|
+
//
|
|
4
|
+
// **A name is edited when a changed line falls inside its top-level declaration** — from the
|
|
5
|
+
// declaration's first line to the line before the next one. Only a name another module can reach is
|
|
6
|
+
// returned, spelled the way a reader writes it: a direct export as itself, a member of an exported
|
|
7
|
+
// namespace object (`export { issue_merged }`) as `issue_merged.read_merged`. The namespace object
|
|
8
|
+
// itself is skipped — a member added to it changes none of its readers.
|
|
9
|
+
|
|
10
|
+
const HUNK_HEADER = /^@@ -\d+(?:,\d+)? \+(?<start>\d+)(?:,(?<count>\d+))? @@/u
|
|
11
|
+
const DECLARATION =
|
|
12
|
+
/^(?:export\s+)?(?:async\s+)?(?:function\*?|const|let|class|type|interface|enum)\s+(?<name>\w+)/u
|
|
13
|
+
const EXPORT_LIST = /^export\s+(?:type\s+)?\{(?<names>[^}]*)\}/gmu
|
|
14
|
+
const IDENTIFIER = /^(?:type\s+)?(?<name>\w+)/u
|
|
15
|
+
const DIRECT_EXPORT = /^export\s/u
|
|
16
|
+
const LIST_SEPARATOR = ','
|
|
17
|
+
// A blank line or a comment line — `//`, `/*`, or a block comment's ` *` continuation.
|
|
18
|
+
const PREAMBLE = /^(?:\s*$|\s*\/[/*]|\s+\*)/u
|
|
19
|
+
// From a 1-based line number to the index of the line above it.
|
|
20
|
+
const TWO = 2
|
|
21
|
+
|
|
22
|
+
interface Declaration {
|
|
23
|
+
name: string
|
|
24
|
+
line: number
|
|
25
|
+
is_exported: boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface Edited {
|
|
29
|
+
// The spelling a reader uses — `name` or `namespace.member`.
|
|
30
|
+
target: string
|
|
31
|
+
line: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function to_range(start: number, count: number): Array<number> {
|
|
35
|
+
return Array.from({ length: count }, (_unused, offset) => start + offset)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// A pure deletion (`+c,0`) is placed on the line before it, which still lies inside the declaration
|
|
39
|
+
// it was cut from.
|
|
40
|
+
function hunk_lines(header: string): Array<number> {
|
|
41
|
+
const groups = HUNK_HEADER.exec(header)?.groups
|
|
42
|
+
|
|
43
|
+
if (groups === undefined) return []
|
|
44
|
+
|
|
45
|
+
const start = Number(groups['start'])
|
|
46
|
+
const count = groups['count'] === undefined ? 1 : Number(groups['count'])
|
|
47
|
+
|
|
48
|
+
return count === 0 ? [start] : to_range(start, count)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function changed_lines(diff: string): Array<number> {
|
|
52
|
+
return diff.split('\n').flatMap((line) => hunk_lines(line))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function to_declaration(text: string, index: number): Declaration | undefined {
|
|
56
|
+
const name = DECLARATION.exec(text)?.groups?.['name']
|
|
57
|
+
|
|
58
|
+
if (name === undefined) return undefined
|
|
59
|
+
|
|
60
|
+
return { name, line: index + 1, is_exported: DIRECT_EXPORT.test(text) }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function declarations(source: string): Array<Declaration> {
|
|
64
|
+
const found = source.split('\n').map((text, index) => to_declaration(text, index))
|
|
65
|
+
|
|
66
|
+
return found.filter((entry): entry is Declaration => entry !== undefined)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function first_identifier(entry: string): string | undefined {
|
|
70
|
+
return IDENTIFIER.exec(entry.trim())?.groups?.['name']
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function list_names(list: string): Array<string> {
|
|
74
|
+
const names = list.split(LIST_SEPARATOR).map((entry) => first_identifier(entry))
|
|
75
|
+
|
|
76
|
+
return names.filter((name): name is string => name !== undefined)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function exported_names(source: string): Set<string> {
|
|
80
|
+
const lists = [...source.matchAll(EXPORT_LIST)].map((match) => match.groups?.['names'] ?? '')
|
|
81
|
+
|
|
82
|
+
return new Set(lists.flatMap((list) => list_names(list)))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The members of `const <name> = { … }`, or `undefined` where `name` is not an object literal. `name`
|
|
86
|
+
// is a `\w+` match, so it carries no pattern syntax.
|
|
87
|
+
function namespace_members(source: string, name: string): Array<string> | undefined {
|
|
88
|
+
const literal = new RegExp(String.raw`^const\s+${name}\s*=\s*\{(?<body>[^}]*)\}`, 'mu')
|
|
89
|
+
const body = literal.exec(source)?.groups?.['body']
|
|
90
|
+
|
|
91
|
+
return body === undefined ? undefined : list_names(body)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function namespaces(source: string, exported: ReadonlySet<string>): Map<string, Array<string>> {
|
|
95
|
+
const entries = [...exported].map((name) => [name, namespace_members(source, name)] as const)
|
|
96
|
+
|
|
97
|
+
return new Map(
|
|
98
|
+
entries.filter((entry): entry is [string, Array<string>] => entry[1] !== undefined),
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The line after a declaration's own text: the next declaration's line, moved back past the blank and
|
|
103
|
+
// comment lines that introduce it — a comment edited above `b` edits `b`, not the `a` before it.
|
|
104
|
+
function range_end(texts: ReadonlyArray<string>, next: number | undefined): number {
|
|
105
|
+
if (next === undefined) return Infinity
|
|
106
|
+
|
|
107
|
+
let end = next
|
|
108
|
+
|
|
109
|
+
while (end > 1 && PREAMBLE.test(texts[end - TWO] ?? '')) end -= 1
|
|
110
|
+
|
|
111
|
+
return end
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function touched(source: string, lines: ReadonlySet<number>): Array<Declaration> {
|
|
115
|
+
const found = declarations(source)
|
|
116
|
+
const texts = source.split('\n')
|
|
117
|
+
|
|
118
|
+
return found.filter((declaration, index) => {
|
|
119
|
+
const end = range_end(texts, found[index + 1]?.line)
|
|
120
|
+
|
|
121
|
+
return [...lines].some((line) => line >= declaration.line && line < end)
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function namespace_of(
|
|
126
|
+
name: string,
|
|
127
|
+
spaces: ReadonlyMap<string, ReadonlyArray<string>>,
|
|
128
|
+
): string | undefined {
|
|
129
|
+
return [...spaces].find(([, members]) => members.includes(name))?.[0]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface ExportView {
|
|
133
|
+
exported: ReadonlySet<string>
|
|
134
|
+
spaces: ReadonlyMap<string, ReadonlyArray<string>>
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function target_of(declaration: Declaration, view: ExportView): string | undefined {
|
|
138
|
+
const { name } = declaration
|
|
139
|
+
|
|
140
|
+
if (view.spaces.has(name)) return undefined
|
|
141
|
+
if (declaration.is_exported || view.exported.has(name)) return name
|
|
142
|
+
|
|
143
|
+
const space = namespace_of(name, view.spaces)
|
|
144
|
+
|
|
145
|
+
return space === undefined ? undefined : `${space}.${name}`
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function edited(source: string, diff: string): Array<Edited> {
|
|
149
|
+
const exported = exported_names(source)
|
|
150
|
+
const view = { exported, spaces: namespaces(source, exported) }
|
|
151
|
+
const edited_declarations = touched(source, new Set(changed_lines(diff)))
|
|
152
|
+
const found_targets = edited_declarations.map((declaration) => ({
|
|
153
|
+
target: target_of(declaration, view),
|
|
154
|
+
line: declaration.line,
|
|
155
|
+
}))
|
|
156
|
+
|
|
157
|
+
return found_targets.filter((entry): entry is Edited => entry.target !== undefined)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const review_readers_scan = { changed_lines, edited }
|
|
161
|
+
|
|
162
|
+
export type { Edited }
|
|
163
|
+
export { review_readers_scan }
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
import { fileURLToPath } from 'node:url'
|
|
3
1
|
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
4
2
|
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
5
3
|
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
6
4
|
import { observation_ledger_home } from '#scripts/observations/observation-ledger-home'
|
|
7
5
|
import { review_comment_round } from './review-comment-round'
|
|
8
|
-
import { review_finding_ledger, type Finding } from './review-finding-ledger'
|
|
6
|
+
import { review_finding_ledger, type Finding, type LineKind } from './review-finding-ledger'
|
|
7
|
+
import { review_interaction } from './review-interaction'
|
|
9
8
|
import { review_record, type RecordVerdict } from './review-record'
|
|
10
9
|
|
|
11
10
|
// `josh review:record --issue <N> [<category>:<severity>:<file> ...]` — the one write path for a
|
|
@@ -23,16 +22,21 @@ import { review_record, type RecordVerdict } from './review-record'
|
|
|
23
22
|
// `josh review:record --check --issue <N>` is the read half `pnpm josh followup` runs before it
|
|
24
23
|
// merges: `ok` / `not-required` exit zero, `missing` exits non-zero so the
|
|
25
24
|
// merge is refused until the round is recorded. It mirrors `josh review:attest --check`.
|
|
25
|
+
//
|
|
26
|
+
// **`--interaction` records and checks the interaction review's pass instead** (`review-interaction.ts`):
|
|
27
|
+
// the same grammar under `- ri:`. It takes no `--comment` — the pass runs before the pull request, and
|
|
28
|
+
// a pass kept only on the issue would leave the merge gate reading it as missing.
|
|
26
29
|
|
|
27
|
-
const ARGV_OFFSET = 2
|
|
28
30
|
const FAILURE_EXIT_CODE = 1
|
|
29
31
|
const USAGE =
|
|
30
|
-
'Usage: josh review:record --issue <N> [--comment] [<category>:<severity>:<file> ...] | josh review:record --check --issue <N>'
|
|
32
|
+
'Usage: josh review:record --issue <N> [--comment | --interaction] [<category>:<severity>:<file> ...] | josh review:record --check [--interaction] --issue <N>'
|
|
31
33
|
const FILE_HINT = ' <file>: the cited path, optionally with :line'
|
|
32
|
-
const CHECK_USAGE = 'Usage: josh review:record --check --issue <N>'
|
|
34
|
+
const CHECK_USAGE = 'Usage: josh review:record --check [--interaction] --issue <N>'
|
|
33
35
|
const RECORDED_LINE = 'Recorded: the review round for this issue is in the ledger.'
|
|
34
36
|
const NOT_REQUIRED_LINE =
|
|
35
37
|
'No review-finding ledger is kept in this checkout, so there is nothing to check.'
|
|
38
|
+
const INTERACTION_NOT_REQUIRED_LINE =
|
|
39
|
+
'No interaction review is due: the change touches no run tooling, or this checkout keeps no ledger.'
|
|
36
40
|
const CARRIED_LINE =
|
|
37
41
|
'review-finding line(s) recorded on closed issues after their pull requests opened into the ledger.'
|
|
38
42
|
const CARRY_FAILED_LINE =
|
|
@@ -41,6 +45,7 @@ const OPTIONS = {
|
|
|
41
45
|
issue: { type: 'string' },
|
|
42
46
|
check: { type: 'boolean' },
|
|
43
47
|
comment: { type: 'boolean' },
|
|
48
|
+
interaction: { type: 'boolean' },
|
|
44
49
|
} as const
|
|
45
50
|
|
|
46
51
|
interface Request {
|
|
@@ -51,6 +56,7 @@ interface Request {
|
|
|
51
56
|
interface Parsed {
|
|
52
57
|
check: boolean
|
|
53
58
|
comment: boolean
|
|
59
|
+
interaction: boolean
|
|
54
60
|
issue: string | undefined
|
|
55
61
|
positionals: ReadonlyArray<string>
|
|
56
62
|
}
|
|
@@ -99,6 +105,7 @@ function parse_argv(argv: ReadonlyArray<string>): Parsed | undefined {
|
|
|
99
105
|
return {
|
|
100
106
|
check: parsed.values.check === true,
|
|
101
107
|
comment: parsed.values.comment === true,
|
|
108
|
+
interaction: parsed.values.interaction === true,
|
|
102
109
|
issue: parsed.values.issue,
|
|
103
110
|
positionals: parsed.positionals,
|
|
104
111
|
}
|
|
@@ -129,13 +136,17 @@ function usage_text(): string {
|
|
|
129
136
|
].join('\n')
|
|
130
137
|
}
|
|
131
138
|
|
|
132
|
-
function build_lines(
|
|
139
|
+
function build_lines(
|
|
140
|
+
request: Request,
|
|
141
|
+
date: string,
|
|
142
|
+
kind: LineKind = 'code',
|
|
143
|
+
): ReadonlyArray<string> {
|
|
133
144
|
if (request.findings.length === 0) {
|
|
134
|
-
return [review_finding_ledger.zero_round_line(date, request.issue)]
|
|
145
|
+
return [review_finding_ledger.zero_round_line(date, request.issue, kind)]
|
|
135
146
|
}
|
|
136
147
|
|
|
137
148
|
return request.findings.map((finding) =>
|
|
138
|
-
review_finding_ledger.finding_line(finding, date, request.issue),
|
|
149
|
+
review_finding_ledger.finding_line(finding, date, request.issue, kind),
|
|
139
150
|
)
|
|
140
151
|
}
|
|
141
152
|
|
|
@@ -143,28 +154,62 @@ function confirmation(count: number, ledger_path: string): string {
|
|
|
143
154
|
return `Recorded ${String(count)} review-finding line(s) in ${ledger_path}.`
|
|
144
155
|
}
|
|
145
156
|
|
|
146
|
-
|
|
147
|
-
|
|
157
|
+
type CheckStatus = RecordVerdict['status']
|
|
158
|
+
|
|
159
|
+
interface CheckMode {
|
|
160
|
+
status: (issue: number, root: string) => Promise<CheckStatus>
|
|
161
|
+
refusal: (issue: number) => string
|
|
162
|
+
not_required: string
|
|
148
163
|
}
|
|
149
164
|
|
|
150
|
-
async function
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
async function code_status(issue: number, root: string): Promise<CheckStatus> {
|
|
166
|
+
const verdict = await review_record.check(issue, root)
|
|
167
|
+
|
|
168
|
+
return verdict.status
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// The two rounds a check reads, each with its own ledger line, refusal and quiet answer.
|
|
172
|
+
const CHECK_MODES: Record<LineKind, CheckMode> = {
|
|
173
|
+
code: {
|
|
174
|
+
status: code_status,
|
|
175
|
+
refusal: review_record.refusal_message,
|
|
176
|
+
not_required: NOT_REQUIRED_LINE,
|
|
177
|
+
},
|
|
178
|
+
interaction: {
|
|
179
|
+
status: review_interaction.status,
|
|
180
|
+
refusal: review_interaction.refusal_message,
|
|
181
|
+
not_required: INTERACTION_NOT_REQUIRED_LINE,
|
|
182
|
+
},
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function kind_of(parsed: Parsed): LineKind {
|
|
186
|
+
return parsed.interaction ? 'interaction' : 'code'
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function report_check(issue: number, mode: CheckMode, root: string): Promise<number> {
|
|
190
|
+
const status = await mode.status(issue, root)
|
|
191
|
+
|
|
192
|
+
if (status === 'missing') {
|
|
193
|
+
console.error(mode.refusal(issue))
|
|
153
194
|
|
|
154
195
|
return FAILURE_EXIT_CODE
|
|
155
196
|
}
|
|
156
197
|
|
|
157
|
-
|
|
198
|
+
console.info(status === 'ok' ? RECORDED_LINE : mode.not_required)
|
|
158
199
|
|
|
159
|
-
|
|
160
|
-
|
|
200
|
+
return 0
|
|
201
|
+
}
|
|
161
202
|
|
|
162
|
-
|
|
163
|
-
}
|
|
203
|
+
async function run_check(parsed: Parsed, root: string): Promise<number> {
|
|
204
|
+
const { issue } = parsed
|
|
205
|
+
|
|
206
|
+
if (issue === undefined || !issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue)) {
|
|
207
|
+
console.error(CHECK_USAGE)
|
|
164
208
|
|
|
165
|
-
|
|
209
|
+
return FAILURE_EXIT_CODE
|
|
210
|
+
}
|
|
166
211
|
|
|
167
|
-
return
|
|
212
|
+
return await report_check(Number(issue), CHECK_MODES[kind_of(parsed)], root)
|
|
168
213
|
}
|
|
169
214
|
|
|
170
215
|
// **A comment that could not be posted fails the record**: it is the round's only copy, so a
|
|
@@ -216,7 +261,7 @@ async function append_round(
|
|
|
216
261
|
}
|
|
217
262
|
|
|
218
263
|
async function run_record(parsed: Parsed, now: Date, root: string): Promise<number> {
|
|
219
|
-
const request = to_request(parsed)
|
|
264
|
+
const request = parsed.comment && parsed.interaction ? undefined : to_request(parsed)
|
|
220
265
|
|
|
221
266
|
if (request === undefined) {
|
|
222
267
|
console.error(usage_text())
|
|
@@ -224,7 +269,7 @@ async function run_record(parsed: Parsed, now: Date, root: string): Promise<numb
|
|
|
224
269
|
return FAILURE_EXIT_CODE
|
|
225
270
|
}
|
|
226
271
|
|
|
227
|
-
const lines = build_lines(request, observation_ledger_home.ledger_date(now))
|
|
272
|
+
const lines = build_lines(request, observation_ledger_home.ledger_date(now), kind_of(parsed))
|
|
228
273
|
|
|
229
274
|
if (parsed.comment) return await post_comment(request.issue, lines)
|
|
230
275
|
|
|
@@ -247,15 +292,11 @@ async function run(
|
|
|
247
292
|
return FAILURE_EXIT_CODE
|
|
248
293
|
}
|
|
249
294
|
|
|
250
|
-
if (parsed.check) return await run_check(parsed
|
|
295
|
+
if (parsed.check) return await run_check(parsed, root)
|
|
251
296
|
|
|
252
297
|
return await run_record(parsed, now, root)
|
|
253
298
|
}
|
|
254
299
|
|
|
255
|
-
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
256
|
-
process.exitCode = await run(argv, new Date())
|
|
257
|
-
}
|
|
258
|
-
|
|
259
300
|
const review_record_cli = {
|
|
260
301
|
accepted_values,
|
|
261
302
|
build_lines,
|
|
@@ -264,6 +305,4 @@ const review_record_cli = {
|
|
|
264
305
|
usage_text,
|
|
265
306
|
}
|
|
266
307
|
|
|
267
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
268
|
-
|
|
269
308
|
export { review_record_cli }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { review_record_cli } from './review-record-cli'
|
|
4
|
+
|
|
5
|
+
// The `josh review:record` entry, kept apart from `review-record-cli.ts` because `run-ship-review.ts`
|
|
6
|
+
// imports that one: a bundle is one file, so a main guard there would fire for every command that
|
|
7
|
+
// carries it (joshuafolkken/kit#4186).
|
|
8
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
9
|
+
const ARGV_OFFSET = 2
|
|
10
|
+
|
|
11
|
+
process.exitCode = await review_record_cli.run(process.argv.slice(ARGV_OFFSET), new Date())
|
|
12
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { git_spawn_sync } from '#scripts/git/git-spawn-sync'
|
|
4
|
+
import { review_tree } from './review-tree'
|
|
5
|
+
|
|
6
|
+
// Round 1's files as git blobs, so round 2 can still name the fix delta after the change base moved
|
|
7
|
+
// (joshuafolkken/kit#4165).
|
|
8
|
+
//
|
|
9
|
+
// **A lane merges the default branch between the rounds**, which moves the base, and the round-1 file
|
|
10
|
+
// map then covers a different set of paths from the one read now. Its digests cannot be carried onto
|
|
11
|
+
// the new base; blobs can. `capture` writes each round-1 path into the object store — nothing else:
|
|
12
|
+
// no index, no commit, no ref. `carried_delta` then carries each path three ways — the old base, round
|
|
13
|
+
// 1, the new base — and names the paths whose carried content differs from the working tree now. A
|
|
14
|
+
// path the default branch alone changed carries to exactly what the merge left, so it drops out; what
|
|
15
|
+
// is left is round 1's fixes.
|
|
16
|
+
//
|
|
17
|
+
// **Every failure answers `undefined`**, which round 2 reads as the moved-base refusal it gave before:
|
|
18
|
+
// no recorded blobs, a carry that conflicts, or a git that cannot run one of the reads.
|
|
19
|
+
|
|
20
|
+
// A path the working tree or a commit does not hold.
|
|
21
|
+
const ABSENT = review_tree.ABSENT_DIGEST
|
|
22
|
+
const SUCCESS_EXIT_CODE = 0
|
|
23
|
+
const NUL = '\0'
|
|
24
|
+
const NEWLINE = '\n'
|
|
25
|
+
const TAB = '\t'
|
|
26
|
+
const SPACE = ' '
|
|
27
|
+
const OID_FIELD = 2
|
|
28
|
+
const WRITE_FLAGS: ReadonlyArray<string> = ['-w']
|
|
29
|
+
const READ_FLAGS: ReadonlyArray<string> = []
|
|
30
|
+
|
|
31
|
+
interface Move {
|
|
32
|
+
// The base round 1 was read against, and the base now.
|
|
33
|
+
from: string | undefined
|
|
34
|
+
to: string | undefined
|
|
35
|
+
// The paths to read: for a carry, those changed against the base now.
|
|
36
|
+
paths: ReadonlyArray<string>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface CarryInput extends Move {
|
|
40
|
+
// Round 1's blobs, from the snapshot.
|
|
41
|
+
blobs: Record<string, string> | undefined
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface Carry {
|
|
45
|
+
blobs: Record<string, string>
|
|
46
|
+
from: string
|
|
47
|
+
to: string
|
|
48
|
+
paths: ReadonlyArray<string>
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface Readings {
|
|
52
|
+
blobs: Record<string, string>
|
|
53
|
+
before: Record<string, string>
|
|
54
|
+
after: Record<string, string>
|
|
55
|
+
now: Record<string, string>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface Sides {
|
|
59
|
+
base: string
|
|
60
|
+
round_one: string
|
|
61
|
+
moved: string
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// git's paths are root-relative, so every command runs from the root rather than the caller's cwd.
|
|
65
|
+
function repository_root(): string | undefined {
|
|
66
|
+
return git_spawn_sync.read(['rev-parse', '--show-toplevel'])
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function hash_paths(
|
|
70
|
+
root: string,
|
|
71
|
+
paths: ReadonlyArray<string>,
|
|
72
|
+
flags: ReadonlyArray<string>,
|
|
73
|
+
): Record<string, string> | undefined {
|
|
74
|
+
const present = paths.filter((relative) => existsSync(path.join(root, relative)))
|
|
75
|
+
const output =
|
|
76
|
+
present.length === 0
|
|
77
|
+
? ''
|
|
78
|
+
: git_spawn_sync.read(['hash-object', ...flags, '--', ...present], { cwd: root })
|
|
79
|
+
|
|
80
|
+
if (output === undefined) return undefined
|
|
81
|
+
|
|
82
|
+
const hashes = output.split(NEWLINE)
|
|
83
|
+
const hashed = new Map(present.map((relative, index) => [relative, hashes[index] ?? ABSENT]))
|
|
84
|
+
|
|
85
|
+
return Object.fromEntries(paths.map((relative) => [relative, hashed.get(relative) ?? ABSENT]))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// `<mode> <type> <oid>\t<path>`.
|
|
89
|
+
function parse_entry(entry: string): [string, string] {
|
|
90
|
+
const tab = entry.indexOf(TAB)
|
|
91
|
+
|
|
92
|
+
return [entry.slice(tab + 1), entry.slice(0, tab).split(SPACE)[OID_FIELD] ?? ABSENT]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function blobs_at(
|
|
96
|
+
commit: string,
|
|
97
|
+
paths: ReadonlyArray<string>,
|
|
98
|
+
root: string,
|
|
99
|
+
): Record<string, string> | undefined {
|
|
100
|
+
const result = git_spawn_sync.run(['ls-tree', '-r', '-z', commit, '--', ...paths], { cwd: root })
|
|
101
|
+
|
|
102
|
+
if (result.exit_code !== SUCCESS_EXIT_CODE) return undefined
|
|
103
|
+
|
|
104
|
+
return Object.fromEntries(
|
|
105
|
+
result.stdout
|
|
106
|
+
.split(NUL)
|
|
107
|
+
.filter((entry) => entry !== '')
|
|
108
|
+
.map((entry) => parse_entry(entry)),
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// `git merge-file` exits with the number of conflicts, so only a clean merge answers an oid.
|
|
113
|
+
function merged_blob({ base, round_one, moved }: Sides, root: string): string | undefined {
|
|
114
|
+
if ([base, round_one, moved].includes(ABSENT)) return undefined
|
|
115
|
+
|
|
116
|
+
return git_spawn_sync.read(['merge-file', '--object-id', round_one, base, moved], { cwd: root })
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function carried_blob(sides: Sides, root: string): string | undefined {
|
|
120
|
+
if (sides.round_one === sides.base) return sides.moved
|
|
121
|
+
if (sides.moved === sides.base || sides.moved === sides.round_one) return sides.round_one
|
|
122
|
+
|
|
123
|
+
return merged_blob(sides, root)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// A path round 1 did not list was unchanged against its base, so round 1 held the base's blob.
|
|
127
|
+
function sides_of(relative: string, readings: Readings): Sides {
|
|
128
|
+
const base = readings.before[relative] ?? ABSENT
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
base,
|
|
132
|
+
round_one: readings.blobs[relative] ?? base,
|
|
133
|
+
moved: readings.after[relative] ?? ABSENT,
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function differing(
|
|
138
|
+
paths: ReadonlyArray<string>,
|
|
139
|
+
readings: Readings,
|
|
140
|
+
root: string,
|
|
141
|
+
): ReadonlyArray<string> | undefined {
|
|
142
|
+
const carried = paths.map((relative) => carried_blob(sides_of(relative, readings), root))
|
|
143
|
+
|
|
144
|
+
if (carried.includes(undefined)) return undefined
|
|
145
|
+
|
|
146
|
+
return paths.filter((relative, index) => carried[index] !== readings.now[relative])
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function read_readings(
|
|
150
|
+
input: Carry,
|
|
151
|
+
paths: ReadonlyArray<string>,
|
|
152
|
+
root: string,
|
|
153
|
+
): Readings | undefined {
|
|
154
|
+
const before = blobs_at(input.from, paths, root)
|
|
155
|
+
const after = blobs_at(input.to, paths, root)
|
|
156
|
+
const now = hash_paths(root, paths, READ_FLAGS)
|
|
157
|
+
|
|
158
|
+
if (before === undefined || after === undefined || now === undefined) return undefined
|
|
159
|
+
|
|
160
|
+
return { blobs: input.blobs, before, after, now }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// No paths at all is an empty delta: `ls-tree` given none would list the whole tree.
|
|
164
|
+
function delta_of(input: Carry, root: string): ReadonlyArray<string> | undefined {
|
|
165
|
+
const paths = [...new Set([...Object.keys(input.blobs), ...input.paths])].toSorted(
|
|
166
|
+
(left, right) => left.localeCompare(right),
|
|
167
|
+
)
|
|
168
|
+
const readings = paths.length === 0 ? undefined : read_readings(input, paths, root)
|
|
169
|
+
|
|
170
|
+
if (paths.length === 0) return []
|
|
171
|
+
|
|
172
|
+
return readings === undefined ? undefined : differing(paths, readings, root)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function carried_delta(input: CarryInput): ReadonlyArray<string> | undefined {
|
|
176
|
+
const { blobs, from, to } = input
|
|
177
|
+
const root = repository_root()
|
|
178
|
+
|
|
179
|
+
if (root === undefined || blobs === undefined || from === undefined || to === undefined) {
|
|
180
|
+
return undefined
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return delta_of({ blobs, from, to, paths: input.paths }, root)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function unmoved_between(
|
|
187
|
+
from: string,
|
|
188
|
+
to: string,
|
|
189
|
+
paths: ReadonlyArray<string>,
|
|
190
|
+
root: string,
|
|
191
|
+
): ReadonlyArray<string> | undefined {
|
|
192
|
+
if (from === to || paths.length === 0) return paths
|
|
193
|
+
const before = blobs_at(from, paths, root)
|
|
194
|
+
const after = blobs_at(to, paths, root)
|
|
195
|
+
|
|
196
|
+
if (before === undefined || after === undefined) return undefined
|
|
197
|
+
|
|
198
|
+
return paths.filter((relative) => (before[relative] ?? ABSENT) === (after[relative] ?? ABSENT))
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// The paths the base move left alone: there the carry reproduces round 1's file, so the fix delta on
|
|
202
|
+
// them is round 1 against the working tree, as on an unmoved base. `undefined` when git cannot say.
|
|
203
|
+
function unmoved({ from, to, paths }: Move): ReadonlyArray<string> | undefined {
|
|
204
|
+
const root = repository_root()
|
|
205
|
+
|
|
206
|
+
if (root === undefined || from === undefined || to === undefined) return undefined
|
|
207
|
+
|
|
208
|
+
return unmoved_between(from, to, paths, root)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Each path's blob, written into the object store so a later carry can merge it; `undefined` when git
|
|
212
|
+
// cannot answer, which the record then omits.
|
|
213
|
+
function capture(paths: ReadonlyArray<string>): Record<string, string> | undefined {
|
|
214
|
+
const root = repository_root()
|
|
215
|
+
|
|
216
|
+
return root === undefined ? undefined : hash_paths(root, paths, WRITE_FLAGS)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const review_round_one_blobs = { capture, carried_delta, unmoved }
|
|
220
|
+
|
|
221
|
+
export { review_round_one_blobs }
|