@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
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { readFileSync } from 'node:fs'
|
|
8
8
|
import { fileURLToPath } from 'node:url'
|
|
9
|
+
import { COMMAND_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
9
10
|
import { execaSync } from 'execa'
|
|
10
11
|
import {
|
|
11
12
|
publishable_range,
|
|
@@ -15,7 +16,6 @@ import {
|
|
|
15
16
|
} from './publishable-range'
|
|
16
17
|
|
|
17
18
|
const PACKAGE_JSON_PATH = 'package.json'
|
|
18
|
-
const VIEW_TIMEOUT_MS = 30_000
|
|
19
19
|
const FAILURE_EXIT_CODE = 1
|
|
20
20
|
|
|
21
21
|
// A registry query rather than a direct fetch: safe-chain installs shims ahead of the package
|
|
@@ -29,7 +29,7 @@ const FAILURE_EXIT_CODE = 1
|
|
|
29
29
|
function probe_range(name: string, range: string): ProbeResult {
|
|
30
30
|
const result = execaSync('pnpm', ['view', `${name}@${range}`, 'version'], {
|
|
31
31
|
reject: false,
|
|
32
|
-
timeout:
|
|
32
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
return { exit_code: result.exitCode ?? FAILURE_EXIT_CODE, stdout: result.stdout }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { package_with_deps_schema } from '#scripts/overrides/schemas'
|
|
1
|
+
import { package_with_deps_schema } from '#scripts/overrides/overrides-schemas'
|
|
2
2
|
import semver from 'semver'
|
|
3
3
|
|
|
4
4
|
// kit ships a `preinstall` hook that installs @aikidosec/safe-chain, whose minimum-age policy hides
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
+
import { yaml_document } from '#scripts/lib/yaml-document'
|
|
3
4
|
import semver from 'semver'
|
|
4
5
|
import { z } from 'zod'
|
|
5
6
|
|
|
@@ -7,30 +8,41 @@ import { z } from 'zod'
|
|
|
7
8
|
// safe-chain's interception. safe-chain filters the registry only when the process tree was
|
|
8
9
|
// started through one of its six wrapped shell commands, so `josh latest` and
|
|
9
10
|
// `pnpm josh latest` used to resolve different "newest release" answers. These functions
|
|
10
|
-
// make the resolution deterministic: the policy comes from the repo-managed
|
|
11
|
-
// publish timestamps from the registry, and the selection is a pure computation over both.
|
|
11
|
+
// make the resolution deterministic: the policy comes from the repo-managed `pnpm-workspace.yaml`,
|
|
12
|
+
// the publish timestamps from the registry, and the selection is a pure computation over both.
|
|
13
|
+
// pnpm 12 reads its settings from `pnpm-workspace.yaml` — a `minimum-release-age` line in `.npmrc`
|
|
14
|
+
// is ignored there, so reading it would report a window pnpm does not apply (kit#3267).
|
|
12
15
|
|
|
13
|
-
const MINIMUM_RELEASE_AGE_RE = /^minimum-release-age\s*=\s*(\d+)\s*$/mu
|
|
14
16
|
const NO_QUARANTINE_MINUTES = 0
|
|
15
|
-
const
|
|
17
|
+
const WORKSPACE_PATH = 'pnpm-workspace.yaml'
|
|
18
|
+
const workspace_age_schema = z.object({ minimumReleaseAge: z.number().int().nonnegative() })
|
|
16
19
|
|
|
17
20
|
// A version → ISO publish date map, the shape both the registry and the GitHub Packages API are
|
|
18
21
|
// reduced to before the aged-version selection runs.
|
|
19
22
|
const release_times_schema = z.record(z.string(), z.string())
|
|
20
23
|
const MS_PER_MINUTE = 60_000
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
function parse_workspace(workspace_content: string): unknown {
|
|
26
|
+
try {
|
|
27
|
+
return yaml_document.parse_yaml(workspace_content)
|
|
28
|
+
} catch {
|
|
29
|
+
return undefined
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// The window `pnpm-workspace.yaml` content declares, or nothing when it does not declare one or the
|
|
34
|
+
// document is malformed — an explicit `minimumReleaseAge: 0` stays 0 rather than collapsing into
|
|
35
|
+
// "not declared".
|
|
36
|
+
function parse_declared_minimum_release_age(workspace_content: string): number | undefined {
|
|
37
|
+
const parsed = workspace_age_schema.safeParse(parse_workspace(workspace_content))
|
|
26
38
|
|
|
27
|
-
return
|
|
39
|
+
return parsed.success ? parsed.data.minimumReleaseAge : undefined
|
|
28
40
|
}
|
|
29
41
|
|
|
30
|
-
// The quarantine window in minutes from
|
|
31
|
-
// quarantine, matching pnpm's own default for the setting.
|
|
32
|
-
function parse_minimum_release_age(
|
|
33
|
-
return parse_declared_minimum_release_age(
|
|
42
|
+
// The quarantine window in minutes from `pnpm-workspace.yaml`; a missing or malformed entry means
|
|
43
|
+
// no quarantine, matching pnpm's own default for the setting.
|
|
44
|
+
function parse_minimum_release_age(workspace_content: string): number {
|
|
45
|
+
return parse_declared_minimum_release_age(workspace_content) ?? NO_QUARANTINE_MINUTES
|
|
34
46
|
}
|
|
35
47
|
|
|
36
48
|
// Stable releases only, on the requested major, published at or before the cutoff. The
|
|
@@ -83,49 +95,47 @@ function select_aged_version(
|
|
|
83
95
|
return eligible[0]
|
|
84
96
|
}
|
|
85
97
|
|
|
86
|
-
// The window declared in one
|
|
87
|
-
// declare the setting. Distinguishing "not declared" from "declared as 0" is what lets an
|
|
88
|
-
// `
|
|
89
|
-
function read_declared_minimum_release_age(
|
|
98
|
+
// The window declared in one `pnpm-workspace.yaml`, or nothing when the file is absent, unreadable,
|
|
99
|
+
// or does not declare the setting. Distinguishing "not declared" from "declared as 0" is what lets an
|
|
100
|
+
// explicit `minimumReleaseAge: 0` opt-out stop the walk instead of falling through to an ancestor's.
|
|
101
|
+
function read_declared_minimum_release_age(workspace_path: string): number | undefined {
|
|
90
102
|
try {
|
|
91
|
-
return parse_declared_minimum_release_age(readFileSync(
|
|
103
|
+
return parse_declared_minimum_release_age(readFileSync(workspace_path, 'utf8'))
|
|
92
104
|
} catch {
|
|
93
105
|
return undefined
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
108
|
|
|
97
|
-
// The quarantine window declared by one specific
|
|
98
|
-
// absent, unreadable, or undeclared setting means no quarantine — the policy is advisory,
|
|
99
|
-
// project without one is not held back.
|
|
109
|
+
// The quarantine window declared by one specific `pnpm-workspace.yaml`, defaulting to the project's
|
|
110
|
+
// own. An absent, unreadable, or undeclared setting means no quarantine — the policy is advisory,
|
|
111
|
+
// and a project without one is not held back.
|
|
100
112
|
//
|
|
101
113
|
// Deliberately not the upward walk below: `josh latest` resolves this against the working directory
|
|
102
|
-
// it also writes `corepack use` into, and honouring
|
|
114
|
+
// it also writes `corepack use` into, and honouring an ancestor's policy there could freeze pnpm
|
|
103
115
|
// bumps in a project that declares none (joshuafolkken/kit#808).
|
|
104
|
-
function read_minimum_release_age(
|
|
105
|
-
return read_declared_minimum_release_age(
|
|
116
|
+
function read_minimum_release_age(workspace_path: string = WORKSPACE_PATH): number {
|
|
117
|
+
return read_declared_minimum_release_age(workspace_path) ?? NO_QUARANTINE_MINUTES
|
|
106
118
|
}
|
|
107
119
|
|
|
108
|
-
// The window declared by the nearest
|
|
120
|
+
// The window declared by the nearest `pnpm-workspace.yaml` at or above `start`, or nothing.
|
|
109
121
|
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
// alone would silently read "no quarantine" in every subdirectory.
|
|
113
|
-
//
|
|
114
|
-
// not mask a `~/.npmrc` carrying the policy (joshuafolkken/kit#808).
|
|
122
|
+
// This walks rather than reading one path because `josh version` and `josh latest` both run from
|
|
123
|
+
// anywhere inside a project — and from outside one — so resolving against the working directory
|
|
124
|
+
// alone would silently read "no quarantine" in every subdirectory (joshuafolkken/kit#808). pnpm
|
|
125
|
+
// finds its workspace root the same way, by walking up to the nearest `pnpm-workspace.yaml`.
|
|
115
126
|
//
|
|
116
|
-
// `boundary` stops the walk at a known root. Production passes none
|
|
117
|
-
//
|
|
127
|
+
// `boundary` stops the walk at a known root. Production passes none, while tests bound the search
|
|
128
|
+
// so it cannot depend on the directories above the machine's temp root.
|
|
118
129
|
//
|
|
119
|
-
// Simplification:
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
// complexity here.
|
|
130
|
+
// Simplification: a nearer workspace file that does not declare the window falls through to an
|
|
131
|
+
// ancestor's, and pnpm's user-level `config.yaml` is not consulted. The consequence is one
|
|
132
|
+
// informational `Held:` line — the value never suppresses a command — so modelling pnpm's exact
|
|
133
|
+
// lookup is not worth its complexity here.
|
|
124
134
|
function find_declared_minimum_release_age(
|
|
125
135
|
start: string,
|
|
126
136
|
boundary: string | undefined,
|
|
127
137
|
): number | undefined {
|
|
128
|
-
const declared = read_declared_minimum_release_age(path.join(start,
|
|
138
|
+
const declared = read_declared_minimum_release_age(path.join(start, WORKSPACE_PATH))
|
|
129
139
|
if (declared !== undefined) return declared
|
|
130
140
|
if (start === boundary) return undefined
|
|
131
141
|
const parent = path.dirname(start)
|
|
@@ -8,7 +8,7 @@ import { release_age } from './release-age'
|
|
|
8
8
|
// is by definition the youngest (joshuafolkken/kit#808).
|
|
9
9
|
//
|
|
10
10
|
// **The window binds unpinned resolution only.** Measured on pnpm 11.22.0 with
|
|
11
|
-
// `
|
|
11
|
+
// `minimumReleaseAge: 1440` and a release published 3.5 h earlier:
|
|
12
12
|
//
|
|
13
13
|
// pnpm add pkg@1.80.0 -> 1.80.0 (pnpm records a `minimumReleaseAgeExclude` entry)
|
|
14
14
|
// pnpm add pkg -> 1.78.0 (the newest release past the window)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { COMMAND_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
2
|
+
import { ci_installer_pin } from '#scripts/safe-chain/ci-installer-pin'
|
|
3
|
+
import { npm_registry } from '#scripts/version/npm-registry'
|
|
4
|
+
import { execaSync } from 'execa'
|
|
5
|
+
|
|
6
|
+
const SAFE_CHAIN_PKG = '@aikidosec/safe-chain'
|
|
7
|
+
|
|
8
|
+
// The registry's answer is trusted only as an exact semver version: it ends up in workflow files and
|
|
9
|
+
// in the installer URL (joshuafolkken/kit#3266).
|
|
10
|
+
function fetch_latest_version(): string | undefined {
|
|
11
|
+
const result = execaSync('npm', ['view', SAFE_CHAIN_PKG, 'version'], {
|
|
12
|
+
reject: false,
|
|
13
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
14
|
+
})
|
|
15
|
+
if (result.exitCode !== 0 || !result.stdout) return undefined
|
|
16
|
+
|
|
17
|
+
return npm_registry.valid_version(result.stdout.trim())
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// The hash-verified installer pinned in the workflows is the one place a safe-chain release is
|
|
21
|
+
// recorded; `preinstall` no longer names one (joshuafolkken/kit#3269). Every repository moves the
|
|
22
|
+
// files that carry the pin — app-kit's own `dast.yml` / `load.yml` included (joshuafolkken/kit#2830).
|
|
23
|
+
function sync(): void {
|
|
24
|
+
const latest = fetch_latest_version()
|
|
25
|
+
|
|
26
|
+
if (latest === undefined) {
|
|
27
|
+
console.warn(`\n⚠ Could not fetch a valid latest version of ${SAFE_CHAIN_PKG}; skipping`)
|
|
28
|
+
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
ci_installer_pin.sync(latest)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const safe_chain_version_update = {
|
|
36
|
+
sync,
|
|
37
|
+
fetch_latest_version,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { safe_chain_version_update }
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import type { PackageVersionConfig } from './version-command-config'
|
|
2
2
|
|
|
3
|
+
// One upgrade the version commands offer and run: `text` is the line printed after `Run:`, and
|
|
4
|
+
// `steps` are the argument vectors executed in order, each only after the one before it succeeded.
|
|
5
|
+
// A command kit builds itself is spawned without a shell, so a registry-supplied version is never
|
|
6
|
+
// parsed by one; only the consumer's own configured command goes through `sh -c`.
|
|
7
|
+
interface UpgradeCommand {
|
|
8
|
+
text: string
|
|
9
|
+
steps: ReadonlyArray<ReadonlyArray<string>>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const STEP_SEPARATOR = ' && '
|
|
13
|
+
|
|
3
14
|
function update_scope_flag(is_local: boolean): string {
|
|
4
15
|
return is_local ? '-D' : '-g'
|
|
5
16
|
}
|
|
6
17
|
|
|
18
|
+
function update_argv(
|
|
19
|
+
latest: string,
|
|
20
|
+
is_local: boolean,
|
|
21
|
+
config: PackageVersionConfig,
|
|
22
|
+
): Array<string> {
|
|
23
|
+
return ['pnpm', 'add', update_scope_flag(is_local), `${config.package_name}@${latest}`]
|
|
24
|
+
}
|
|
25
|
+
|
|
7
26
|
// The bare `pnpm add` invocation that installs one package at an exact version, in the global or the
|
|
8
27
|
// project (dev-dependency) scope.
|
|
9
28
|
function format_update_command(
|
|
@@ -11,20 +30,41 @@ function format_update_command(
|
|
|
11
30
|
is_local: boolean,
|
|
12
31
|
config: PackageVersionConfig,
|
|
13
32
|
): string {
|
|
14
|
-
return
|
|
33
|
+
return update_argv(latest, is_local, config).join(' ')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// The upgrade for one target. A project-scope install is followed by kit's lockfile repair
|
|
37
|
+
// (`fix-gh-packages`), which a global install does not need. The printed text is derived from the
|
|
38
|
+
// steps, so the hint and what actually runs cannot drift apart.
|
|
39
|
+
function build_upgrade_command(
|
|
40
|
+
latest: string,
|
|
41
|
+
is_local: boolean,
|
|
42
|
+
config: PackageVersionConfig,
|
|
43
|
+
): UpgradeCommand {
|
|
44
|
+
const steps = [update_argv(latest, is_local, config)]
|
|
45
|
+
if (is_local) steps.push(['node_modules/.bin/tsx', config.fix_gh_packages_path])
|
|
46
|
+
|
|
47
|
+
return { text: steps.map((step) => step.join(' ')).join(STEP_SEPARATOR), steps }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// The consumer's own configured command — `pnpm add -g …`, or a chain with `&&` — is inside the trust
|
|
51
|
+
// boundary and needs a shell to mean what it says.
|
|
52
|
+
function shell_upgrade_command(command: string): UpgradeCommand {
|
|
53
|
+
return { text: command, steps: [['sh', '-c', command]] }
|
|
15
54
|
}
|
|
16
55
|
|
|
17
|
-
// The full shell command for one upgrade target. A project-scope install is chained with kit's
|
|
18
|
-
// lockfile repair (`fix-gh-packages`), which a global install does not need.
|
|
19
56
|
function build_upgrade_shell_command(
|
|
20
57
|
latest: string,
|
|
21
58
|
is_local: boolean,
|
|
22
59
|
config: PackageVersionConfig,
|
|
23
60
|
): string {
|
|
24
|
-
|
|
25
|
-
if (!is_local) return add_command
|
|
26
|
-
|
|
27
|
-
return `${add_command} && node_modules/.bin/tsx ${config.fix_gh_packages_path}`
|
|
61
|
+
return build_upgrade_command(latest, is_local, config).text
|
|
28
62
|
}
|
|
29
63
|
|
|
30
|
-
export {
|
|
64
|
+
export type { UpgradeCommand }
|
|
65
|
+
export {
|
|
66
|
+
build_upgrade_command,
|
|
67
|
+
build_upgrade_shell_command,
|
|
68
|
+
format_update_command,
|
|
69
|
+
shell_upgrade_command,
|
|
70
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { release_hold } from './release-hold'
|
|
2
2
|
import { is_no_op_upgrade_command, type InstalledVersions } from './upgrade-command-guard'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
build_upgrade_command,
|
|
5
|
+
build_upgrade_shell_command,
|
|
6
|
+
format_update_command,
|
|
7
|
+
shell_upgrade_command,
|
|
8
|
+
type UpgradeCommand,
|
|
9
|
+
} from './upgrade-shell-command'
|
|
4
10
|
import type { PackageVersionConfig } from './version-command-config'
|
|
5
11
|
|
|
6
12
|
const NOT_INSTALLED = 'not installed'
|
|
@@ -161,11 +167,11 @@ function resolve_effective_upgrade_hint(report: UpstreamReport): EffectiveUpgrad
|
|
|
161
167
|
// The consumer-supplied global upgrade command for a stale effective upstream, or nothing. Skipped
|
|
162
168
|
// when the consumer did not opt in, the effective install is up to date / unresolved, or the command
|
|
163
169
|
// provably cannot change the effective version it was meant to fix (see the note line instead).
|
|
164
|
-
function build_effective_upgrade_commands(report: UpstreamReport): Array<
|
|
170
|
+
function build_effective_upgrade_commands(report: UpstreamReport): Array<UpgradeCommand> {
|
|
165
171
|
const hint = resolve_effective_upgrade_hint(report)
|
|
166
172
|
if (hint === undefined || hint.is_no_op) return []
|
|
167
173
|
|
|
168
|
-
return [hint.command]
|
|
174
|
+
return [shell_upgrade_command(hint.command)]
|
|
169
175
|
}
|
|
170
176
|
|
|
171
177
|
// The explanation that replaces a suppressed `Run:` hint, so a stale effective install is never left
|
|
@@ -202,8 +208,9 @@ function format_upstream_lines(report: UpstreamReport): Array<string> {
|
|
|
202
208
|
// Drop repeated commands while preserving first-seen order. A consumer with several upstreams can
|
|
203
209
|
// return the same chain-pinning global command from each of them (game-kit returns one command for
|
|
204
210
|
// both app-kit and kit), which would otherwise print an identical `Run:` line once per upstream.
|
|
205
|
-
|
|
206
|
-
|
|
211
|
+
// Keyed on the printed text, which the steps are derived from or carried verbatim inside.
|
|
212
|
+
function unique_upgrade_commands(commands: ReadonlyArray<UpgradeCommand>): Array<UpgradeCommand> {
|
|
213
|
+
return [...new Map(commands.map((command) => [command.text, command])).values()]
|
|
207
214
|
}
|
|
208
215
|
|
|
209
216
|
// The outcome line for an effective install the upgrade command left exactly where it was.
|
|
@@ -235,37 +242,39 @@ function format_effective_outcome(report: UpstreamReport, after: string | undefi
|
|
|
235
242
|
|
|
236
243
|
// The project-scope upgrade command when the upstream's project dependency is installed and stale.
|
|
237
244
|
// Always local (with lockfile repair), since the project path is the only scope kit resolves.
|
|
238
|
-
function build_project_upgrade_commands(report: UpstreamReport): Array<
|
|
245
|
+
function build_project_upgrade_commands(report: UpstreamReport): Array<UpgradeCommand> {
|
|
239
246
|
if (!is_target_stale(report.project_version, report.latest)) return []
|
|
240
247
|
|
|
241
|
-
return [
|
|
248
|
+
return [build_upgrade_command(report.latest, true, report.config)]
|
|
242
249
|
}
|
|
243
250
|
|
|
244
251
|
// Build the upgrade commands for every upstream: the consumer's global command for a stale effective
|
|
245
252
|
// install first, then the project-scope command, mirroring the main report's global-before-project
|
|
246
253
|
// order. Upstreams without either stale target contribute nothing.
|
|
247
|
-
function build_upstream_upgrade_commands(
|
|
254
|
+
function build_upstream_upgrade_commands(
|
|
255
|
+
reports: ReadonlyArray<UpstreamReport>,
|
|
256
|
+
): Array<UpgradeCommand> {
|
|
248
257
|
return reports.flatMap((report) => [
|
|
249
258
|
...build_effective_upgrade_commands(report),
|
|
250
259
|
...build_project_upgrade_commands(report),
|
|
251
260
|
])
|
|
252
261
|
}
|
|
253
262
|
|
|
254
|
-
// Build the
|
|
263
|
+
// Build the upgrade commands for whichever of the two targets are installed and stale.
|
|
255
264
|
// Order: global first, then project (mirrors the display order).
|
|
256
265
|
function build_dual_upgrade_commands(
|
|
257
266
|
snapshot: VersionSnapshot,
|
|
258
267
|
config: PackageVersionConfig,
|
|
259
|
-
): Array<
|
|
268
|
+
): Array<UpgradeCommand> {
|
|
260
269
|
const { global_version, project_version, latest } = snapshot
|
|
261
|
-
const commands: Array<
|
|
270
|
+
const commands: Array<UpgradeCommand> = []
|
|
262
271
|
|
|
263
272
|
if (is_target_stale(global_version, latest)) {
|
|
264
|
-
commands.push(
|
|
273
|
+
commands.push(build_upgrade_command(latest, false, config))
|
|
265
274
|
}
|
|
266
275
|
|
|
267
276
|
if (is_target_stale(project_version, latest)) {
|
|
268
|
-
commands.push(
|
|
277
|
+
commands.push(build_upgrade_command(latest, true, config))
|
|
269
278
|
}
|
|
270
279
|
|
|
271
280
|
return commands
|
|
@@ -298,7 +307,7 @@ function format_dual_version_output(
|
|
|
298
307
|
const hints = unique_upgrade_commands([
|
|
299
308
|
...build_dual_upgrade_commands(snapshot, config),
|
|
300
309
|
...build_upstream_upgrade_commands(upstreams),
|
|
301
|
-
]).map((command) => `Run: ${command}`)
|
|
310
|
+
]).map((command) => `Run: ${command.text}`)
|
|
302
311
|
if (hints.length > 0) lines.push('', ...hints)
|
|
303
312
|
if (extras.warning !== undefined) lines.push('', extras.warning)
|
|
304
313
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { INSTALL_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
1
2
|
import { execaSync } from 'execa'
|
|
2
3
|
import { release_age } from './release-age'
|
|
3
4
|
import { release_hold } from './release-hold'
|
|
4
5
|
import { running_binary } from './running-binary'
|
|
5
6
|
import type { InstalledVersions } from './upgrade-command-guard'
|
|
7
|
+
import type { UpgradeCommand } from './upgrade-shell-command'
|
|
6
8
|
import {
|
|
7
9
|
version_check_logic,
|
|
8
10
|
type ReleaseHold,
|
|
@@ -24,8 +26,6 @@ import { version_targets } from './version-targets'
|
|
|
24
26
|
const FAILURE_EXIT_CODE = 1
|
|
25
27
|
const ALREADY_UP_TO_DATE = 'Already up to date'
|
|
26
28
|
const NO_QUARANTINE_MINUTES = 0
|
|
27
|
-
// A global install that goes to the network — the same ten minutes `lane-install.ts` gives one.
|
|
28
|
-
const UPGRADE_TIMEOUT_MS = 600_000
|
|
29
29
|
|
|
30
30
|
// What the local minimum-release-age policy permits for one package. Resolved per package because
|
|
31
31
|
// the newest installable release is a property of that package's own publish history. Returns a hold
|
|
@@ -197,23 +197,35 @@ function run_check(config: VersionCommandConfig): void {
|
|
|
197
197
|
)
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
function
|
|
205
|
-
const
|
|
200
|
+
// One step as an argument vector — no shell unless the step itself is the consumer's `sh -c`
|
|
201
|
+
// (`shell_upgrade_command`). The bound keeps a registry that never answers from holding `josh
|
|
202
|
+
// version` open forever; a timed-out run has no exit code, so it falls through to the failure code
|
|
203
|
+
// like any other failed step.
|
|
204
|
+
function run_upgrade_step(step: ReadonlyArray<string>): number {
|
|
205
|
+
const [executable = '', ...rest] = step
|
|
206
|
+
const result = execaSync(executable, rest, {
|
|
206
207
|
stdio: 'inherit',
|
|
207
208
|
reject: false,
|
|
208
|
-
timeout:
|
|
209
|
+
timeout: INSTALL_TIMEOUT_MS,
|
|
209
210
|
})
|
|
210
211
|
|
|
211
212
|
return result.exitCode ?? FAILURE_EXIT_CODE
|
|
212
213
|
}
|
|
213
214
|
|
|
215
|
+
// Run one command's steps in order, stopping at the first failure — what the `&&` in its printed
|
|
216
|
+
// text says.
|
|
217
|
+
function run_upgrade_command(command: UpgradeCommand): number {
|
|
218
|
+
for (const step of command.steps) {
|
|
219
|
+
const code = run_upgrade_step(step)
|
|
220
|
+
if (code !== 0) return code
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return 0
|
|
224
|
+
}
|
|
225
|
+
|
|
214
226
|
// Run every upgrade command in order, returning the last non-zero exit code (or 0 when all
|
|
215
227
|
// succeed) so a failure on either target is surfaced without aborting the remaining upgrades.
|
|
216
|
-
function run_all_upgrade_commands(commands: ReadonlyArray<
|
|
228
|
+
function run_all_upgrade_commands(commands: ReadonlyArray<UpgradeCommand>): number {
|
|
217
229
|
let exit_code = 0
|
|
218
230
|
const failed_commands: Array<string> = []
|
|
219
231
|
|
|
@@ -221,7 +233,7 @@ function run_all_upgrade_commands(commands: ReadonlyArray<string>): number {
|
|
|
221
233
|
const code = run_upgrade_command(command)
|
|
222
234
|
if (code === 0) continue
|
|
223
235
|
exit_code = code
|
|
224
|
-
failed_commands.push(command)
|
|
236
|
+
failed_commands.push(command.text)
|
|
225
237
|
}
|
|
226
238
|
|
|
227
239
|
if (failed_commands.length > 0) {
|
|
@@ -23,19 +23,11 @@ function require_endpoint(versions_endpoint: string | undefined, package_name: s
|
|
|
23
23
|
)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
// message instead of a raw ExecaSyncError stack. The detail is the shared layer's failure text: gh's
|
|
32
|
-
// own stderr (e.g. "gh: Not Found (HTTP 404)") when it wrote one, execa's message otherwise, followed
|
|
33
|
-
// by any JSON error body gh wrote to stdout.
|
|
34
|
-
function fetch_latest_version(versions_endpoint: string | undefined, package_name: string): string {
|
|
35
|
-
const endpoint = require_endpoint(versions_endpoint, package_name)
|
|
36
|
-
const public_latest = npm_registry.read_latest(package_name)
|
|
37
|
-
if (public_latest !== undefined) return public_latest
|
|
38
|
-
|
|
26
|
+
// The newest version name on the GitHub Packages versions endpoint. Wraps `gh api` failures with an
|
|
27
|
+
// actionable message instead of a raw ExecaSyncError stack. The detail is the shared layer's failure
|
|
28
|
+
// text: gh's own stderr (e.g. "gh: Not Found (HTTP 404)") when it wrote one, execa's message
|
|
29
|
+
// otherwise, followed by any JSON error body gh wrote to stdout.
|
|
30
|
+
function read_github_name(endpoint: string, package_name: string): string {
|
|
39
31
|
try {
|
|
40
32
|
return git_gh_exec.exec_gh_api_sync({ path: endpoint, jq_filter: '.[0].name' }).trim()
|
|
41
33
|
} catch (error) {
|
|
@@ -50,6 +42,29 @@ function fetch_latest_version(versions_endpoint: string | undefined, package_nam
|
|
|
50
42
|
}
|
|
51
43
|
}
|
|
52
44
|
|
|
45
|
+
// Refused at the source, as public npm's answer is: the value goes into an install command, so
|
|
46
|
+
// anything but a semver version is never passed on (joshuafolkken/kit#3266).
|
|
47
|
+
function read_github_latest(endpoint: string, package_name: string): string {
|
|
48
|
+
const name = read_github_name(endpoint, package_name)
|
|
49
|
+
const version = npm_registry.valid_version(name)
|
|
50
|
+
if (version !== undefined) return version
|
|
51
|
+
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Refused latest version for ${package_name} via ${endpoint}: ${JSON.stringify(name)} is not a semver version`,
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Fetch the latest published version: public npm's `latest` dist-tag first, which needs no
|
|
58
|
+
// credentials (joshuafolkken/kit#2882), then the GitHub Packages versions endpoint for a package
|
|
59
|
+
// public npm does not answer for. The endpoint is supplied per package (e.g.
|
|
60
|
+
// `/users/joshuafolkken/packages/npm/kit/versions?per_page=1`) so the same fetcher serves kit, jgame,
|
|
61
|
+
// and app-kit. Guards an undefined/empty endpoint before either source is asked.
|
|
62
|
+
function fetch_latest_version(versions_endpoint: string | undefined, package_name: string): string {
|
|
63
|
+
const endpoint = require_endpoint(versions_endpoint, package_name)
|
|
64
|
+
|
|
65
|
+
return npm_registry.read_latest(package_name) ?? read_github_latest(endpoint, package_name)
|
|
66
|
+
}
|
|
67
|
+
|
|
53
68
|
// Rewrite the endpoint's page size. The endpoint is consumer-overridable, so `per_page` is set
|
|
54
69
|
// through a query parser rather than by substituting the literal the default happens to carry.
|
|
55
70
|
function with_page_size(endpoint: string, page_size: number): string {
|
|
@@ -13,10 +13,6 @@ concurrency:
|
|
|
13
13
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
14
14
|
cancel-in-progress: true
|
|
15
15
|
|
|
16
|
-
permissions:
|
|
17
|
-
contents: write
|
|
18
|
-
pull-requests: write
|
|
19
|
-
|
|
20
16
|
jobs:
|
|
21
17
|
# Gated on who opened the pull request, not on who triggered this run. `github.actor` names the
|
|
22
18
|
# latter, so a push by anyone other than Dependabot — a maintainer rebasing the branch by hand, or
|
|
@@ -24,11 +20,15 @@ jobs:
|
|
|
24
20
|
# `gh pr merge --auto` is state on the pull request, so a run that never happens cannot withdraw an
|
|
25
21
|
# auto-merge an earlier run armed, and the bump merges itself the moment the checks go green
|
|
26
22
|
# (joshuafolkken/kit#838). The author is the stable fact about a Dependabot pull request; arming is
|
|
27
|
-
# what stays restricted to Dependabot's own events, on the step below.
|
|
23
|
+
# what stays restricted to Dependabot's own events, on the step below. The write rights are granted
|
|
24
|
+
# to this job alone (joshuafolkken/kit#3268).
|
|
28
25
|
auto-merge:
|
|
29
26
|
runs-on: ubuntu-latest
|
|
30
27
|
timeout-minutes: 10
|
|
31
28
|
if: github.event.pull_request.user.login == 'dependabot[bot]'
|
|
29
|
+
permissions:
|
|
30
|
+
contents: write
|
|
31
|
+
pull-requests: write
|
|
32
32
|
steps:
|
|
33
33
|
# Whether the pull request touches a workflow some upstream package overwrites. Decided from
|
|
34
34
|
# the changed files because Dependabot's metadata cannot answer it: for the github-actions
|
|
@@ -7,6 +7,9 @@ name: GitHub Release
|
|
|
7
7
|
# started by the GITHUB_TOKEN never fires one (joshuafolkken/kit#3138). kit's own release is the
|
|
8
8
|
# `create-release` job of its publish.yml, which runs the same `josh release:github`, so this file is
|
|
9
9
|
# distributed but never runs in kit.
|
|
10
|
+
# The title names the tag, so a later tag's release can tell this run is still at work on it.
|
|
11
|
+
run-name: GitHub Release ${{ github.event.client_payload.tag }}
|
|
12
|
+
|
|
10
13
|
on:
|
|
11
14
|
repository_dispatch:
|
|
12
15
|
types: [new-tag-created]
|
|
@@ -17,6 +20,8 @@ on:
|
|
|
17
20
|
jobs:
|
|
18
21
|
release:
|
|
19
22
|
runs-on: ubuntu-latest
|
|
23
|
+
# `josh release:github` waits up to 60 minutes (120 polls, 30 seconds apart) for the Publish run
|
|
24
|
+
# and lower tags' releases; the extra 5 minutes cover the setup before it.
|
|
20
25
|
timeout-minutes: 65
|
|
21
26
|
permissions:
|
|
22
27
|
actions: read
|
|
@@ -65,3 +70,4 @@ jobs:
|
|
|
65
70
|
RELEASE_TAG: ${{ steps.release.outputs.tag }}
|
|
66
71
|
RELEASE_WORKFLOW: ${{ steps.release.outputs.workflow }}
|
|
67
72
|
RELEASE_AWAIT_PUBLISH: ${{ steps.release.outputs.await }}
|
|
73
|
+
RELEASE_RUN_WORKFLOW: github-release.yml
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { error_text } from '#scripts/lib/error-message'
|
|
4
|
-
import { build_library, library_paths } from './build-library'
|
|
5
|
-
|
|
6
|
-
const CONFIG_MERGE_LIBRARY = 'config-merge'
|
|
7
|
-
const { outfile: CONFIG_MERGE_OUTFILE, dts_file: CONFIG_MERGE_DTS_FILE } =
|
|
8
|
-
library_paths(CONFIG_MERGE_LIBRARY)
|
|
9
|
-
|
|
10
|
-
async function build_config_merge_library(): Promise<void> {
|
|
11
|
-
await build_library(CONFIG_MERGE_LIBRARY)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function main(): Promise<void> {
|
|
15
|
-
try {
|
|
16
|
-
await build_config_merge_library()
|
|
17
|
-
console.info(` ✔ ${CONFIG_MERGE_OUTFILE} built`)
|
|
18
|
-
console.info(` ✔ ${CONFIG_MERGE_DTS_FILE} built`)
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.error(error_text.message_of(error))
|
|
21
|
-
process.exit(1)
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
|
|
26
|
-
|
|
27
|
-
export { build_config_merge_library, CONFIG_MERGE_OUTFILE, CONFIG_MERGE_DTS_FILE }
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { error_text } from '#scripts/lib/error-message'
|
|
4
|
-
import { build_library, library_paths } from './build-library'
|
|
5
|
-
|
|
6
|
-
const MANAGED_MARKER_LIBRARY = 'managed-marker'
|
|
7
|
-
const { outfile: MANAGED_MARKER_OUTFILE, dts_file: MANAGED_MARKER_DTS_FILE } =
|
|
8
|
-
library_paths(MANAGED_MARKER_LIBRARY)
|
|
9
|
-
|
|
10
|
-
async function build_managed_marker_library(): Promise<void> {
|
|
11
|
-
await build_library(MANAGED_MARKER_LIBRARY)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function main(): Promise<void> {
|
|
15
|
-
try {
|
|
16
|
-
await build_managed_marker_library()
|
|
17
|
-
console.info(` ✔ ${MANAGED_MARKER_OUTFILE} built`)
|
|
18
|
-
console.info(` ✔ ${MANAGED_MARKER_DTS_FILE} built`)
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.error(error_text.message_of(error))
|
|
21
|
-
process.exit(1)
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
|
|
26
|
-
|
|
27
|
-
export { build_managed_marker_library, MANAGED_MARKER_OUTFILE, MANAGED_MARKER_DTS_FILE }
|