@joshuafolkken/kit 1.1178.0 → 1.1240.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/.claude-plugin/plugin.json +1 -1
- package/.claude/settings.json +2 -2
- package/.claude/skills/dependency-update/SKILL.md +4 -8
- package/.claude/skills/epic-commands/SKILL.md +2 -2
- package/.claude/skills/epic-commands/epic-bundle.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +2 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +6 -4
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +7 -3
- package/.claude/skills/workflow-commands/backlogrun-park.md +23 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +9 -4
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
- package/.claude/skills/workflow-commands/backlogrun-steps.md +21 -13
- package/.claude/skills/workflow-commands/chain-rule.md +1 -1
- package/.claude/skills/workflow-commands/delegation.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +10 -0
- package/.claude/skills/workflow-commands/fullrun-steps.md +1 -1
- package/.claude/skills/workflow-commands/halfrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -1
- package/.claude/skills/workflow-commands/latest-gate.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
- package/.claude/skills/workflow-commands/pre-gate-cut.md +6 -1
- package/.claude/skills/workflow-commands/prerequisite.md +2 -2
- package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +1 -1
- package/.codex/hooks.json +2 -2
- package/.cursorrules +6 -41
- package/.github/actions/setup-node/action.yml +1 -1
- package/.github/workflows/auto-tag.yml +3 -4
- package/.github/workflows/ci.yml +32 -31
- package/.github/workflows/dependabot-auto-merge.yml +13 -6
- package/.github/workflows/publish.yml +50 -4
- package/.github/workflows/sonar-qube.yml +3 -0
- package/.pnpmfile.mjs +4 -3
- package/.prettierignore +8 -2
- package/CLAUDE.md +18 -20
- package/README.md +44 -38
- package/SECURITY.md +15 -1
- package/dist/CLAUDE.md +18 -20
- package/dist/commands/document-section-cli.js +734 -0
- package/dist/hooks/audit-provision.js +346 -0
- package/dist/hooks/batch-guard.js +5 -4
- package/dist/hooks/{chunk-G6KRCKEC.js → chunk-4TZVB44A.js} +496 -378
- package/dist/hooks/chunk-5VNDSNG3.js +12 -0
- package/dist/hooks/chunk-CDY4NFQG.js +15 -0
- package/dist/hooks/chunk-ELCN5LCH.js +135 -0
- package/dist/hooks/{chunk-VQLLNFNT.js → chunk-F3ELQ2AF.js} +3 -3
- package/dist/hooks/{chunk-I4XSL4TT.js → chunk-GPTFMK5E.js} +1 -1
- package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
- package/dist/hooks/{chunk-UAGLLIGZ.js → chunk-KHGB5S3Y.js} +7 -6
- package/dist/hooks/{chunk-GDS5N2KB.js → chunk-KHX4U3BG.js} +735 -683
- package/dist/hooks/{chunk-VESKRQOF.js → chunk-KRBERBBI.js} +3 -3
- package/dist/hooks/{chunk-DO6NWWHU.js → chunk-QVSWU24O.js} +4 -4
- package/dist/hooks/{chunk-S6X6WYKR.js → chunk-WK2XSHSI.js} +1643 -923
- package/dist/hooks/{chunk-ZAL3NRGL.js → chunk-XZYKEM6J.js} +25 -10
- package/dist/hooks/{chunk-32GQTL4F.js → chunk-ZQGD4GBY.js} +4 -2
- package/dist/hooks/codex-hook-adapter.js +14 -12
- package/dist/hooks/duplicate-read-guard.js +6 -5
- package/dist/hooks/format-edited.js +4 -3
- package/dist/hooks/inputs.json +203 -179
- package/dist/hooks/investigation-guard.js +6 -5
- package/dist/hooks/pretool-guard.js +12 -10
- package/dist/hooks/session-lang.js +2 -4
- package/dist/hooks/stop-guard.js +66 -72
- package/dist/josh.js +1088 -78
- package/dist/version/index.d.ts +7 -2
- package/dist/version/index.js +152 -75
- package/eslint/base.js +23 -1
- package/eslint/rules/code-quality.js +3 -0
- package/eslint/rules/early-return-one-liner.js +98 -0
- package/eslint/rules/unicorn.js +16 -1
- package/package.json +7 -6
- package/pnpm-workspace.yaml +9 -4
- package/prettier/basic.d.ts +3 -1
- package/prettier/index.d.ts +3 -1
- package/prettier/static.d.ts +3 -1
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +4 -4
- package/prompts/collaboration-workflow/glossary.md +1 -1
- package/prompts/collaboration-workflow/issue-template.md +1 -0
- package/prompts/collaboration-workflow/operating-rules.md +17 -9
- package/prompts/collaboration-workflow/overview.md +2 -2
- package/prompts/collaboration-workflow/principles.md +14 -12
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +1 -1
- package/prompts/collaboration-workflow/rule-delivery.md +6 -6
- package/prompts/collaboration-workflow/shell-body.md +6 -6
- package/prompts/collaboration-workflow/turn-batching.md +1 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +12 -2
- package/prompts/collaboration-workflow/wip-cap.md +10 -10
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +1 -1
- package/scripts/agent/agent-headless.ts +29 -0
- package/scripts/agent/agent-launch-environment.ts +6 -2
- package/scripts/agent/codex-agent-argv.ts +2 -1
- package/scripts/auto-ok/auto-ok-cli.ts +1 -1
- package/scripts/backlog/backlog-arrival.ts +3 -3
- package/scripts/backlog/backlog-budget.ts +1 -1
- package/scripts/backlog/backlog-drive-args.ts +135 -0
- package/scripts/backlog/backlog-drive-cli.ts +11 -137
- package/scripts/backlog/backlog-drive-launch.ts +39 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +3 -5
- package/scripts/backlog/backlog-drive-named.ts +3 -3
- package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
- package/scripts/backlog/backlog-drive-owner.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +1 -1
- package/scripts/backlog/backlog-drive-retrospective.ts +1 -1
- package/scripts/backlog/backlog-drive.ts +1 -1
- package/scripts/backlog/backlog-next.ts +16 -5
- package/scripts/backlog/backlog-offer-cli.ts +6 -6
- package/scripts/backlog/backlog-offer.ts +1 -1
- package/scripts/backlog/backlog-plan-cli.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +57 -11
- package/scripts/backlog/backlog-ready.ts +1 -1
- package/scripts/backlog/backlog-scope.ts +1 -1
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +3 -1
- package/scripts/build/build-commands.ts +66 -0
- package/scripts/build/build-hooks.ts +2 -1
- package/scripts/build/build-library.ts +12 -3
- package/scripts/build/build.ts +70 -0
- package/scripts/build/local-bin.ts +3 -13
- package/scripts/delegation/investigation-reads.ts +3 -1
- package/scripts/discovery/repo-origin.ts +5 -5
- package/scripts/doctor/doctor-consumer.ts +2 -2
- package/scripts/doctor/doctor-io.ts +2 -3
- package/scripts/document/capped-print-part.ts +30 -0
- package/scripts/document/capped-print.ts +3 -4
- package/scripts/document/document-byte-budget.ts +11 -2
- package/scripts/document/document-scan.ts +117 -0
- package/scripts/document/document-section.ts +143 -16
- package/scripts/document/entry-read-budget.ts +5 -3
- package/scripts/document/entry-read-set.ts +10 -89
- package/scripts/document/read-set-cost.ts +98 -0
- package/scripts/epic/epic-add-body.ts +1 -0
- package/scripts/epic/epic-audit-checks.ts +1 -1
- package/scripts/epic/epic-audit-rationale.ts +4 -3
- package/scripts/epic/epic-bundle-cli.ts +14 -3
- package/scripts/epic/epic-bundle-poll.ts +41 -0
- package/scripts/epic/epic-busy.ts +1 -1
- package/scripts/epic/epic-candidate-confirm.ts +3 -2
- package/scripts/epic/epic-classify.ts +1 -1
- package/scripts/epic/epic-cli-argv.ts +78 -46
- package/scripts/epic/epic-cli-remove.ts +11 -19
- package/scripts/epic/epic-cli.ts +74 -73
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +1 -1
- package/scripts/epic/epic-cross-repo.ts +5 -5
- package/scripts/epic/epic-graph.ts +1 -1
- package/scripts/epic/epic-index.ts +1 -1
- package/scripts/epic/epic-issue.ts +2 -6
- package/scripts/epic/epic-lane-offer.ts +2 -2
- package/scripts/epic/epic-next.ts +29 -42
- package/scripts/epic/epic-solo-stale.ts +1 -1
- package/scripts/epic/epic-triage.ts +8 -4
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/followup/git-followup-finish.ts +2 -2
- package/scripts/followup/git-followup-label.ts +2 -2
- package/scripts/followup/git-followup-merged.ts +2 -2
- package/scripts/followup/git-pr-followup-checks.ts +142 -0
- package/scripts/followup/git-pr-followup.ts +4 -129
- package/scripts/gate/core-admission.ts +162 -0
- package/scripts/gate/core-budget.ts +190 -68
- package/scripts/gate/gate-plan.ts +80 -7
- package/scripts/gate/gate-report.ts +28 -9
- package/scripts/gate/gate-skip.ts +38 -7
- package/scripts/gate/hook-gate-reuse.ts +12 -10
- package/scripts/gate/machine-capacity.ts +175 -0
- package/scripts/gate/pre-commit-type-check.ts +4 -1
- package/scripts/gate/project-checks.ts +6 -9
- package/scripts/gate/type-check-step.ts +2 -3
- package/scripts/gate/verification-gate.ts +34 -10
- package/scripts/gh/git-gh-api-path.ts +2 -2
- package/scripts/gh/git-gh-issue-rest.ts +3 -3
- package/scripts/gh/git-gh-issue-write.ts +53 -7
- package/scripts/gh/git-gh-pr-read.ts +64 -19
- package/scripts/gh/git-gh-pr-rest.ts +1 -1
- package/scripts/gh/git-gh-pr.ts +5 -1
- package/scripts/gh/git-pr-ai-review.ts +1 -1
- package/scripts/gh/git-pr-checks-eval.ts +1 -3
- package/scripts/gh/git-pr-checks-parse.ts +1 -1
- package/scripts/gh/git-pr-checks-watch.ts +6 -5
- package/scripts/gh/git-pr-checks.ts +7 -5
- package/scripts/gh/git-pr-coderabbit.ts +1 -1
- package/scripts/gh/git-pr-error.ts +1 -3
- package/scripts/gh/git-pr.ts +9 -13
- package/scripts/gh/github-issue-url.ts +2 -2
- package/scripts/git/constants.ts +2 -6
- package/scripts/git/git-command.ts +20 -218
- package/scripts/git/git-diff-reads.ts +225 -0
- package/scripts/git/git-error.ts +4 -12
- package/scripts/git/git-pre-push-hook.ts +139 -0
- package/scripts/git/git-prompt.ts +2 -6
- package/scripts/git/git-spawn-sync.ts +3 -1
- package/scripts/git/git-spawn.ts +1 -1
- package/scripts/git/git-staging.ts +4 -6
- package/scripts/git/git-status.ts +3 -9
- package/scripts/hooks/codex-hook-adapter.ts +1 -1
- package/scripts/hooks/edited-cspell.ts +2 -4
- package/scripts/hooks/format-edited-file.ts +3 -12
- package/scripts/hooks/pre-push-unit.ts +31 -9
- package/scripts/hooks/reserved-run.ts +2 -2
- package/scripts/hooks/run-hook.sh +5 -4
- package/scripts/hooks/stop-guard.ts +5 -3
- package/scripts/init/init-actions.ts +0 -5
- package/scripts/init/init-ai-copy.ts +13 -2
- package/scripts/init/init-logic-json-merge.ts +19 -0
- package/scripts/init/init-logic-secretlint.ts +7 -7
- package/scripts/init/init-logic-workspace.ts +41 -2
- package/scripts/init/init-logic.ts +16 -26
- package/scripts/init/init.ts +10 -16
- package/scripts/init/initial-commit.ts +4 -4
- package/scripts/init/kit-development-versions.ts +40 -0
- package/scripts/init/kit-setup-state.ts +2 -2
- package/scripts/init/package-manager-pin.ts +35 -0
- package/scripts/init/start-exec.ts +68 -19
- package/scripts/init/start-setup-pr.ts +9 -9
- package/scripts/init/start-steps.ts +6 -10
- package/scripts/issue/defect-rate-cli.ts +1 -1
- package/scripts/issue/git-next-issues.ts +1 -1
- package/scripts/issue/issue-auto-ok.ts +32 -7
- package/scripts/issue/issue-backlinks-cli.ts +2 -2
- package/scripts/issue/issue-backlinks.ts +9 -9
- package/scripts/issue/issue-comment-cli.ts +19 -13
- package/scripts/issue/issue-file-cli.ts +72 -22
- package/scripts/issue/issue-file.ts +29 -1
- package/scripts/issue/issue-labels.ts +13 -0
- package/scripts/issue/issue-release-cli.ts +155 -0
- package/scripts/issue/issue-release.ts +58 -0
- package/scripts/issue/issue-scout-closed.ts +1 -1
- package/scripts/issue/issue-state-cli.ts +30 -74
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-command-types.ts +14 -0
- package/scripts/josh/josh-commands-ai.ts +4 -4
- package/scripts/josh/josh-commands-backlog.ts +4 -1
- package/scripts/josh/josh-commands-development.ts +18 -0
- package/scripts/josh/josh-commands-document.ts +1 -0
- package/scripts/josh/josh-commands-issue.ts +8 -1
- package/scripts/josh/josh-commands-lane.ts +24 -1
- package/scripts/josh/josh-commands-maintenance.ts +6 -6
- package/scripts/josh/josh-commands-run.ts +12 -7
- package/scripts/josh/josh-in-process.ts +28 -9
- package/scripts/josh/josh-logic.ts +34 -15
- package/scripts/josh/process-identity.ts +1 -3
- package/scripts/josh/session-language-cli.ts +3 -4
- package/scripts/lane/lane-await.ts +5 -1
- package/scripts/lane/lane-child-invocation.ts +2 -2
- package/scripts/lane/lane-cli.ts +12 -4
- package/scripts/lane/lane-dispatch.ts +14 -10
- package/scripts/lane/lane-environment.ts +5 -1
- package/scripts/lane/lane-handoff.ts +1 -1
- package/scripts/lane/lane-install.ts +2 -13
- package/scripts/lane/lane-launch-cli.ts +15 -1
- package/scripts/lane/lane-ledger.ts +145 -0
- package/scripts/lane/lane-leftover.ts +44 -30
- package/scripts/lane/lane-load.ts +108 -0
- package/scripts/lane/lane-measure-cli.ts +149 -0
- package/scripts/lane/lane-occupancy.ts +3 -0
- package/scripts/lane/lane-open.ts +5 -5
- package/scripts/lane/lane-paths.ts +13 -0
- package/scripts/lane/lane-reap.ts +1 -3
- package/scripts/lane/lane-registry.ts +11 -0
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-stats.ts +224 -0
- package/scripts/lane/lane-stray.ts +140 -0
- package/scripts/lane/lane-vacant.ts +36 -0
- package/scripts/lane/openai-lane-ship.ts +2 -2
- package/scripts/lane/openai-lane-supervisor-owner.ts +180 -0
- package/scripts/lane/openai-lane-supervisor.ts +7 -165
- package/scripts/lane/openai-review-broker.ts +2 -4
- package/scripts/lib/ancestor-directories.ts +35 -0
- package/scripts/lib/animation-helpers.ts +2 -2
- package/scripts/lib/buffered-process.ts +3 -7
- package/scripts/lib/cli-flags.ts +71 -1
- package/scripts/lib/spawn-exit.ts +2 -2
- package/scripts/lib/timeouts.ts +35 -2
- package/scripts/lines/line-budget.ts +4 -6
- package/scripts/notify/telegram-test.ts +6 -0
- package/scripts/observations/observation-ledger-line.ts +6 -6
- package/scripts/observations/observation-ledger-migrate.ts +55 -4
- package/scripts/observations/observation-ledger.ts +26 -7
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/propagate/propagate-git.ts +1 -1
- package/scripts/propagate/propagate-publish.ts +2 -2
- package/scripts/propagate/propagate-steps.ts +20 -15
- package/scripts/propagate/propagate.ts +36 -27
- package/scripts/refactor/import-graph.ts +18 -1
- package/scripts/refactor/refactor-lint.ts +4 -4
- package/scripts/release/github-release-environment.ts +1 -0
- package/scripts/release/github-release-runs.ts +115 -0
- package/scripts/release/github-release.ts +13 -67
- package/scripts/repo/repository-labels.ts +2 -2
- package/scripts/repo/required-checks-logic.ts +1 -3
- package/scripts/review/live-evidence.ts +2 -4
- package/scripts/review/review-brief-cli.ts +1 -1
- package/scripts/review/review-finding-ledger.ts +1 -1
- package/scripts/review/review-findings-cli.ts +1 -3
- package/scripts/rules/decision-oracle-batch.ts +128 -0
- package/scripts/rules/decision-oracle-tokens.ts +21 -0
- package/scripts/rules/decision-oracle.ts +8 -120
- package/scripts/rules/delivered-rules.ts +26 -182
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/early-heartbeat.ts +3 -3
- package/scripts/rules/git-argv.ts +1 -1
- package/scripts/rules/git-force.ts +1 -1
- package/scripts/rules/implementation-cut.ts +2 -2
- package/scripts/rules/index-guard.ts +1 -1
- package/scripts/rules/issue-comments.ts +118 -0
- package/scripts/rules/{issue-fold.ts → issue-fold-rule.ts} +2 -2
- package/scripts/rules/lane-background.ts +2 -2
- package/scripts/rules/lane-park.ts +18 -0
- package/scripts/rules/lane-split-park.ts +128 -0
- package/scripts/rules/oracle-firing.ts +1 -1
- package/scripts/rules/poll-loop.ts +1 -1
- package/scripts/rules/pre-gate-cut.ts +1 -1
- package/scripts/rules/protected-files.ts +59 -4
- package/scripts/rules/{run-tail.ts → run-tail-rule.ts} +2 -2
- package/scripts/rules/shell-body-trigger.ts +1 -1
- package/scripts/rules/stop-rules.ts +18 -7
- package/scripts/rules/test-declared-commit.ts +4 -4
- package/scripts/rules/wip-cap.ts +63 -0
- package/scripts/run/{run-carry-args.ts → carry/run-carry-args.ts} +37 -13
- package/scripts/run/{run-carry-change.ts → carry/run-carry-change.ts} +29 -7
- package/scripts/run/{run-carry-cli.ts → carry/run-carry-cli.ts} +4 -6
- package/scripts/run/{run-carry.ts → carry/run-carry.ts} +1 -1
- package/scripts/run/{run-cut-args.ts → cut/run-cut-args.ts} +1 -1
- package/scripts/run/{run-cut-cli.ts → cut/run-cut-cli.ts} +18 -5
- package/scripts/run/{run-cut.ts → cut/run-cut.ts} +1 -1
- package/scripts/run/{run-entry-cli.ts → entry/run-entry-cli.ts} +11 -11
- package/scripts/run/{run-entry.ts → entry/run-entry.ts} +2 -2
- package/scripts/run/{run-event-render.ts → event/run-event-render.ts} +1 -0
- package/scripts/run/{run-event-scope.ts → event/run-event-scope.ts} +1 -1
- package/scripts/run/{run-event-stream-emit.ts → event/run-event-stream-emit.ts} +1 -1
- package/scripts/run/{run-event-stream.ts → event/run-event-stream.ts} +20 -2
- package/scripts/run/{run-hold-cli.ts → hold/run-hold-cli.ts} +5 -5
- package/scripts/run/{run-merge-cli.ts → merge/run-merge-cli.ts} +10 -5
- package/scripts/run/{run-merge-steps.ts → merge/run-merge-steps.ts} +53 -5
- package/scripts/run/{run-merge.ts → merge/run-merge.ts} +1 -1
- package/scripts/run/{run-progress-cli.ts → progress/run-progress-cli.ts} +1 -1
- package/scripts/run/{run-progress-config.ts → progress/run-progress-config.ts} +2 -17
- package/scripts/run/{run-progress-read.ts → progress/run-progress-read.ts} +5 -5
- package/scripts/run/{run-progress.ts → progress/run-progress.ts} +1 -1
- package/scripts/run/{run-review-steps.ts → review/run-review-steps.ts} +2 -3
- package/scripts/run/run-ending.ts +2 -2
- package/scripts/run/run-halfrun-resume.ts +6 -1
- package/scripts/run/run-headless.ts +1 -1
- package/scripts/run/run-invocation.ts +85 -84
- package/scripts/run/run-liveness.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +1 -1
- package/scripts/run/run-preflight.ts +6 -6
- package/scripts/run/run-prep-cli.ts +1 -1
- package/scripts/run/run-prrun-resume.ts +1 -1
- package/scripts/run/run-report-cli.ts +4 -4
- package/scripts/run/run-report.ts +2 -2
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +3 -3
- package/scripts/run/run-step.ts +7 -4
- package/scripts/run/run-stop-notify.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +4 -4
- package/scripts/run/run-stranded.ts +2 -2
- package/scripts/run/run-watcher-guard-cli.ts +1 -1
- package/scripts/run/run-watcher-guard.ts +5 -3
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/run/{run-ship-cli.ts → ship/run-ship-cli.ts} +2 -2
- package/scripts/run/{run-ship-detach.ts → ship/run-ship-detach.ts} +3 -3
- package/scripts/run/ship/run-ship-lock.ts +50 -0
- package/scripts/run/{run-ship-preflight.ts → ship/run-ship-preflight.ts} +6 -2
- package/scripts/run/{run-ship-probe.ts → ship/run-ship-probe.ts} +2 -2
- package/scripts/run/{run-ship-return.ts → ship/run-ship-return.ts} +4 -3
- package/scripts/run/{run-ship-review-steps.ts → ship/run-ship-review-steps.ts} +3 -3
- package/scripts/run/{run-ship-scoped.ts → ship/run-ship-scoped.ts} +10 -1
- package/scripts/run/{run-ship-steps.ts → ship/run-ship-steps.ts} +11 -12
- package/scripts/run/ship/run-ship-stop-text.ts +13 -0
- package/scripts/run/{run-ship-sync.ts → ship/run-ship-sync.ts} +25 -11
- package/scripts/run/{run-tidy-lanes.ts → tidy/run-tidy-lanes.ts} +1 -1
- package/scripts/run/{run-wake-cli.ts → wake/run-wake-cli.ts} +25 -11
- package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +58 -7
- package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +59 -8
- package/scripts/run/{run-wake-handoff.ts → wake/run-wake-handoff.ts} +1 -1
- package/scripts/run/{run-wake-loop.ts → wake/run-wake-loop.ts} +13 -15
- package/scripts/run/wake/run-wake-restart.ts +58 -0
- package/scripts/run/{run-wake-session.ts → wake/run-wake-session.ts} +3 -3
- package/scripts/run/{run-wake.ts → wake/run-wake.ts} +16 -65
- package/scripts/safe-chain/preinstall-command.ts +20 -21
- package/scripts/safe-chain/project-config.ts +19 -15
- package/scripts/sync/sync-ai-files.ts +1 -1
- package/scripts/sync/sync-configs.ts +2 -1
- package/scripts/sync/sync.ts +15 -2
- package/scripts/test/unit-worker-share.ts +1 -0
- package/scripts/time-runtime/time-background.ts +5 -1
- package/scripts/time-runtime/time-instant.ts +3 -1
- package/scripts/time-runtime/time-spans.ts +6 -139
- package/scripts/time-runtime/time-tool-call.ts +160 -0
- package/scripts/version/effective-upstream.ts +2 -20
- package/scripts/version/latest-corepack.ts +124 -93
- package/scripts/version/latest-regression.ts +1 -1
- package/scripts/version/latest-update.ts +4 -4
- package/scripts/version/npm-registry.ts +20 -5
- package/scripts/version/publishable-range-check.ts +2 -2
- package/scripts/version/publishable-range.ts +1 -1
- package/scripts/version/release-age.ts +48 -38
- package/scripts/version/release-hold.ts +1 -1
- package/scripts/version/safe-chain-version-update.ts +40 -0
- package/scripts/version/upgrade-shell-command.ts +48 -8
- package/scripts/version/version-check-logic.ts +23 -14
- package/scripts/version/version-commands.ts +23 -11
- package/scripts/version/version-remote.ts +28 -13
- package/templates/pnpm-workspace.basic.yaml +4 -0
- package/templates/workflows/dependabot-auto-merge.yml +5 -5
- package/templates/workflows/github-release.yml +6 -0
- package/scripts/build/build-config-merge.ts +0 -27
- package/scripts/build/build-managed-marker.ts +0 -27
- package/scripts/build/build-self-sync-guard.ts +0 -27
- package/scripts/build/build-version.ts +0 -26
- package/scripts/version/preinstall-version-update.ts +0 -86
- /package/scripts/git/{schemas.ts → git-schemas.ts} +0 -0
- /package/scripts/overrides/{schemas.ts → overrides-schemas.ts} +0 -0
- /package/scripts/run/{run-carry-conversation.ts → carry/run-carry-conversation.ts} +0 -0
- /package/scripts/run/{run-carry-reclaim.ts → carry/run-carry-reclaim.ts} +0 -0
- /package/scripts/run/{run-carry-stash.ts → carry/run-carry-stash.ts} +0 -0
- /package/scripts/run/{run-carry-streak.ts → carry/run-carry-streak.ts} +0 -0
- /package/scripts/run/{run-cut-handoff.ts → cut/run-cut-handoff.ts} +0 -0
- /package/scripts/run/{run-cut-report.ts → cut/run-cut-report.ts} +0 -0
- /package/scripts/run/{run-entry-stop.ts → entry/run-entry-stop.ts} +0 -0
- /package/scripts/run/{run-event-cli.ts → event/run-event-cli.ts} +0 -0
- /package/scripts/run/{run-event-follow.ts → event/run-event-follow.ts} +0 -0
- /package/scripts/run/{run-event-watch.ts → event/run-event-watch.ts} +0 -0
- /package/scripts/run/{run-hold.ts → hold/run-hold.ts} +0 -0
- /package/scripts/run/{run-progress-args.ts → progress/run-progress-args.ts} +0 -0
- /package/scripts/run/{run-progress-clock.ts → progress/run-progress-clock.ts} +0 -0
- /package/scripts/run/{run-review-cli.ts → review/run-review-cli.ts} +0 -0
- /package/scripts/run/{run-review.ts → review/run-review.ts} +0 -0
- /package/scripts/run/{run-ship-next.ts → ship/run-ship-next.ts} +0 -0
- /package/scripts/run/{run-ship-pre-detach.ts → ship/run-ship-pre-detach.ts} +0 -0
- /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
- /package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +0 -0
- /package/scripts/run/{run-ship.ts → ship/run-ship.ts} +0 -0
- /package/scripts/run/{run-tidy-cli.ts → tidy/run-tidy-cli.ts} +0 -0
- /package/scripts/run/{run-tidy-stashes.ts → tidy/run-tidy-stashes.ts} +0 -0
- /package/scripts/run/{run-tidy.ts → tidy/run-tidy.ts} +0 -0
|
@@ -62,9 +62,7 @@ function create_prompt(): Interface | undefined {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
function handle_prompt_fallback<T>(fallback_value?: T): T {
|
|
65
|
-
if (fallback_value !== undefined)
|
|
66
|
-
return fallback_value
|
|
67
|
-
}
|
|
65
|
+
if (fallback_value !== undefined) return fallback_value
|
|
68
66
|
|
|
69
67
|
throw new Error('TTY not available')
|
|
70
68
|
}
|
|
@@ -72,9 +70,7 @@ function handle_prompt_fallback<T>(fallback_value?: T): T {
|
|
|
72
70
|
async function with_prompt<T>(callback: PromptCallback<T>, fallback_value?: T): Promise<T> {
|
|
73
71
|
const prompt = create_prompt()
|
|
74
72
|
|
|
75
|
-
if (prompt === undefined)
|
|
76
|
-
return handle_prompt_fallback(fallback_value)
|
|
77
|
-
}
|
|
73
|
+
if (prompt === undefined) return handle_prompt_fallback(fallback_value)
|
|
78
74
|
|
|
79
75
|
try {
|
|
80
76
|
// eslint-disable-next-line promise/prefer-await-to-callbacks
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { read_spawn_stderr, read_spawn_stdout } from '#scripts/lib/spawn-exit'
|
|
2
|
+
import { GIT_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
2
3
|
import { execaSync } from 'execa'
|
|
3
4
|
import { git_utilities } from './constants'
|
|
4
5
|
|
|
@@ -7,7 +8,6 @@ import { git_utilities } from './constants'
|
|
|
7
8
|
// non-zero exit is returned as a result, and every call is bounded: a git that never answers is an
|
|
8
9
|
// unknown the caller already handles, never a hang.
|
|
9
10
|
|
|
10
|
-
const GIT_TIMEOUT_MS = 10_000
|
|
11
11
|
const SUCCESS_EXIT_CODE = 0
|
|
12
12
|
// git translates its messages, so a caller matching stderr would fail under any non-English locale.
|
|
13
13
|
const C_LOCALE: Record<string, string> = { LC_ALL: 'C', LANGUAGE: 'C' }
|
|
@@ -16,6 +16,8 @@ interface GitSyncOptions {
|
|
|
16
16
|
cwd?: string
|
|
17
17
|
timeout?: number
|
|
18
18
|
env?: Record<string, string | undefined>
|
|
19
|
+
// A step a person watches (`josh start`) shows git's own progress and hook output as it runs.
|
|
20
|
+
stdio?: 'inherit'
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
interface GitSyncResult {
|
package/scripts/git/git-spawn.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { git_ssh_keepalive } from './git-ssh-keepalive'
|
|
|
20
20
|
// spawns git itself. The timeout it carries is shared here by `read_remote` / `with_output_remote`. Those two files are the spawn sites of the ordinary command
|
|
21
21
|
// modules — the claim stops there. A synchronous caller goes through `git-spawn-sync.ts`, the same
|
|
22
22
|
// binary resolution with a result instead of an exception (joshuafolkken/kit#3065). Other parts of
|
|
23
|
-
// this package spawn git for their own purposes (`scripts/run/run-progress-clock.ts`,
|
|
23
|
+
// this package spawn git for their own purposes (`scripts/run/progress/run-progress-clock.ts`,
|
|
24
24
|
// `scripts/git/git-fixture-workspace.ts`), and an audit of how the git binary is resolved has to read
|
|
25
25
|
// those too.
|
|
26
26
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
LEDGER_DIRECTORIES,
|
|
2
3
|
LEGACY_OBSERVATION_LEDGER_PATHS,
|
|
3
4
|
observation_ledger,
|
|
4
|
-
OBSERVATION_LEDGER_DIRECTORY,
|
|
5
5
|
} from '#scripts/observations/observation-ledger'
|
|
6
6
|
import { observation_ledger_prepare } from '#scripts/observations/observation-ledger-prepare'
|
|
7
7
|
import { git_command } from './git-command'
|
|
@@ -29,9 +29,7 @@ async function confirm_package_json_staged(should_force = false): Promise<boolea
|
|
|
29
29
|
async function confirm_package_json_version(should_force = false): Promise<void> {
|
|
30
30
|
const is_version_updated = await git_status.check_package_json_version()
|
|
31
31
|
|
|
32
|
-
if (is_version_updated)
|
|
33
|
-
return
|
|
34
|
-
}
|
|
32
|
+
if (is_version_updated) return
|
|
35
33
|
|
|
36
34
|
if (should_force) {
|
|
37
35
|
console.info('💡 Skipping package.json version check (force).')
|
|
@@ -83,7 +81,7 @@ async function stage_untracked_files(files: ReadonlyArray<string>): Promise<void
|
|
|
83
81
|
// own lines** (joshuafolkken/kit#2919): its writers append to its own tree's issue file, so this is
|
|
84
82
|
// the step that takes them to the default branch.
|
|
85
83
|
const LEDGER_PATHSPECS: ReadonlyArray<string> = [
|
|
86
|
-
|
|
84
|
+
...LEDGER_DIRECTORIES,
|
|
87
85
|
...LEGACY_OBSERVATION_LEDGER_PATHS,
|
|
88
86
|
]
|
|
89
87
|
|
|
@@ -108,7 +106,7 @@ function is_stageable(file_path: string, excluded: ReadonlyArray<string>): boole
|
|
|
108
106
|
// step dies on git's empty index with `Failed to commit changes` — a message naming nothing that
|
|
109
107
|
// caused it. This line is what turns that into a diagnosis.
|
|
110
108
|
//
|
|
111
|
-
// **The paths are parsed rather than matched as substrings**:
|
|
109
|
+
// **The paths are parsed rather than matched as substrings**: `.josh/observations-old/x.md`
|
|
112
110
|
// contains the ledger's path, and a hint naming a file the exclusion never touched is a hint that
|
|
113
111
|
// teaches the reader to ignore it.
|
|
114
112
|
function report_excluded_paths(status_output: string, excluded: ReadonlyArray<string>): void {
|
|
@@ -31,9 +31,7 @@ function has_unstaged_files(status_output: string): boolean {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function is_staged_file(line: string): boolean {
|
|
34
|
-
if (line.length < REQUIRED_STATUS_LENGTH || is_untracked_file(line))
|
|
35
|
-
return false
|
|
36
|
-
}
|
|
34
|
+
if (line.length < REQUIRED_STATUS_LENGTH || is_untracked_file(line)) return false
|
|
37
35
|
|
|
38
36
|
const [staged_status] = line
|
|
39
37
|
|
|
@@ -47,9 +45,7 @@ function has_unstaged_changes(line: string): boolean {
|
|
|
47
45
|
function has_all_files_staged(status_output: string): boolean {
|
|
48
46
|
const lines = parse_status_lines(status_output)
|
|
49
47
|
|
|
50
|
-
if (lines.length === 0)
|
|
51
|
-
return true
|
|
52
|
-
}
|
|
48
|
+
if (lines.length === 0) return true
|
|
53
49
|
|
|
54
50
|
return lines.every((line) => !has_unstaged_changes(line))
|
|
55
51
|
}
|
|
@@ -62,9 +58,7 @@ function is_package_json_staged(status_output: string): boolean {
|
|
|
62
58
|
const lines = parse_status_lines(status_output)
|
|
63
59
|
|
|
64
60
|
return lines.some((line) => {
|
|
65
|
-
if (!is_staged_file(line))
|
|
66
|
-
return false
|
|
67
|
-
}
|
|
61
|
+
if (!is_staged_file(line)) return false
|
|
68
62
|
|
|
69
63
|
const filename = extract_filename(line)
|
|
70
64
|
|
|
@@ -49,7 +49,7 @@ function paths_matching(command: string, pattern: RegExp): Array<string> {
|
|
|
49
49
|
return [...command.matchAll(pattern)].flatMap((match) => {
|
|
50
50
|
const file_path = match[1]?.trim()
|
|
51
51
|
|
|
52
|
-
return file_path === undefined || file_path === '' ? [] :
|
|
52
|
+
return file_path === undefined || file_path === '' ? [] : file_path
|
|
53
53
|
})
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
+
import { HOOK_PROCESS_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
3
4
|
import { execa } from 'execa'
|
|
4
5
|
|
|
5
6
|
// The spell half of the edit hook (joshuafolkken/kit#2296). joshuafolkken/kit#2275 gave the hook a way
|
|
@@ -47,9 +48,6 @@ const CSPELL_ARGS: ReadonlyArray<string> = [
|
|
|
47
48
|
'--no-summary',
|
|
48
49
|
]
|
|
49
50
|
const PNPM = 'pnpm'
|
|
50
|
-
// A spell check that hangs would hold the edit's turn open; the bound is generous because reaching it
|
|
51
|
-
// means something is already wrong, exactly as the formatter spawns in `format-edited-file.ts`.
|
|
52
|
-
const PROCESS_TIMEOUT_MS = 15_000
|
|
53
51
|
|
|
54
52
|
const HEADER =
|
|
55
53
|
'The edit hook found words cspell does not know; fix them or add them to `cspell.config.yaml` now rather than at the gate:'
|
|
@@ -79,7 +77,7 @@ async function run_cspell(file_path: string, project_root: string): Promise<stri
|
|
|
79
77
|
cwd: project_root,
|
|
80
78
|
stdout: 'pipe',
|
|
81
79
|
stderr: 'ignore',
|
|
82
|
-
timeout:
|
|
80
|
+
timeout: HOOK_PROCESS_TIMEOUT_MS,
|
|
83
81
|
})
|
|
84
82
|
|
|
85
83
|
return result.stdout
|
|
@@ -4,6 +4,7 @@ import path from 'node:path'
|
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
5
|
import { resolve_local_bin, resolve_package_bin } from '#scripts/build/local-bin'
|
|
6
6
|
import { ESLINT_EDIT_CACHE_FLAGS } from '#scripts/josh/josh-command-types'
|
|
7
|
+
import { HOOK_PROCESS_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
7
8
|
import { time_density_hook } from '#scripts/time-runtime/time-density-hook'
|
|
8
9
|
import { execa } from 'execa'
|
|
9
10
|
import { z } from 'zod'
|
|
@@ -87,15 +88,6 @@ const DAEMON_RESTART = 'restart'
|
|
|
87
88
|
// `eslint.config.*` entry, and the rule modules under `eslint/` that it imports.
|
|
88
89
|
const ESLINT_CONFIG_DIR = 'eslint'
|
|
89
90
|
const ESLINT_CONFIG_ENTRY = /^eslint\.config\.[cm]?[jt]s$/u
|
|
90
|
-
// A formatter that hangs would hold the edit's turn open, so each spawn is bounded. The bound has
|
|
91
|
-
// to be read against the *worst-case run* rather than one spawn: an edit to a config input plans
|
|
92
|
-
// eslint, prettier and `eslint_d restart`, and the first and last each have a second route behind
|
|
93
|
-
// the daemon — five spawns. The hook entry in `.claude/settings.json` declares 90 seconds, so the
|
|
94
|
-
// per-spawn bound must leave five of them under it, or the harness kill lands first and lands at a
|
|
95
|
-
// moment this file did not choose — possibly inside `prettier --write`, which rewrites in place and
|
|
96
|
-
// can leave the file truncated. 15s × 5 = 75s. It is still two orders of magnitude beyond the 0.84s
|
|
97
|
-
// a warm run takes, so reaching it means something is already wrong.
|
|
98
|
-
const PROCESS_TIMEOUT_MS = 15_000
|
|
99
91
|
|
|
100
92
|
// The problems eslint could not auto-fix are handed to the model verbatim from eslint's own stdout —
|
|
101
93
|
// its default formatter already prints the file, the `line:col`, and the rule name the issue asks
|
|
@@ -315,7 +307,7 @@ async function spawn_invocation(
|
|
|
315
307
|
env: { ESLINT_D_MISS: 'fail' },
|
|
316
308
|
stdout: 'pipe',
|
|
317
309
|
stderr: 'ignore',
|
|
318
|
-
timeout:
|
|
310
|
+
timeout: HOOK_PROCESS_TIMEOUT_MS,
|
|
319
311
|
})
|
|
320
312
|
|
|
321
313
|
return { exit_code: result.exitCode ?? 1, stdout: result.stdout }
|
|
@@ -469,7 +461,7 @@ function report_no_payload(): void {
|
|
|
469
461
|
// have (joshuafolkken/kit#2314). The rewrite, lint and spell blocks are composed together first, then
|
|
470
462
|
// joined to the density line — one envelope, since a `PostToolUse` hook's stdout carries only one
|
|
471
463
|
// (joshuafolkken/kit#2296). A hook killed at its 15s timeout is the one case this loses the density
|
|
472
|
-
// line to — a run already gone pathologically wrong, per
|
|
464
|
+
// line to — a run already gone pathologically wrong, per HOOK_PROCESS_TIMEOUT_MS.
|
|
473
465
|
async function run_hook(payload: string): Promise<void> {
|
|
474
466
|
const notice = time_density_hook.density_notice(payload)
|
|
475
467
|
const file_path = parse_edited_path(payload)
|
|
@@ -500,6 +492,5 @@ export {
|
|
|
500
492
|
select_invocation,
|
|
501
493
|
ESLINT_DAEMON,
|
|
502
494
|
MAX_DIAGNOSTIC_CHARS,
|
|
503
|
-
PROCESS_TIMEOUT_MS,
|
|
504
495
|
}
|
|
505
496
|
export type { CommandRunner, FormatCommand }
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { gate_skip } from '#scripts/gate/gate-skip'
|
|
3
|
+
import { gate_skip, type GateReuse } from '#scripts/gate/gate-skip'
|
|
4
4
|
import { gate_tree, type GateTree } from '#scripts/gate/gate-tree'
|
|
5
5
|
import { hook_gate_reuse } from '#scripts/gate/hook-gate-reuse'
|
|
6
|
-
import type { FileMapStamp } from '#scripts/josh/file-map-stamp'
|
|
7
6
|
import { test_unit_guard } from '#scripts/test/test-unit-guard'
|
|
8
7
|
|
|
9
8
|
// The pre-push hook's unit run, which no longer re-runs a suite a green gate already covers
|
|
@@ -42,6 +41,15 @@ const FORCE_ENV = 'JOSH_PRE_PUSH_FORCE'
|
|
|
42
41
|
// `gate-tree.ts` rather than read a second way here — plus the one this hook adds.
|
|
43
42
|
interface PushTree extends GateTree {
|
|
44
43
|
is_clean: boolean
|
|
44
|
+
// What a dirty tree reports as the reason the record was not reused (joshuafolkken/kit#3307) — the
|
|
45
|
+
// paths name a lock file a hook's own `pnpm install` rewrote, the case that went unexplained.
|
|
46
|
+
carry_miss: string
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function carry_miss(lines: ReadonlyArray<string> | undefined): string {
|
|
50
|
+
if (lines === undefined) return 'git status could not be read'
|
|
51
|
+
|
|
52
|
+
return `the working tree differs from HEAD (${lines.join('; ')})`
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
// `git status --porcelain` prints one line per difference from HEAD, untracked files included — so an
|
|
@@ -57,7 +65,11 @@ async function read_push_tree(): Promise<PushTree> {
|
|
|
57
65
|
hook_gate_reuse.read_status_lines(),
|
|
58
66
|
])
|
|
59
67
|
|
|
60
|
-
return {
|
|
68
|
+
return {
|
|
69
|
+
...tree,
|
|
70
|
+
is_clean: hook_gate_reuse.is_worktree_clean(lines),
|
|
71
|
+
carry_miss: carry_miss(lines),
|
|
72
|
+
}
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
// `--force` is the gate's own flag, reused rather than respelled: it and `JOSH_PRE_PUSH_FORCE` are
|
|
@@ -74,14 +86,15 @@ function forwarded_arguments(extra_arguments: ReadonlyArray<string>): ReadonlyAr
|
|
|
74
86
|
// **Any argument at all refuses the reuse**, not only `--force`. Everything else is forwarded to
|
|
75
87
|
// vitest, and a caller who narrowed the run to one spec asked for that run rather than for a
|
|
76
88
|
// recorded result about a whole tree. The hook's own line passes none, so this costs it nothing.
|
|
77
|
-
function
|
|
89
|
+
function push_reuse(
|
|
78
90
|
tree: PushTree,
|
|
79
91
|
extra_arguments: ReadonlyArray<string>,
|
|
80
92
|
source?: string,
|
|
81
|
-
):
|
|
82
|
-
return hook_gate_reuse.
|
|
93
|
+
): GateReuse {
|
|
94
|
+
return hook_gate_reuse.hook_reuse({
|
|
83
95
|
tree,
|
|
84
96
|
is_tree_carried: tree.is_clean,
|
|
97
|
+
carry_miss: tree.carry_miss,
|
|
85
98
|
extra_arguments,
|
|
86
99
|
force_env: FORCE_ENV,
|
|
87
100
|
source,
|
|
@@ -107,20 +120,29 @@ function format_skip(taken_at: string): string {
|
|
|
107
120
|
// other commands already have. **A project that has vitest and no test file at all fails the push
|
|
108
121
|
// instead** (joshuafolkken/kit#1224): the guard treats that half as a broken state rather than a
|
|
109
122
|
// young project, and the hook returns what the guard returns.
|
|
123
|
+
// **A fall back to the whole suite says why, in one line** (joshuafolkken/kit#3307): under a crowded
|
|
124
|
+
// machine the suite costs minutes, and a silent miss left a moved merge base, a dirty tree and a
|
|
125
|
+
// mismatched record indistinguishable from one another.
|
|
126
|
+
function format_miss(reason: string): string {
|
|
127
|
+
return `↻ running the whole unit suite — the green gate record does not cover this push: ${reason}.`
|
|
128
|
+
}
|
|
129
|
+
|
|
110
130
|
async function run_pre_push_unit(
|
|
111
131
|
extra_arguments: ReadonlyArray<string> = [],
|
|
112
132
|
source?: string,
|
|
113
133
|
): Promise<number> {
|
|
114
|
-
const
|
|
134
|
+
const reuse = push_reuse(await read_push_tree(), extra_arguments, source)
|
|
135
|
+
|
|
136
|
+
if ('miss' in reuse) {
|
|
137
|
+
process.stdout.write(`${format_miss(reuse.miss)}\n`)
|
|
115
138
|
|
|
116
|
-
if (reusable === undefined) {
|
|
117
139
|
return await test_unit_guard.run_guarded_unit(
|
|
118
140
|
process.cwd(),
|
|
119
141
|
forwarded_arguments(extra_arguments),
|
|
120
142
|
)
|
|
121
143
|
}
|
|
122
144
|
|
|
123
|
-
process.stdout.write(`${format_skip(
|
|
145
|
+
process.stdout.write(`${format_skip(reuse.stamp.taken_at)}\n`)
|
|
124
146
|
|
|
125
147
|
return 0
|
|
126
148
|
}
|
|
@@ -54,8 +54,8 @@ function parse_arguments(argv: ReadonlyArray<string>): ReservedCommand | undefin
|
|
|
54
54
|
// command becomes an exit code the caller returns rather than a throw — the reservation is released by
|
|
55
55
|
// `with_core_reservation`'s `finally` on either path.
|
|
56
56
|
async function run_command(command: ReadonlyArray<string>): Promise<number> {
|
|
57
|
-
const [file, ...args] = command
|
|
58
|
-
const result = await execa(file
|
|
57
|
+
const [file = '', ...args] = command
|
|
58
|
+
const result = await execa(file, args, { stdio: 'inherit', reject: false })
|
|
59
59
|
|
|
60
60
|
return result.exitCode ?? FAIL_EXIT_CODE
|
|
61
61
|
}
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
# runs through josh, whose command is the name with its first `-` turned into `:`
|
|
13
13
|
# (`pretool-guard` → `pretool:guard`).
|
|
14
14
|
# - In kit's own checkout the gate is `hook-bundle-ready.ts`, which rebuilds stale bundles
|
|
15
|
-
# (joshuafolkken/kit#2984)
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
# (joshuafolkken/kit#2984) and then runs the bundle — or the josh fallback — itself, so a hook call
|
|
16
|
+
# starts node once (joshuafolkken/kit#3327). In an installed package it is a presence check: the
|
|
17
|
+
# published bundles cannot be stale against a source the consumer never edits, and Node strips no
|
|
18
|
+
# types under `node_modules`.
|
|
18
19
|
# - An `if`/`else`, never `&&`/`||`: a guard's refusal is a non-zero exit, and a chain would read it as
|
|
19
20
|
# a missing bundle and run the hook twice.
|
|
20
21
|
|
|
@@ -36,6 +37,6 @@ case $0 in
|
|
|
36
37
|
if [ -d "$package_dir/dist/hooks" ]; then node "$bundle" "$@"; else node "$package_dir/dist/josh.js" "$josh_command" "$@"; fi
|
|
37
38
|
;;
|
|
38
39
|
*)
|
|
39
|
-
|
|
40
|
+
node --disable-warning=ExperimentalWarning "$hooks_dir/hook-bundle-ready.ts" "$hook_name" "$josh_command" "$@"
|
|
40
41
|
;;
|
|
41
42
|
esac
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { text } from 'node:stream/consumers'
|
|
3
3
|
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { agent_headless } from '#scripts/agent/agent-headless'
|
|
4
5
|
import { backlog_ready } from '#scripts/backlog/backlog-ready'
|
|
5
6
|
import { backlog_stalled_detect } from '#scripts/backlog/backlog-stalled-detect'
|
|
6
7
|
import { repo_party } from '#scripts/discovery/repo-party'
|
|
@@ -13,11 +14,11 @@ import { lane_background } from '#scripts/rules/lane-background'
|
|
|
13
14
|
import { lane_park } from '#scripts/rules/lane-park'
|
|
14
15
|
import { last_prompt } from '#scripts/rules/last-prompt'
|
|
15
16
|
import { stop_rules, type StopContext, type StopOutcome } from '#scripts/rules/stop-rules'
|
|
16
|
-
import { run_carry } from '#scripts/run/run-carry'
|
|
17
|
-
import { run_cut } from '#scripts/run/run-cut'
|
|
17
|
+
import { run_carry } from '#scripts/run/carry/run-carry'
|
|
18
|
+
import { run_cut } from '#scripts/run/cut/run-cut'
|
|
19
|
+
import { run_hold } from '#scripts/run/hold/run-hold'
|
|
18
20
|
import { run_halfrun_resume } from '#scripts/run/run-halfrun-resume'
|
|
19
21
|
import { run_headless } from '#scripts/run/run-headless'
|
|
20
|
-
import { run_hold } from '#scripts/run/run-hold'
|
|
21
22
|
import { run_stranded_detect } from '#scripts/run/run-stranded-detect'
|
|
22
23
|
import { time_density_hook } from '#scripts/time-runtime/time-density-hook'
|
|
23
24
|
import { time_hook_transcript } from '#scripts/time-runtime/time-hook-transcript'
|
|
@@ -87,6 +88,7 @@ async function build_context(
|
|
|
87
88
|
agent_pending: lane_background.pending_agent_ids(tail).length > 0,
|
|
88
89
|
handed_off: lane_handoff.is_handed_off(process.cwd()),
|
|
89
90
|
session_lang: session_lang(),
|
|
91
|
+
headless_agent: agent_headless.is_headless(),
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
|
|
@@ -217,11 +217,6 @@ function build_file_actions(shape?: ProjectShape): ReadonlyArray<FileAction> {
|
|
|
217
217
|
|
|
218
218
|
return [
|
|
219
219
|
...(shape?.has_git === false ? [] : [build_gitignore_action()]),
|
|
220
|
-
build_action(
|
|
221
|
-
'.npmrc',
|
|
222
|
-
() => init_logic.generate_npmrc(),
|
|
223
|
-
(existing) => init_logic.merge_npmrc(existing),
|
|
224
|
-
),
|
|
225
220
|
build_eslint_action(),
|
|
226
221
|
build_action(
|
|
227
222
|
PRETTIER_CONFIG_JS,
|
|
@@ -104,8 +104,16 @@ function did_skip_copy_if_absent(
|
|
|
104
104
|
|
|
105
105
|
// The merged file is written back, and reported as `updated`, only when the merge changed it — a
|
|
106
106
|
// second `josh init` over an already-merged file reports `unchanged` (joshuafolkken/kit#2873).
|
|
107
|
+
// The workspace template with the project's own `.npmrc` values carried over: once the file holds a
|
|
108
|
+
// key, the merge keeps it, so this is the one chance to move the value (joshuafolkken/kit#3267).
|
|
109
|
+
function read_workspace_template(source_path: string, destination_path: string): string {
|
|
110
|
+
const npmrc = file_reader.read_file_or_empty(path.join(path.dirname(destination_path), '.npmrc'))
|
|
111
|
+
|
|
112
|
+
return init_logic.carry_npmrc_settings(readFileSync(source_path, 'utf8'), npmrc)
|
|
113
|
+
}
|
|
114
|
+
|
|
107
115
|
function merge_existing_workspace_yaml(source_path: string, destination_path: string): void {
|
|
108
|
-
const template =
|
|
116
|
+
const template = read_workspace_template(source_path, destination_path)
|
|
109
117
|
const existing = readFileSync(destination_path, 'utf8')
|
|
110
118
|
const merged = init_logic.merge_workspace_yaml(existing, template)
|
|
111
119
|
|
|
@@ -126,7 +134,9 @@ function did_skip_workspace_yaml_copy(source_path: string, destination_path: str
|
|
|
126
134
|
return false
|
|
127
135
|
}
|
|
128
136
|
|
|
129
|
-
|
|
137
|
+
const template = read_workspace_template(source_path, destination_path)
|
|
138
|
+
|
|
139
|
+
writeFileSync(destination_path, transform_copied_content(destination_path, template))
|
|
130
140
|
console.info(` ✔ created ${WORKSPACE_YAML}`)
|
|
131
141
|
|
|
132
142
|
return false
|
|
@@ -385,6 +395,7 @@ const init_ai_copy = {
|
|
|
385
395
|
ai_file_source,
|
|
386
396
|
ai_file_mappings,
|
|
387
397
|
ensure_basic_claude_md,
|
|
398
|
+
read_workspace_template,
|
|
388
399
|
}
|
|
389
400
|
|
|
390
401
|
export { init_ai_copy, CLAUDE_MD_FILENAME }
|
|
@@ -3,6 +3,7 @@ import { json_format } from '#scripts/config-merge/json-format'
|
|
|
3
3
|
import { parse_jsonc } from '#scripts/config-merge/parse-jsonc'
|
|
4
4
|
import { patch_json_key } from '#scripts/config-merge/patch-json-key'
|
|
5
5
|
import { json_object_schema, string_array_schema, string_record_schema } from '#scripts/lib/schemas'
|
|
6
|
+
import { safe_chain_preinstall } from '#scripts/safe-chain/preinstall-command'
|
|
6
7
|
import { apply_jf_migrations, remove_retired_scripts } from './init-logic-migrate'
|
|
7
8
|
import { PACKAGE_JSON_KEY_ORDER } from './init-logic-package-key-order'
|
|
8
9
|
import { kit_base_preset } from './kit-base-preset'
|
|
@@ -216,6 +217,23 @@ function merge_package_scripts(content: string, scripts: Record<string, string>)
|
|
|
216
217
|
return serialize_package_json({ ...parsed, scripts: { ...prepend, ...migrated, ...append } })
|
|
217
218
|
}
|
|
218
219
|
|
|
220
|
+
// Replace only a safe-chain `preinstall` an earlier kit wrote, for a consumer that never re-runs
|
|
221
|
+
// `josh init`; every other key and script is kept (joshuafolkken/kit#3269).
|
|
222
|
+
function upgrade_safe_chain_preinstall(content: string): string {
|
|
223
|
+
const parsed = parse_jsonc(content)
|
|
224
|
+
const raw = parsed['scripts']
|
|
225
|
+
if (raw === undefined) return content
|
|
226
|
+
|
|
227
|
+
const scripts = string_record_schema.parse(raw)
|
|
228
|
+
const current = scripts['preinstall']
|
|
229
|
+
if (current === undefined) return content
|
|
230
|
+
|
|
231
|
+
const migrated = safe_chain_preinstall.migrate_preinstall(current)
|
|
232
|
+
if (migrated === current) return content
|
|
233
|
+
|
|
234
|
+
return serialize_package_json({ ...parsed, scripts: { ...scripts, preinstall: migrated } })
|
|
235
|
+
}
|
|
236
|
+
|
|
219
237
|
function merge_development_dependencies(
|
|
220
238
|
content: string,
|
|
221
239
|
additions: Record<string, string>,
|
|
@@ -327,6 +345,7 @@ const init_logic_json_merge = {
|
|
|
327
345
|
merge_json_array_field,
|
|
328
346
|
merge_json_object,
|
|
329
347
|
merge_package_scripts,
|
|
348
|
+
upgrade_safe_chain_preinstall,
|
|
330
349
|
merge_package_script_suffix,
|
|
331
350
|
replace_in_package_script,
|
|
332
351
|
remove_script_with_marker,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { init_logic_json_merge } from './init-logic-json-merge'
|
|
2
|
+
import { kit_development_versions } from './kit-development-versions'
|
|
2
3
|
|
|
3
4
|
const SECRETLINT_CONFIG_FILENAME = '.secretlintrc.json'
|
|
4
5
|
const SECRETLINT_RULE_PRESET = '@secretlint/secretlint-rule-preset-recommend'
|
|
@@ -6,12 +7,8 @@ const SECRETLINT_RULE_PRESET = '@secretlint/secretlint-rule-preset-recommend'
|
|
|
6
7
|
// secretlint resolves both its CLI and every rule package from the project it runs in, not
|
|
7
8
|
// transitively through the kit — the same constraint that forces the prettier plugins into
|
|
8
9
|
// consumer devDependencies (as kit peers, see init.ts). Omitting either
|
|
9
|
-
// entry makes the pre-commit hook fail with "Cannot find module".
|
|
10
|
-
|
|
11
|
-
const SECRETLINT_DEV_DEPS: Record<string, string> = {
|
|
12
|
-
secretlint: '^13.0.2',
|
|
13
|
-
[SECRETLINT_RULE_PRESET]: '^13.0.2',
|
|
14
|
-
}
|
|
10
|
+
// entry makes the pre-commit hook fail with "Cannot find module". The versions are kit's own.
|
|
11
|
+
const SECRETLINT_PACKAGES = ['secretlint', SECRETLINT_RULE_PRESET]
|
|
15
12
|
|
|
16
13
|
function generate_secretlint_config(): string {
|
|
17
14
|
const config = { rules: [{ id: SECRETLINT_RULE_PRESET }] }
|
|
@@ -24,7 +21,10 @@ function get_secretlint_config_filename(): string {
|
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
function merge_secretlint_development_deps(content: string): string {
|
|
27
|
-
return init_logic_json_merge.merge_development_dependencies(
|
|
24
|
+
return init_logic_json_merge.merge_development_dependencies(
|
|
25
|
+
content,
|
|
26
|
+
kit_development_versions.versions_of(SECRETLINT_PACKAGES),
|
|
27
|
+
)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const init_logic_secretlint = {
|
|
@@ -2,7 +2,7 @@ function extract_yaml_top_level_keys(content: string): Array<string> {
|
|
|
2
2
|
return content.split('\n').flatMap((line) => {
|
|
3
3
|
const key = /^([a-zA-Z][a-zA-Z0-9_-]*):/u.exec(line)?.[1]
|
|
4
4
|
|
|
5
|
-
return key
|
|
5
|
+
return key ?? []
|
|
6
6
|
})
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -125,6 +125,45 @@ function add_missing_build_entries(existing: string, template: string): string {
|
|
|
125
125
|
return existing.replace(block, () => [block, ...missing].join('\n'))
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
interface MovedNpmrcSetting {
|
|
129
|
+
npmrc_key: string
|
|
130
|
+
workspace_key: string
|
|
131
|
+
value_pattern: RegExp
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// `.npmrc` settings pnpm 12 reads only from `pnpm-workspace.yaml`, with the value shape each takes.
|
|
135
|
+
// A project's own value (a longer age window, `engine-strict=false`) replaces the template's, so the
|
|
136
|
+
// move neither loosens nor tightens what the project chose (joshuafolkken/kit#3267).
|
|
137
|
+
const MOVED_NPMRC_SETTINGS: ReadonlyArray<MovedNpmrcSetting> = [
|
|
138
|
+
{ npmrc_key: 'minimum-release-age', workspace_key: 'minimumReleaseAge', value_pattern: /^\d+$/u },
|
|
139
|
+
{ npmrc_key: 'engine-strict', workspace_key: 'engineStrict', value_pattern: /^(?:true|false)$/u },
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
// The last assignment wins, as it does when npm reads the file.
|
|
143
|
+
function npmrc_value(npmrc: string, key: string): string | undefined {
|
|
144
|
+
const pattern = new RegExp(String.raw`^[ \t]*${key}[ \t]*=[ \t]*(\S+)[ \t]*$`, 'gmu')
|
|
145
|
+
|
|
146
|
+
return [...npmrc.matchAll(pattern)].at(-1)?.[1]
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function carry_npmrc_setting(template: string, npmrc: string, setting: MovedNpmrcSetting): string {
|
|
150
|
+
const value = npmrc_value(npmrc, setting.npmrc_key)
|
|
151
|
+
if (value === undefined || !setting.value_pattern.test(value)) return template
|
|
152
|
+
const line_pattern = new RegExp(`^${setting.workspace_key}:.*$`, 'mu')
|
|
153
|
+
|
|
154
|
+
return template.replace(line_pattern, () => `${setting.workspace_key}: ${value}`)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function carry_npmrc_settings(template: string, npmrc: string): string {
|
|
158
|
+
let result = template
|
|
159
|
+
|
|
160
|
+
for (const setting of MOVED_NPMRC_SETTINGS) {
|
|
161
|
+
result = carry_npmrc_setting(result, npmrc, setting)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return result
|
|
165
|
+
}
|
|
166
|
+
|
|
128
167
|
function merge_workspace_yaml(existing: string, template: string): string {
|
|
129
168
|
if (!existing.trim()) return template
|
|
130
169
|
const normalized = existing.endsWith('\n') ? existing : `${existing}\n`
|
|
@@ -138,6 +177,6 @@ function merge_workspace_yaml(existing: string, template: string): string {
|
|
|
138
177
|
return append_user_blocks(cleaned, new_keys, template)
|
|
139
178
|
}
|
|
140
179
|
|
|
141
|
-
const init_logic_workspace = { merge_workspace_yaml, template_build_values }
|
|
180
|
+
const init_logic_workspace = { carry_npmrc_settings, merge_workspace_yaml, template_build_values }
|
|
142
181
|
|
|
143
182
|
export { init_logic_workspace }
|
|
@@ -14,16 +14,15 @@ const DEV_ENGINES_VALUE = {
|
|
|
14
14
|
packageManager: { name: 'pnpm', version: '>=12.1.0', onFail: 'error' },
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
|
|
17
|
+
// The settings lines earlier kit releases wrote into a project `.npmrc`. pnpm 12 reads only registry
|
|
18
|
+
// and auth settings from `.npmrc`, so all four are inert there: the age window and engine check now
|
|
19
|
+
// live in `pnpm-workspace.yaml`, and `confirmModulesPurge` no longer exists (joshuafolkken/kit#3267).
|
|
20
|
+
const LEGACY_NPMRC_LINES: ReadonlySet<string> = new Set([
|
|
20
21
|
'engine-strict=true',
|
|
21
22
|
'minimum-release-age=1440',
|
|
22
23
|
'confirmModulesPurge=false',
|
|
23
|
-
// Pin full GitHub Packages tarball URLs in the lockfile so pnpm >=11.5 frozen-lockfile
|
|
24
|
-
// installs hit the correct authenticated download path (avoids ERR_PNPM_FETCH_401 on CI).
|
|
25
24
|
'lockfile-include-tarball-url=true',
|
|
26
|
-
]
|
|
25
|
+
])
|
|
27
26
|
|
|
28
27
|
const CSPELL_IMPORT = '@joshuafolkken/kit/cspell'
|
|
29
28
|
|
|
@@ -254,10 +253,6 @@ function generate_cspell_config(): string {
|
|
|
254
253
|
return `version: "0.2"\nimport:\n - "${CSPELL_IMPORT}"\nwords: []\nignorePaths: []\n`
|
|
255
254
|
}
|
|
256
255
|
|
|
257
|
-
function generate_npmrc(): string {
|
|
258
|
-
return `${NPMRC_LINES.join('\n')}\n`
|
|
259
|
-
}
|
|
260
|
-
|
|
261
256
|
// Append `missing` lines to `existing`, inserting a separating newline when the base is
|
|
262
257
|
// non-empty and lacks a trailing one. Returns `existing` untouched when nothing is missing.
|
|
263
258
|
function append_missing_lines(existing: string, missing: ReadonlyArray<string>): string {
|
|
@@ -267,18 +262,19 @@ function append_missing_lines(existing: string, missing: ReadonlyArray<string>):
|
|
|
267
262
|
return `${prefix}${missing.join('\n')}\n`
|
|
268
263
|
}
|
|
269
264
|
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
//
|
|
273
|
-
//
|
|
274
|
-
// `PNPM_CONFIG_NPMRC_AUTH_FILE`, for instance) gets
|
|
275
|
-
// live in a deploy platform's dashboard — so no
|
|
276
|
-
// apart from a live one. Deleting it took down a
|
|
277
|
-
//
|
|
265
|
+
// Removes only an exact kit-written legacy line; every other line survives verbatim, including a
|
|
266
|
+
// `_authToken` line the consumer added themselves and a setting carrying a value of their own. Kit
|
|
267
|
+
// removed the env-var auth form until #759, on the premise that pnpm always ignores it in a project
|
|
268
|
+
// .npmrc — true only while `npmrcAuthFile` is unset. A consumer that declares the project file its
|
|
269
|
+
// trusted auth file (Cloudflare Workers Builds via `PNPM_CONFIG_NPMRC_AUTH_FILE`, for instance) gets
|
|
270
|
+
// the credential expanded, and that setting can live in a deploy platform's dashboard — so no
|
|
271
|
+
// reading of the repository tells an inert auth line apart from a live one. Deleting it took down a
|
|
272
|
+
// working production deploy. See docs/authentication.md §4(d).
|
|
278
273
|
function merge_npmrc(content: string): string {
|
|
279
|
-
const
|
|
274
|
+
const lines = content.split('\n')
|
|
275
|
+
const kept = lines.filter((line) => !LEGACY_NPMRC_LINES.has(line.trim()))
|
|
280
276
|
|
|
281
|
-
return
|
|
277
|
+
return kept.length === lines.length ? content : kept.join('\n')
|
|
282
278
|
}
|
|
283
279
|
|
|
284
280
|
// A gitignore line worth appending during a union merge: real ignore patterns only.
|
|
@@ -349,10 +345,6 @@ function strip_kit_only_vscode_settings_content(raw: string): string {
|
|
|
349
345
|
return json_format.format_json(stripped)
|
|
350
346
|
}
|
|
351
347
|
|
|
352
|
-
function get_npmrc_lines(): ReadonlyArray<string> {
|
|
353
|
-
return NPMRC_LINES
|
|
354
|
-
}
|
|
355
|
-
|
|
356
348
|
function get_development_engines_value(): typeof DEV_ENGINES_VALUE {
|
|
357
349
|
return DEV_ENGINES_VALUE
|
|
358
350
|
}
|
|
@@ -436,7 +428,6 @@ const init_logic = {
|
|
|
436
428
|
get_tsconfig_exclude_entries,
|
|
437
429
|
generate_lefthook_config,
|
|
438
430
|
generate_cspell_config,
|
|
439
|
-
generate_npmrc,
|
|
440
431
|
merge_npmrc,
|
|
441
432
|
merge_gitignore,
|
|
442
433
|
get_tsconfig_extends_entry,
|
|
@@ -450,7 +441,6 @@ const init_logic = {
|
|
|
450
441
|
SAFE_CHAIN_CMD,
|
|
451
442
|
GUARDED_LEFTHOOK_CMD,
|
|
452
443
|
upgrade_prepare_lefthook_warning,
|
|
453
|
-
get_npmrc_lines,
|
|
454
444
|
get_development_engines_value,
|
|
455
445
|
get_ai_copy_files,
|
|
456
446
|
get_ai_copy_file_mappings,
|