@joshuafolkken/kit 1.1050.0 → 1.1094.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +9 -8
- package/.claude/skills/epic-commands/SKILL.md +5 -7
- package/.claude/skills/workflow-commands/SKILL.md +19 -11
- package/.claude/skills/workflow-commands/background-commands.md +4 -3
- package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +8 -6
- package/.claude/skills/workflow-commands/backlogrun-progress.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +4 -2
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +1 -1
- package/.claude/skills/workflow-commands/followup.md +7 -3
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/fullrun.md +3 -2
- package/.claude/skills/workflow-commands/halfrun.md +16 -19
- package/.claude/skills/workflow-commands/issue-comments.md +1 -1
- package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +9 -4
- package/.claude/skills/workflow-commands/latest-gate.md +1 -1
- package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +3 -3
- package/.claude/skills/workflow-commands/prerequisite.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +36 -0
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/ci.yml +26 -128
- package/.github/workflows/pr-classification.yml +5 -41
- package/.github/workflows/publish.yml +33 -38
- package/.github/workflows/sonar-qube.yml +37 -4
- package/AGENTS.md +12 -2
- package/CLAUDE.md +15 -16
- package/GEMINI.md +14 -2
- package/README.md +59 -18
- package/SECURITY.md +36 -6
- package/cspell/index.yaml +2 -1
- package/dist/CLAUDE.md +15 -16
- package/dist/config-merge/index.js +15 -3
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-HJIISEAC.js → chunk-3C4YCCEF.js} +5 -13
- package/dist/hooks/{chunk-EJDX2TOB.js → chunk-7ZPFAVR7.js} +7 -88
- package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-E54KGFEQ.js} +2 -2
- package/dist/hooks/{chunk-GQ7KP45M.js → chunk-IL27YTPH.js} +2 -2
- package/dist/hooks/{chunk-DMQN45FN.js → chunk-KHWHKJOM.js} +3 -3
- package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M2XDCUKD.js} +997 -478
- package/dist/hooks/{chunk-7VPDUBRN.js → chunk-NKOG3XAV.js} +150 -153
- package/dist/hooks/{chunk-NJQOBE6L.js → chunk-O4LL4HTI.js} +2 -7
- package/dist/hooks/{chunk-NAS4C7GP.js → chunk-OIZUHPJI.js} +2 -2
- package/dist/hooks/{chunk-RLDX5SOC.js → chunk-UD24EAIL.js} +2084 -1412
- package/dist/hooks/codex-hook-adapter.js +10 -11
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +279 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +9 -9
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +178 -324
- package/dist/josh.js +162 -119
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +34 -58
- package/eslint/rules/promise.js +5 -0
- package/package.json +9 -4
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/operating-rules.md +4 -4
- package/prompts/collaboration-workflow/overview.md +13 -1
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +3 -3
- package/prompts/collaboration-workflow/rule-delivery.md +1 -1
- package/prompts/collaboration-workflow/turn-batching.md +3 -3
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +25 -22
- package/prompts/collaboration-workflow.md +5 -8
- package/prompts/review-rubric.md +1 -1
- package/prompts/review.md +3 -3
- package/prompts/sonar-hotspot-handling.md +11 -3
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +0 -2
- package/scripts/adopt/adopt.ts +0 -2
- package/scripts/agent/agent-argv.ts +0 -2
- package/scripts/agent/agent-diagnostics.ts +1 -1
- package/scripts/agent/agent-role-profile.ts +0 -7
- package/scripts/agent/claude-agent-argv.ts +0 -2
- package/scripts/agent/codex-agent-argv.ts +1 -1
- package/scripts/agent/codex-hooks.ts +92 -0
- package/scripts/agent/interactive-ask.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +6 -16
- package/scripts/backlog/backlog-budget.ts +0 -2
- package/scripts/backlog/backlog-defect-priority.ts +2 -2
- package/scripts/backlog/backlog-drive-cli.ts +10 -8
- package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
- package/scripts/backlog/backlog-drive-named.ts +2 -1
- package/scripts/backlog/backlog-drive.ts +76 -16
- package/scripts/backlog/backlog-named.ts +0 -3
- package/scripts/backlog/backlog-next.ts +9 -15
- package/scripts/backlog/backlog-offer-cli.ts +0 -5
- package/scripts/backlog/backlog-plan-cli.ts +1 -7
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +3 -6
- package/scripts/backlog/backlog-rank.ts +2 -2
- package/scripts/backlog/backlog-ready.ts +19 -3
- package/scripts/backlog/backlog-scope.ts +1 -3
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +0 -1
- package/scripts/backlog/backlog-waves.ts +5 -2
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +85 -9
- package/scripts/build/hook-bundle-stamp.ts +111 -0
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +1 -1
- package/scripts/ci/composite-actions.ts +30 -0
- package/scripts/ci/pr-classification.ts +3 -3
- package/scripts/claude/workflow-destination.ts +10 -1
- package/scripts/clone/clone-fingerprint.ts +0 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/json-format.ts +0 -1
- package/scripts/config-merge/patch-yaml-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +2 -9
- package/scripts/cost-runtime/cost-attribute.ts +0 -1
- package/scripts/cost-runtime/cost-cli.ts +0 -3
- package/scripts/cost-runtime/cost-corpus.ts +0 -2
- package/scripts/cost-runtime/cost-format.ts +0 -3
- package/scripts/cost-runtime/cost-pricing.ts +0 -1
- package/scripts/cost-runtime/cost-tokens.ts +0 -1
- package/scripts/delegation/delegation-cli.ts +1 -1
- package/scripts/delegation/delegation-policy.ts +0 -1
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +0 -2
- package/scripts/delegation/investigation-reads.ts +1 -164
- package/scripts/discovery/repo-map-logic.ts +0 -1
- package/scripts/discovery/repo-party-cli.ts +1 -1
- package/scripts/doctor/doctor-consumer.ts +4 -6
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/document-byte-budget.ts +4 -5
- package/scripts/document/document-byte-check.ts +0 -1
- package/scripts/document/document-read-cli.ts +0 -2
- package/scripts/document/document-section-cli.ts +1 -1
- package/scripts/document/document-section.ts +0 -3
- package/scripts/document/edit-files-cli.ts +0 -1
- package/scripts/document/entry-read-budget.ts +10 -2
- package/scripts/document/lane-child-read-set.ts +1 -6
- package/scripts/document/read-files-cli.ts +0 -4
- package/scripts/document/read-set-cli.ts +0 -2
- package/scripts/document/read-set-point-of-use.ts +1 -0
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +1 -1
- package/scripts/epic/epic-add.ts +1 -1
- package/scripts/epic/epic-audit-cli.ts +1 -4
- package/scripts/epic/epic-audit-orphans.ts +1 -3
- package/scripts/epic/epic-audit-rationale.ts +0 -1
- package/scripts/epic/epic-audit-report.ts +0 -2
- package/scripts/epic/epic-audit.ts +5 -4
- package/scripts/epic/epic-bundle-cli.ts +1 -1
- package/scripts/epic/epic-bundle-evidence.ts +0 -1
- package/scripts/epic/epic-bundle-referenced.ts +1 -5
- package/scripts/epic/epic-bundle.ts +0 -4
- package/scripts/epic/epic-busy.ts +4 -5
- package/scripts/epic/epic-candidate-confirm.ts +0 -5
- package/scripts/epic/epic-classify.ts +2 -2
- package/scripts/epic/epic-cli-argv.ts +0 -1
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +5 -2
- package/scripts/epic/epic-cross-repo.ts +2 -4
- package/scripts/epic/epic-decision.ts +0 -1
- package/scripts/epic/epic-fetch.ts +2 -2
- package/scripts/epic/epic-index.ts +2 -3
- package/scripts/epic/epic-issue.ts +1 -15
- package/scripts/epic/epic-lane-offer.ts +9 -8
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +1 -3
- package/scripts/epic/epic-next-views.ts +0 -1
- package/scripts/epic/epic-next.ts +1 -10
- package/scripts/epic/epic-parse.ts +0 -1
- package/scripts/epic/epic-promote.ts +0 -9
- package/scripts/epic/epic-rank.ts +2 -2
- package/scripts/epic/epic-read.ts +1 -2
- package/scripts/epic/epic-reconcile.ts +1 -1
- package/scripts/epic/epic-reference.ts +1 -13
- package/scripts/epic/epic-relation-recheck.ts +1 -1
- package/scripts/epic/epic-relations.ts +1 -1
- package/scripts/epic/epic-remove.ts +1 -1
- package/scripts/epic/epic-report.ts +0 -1
- package/scripts/epic/epic-run.ts +2 -3
- package/scripts/epic/epic-shape.ts +1 -1
- package/scripts/epic/epic-solo-stale.ts +107 -0
- package/scripts/epic/epic-solo.ts +3 -2
- package/scripts/epic/epic-triage.ts +1 -1
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/epic/epic.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +53 -0
- package/scripts/{git → followup}/followup-issue-number.ts +1 -6
- package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
- package/scripts/{git → followup}/git-followup-finish.ts +1 -3
- package/scripts/{git → followup}/git-followup-flush.ts +2 -2
- package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
- package/scripts/{git → followup}/git-followup-label.ts +4 -4
- package/scripts/followup/git-followup-merged.ts +112 -0
- package/scripts/{git → followup}/git-followup-pending.ts +1 -1
- package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
- package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
- package/scripts/{git → followup}/git-pr-followup.ts +53 -16
- package/scripts/gate/core-budget.ts +3 -9
- package/scripts/gate/gate-plan.ts +7 -4
- package/scripts/gate/gate-report.ts +0 -6
- package/scripts/gate/gate-tree.ts +1 -1
- package/scripts/gate/pre-commit-type-check.ts +0 -6
- package/scripts/gate/project-checks.ts +7 -8
- package/scripts/gate/scoped-green.ts +0 -1
- package/scripts/gate/type-check-step.ts +1 -1
- package/scripts/gate/verification-gate.ts +0 -2
- package/scripts/gh/fix-gh-packages.ts +15 -12
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
- package/scripts/{git → gh}/git-gh-check.ts +2 -1
- package/scripts/{git → gh}/git-gh-exec.ts +1 -1
- package/scripts/{git → gh}/git-gh-failure.ts +1 -1
- package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
- package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
- package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
- package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
- package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
- package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
- package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
- package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
- package/scripts/{git → gh}/git-gh-pr.ts +3 -1
- package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
- package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
- package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
- package/scripts/{git → gh}/git-pr-checks.ts +2 -1
- package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
- package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
- package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
- package/scripts/{git → gh}/git-pr.ts +3 -3
- package/scripts/git/changed-file-scope.ts +0 -1
- package/scripts/git/git-branch.ts +3 -6
- package/scripts/git/git-commit.ts +1 -1
- package/scripts/git/git-common-directory.ts +80 -24
- package/scripts/git/git-error.ts +66 -9
- package/scripts/git/git-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +2 -2
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-staging.ts +1 -0
- package/scripts/git/git-status.ts +1 -1
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/gone-branch.ts +1 -0
- package/scripts/git/listing-cutoff.ts +1 -1
- package/scripts/git/main-merge.ts +1 -1
- package/scripts/git/main-sync.ts +19 -1
- package/scripts/git/parse-json-array.ts +0 -3
- package/scripts/git/repository-lock.ts +16 -16
- package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
- package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
- package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
- package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
- package/scripts/hooks/codex-hook-adapter.ts +0 -1
- package/scripts/hooks/edited-cspell.ts +1 -1
- package/scripts/hooks/format-edited-file.ts +2 -0
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard.ts +22 -4
- package/scripts/hooks/reserved-run.ts +1 -1
- package/scripts/hooks/step-zero-notice.ts +76 -0
- package/scripts/hooks/stop-guard.ts +47 -21
- package/scripts/init/claude-plugin-config.ts +4 -5
- package/scripts/init/hook-command-rewrite.ts +16 -8
- package/scripts/init/hook-launch.ts +41 -15
- package/scripts/init/init-basic.ts +2 -5
- package/scripts/init/init-logic.ts +7 -0
- package/scripts/init/init.ts +0 -3
- package/scripts/init/project-profile.ts +6 -11
- package/scripts/init/start-exec.ts +1 -1
- package/scripts/init/start-setup-pr.ts +6 -6
- package/scripts/init/start-steps.ts +1 -0
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +3 -3
- package/scripts/issue/defect-rate.ts +1 -2
- package/scripts/{git → issue}/git-next-issues.ts +3 -3
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +0 -2
- package/scripts/issue/issue-classification.ts +1 -9
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +2 -2
- package/scripts/issue/issue-file-cli.ts +5 -5
- package/scripts/issue/issue-file.ts +2 -2
- package/scripts/issue/issue-fold-cli.ts +1 -1
- package/scripts/issue/issue-fold-existing-cli.ts +1 -1
- package/scripts/{git → issue}/issue-labels.ts +8 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/{git → issue}/issue-rank.ts +1 -1
- package/scripts/issue/issue-read-cli.ts +8 -47
- package/scripts/issue/issue-read.ts +0 -2
- package/scripts/issue/issue-report-failures.ts +80 -0
- package/scripts/issue/issue-scout-cli.ts +1 -7
- package/scripts/issue/issue-scout-closed.ts +2 -2
- package/scripts/issue/issue-scout.ts +0 -2
- package/scripts/issue/issue-state-cli.ts +5 -46
- package/scripts/issue/issue-state.ts +1 -5
- package/scripts/issue/markdown-section.ts +1 -1
- package/scripts/issue/measure-rerun-cli.ts +1 -1
- package/scripts/issue/reproduction-measure.ts +1 -1
- package/scripts/josh/cli-body.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +0 -3
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-commands-ai.ts +9 -102
- package/scripts/josh/josh-commands-backlog.ts +5 -1
- package/scripts/josh/josh-commands-development.ts +8 -1
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/josh/josh-commands-maintenance.ts +7 -0
- package/scripts/josh/josh-commands-project.ts +6 -0
- package/scripts/josh/josh-commands-run.ts +114 -0
- package/scripts/josh/josh-commands-versioning.ts +8 -0
- package/scripts/josh/josh-commands-workflow.ts +2 -2
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +3 -6
- package/scripts/lane/lane-capacity.ts +6 -3
- package/scripts/lane/lane-child-invocation.ts +20 -7
- package/scripts/lane/lane-cli.ts +1 -4
- package/scripts/lane/lane-close.ts +1 -3
- package/scripts/lane/lane-dispatch.ts +3 -4
- package/scripts/lane/lane-environment.ts +0 -9
- package/scripts/lane/lane-handoff.ts +38 -0
- package/scripts/lane/lane-launch-cli.ts +21 -11
- package/scripts/lane/lane-open.ts +0 -3
- package/scripts/lane/lane-output.ts +0 -1
- package/scripts/lane/lane-registry.ts +9 -0
- package/scripts/lane/openai-lane-ship.ts +2 -0
- package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
- package/scripts/lane/openai-lane-supervisor.ts +6 -4
- package/scripts/lane/openai-review-broker.ts +3 -0
- package/scripts/lib/bounded-pool.ts +1 -0
- package/scripts/lib/json-value.ts +5 -4
- package/scripts/lib/poll.ts +3 -1
- package/scripts/lib/timed-fetch.ts +15 -0
- package/scripts/lib/timeouts.ts +13 -0
- package/scripts/{yaml → lib}/yaml-document.ts +3 -1
- package/scripts/{bytes → lines}/bytes-command.ts +0 -2
- package/scripts/lines/lines-command.ts +0 -1
- package/scripts/lint/lint-related-scope.ts +0 -1
- package/scripts/lint/lint-related.ts +1 -1
- package/scripts/{git → notify}/telegram-notify.ts +2 -2
- package/scripts/{git → notify}/telegram-test.ts +4 -4
- package/scripts/observations/observation-ledger-home.ts +0 -1
- package/scripts/observations/observation-ledger-line.ts +0 -1
- package/scripts/observations/observation-ledger-migrate.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +3 -3
- package/scripts/observations/observations-flush.ts +2 -2
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/package/package-scout-cli.ts +2 -7
- package/scripts/package/package-scout.ts +0 -2
- package/scripts/propagate/propagate-git-failure.ts +0 -1
- package/scripts/propagate/propagate-git.ts +0 -2
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +0 -2
- package/scripts/propagate/propagate-steps.ts +3 -5
- package/scripts/propagate/propagate-targets.ts +0 -4
- package/scripts/propagate/propagate.ts +0 -4
- package/scripts/refactor/import-graph.ts +0 -1
- package/scripts/refactor/refactor-lint.ts +0 -2
- package/scripts/refactor/refactor-scan.ts +0 -1
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +0 -2
- package/scripts/registry-migration/migrate.ts +19 -9
- package/scripts/release/github-release-cli.ts +8 -6
- package/scripts/release/github-release-environment.ts +46 -0
- package/scripts/release/github-release.ts +151 -94
- package/scripts/release/release-history.ts +0 -1
- package/scripts/release/release-plan.ts +0 -1
- package/scripts/release/release-publish.ts +2 -3
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- package/scripts/repo/auto-merge-setting-logic.ts +1 -4
- package/scripts/repo/repo-setting.ts +1 -1
- package/scripts/repo/repository-labels.ts +3 -3
- package/scripts/repo/required-checks-logic.ts +206 -0
- package/scripts/repo/required-checks-report.ts +71 -0
- package/scripts/repo/ruleset-check-cli.ts +53 -0
- package/scripts/repo/ruleset-check.ts +147 -0
- package/scripts/report/report-lint-cli.ts +0 -4
- package/scripts/review/disposition-cli.ts +1 -1
- package/scripts/review/live-evidence.ts +1 -1
- package/scripts/review/review-attest-cli.ts +0 -6
- package/scripts/review/review-attest.ts +4 -16
- package/scripts/review/review-brief-cli.ts +23 -6
- package/scripts/review/review-brief.ts +21 -8
- package/scripts/review/review-diff-parts.ts +89 -0
- package/scripts/review/review-diff-write.ts +97 -0
- package/scripts/review/review-finding-ledger.ts +0 -1
- package/scripts/review/review-record-cli.ts +1 -1
- package/scripts/review/review-record.ts +0 -1
- package/scripts/review/review-round2-cli.ts +1 -1
- package/scripts/review/review-stamps.ts +0 -3
- package/scripts/review/review-tree.ts +14 -2
- package/scripts/rules/decision-oracle-stage.ts +18 -0
- package/scripts/rules/decision-oracle.ts +10 -7
- package/scripts/rules/delivered-rules.ts +9 -1
- package/scripts/rules/destructive-command.ts +119 -0
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/file-body.ts +0 -3
- package/scripts/rules/filing-cap.ts +0 -2
- package/scripts/rules/gh-api.ts +7 -2
- package/scripts/rules/git-argv.ts +18 -7
- package/scripts/rules/git-force.ts +0 -2
- package/scripts/rules/implementation-cut.ts +0 -1
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-park.ts +13 -6
- package/scripts/rules/last-prompt.ts +1 -0
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +0 -3
- package/scripts/rules/permission-guards.ts +14 -0
- package/scripts/rules/protected-files.ts +74 -0
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +0 -3
- package/scripts/rules/rule-value-cli.ts +0 -1
- package/scripts/rules/shell-body-trigger.ts +0 -1
- package/scripts/rules/shell-segments.ts +0 -1
- package/scripts/rules/stop-rules.ts +13 -5
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +0 -1
- package/scripts/rules/worktree-guard.ts +26 -9
- package/scripts/run/run-carry-cli.ts +0 -2
- package/scripts/run/run-carry-stash.ts +2 -2
- package/scripts/run/run-carry-streak.ts +1 -1
- package/scripts/run/run-cut-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +1 -1
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +101 -24
- package/scripts/run/run-entry.ts +0 -1
- package/scripts/run/run-event-cli.ts +0 -2
- package/scripts/run/run-event-follow.ts +1 -0
- package/scripts/run/run-event-render.ts +1 -1
- package/scripts/run/run-event-scope.ts +53 -4
- package/scripts/run/run-event-stream.ts +0 -3
- package/scripts/run/run-event-watch.ts +1 -0
- package/scripts/run/run-halfrun-resume.ts +20 -7
- package/scripts/run/run-headless.ts +2 -2
- package/scripts/run/run-hold-cli.ts +33 -10
- package/scripts/run/run-hold.ts +25 -5
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +1 -1
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +5 -13
- package/scripts/run/run-merge-steps.ts +5 -5
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-next-cli.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +0 -1
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +2 -2
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-cli.ts +4 -7
- package/scripts/run/run-progress-clock.ts +6 -34
- package/scripts/run/run-progress-config.ts +0 -4
- package/scripts/run/run-progress-read.ts +1 -2
- package/scripts/run/run-progress.ts +1 -2
- package/scripts/run/run-prrun-resume.ts +117 -0
- package/scripts/run/run-report-cli.ts +1 -2
- package/scripts/run/run-report.ts +0 -1
- package/scripts/run/run-retrospective.ts +1 -1
- package/scripts/run/run-review-cli.ts +0 -3
- package/scripts/run/run-review-steps.ts +2 -0
- package/scripts/run/run-review.ts +0 -2
- package/scripts/run/run-ship-cli.ts +21 -3
- package/scripts/run/run-ship-detach.ts +1 -0
- package/scripts/run/run-ship-next.ts +106 -0
- package/scripts/run/run-ship-preflight.ts +1 -1
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +18 -4
- package/scripts/run/run-ship-review.ts +11 -0
- package/scripts/run/run-ship-scoped.ts +1 -0
- package/scripts/run/run-ship-steps.ts +1 -1
- package/scripts/run/run-ship.ts +0 -1
- package/scripts/run/run-stage-read.ts +62 -0
- package/scripts/run/run-stage.ts +160 -0
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +21 -14
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stop-notify.ts +1 -3
- package/scripts/run/run-stranded-cli.ts +0 -4
- package/scripts/run/run-stranded-detect.ts +2 -2
- package/scripts/run/run-tail-cli.ts +17 -11
- package/scripts/run/run-tail.ts +2 -0
- package/scripts/run/run-tidy-lanes.ts +2 -1
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +2 -3
- package/scripts/run/run-wake-loop.ts +2 -2
- package/scripts/run/run-wake.ts +2 -4
- package/scripts/run/run-watcher-guard-cli.ts +0 -4
- package/scripts/run/run-watcher-guard.ts +9 -7
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- package/scripts/safe-chain/project-config.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +0 -1
- package/scripts/security/security-audit-provision.ts +3 -2
- package/scripts/security/security-audit.ts +0 -1
- package/scripts/security/security-updates-logic.ts +0 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
- package/scripts/sonar/sonar-hotspots.ts +0 -1
- package/scripts/sonar/sonar-new-code-cli.ts +150 -0
- package/scripts/sonar/sonar-new-code.ts +79 -0
- package/scripts/sonar/sonar-project.ts +97 -0
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +2 -5
- package/scripts/sync/managed-config-scope-cli.ts +1 -1
- package/scripts/sync/skill-migration.ts +0 -1
- package/scripts/sync/sync-hook-safety.ts +2 -3
- package/scripts/sync/sync.ts +1 -8
- package/scripts/sync/template-source-logic.ts +0 -1
- package/scripts/sync/workflow-pin-logic.ts +16 -28
- package/scripts/test/test-declared-logic.ts +0 -1
- package/scripts/test/test-declared.ts +0 -2
- package/scripts/test/test-red-commit.ts +2 -2
- package/scripts/test/test-red.ts +14 -7
- package/scripts/test/test-type-logic.ts +1 -1
- package/scripts/test/unit-worker-share.ts +7 -16
- package/scripts/time-runtime/time-batch-guard.ts +1 -2
- package/scripts/time-runtime/time-bundle-call.ts +0 -1
- package/scripts/time-runtime/time-bundles.ts +0 -4
- package/scripts/time-runtime/time-density-hook.ts +0 -2
- package/scripts/time-runtime/time-followup-stage.ts +1 -1
- package/scripts/time-runtime/time-format.ts +0 -73
- package/scripts/time-runtime/time-round-trips.ts +0 -4
- package/scripts/time-runtime/time-single-check.ts +1 -1
- package/scripts/time-runtime/time-spans.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +1 -2
- package/scripts/ui/ui-routes-cli.ts +0 -5
- package/scripts/ui/ui-routes.ts +0 -5
- package/scripts/version/effective-upstream.ts +2 -2
- package/scripts/version/latest-corepack.ts +7 -9
- package/scripts/version/latest-scope-cli.ts +0 -2
- package/scripts/version/latest-update.ts +0 -2
- package/scripts/version/npm-registry.ts +2 -2
- package/scripts/version/publishable-range-check.ts +1 -1
- package/scripts/version/release-hold.ts +0 -4
- package/scripts/version/running-binary.ts +2 -2
- package/scripts/version/version-check-logic.ts +0 -2
- package/scripts/version/version-remote.ts +3 -3
- package/scripts/version/version-targets.ts +4 -4
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/dependabot-auto-merge.yml +5 -3
- package/templates/workflows/github-release.yml +81 -0
- package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
- package/prompts/collaboration-workflow/epic-audit.md +0 -5
- package/prompts/collaboration-workflow/epic-bundle.md +0 -5
- package/scripts/init/plugin-install-hint.ts +0 -47
- package/scripts/version/parse-json.ts +0 -13
- /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
- /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
- /package/scripts/{git → gh}/git-gh-command.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
- /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
- /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
- /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
- /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
- /package/scripts/{git → gh}/git-pr-error.ts +0 -0
- /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
- /package/scripts/{git → gh}/github-issue-url.ts +0 -0
- /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
- /package/scripts/{git → issue}/issue-reference.ts +0 -0
- /package/scripts/{git → lib}/animation-helpers.ts +0 -0
- /package/scripts/{git → lib}/git-animation.ts +0 -0
- /package/scripts/{git → notify}/git-notify.ts +0 -0
- /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
|
@@ -159,11 +159,7 @@ function resolve_targets(
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
const propagate_targets = {
|
|
162
|
-
has_checkout,
|
|
163
162
|
read_manifest,
|
|
164
|
-
classify_manifest_absence,
|
|
165
|
-
classify_before_dependency,
|
|
166
|
-
declared_range,
|
|
167
163
|
installed_version,
|
|
168
164
|
classify_target,
|
|
169
165
|
resolve_targets,
|
|
@@ -279,16 +279,12 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
const propagate = {
|
|
282
|
-
DRY_RUN_REASON,
|
|
283
282
|
KNOWN_FLAGS,
|
|
284
283
|
TARGET_FLAG,
|
|
285
284
|
parse_options,
|
|
286
285
|
refuse_outside_source_repository,
|
|
287
286
|
resolve_target_version,
|
|
288
287
|
resolve_run_version,
|
|
289
|
-
announce_run_version,
|
|
290
|
-
run,
|
|
291
|
-
main,
|
|
292
288
|
}
|
|
293
289
|
|
|
294
290
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
@@ -2,6 +2,8 @@ import { existsSync, rmSync, writeFileSync } from 'node:fs'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { fileURLToPath } from 'node:url'
|
|
4
4
|
import { file_reader } from '#scripts/lib/read-file'
|
|
5
|
+
import { timed_fetch } from '#scripts/lib/timed-fetch'
|
|
6
|
+
import { COMMAND_TIMEOUT_MS, INSTALL_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
5
7
|
import { execa } from 'execa'
|
|
6
8
|
import { z } from 'zod'
|
|
7
9
|
import { migrate_logic, type MigrationPlan } from './migrate-logic'
|
|
@@ -11,7 +13,6 @@ const NPMRC = '.npmrc'
|
|
|
11
13
|
const LOCKFILE = 'pnpm-lock.yaml'
|
|
12
14
|
const WORKSPACE = 'pnpm-workspace.yaml'
|
|
13
15
|
const PUBLIC_REGISTRY = 'https://registry.npmjs.org/'
|
|
14
|
-
const FETCH_TIMEOUT_MS = 10_000
|
|
15
16
|
const SCOPE = '@joshuafolkken/'
|
|
16
17
|
const manifest_schema = z.looseObject({
|
|
17
18
|
dependencies: z.record(z.string(), z.string()).optional(),
|
|
@@ -104,11 +105,16 @@ async function verify_public_versions(
|
|
|
104
105
|
lockfile: string,
|
|
105
106
|
probe_version: MigrationDependencies['fetch_version'],
|
|
106
107
|
): Promise<VersionCheck> {
|
|
108
|
+
const versions = migrate_logic.scoped_versions(lockfile)
|
|
109
|
+
// Each probe reads its own package, so they run together; the report keeps the lockfile's order.
|
|
110
|
+
const probed = await Promise.all(
|
|
111
|
+
versions.map(async ([name, version]) => await probe_integrity(name, version, probe_version)),
|
|
112
|
+
)
|
|
107
113
|
const missing: Array<string> = []
|
|
108
114
|
const integrities = new Map<string, string>()
|
|
109
115
|
|
|
110
|
-
for (const [name, version] of
|
|
111
|
-
const integrity =
|
|
116
|
+
for (const [index, [name, version]] of versions.entries()) {
|
|
117
|
+
const integrity = probed[index]
|
|
112
118
|
if (integrity === undefined) missing.push(`${name}@${version}`)
|
|
113
119
|
else integrities.set(version, integrity)
|
|
114
120
|
}
|
|
@@ -238,9 +244,7 @@ async function migrate(cwd: string, dependencies: MigrationDependencies): Promis
|
|
|
238
244
|
|
|
239
245
|
async function fetch_version(name: string, version: string): Promise<string | undefined> {
|
|
240
246
|
const encoded = encodeURIComponent(name)
|
|
241
|
-
const response = await
|
|
242
|
-
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
243
|
-
})
|
|
247
|
+
const response = await timed_fetch(`${PUBLIC_REGISTRY}${encoded}/${encodeURIComponent(version)}`)
|
|
244
248
|
|
|
245
249
|
if (!response.ok) return undefined
|
|
246
250
|
const parsed = version_schema.safeParse(await response.json())
|
|
@@ -250,11 +254,17 @@ async function fetch_version(name: string, version: string): Promise<string | un
|
|
|
250
254
|
}
|
|
251
255
|
|
|
252
256
|
async function install(cwd: string): Promise<void> {
|
|
253
|
-
await execa('pnpm', ['install', '--lockfile-only', '--ignore-scripts', '--force'], {
|
|
257
|
+
await execa('pnpm', ['install', '--lockfile-only', '--ignore-scripts', '--force'], {
|
|
258
|
+
cwd,
|
|
259
|
+
timeout: INSTALL_TIMEOUT_MS,
|
|
260
|
+
})
|
|
254
261
|
}
|
|
255
262
|
|
|
256
263
|
async function effective_registry(cwd: string): Promise<string> {
|
|
257
|
-
const result = await execa('pnpm', ['config', 'get', '@joshuafolkken:registry'], {
|
|
264
|
+
const result = await execa('pnpm', ['config', 'get', '@joshuafolkken:registry'], {
|
|
265
|
+
cwd,
|
|
266
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
267
|
+
})
|
|
258
268
|
|
|
259
269
|
return result.stdout.trim()
|
|
260
270
|
}
|
|
@@ -275,7 +285,7 @@ async function main(): Promise<void> {
|
|
|
275
285
|
|
|
276
286
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
|
|
277
287
|
|
|
278
|
-
const registry_migration = { migrate }
|
|
288
|
+
const registry_migration = { migrate, install, effective_registry }
|
|
279
289
|
|
|
280
290
|
export { registry_migration }
|
|
281
291
|
export type { MigrationDependencies }
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
2
3
|
import { github_release } from './github-release'
|
|
4
|
+
import { github_release_environment } from './github-release-environment'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
const tag = process.env
|
|
6
|
+
async function main(): Promise<void> {
|
|
7
|
+
const { token, tag, settings } = github_release_environment.read_release_input(process.env)
|
|
8
|
+
const tags = execFileSync('git', ['tag', '--list'], { encoding: 'utf8' }).trim().split('\n')
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
console.info(await github_release.publish(fetch, token, tag, { ...settings, tags }))
|
|
11
|
+
}
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console.info(await github_release.publish(fetch, token, tag, { tags }))
|
|
13
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ReleaseSettings } from './github-release'
|
|
2
|
+
|
|
3
|
+
interface ReleaseInput {
|
|
4
|
+
token: string
|
|
5
|
+
tag: string
|
|
6
|
+
settings: ReleaseSettings
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type Environment = Readonly<Record<string, string | undefined>>
|
|
10
|
+
|
|
11
|
+
// A workflow expression renders an unset input as the empty string, so empty means "not given".
|
|
12
|
+
function optional(value: string | undefined): string | undefined {
|
|
13
|
+
return value === undefined || value === '' ? undefined : value
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function job_names(value: string | undefined): ReadonlyArray<string> {
|
|
17
|
+
return (optional(value) ?? '')
|
|
18
|
+
.split(',')
|
|
19
|
+
.map((name) => name.trim())
|
|
20
|
+
.filter((name) => name !== '')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function read_release_input(environment: Environment): ReleaseInput {
|
|
24
|
+
const token = optional(environment['GH_TOKEN'])
|
|
25
|
+
const tag = optional(environment['RELEASE_TAG'])
|
|
26
|
+
const repository = optional(environment['GITHUB_REPOSITORY'])
|
|
27
|
+
|
|
28
|
+
if (!token || !tag || !repository) {
|
|
29
|
+
throw new Error('GH_TOKEN, RELEASE_TAG and GITHUB_REPOSITORY are required')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
token,
|
|
34
|
+
tag,
|
|
35
|
+
settings: {
|
|
36
|
+
repository,
|
|
37
|
+
start_tag: optional(environment['RELEASE_START_TAG']),
|
|
38
|
+
workflow: optional(environment['RELEASE_WORKFLOW']),
|
|
39
|
+
jobs: job_names(environment['RELEASE_JOBS']),
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const github_release_environment = { read_release_input }
|
|
45
|
+
|
|
46
|
+
export { github_release_environment }
|
|
@@ -2,15 +2,15 @@ import { setTimeout } from 'node:timers/promises'
|
|
|
2
2
|
import semver from 'semver'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const WORKFLOW_JOBS_URL = 'https://api.github.com/repos/joshuafolkken/kit/actions/runs'
|
|
5
|
+
const API_ROOT = 'https://api.github.com/repos'
|
|
6
|
+
const LATEST_PATH = '/releases/latest'
|
|
7
|
+
const REPOSITORY_PATTERN = /^[\w.-]+\/[\w.-]+$/u
|
|
9
8
|
const TAG_PATTERN = /^v\d+\.\d+\.\d+(?:[.-][0-9A-Za-z.-]+)?$/u
|
|
10
9
|
const REQUEST_TIMEOUT_MS = 30_000
|
|
11
10
|
const NOT_FOUND_STATUS = 404
|
|
12
|
-
//
|
|
13
|
-
|
|
11
|
+
// A job skipped by its `if:` (or neutral) belongs to a run that succeeded; counting it would skip a
|
|
12
|
+
// lower tag whose release is still on its way.
|
|
13
|
+
const FAILED_CONCLUSIONS = new Set(['failure', 'cancelled', 'timed_out', 'startup_failure'])
|
|
14
14
|
const POLL_INTERVAL_MS = 30_000
|
|
15
15
|
const MAX_WAIT_ATTEMPTS = 120
|
|
16
16
|
const RELEASE_SCHEMA = z.object({ tag_name: z.string().min(1) })
|
|
@@ -23,16 +23,42 @@ const JOB_SCHEMA = z.object({
|
|
|
23
23
|
})
|
|
24
24
|
const RUNS_SCHEMA = z.object({ workflow_runs: z.array(RUN_SCHEMA) })
|
|
25
25
|
const JOBS_SCHEMA = z.object({ jobs: z.array(JOB_SCHEMA) })
|
|
26
|
-
const PREREQUISITES = ['publish-github', 'publish-npm', 'update-production']
|
|
27
26
|
|
|
28
27
|
type ReleaseRequest = (url: string, init: RequestInit) => Promise<Response>
|
|
29
28
|
type Wait = () => Promise<void>
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
// What differs between repositories. `start_tag` is the last tag that predates automatic releases;
|
|
31
|
+
// without it the latest existing release is the floor. `workflow` names the publish workflow whose
|
|
32
|
+
// failed run lets a lower tag be skipped, and `jobs` the jobs in it that count (empty: every job).
|
|
33
|
+
interface ReleaseSettings {
|
|
34
|
+
repository: string
|
|
35
|
+
start_tag?: string | undefined
|
|
36
|
+
workflow?: string | undefined
|
|
37
|
+
jobs?: ReadonlyArray<string> | undefined
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface PublishOptions extends ReleaseSettings {
|
|
32
41
|
tags?: ReadonlyArray<string>
|
|
33
42
|
wait?: Wait
|
|
34
43
|
}
|
|
35
44
|
|
|
45
|
+
interface Client {
|
|
46
|
+
request: ReleaseRequest
|
|
47
|
+
token: string
|
|
48
|
+
url: string
|
|
49
|
+
workflow: string | undefined
|
|
50
|
+
jobs: ReadonlyArray<string>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// `fallback` answers when no tag sits between the floor and the target; without one the floor itself
|
|
54
|
+
// is the latest release and the answer.
|
|
55
|
+
interface Ladder {
|
|
56
|
+
tags: ReadonlyArray<string>
|
|
57
|
+
floor: string | undefined
|
|
58
|
+
fallback?: () => Promise<string>
|
|
59
|
+
wait: Wait
|
|
60
|
+
}
|
|
61
|
+
|
|
36
62
|
function request_options(token: string, method: string, body?: object): RequestInit {
|
|
37
63
|
return {
|
|
38
64
|
method,
|
|
@@ -46,21 +72,22 @@ function request_options(token: string, method: string, body?: object): RequestI
|
|
|
46
72
|
}
|
|
47
73
|
}
|
|
48
74
|
|
|
75
|
+
async function api_get(client: Client, path: string): Promise<Response> {
|
|
76
|
+
return await client.request(`${client.url}${path}`, request_options(client.token, 'GET'))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function api_post(client: Client, path: string, body: object): Promise<Response> {
|
|
80
|
+
return await client.request(`${client.url}${path}`, request_options(client.token, 'POST', body))
|
|
81
|
+
}
|
|
82
|
+
|
|
49
83
|
async function read_response(response: Response): Promise<unknown> {
|
|
50
84
|
if (!response.ok) throw new Error(`GitHub Releases API returned HTTP ${String(response.status)}`)
|
|
51
85
|
|
|
52
86
|
return await response.json()
|
|
53
87
|
}
|
|
54
88
|
|
|
55
|
-
async function existing_release(
|
|
56
|
-
|
|
57
|
-
token: string,
|
|
58
|
-
tag: string,
|
|
59
|
-
): Promise<boolean> {
|
|
60
|
-
const response = await request(
|
|
61
|
-
`${API_URL}/tags/${encodeURIComponent(tag)}`,
|
|
62
|
-
request_options(token, 'GET'),
|
|
63
|
-
)
|
|
89
|
+
async function existing_release(client: Client, tag: string): Promise<boolean> {
|
|
90
|
+
const response = await api_get(client, `/releases/tags/${encodeURIComponent(tag)}`)
|
|
64
91
|
if (response.status === NOT_FOUND_STATUS) return false
|
|
65
92
|
|
|
66
93
|
RELEASE_SCHEMA.parse(await read_response(response))
|
|
@@ -68,153 +95,183 @@ async function existing_release(
|
|
|
68
95
|
return true
|
|
69
96
|
}
|
|
70
97
|
|
|
71
|
-
async function previous_tag(
|
|
72
|
-
const response = await
|
|
73
|
-
const release = RELEASE_SCHEMA.parse(await read_response(response))
|
|
98
|
+
async function previous_tag(client: Client): Promise<string> {
|
|
99
|
+
const response = await api_get(client, LATEST_PATH)
|
|
74
100
|
|
|
75
|
-
return
|
|
101
|
+
return RELEASE_SCHEMA.parse(await read_response(response)).tag_name
|
|
76
102
|
}
|
|
77
103
|
|
|
78
|
-
function
|
|
104
|
+
async function latest_release(client: Client): Promise<string | undefined> {
|
|
105
|
+
const response = await api_get(client, LATEST_PATH)
|
|
106
|
+
if (response.status === NOT_FOUND_STATUS) return undefined
|
|
107
|
+
|
|
108
|
+
return RELEASE_SCHEMA.parse(await read_response(response)).tag_name
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function predecessor(
|
|
112
|
+
tags: ReadonlyArray<string>,
|
|
113
|
+
target: string,
|
|
114
|
+
floor: string | undefined,
|
|
115
|
+
): string | undefined {
|
|
79
116
|
return tags
|
|
80
117
|
.filter(
|
|
81
|
-
(tag) =>
|
|
118
|
+
(tag) =>
|
|
119
|
+
semver.valid(tag) &&
|
|
120
|
+
(floor === undefined || semver.gt(tag, floor)) &&
|
|
121
|
+
semver.lt(tag, target),
|
|
82
122
|
)
|
|
83
123
|
.toSorted((left, right) => semver.compare(right, left))[0]
|
|
84
124
|
}
|
|
85
125
|
|
|
86
|
-
function is_failed_job(job: z.infer<typeof JOB_SCHEMA>): boolean {
|
|
87
|
-
if (job.status !== 'completed' || job.conclusion
|
|
126
|
+
function is_failed_job(job: z.infer<typeof JOB_SCHEMA>, names: ReadonlyArray<string>): boolean {
|
|
127
|
+
if (job.status !== 'completed' || !FAILED_CONCLUSIONS.has(job.conclusion ?? '')) return false
|
|
128
|
+
if (names.length === 0) return true
|
|
88
129
|
|
|
89
|
-
return
|
|
130
|
+
return names.some((name) => job.name === name || job.name.startsWith(`${name} /`))
|
|
90
131
|
}
|
|
91
132
|
|
|
92
|
-
function
|
|
93
|
-
|
|
94
|
-
}
|
|
133
|
+
async function failed_publication(client: Client, tag: string): Promise<boolean> {
|
|
134
|
+
if (client.workflow === undefined) return false
|
|
95
135
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
token: string,
|
|
99
|
-
tag: string,
|
|
100
|
-
): Promise<boolean> {
|
|
101
|
-
const runs_response = await request(WORKFLOW_RUNS_URL, request_options(token, 'GET'))
|
|
136
|
+
const workflow = encodeURIComponent(client.workflow)
|
|
137
|
+
const runs_response = await api_get(client, `/actions/workflows/${workflow}/runs?per_page=100`)
|
|
102
138
|
const runs = RUNS_SCHEMA.parse(await read_response(runs_response)).workflow_runs
|
|
103
139
|
const run = runs.find((item) => item.display_title === `Publish ${tag}`)
|
|
104
140
|
if (!run) return false
|
|
105
141
|
|
|
106
|
-
const
|
|
107
|
-
const
|
|
142
|
+
const jobs_response = await api_get(client, `/actions/runs/${String(run.id)}/jobs?per_page=100`)
|
|
143
|
+
const { jobs } = JOBS_SCHEMA.parse(await read_response(jobs_response))
|
|
108
144
|
|
|
109
|
-
return
|
|
145
|
+
return jobs.some((job) => is_failed_job(job, client.jobs))
|
|
110
146
|
}
|
|
111
147
|
|
|
112
148
|
async function default_wait(): Promise<void> {
|
|
113
149
|
await setTimeout(POLL_INTERVAL_MS)
|
|
114
150
|
}
|
|
115
151
|
|
|
116
|
-
async function release_state(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
tag: string,
|
|
120
|
-
): Promise<'ready' | 'failed' | 'pending'> {
|
|
121
|
-
if (await existing_release(request, token, tag)) return 'ready'
|
|
122
|
-
if (await failed_publication(request, token, tag)) return 'failed'
|
|
152
|
+
async function release_state(client: Client, tag: string): Promise<'ready' | 'failed' | 'pending'> {
|
|
153
|
+
if (await existing_release(client, tag)) return 'ready'
|
|
154
|
+
if (await failed_publication(client, tag)) return 'failed'
|
|
123
155
|
|
|
124
156
|
return 'pending'
|
|
125
157
|
}
|
|
126
158
|
|
|
127
|
-
async function wait_for_release(
|
|
128
|
-
request: ReleaseRequest,
|
|
129
|
-
token: string,
|
|
130
|
-
tag: string,
|
|
131
|
-
wait: Wait,
|
|
132
|
-
): Promise<boolean> {
|
|
159
|
+
async function wait_for_release(client: Client, tag: string, wait: Wait): Promise<boolean> {
|
|
133
160
|
for (let attempt = 0; attempt < MAX_WAIT_ATTEMPTS; attempt += 1) {
|
|
134
|
-
|
|
161
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
162
|
+
const state = await release_state(client, tag)
|
|
135
163
|
if (state !== 'pending') return state === 'ready'
|
|
136
164
|
|
|
165
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
137
166
|
await wait()
|
|
138
167
|
}
|
|
139
168
|
|
|
140
169
|
throw new Error(`Timed out waiting for previous GitHub Release ${tag}`)
|
|
141
170
|
}
|
|
142
171
|
|
|
172
|
+
async function ladder_end(ladder: Ladder): Promise<string | undefined> {
|
|
173
|
+
return ladder.fallback ? await ladder.fallback() : ladder.floor
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// With no floor the repository has no release at all, so no lower tag will ever gain one: the
|
|
177
|
+
// nearest lower tag is the baseline as it stands, and none means notes without a baseline.
|
|
143
178
|
async function baseline_tag(
|
|
144
|
-
|
|
145
|
-
token: string,
|
|
179
|
+
client: Client,
|
|
146
180
|
tag: string,
|
|
147
|
-
|
|
148
|
-
): Promise<string> {
|
|
149
|
-
const prior = predecessor(
|
|
150
|
-
if (
|
|
181
|
+
ladder: Ladder,
|
|
182
|
+
): Promise<string | undefined> {
|
|
183
|
+
const prior = predecessor(ladder.tags, tag, ladder.floor)
|
|
184
|
+
if (ladder.floor === undefined) return prior
|
|
185
|
+
if (!prior) return await ladder_end(ladder)
|
|
186
|
+
|
|
187
|
+
return (await wait_for_release(client, prior, ladder.wait))
|
|
188
|
+
? prior
|
|
189
|
+
: await baseline_tag(client, prior, ladder)
|
|
190
|
+
}
|
|
151
191
|
|
|
152
|
-
|
|
153
|
-
|
|
192
|
+
function assert_older(previous: string | undefined, tag: string): void {
|
|
193
|
+
if (previous !== undefined && !semver.lt(previous, tag)) {
|
|
194
|
+
throw new Error(`Latest release ${previous} is not older than ${tag}`)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function build_ladder(client: Client, options: PublishOptions): Promise<Ladder> {
|
|
199
|
+
const tags = options.tags ?? []
|
|
200
|
+
const wait = options.wait ?? default_wait
|
|
201
|
+
const { start_tag } = options
|
|
202
|
+
|
|
203
|
+
if (start_tag !== undefined) {
|
|
204
|
+
return { tags, wait, floor: start_tag, fallback: async () => await previous_tag(client) }
|
|
154
205
|
}
|
|
155
206
|
|
|
156
|
-
return
|
|
207
|
+
return { tags, wait, floor: await latest_release(client) }
|
|
157
208
|
}
|
|
158
209
|
|
|
159
210
|
async function generate_notes(
|
|
160
|
-
|
|
161
|
-
token: string,
|
|
211
|
+
client: Client,
|
|
162
212
|
tag: string,
|
|
163
|
-
previous: string,
|
|
213
|
+
previous: string | undefined,
|
|
164
214
|
): Promise<z.infer<typeof NOTES_SCHEMA>> {
|
|
165
|
-
const response = await
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
configuration_file_path: '.github/release.yml',
|
|
171
|
-
}),
|
|
172
|
-
)
|
|
215
|
+
const response = await api_post(client, '/releases/generate-notes', {
|
|
216
|
+
tag_name: tag,
|
|
217
|
+
...(previous !== undefined && { previous_tag_name: previous }),
|
|
218
|
+
configuration_file_path: '.github/release.yml',
|
|
219
|
+
})
|
|
173
220
|
|
|
174
221
|
return NOTES_SCHEMA.parse(await read_response(response))
|
|
175
222
|
}
|
|
176
223
|
|
|
177
224
|
async function create_release(
|
|
178
|
-
|
|
179
|
-
token: string,
|
|
225
|
+
client: Client,
|
|
180
226
|
tag: string,
|
|
181
|
-
previous: string,
|
|
227
|
+
previous: string | undefined,
|
|
182
228
|
): Promise<void> {
|
|
183
|
-
const notes = await generate_notes(
|
|
184
|
-
const response = await
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
prerelease: false,
|
|
192
|
-
}),
|
|
193
|
-
)
|
|
229
|
+
const notes = await generate_notes(client, tag, previous)
|
|
230
|
+
const response = await api_post(client, '/releases', {
|
|
231
|
+
tag_name: tag,
|
|
232
|
+
name: notes.name,
|
|
233
|
+
body: notes.body,
|
|
234
|
+
draft: false,
|
|
235
|
+
prerelease: false,
|
|
236
|
+
})
|
|
194
237
|
|
|
195
238
|
RELEASE_SCHEMA.parse(await read_response(response))
|
|
196
239
|
}
|
|
197
240
|
|
|
241
|
+
function create_client(request: ReleaseRequest, token: string, settings: ReleaseSettings): Client {
|
|
242
|
+
if (!REPOSITORY_PATTERN.test(settings.repository)) {
|
|
243
|
+
throw new Error(`Invalid repository: ${settings.repository}`)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
request,
|
|
248
|
+
token,
|
|
249
|
+
url: `${API_ROOT}/${settings.repository}`,
|
|
250
|
+
workflow: settings.workflow,
|
|
251
|
+
jobs: settings.jobs ?? [],
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
198
255
|
async function publish(
|
|
199
256
|
request: ReleaseRequest,
|
|
200
257
|
token: string,
|
|
201
258
|
tag: string,
|
|
202
|
-
options: PublishOptions
|
|
259
|
+
options: PublishOptions,
|
|
203
260
|
): Promise<string> {
|
|
204
261
|
if (!TAG_PATTERN.test(tag)) throw new Error(`Invalid release tag: ${tag}`)
|
|
205
|
-
if (await existing_release(request, token, tag)) return 'already-published'
|
|
206
262
|
|
|
207
|
-
const
|
|
263
|
+
const client = create_client(request, token, options)
|
|
264
|
+
if (await existing_release(client, tag)) return 'already-published'
|
|
208
265
|
|
|
209
|
-
|
|
210
|
-
throw new Error(`Latest release ${previous} is not older than ${tag}`)
|
|
211
|
-
}
|
|
266
|
+
const previous = await baseline_tag(client, tag, await build_ladder(client, options))
|
|
212
267
|
|
|
213
|
-
|
|
268
|
+
assert_older(previous, tag)
|
|
269
|
+
await create_release(client, tag, previous)
|
|
214
270
|
|
|
215
|
-
return `published ${tag} from ${previous}`
|
|
271
|
+
return `published ${tag} from ${previous ?? 'the first commit'}`
|
|
216
272
|
}
|
|
217
273
|
|
|
218
274
|
const github_release = { publish }
|
|
219
275
|
|
|
276
|
+
export type { ReleaseSettings }
|
|
220
277
|
export { github_release }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
2
|
+
import { git_pr_checks } from '#scripts/gh/git-pr-checks'
|
|
1
3
|
import { git_command } from '#scripts/git/git-command'
|
|
2
|
-
import { git_gh_command } from '#scripts/git/git-gh-command'
|
|
3
|
-
import { git_pr_checks } from '#scripts/git/git-pr-checks'
|
|
4
4
|
import { git_remote_branch } from '#scripts/git/git-remote-branch'
|
|
5
5
|
import { write_version } from '#scripts/version/bump-version'
|
|
6
6
|
import { version_targets } from '#scripts/version/version-targets'
|
|
@@ -150,7 +150,6 @@ const release_publish = {
|
|
|
150
150
|
publish,
|
|
151
151
|
pull_request_body,
|
|
152
152
|
unreachable_remote_message,
|
|
153
|
-
FAILURE_EXIT_CODE,
|
|
154
153
|
SUCCESS_EXIT_CODE,
|
|
155
154
|
}
|
|
156
155
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { git_followup_pending } from '#scripts/
|
|
3
|
+
import { git_followup_pending } from '#scripts/followup/git-followup-pending'
|
|
4
4
|
import { path_decision } from '#scripts/josh/path-decision'
|
|
5
5
|
import { release_plan } from './release-plan'
|
|
6
6
|
|
|
@@ -87,7 +87,6 @@ const release_scope_cli = {
|
|
|
87
87
|
main,
|
|
88
88
|
run,
|
|
89
89
|
JSON_KEY,
|
|
90
|
-
KNOWN_FLAGS,
|
|
91
90
|
NOTHING_PENDING_REASON,
|
|
92
91
|
RELEASE_HINT,
|
|
93
92
|
REQUIRED_SCOPE,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { git_gh_api_path } from '#scripts/
|
|
2
|
-
import { git_gh_exec } from '#scripts/
|
|
1
|
+
import { git_gh_api_path } from '#scripts/gh/git-gh-api-path'
|
|
2
|
+
import { git_gh_exec } from '#scripts/gh/git-gh-exec'
|
|
3
3
|
import { poll, type PollOptions } from '#scripts/lib/poll'
|
|
4
4
|
|
|
5
5
|
// **The release is not finished when the pull request merges — it is finished when the tag exists.**
|
|
@@ -82,12 +82,10 @@ const release_tag = {
|
|
|
82
82
|
attempts_for,
|
|
83
83
|
configured_timeout_seconds,
|
|
84
84
|
format_result,
|
|
85
|
-
tag_exists,
|
|
86
85
|
tag_name,
|
|
87
86
|
wait_for_tag,
|
|
88
87
|
DEFAULT_TIMEOUT_SECONDS,
|
|
89
88
|
TAG_POLL_INTERVAL_MS,
|
|
90
|
-
TIMEOUT_ENV,
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
export { release_tag }
|