@joshuafolkken/kit 1.1035.0 → 1.1094.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +9 -8
- package/.claude/skills/epic-commands/SKILL.md +5 -7
- package/.claude/skills/verify-ui/SKILL.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +21 -13
- package/.claude/skills/workflow-commands/background-commands.md +5 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -3
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -7
- package/.claude/skills/workflow-commands/backlogrun-park.md +6 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +31 -37
- package/.claude/skills/workflow-commands/backlogrun-steps.md +25 -25
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +6 -4
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +3 -3
- package/.claude/skills/workflow-commands/followup.md +7 -3
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/fullrun.md +3 -2
- package/.claude/skills/workflow-commands/halfrun.md +16 -19
- package/.claude/skills/workflow-commands/issue-comments.md +2 -2
- package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +9 -4
- package/.claude/skills/workflow-commands/latest-gate.md +1 -1
- package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +44 -89
- package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -36
- package/.claude/skills/workflow-commands/prerequisite.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +36 -0
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +24 -4
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/auto-tag.yml +21 -0
- package/.github/workflows/ci.yml +26 -128
- package/.github/workflows/pr-classification.yml +5 -41
- package/.github/workflows/publish.yml +42 -48
- package/.github/workflows/sonar-qube.yml +37 -4
- package/AGENTS.md +12 -2
- package/CLAUDE.md +15 -16
- package/GEMINI.md +14 -2
- package/README.md +59 -18
- package/SECURITY.md +36 -6
- package/cspell/index.yaml +2 -1
- package/dist/CLAUDE.md +15 -16
- package/dist/config-merge/index.js +15 -3
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-Y27M6A7X.js → chunk-3C4YCCEF.js} +5 -13
- package/dist/hooks/{chunk-D67KVGGY.js → chunk-7ZPFAVR7.js} +17 -88
- package/dist/hooks/{chunk-HOYJU5RM.js → chunk-E54KGFEQ.js} +11 -4
- package/dist/hooks/{chunk-KG6PZD72.js → chunk-IL27YTPH.js} +2 -2
- package/dist/hooks/{chunk-GJT4BNVE.js → chunk-KHWHKJOM.js} +3 -3
- package/dist/hooks/{chunk-HU66PWWL.js → chunk-M2XDCUKD.js} +1076 -509
- package/dist/hooks/{chunk-GLBDBJOK.js → chunk-NKOG3XAV.js} +199 -304
- package/dist/hooks/{chunk-ZXNE6NY3.js → chunk-O4LL4HTI.js} +2 -7
- package/dist/hooks/{chunk-XPLP27WA.js → chunk-OIZUHPJI.js} +5 -27
- package/dist/hooks/{chunk-EIFCAJRB.js → chunk-UD24EAIL.js} +2546 -1636
- package/dist/hooks/codex-hook-adapter.js +10 -11
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +15 -34
- package/dist/hooks/inputs.json +279 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +23 -16
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +188 -509
- package/dist/josh.js +166 -225
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +412 -64
- package/eslint/rules/promise.js +5 -0
- package/package.json +13 -8
- package/prompts/collaboration-workflow/file-edits.md +6 -53
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/operating-rules.md +4 -4
- package/prompts/collaboration-workflow/overview.md +13 -1
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +4 -4
- package/prompts/collaboration-workflow/rule-delivery.md +5 -36
- package/prompts/collaboration-workflow/shell-body.md +7 -9
- package/prompts/collaboration-workflow/turn-batching.md +21 -37
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +36 -36
- package/prompts/collaboration-workflow.md +5 -8
- package/prompts/review-rubric.md +1 -1
- package/prompts/review.md +3 -3
- package/prompts/sonar-hotspot-handling.md +12 -4
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +2 -2
- package/scripts/adopt/adopt.ts +0 -2
- package/scripts/agent/agent-argv.ts +0 -2
- package/scripts/agent/agent-diagnostics.ts +1 -1
- package/scripts/agent/agent-role-profile.ts +0 -7
- package/scripts/agent/claude-agent-argv.ts +0 -2
- package/scripts/agent/codex-agent-argv.ts +1 -1
- package/scripts/agent/codex-hooks.ts +92 -0
- package/scripts/agent/interactive-ask.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +15 -25
- package/scripts/backlog/backlog-budget.ts +0 -2
- package/scripts/backlog/backlog-defect-priority.ts +2 -2
- package/scripts/backlog/backlog-drive-cli.ts +10 -8
- package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
- package/scripts/backlog/backlog-drive-named.ts +2 -1
- package/scripts/backlog/backlog-drive.ts +76 -16
- package/scripts/backlog/backlog-named.ts +0 -3
- package/scripts/backlog/backlog-next.ts +32 -22
- package/scripts/backlog/backlog-offer-cli.ts +0 -5
- package/scripts/backlog/backlog-plan-cli.ts +6 -8
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +34 -17
- package/scripts/backlog/backlog-rank.ts +106 -0
- package/scripts/backlog/backlog-ready.ts +19 -3
- package/scripts/backlog/backlog-scope.ts +1 -3
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +0 -1
- package/scripts/backlog/backlog-waves.ts +47 -31
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +92 -11
- package/scripts/build/hook-bundle-stamp.ts +111 -0
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +1 -1
- package/scripts/ci/composite-actions.ts +30 -0
- package/scripts/ci/pr-classification.ts +3 -3
- package/scripts/claude/workflow-destination.ts +10 -1
- package/scripts/clone/clone-fingerprint.ts +0 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/json-format.ts +0 -1
- package/scripts/config-merge/patch-yaml-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +2 -9
- package/scripts/cost-runtime/cost-attribute.ts +0 -1
- package/scripts/cost-runtime/cost-cli.ts +0 -3
- package/scripts/cost-runtime/cost-corpus.ts +0 -2
- package/scripts/cost-runtime/cost-format.ts +0 -3
- package/scripts/cost-runtime/cost-pricing.ts +0 -1
- package/scripts/cost-runtime/cost-tokens.ts +0 -1
- package/scripts/delegation/delegation-cli.ts +1 -1
- package/scripts/delegation/delegation-policy.ts +11 -1
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +0 -2
- package/scripts/delegation/investigation-reads.ts +1 -164
- package/scripts/discovery/repo-map-logic.ts +0 -1
- package/scripts/discovery/repo-party-cli.ts +1 -1
- package/scripts/doctor/doctor-consumer.ts +4 -6
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/document-byte-budget.ts +8 -9
- package/scripts/document/document-byte-check.ts +0 -1
- package/scripts/document/document-read-cli.ts +0 -2
- package/scripts/document/document-section-cli.ts +1 -1
- package/scripts/document/document-section.ts +0 -3
- package/scripts/document/edit-files-cli.ts +0 -1
- package/scripts/document/entry-read-budget.ts +13 -4
- package/scripts/document/lane-child-read-set.ts +1 -6
- package/scripts/document/read-files-cli.ts +0 -4
- package/scripts/document/read-set-cli.ts +0 -2
- package/scripts/document/read-set-point-of-use.ts +1 -0
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +1 -1
- package/scripts/epic/epic-add.ts +1 -1
- package/scripts/epic/epic-audit-cli.ts +1 -4
- package/scripts/epic/epic-audit-orphans.ts +1 -3
- package/scripts/epic/epic-audit-rationale.ts +0 -1
- package/scripts/epic/epic-audit-report.ts +0 -2
- package/scripts/epic/epic-audit.ts +5 -4
- package/scripts/epic/epic-bundle-cli.ts +1 -1
- package/scripts/epic/epic-bundle-evidence.ts +0 -1
- package/scripts/epic/epic-bundle-referenced.ts +1 -5
- package/scripts/epic/epic-bundle.ts +0 -4
- package/scripts/epic/epic-busy.ts +4 -5
- package/scripts/epic/epic-candidate-confirm.ts +0 -5
- package/scripts/epic/epic-classify.ts +2 -2
- package/scripts/epic/epic-cli-argv.ts +0 -1
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +5 -2
- package/scripts/epic/epic-cross-repo.ts +2 -4
- package/scripts/epic/epic-decision.ts +0 -1
- package/scripts/epic/epic-fetch.ts +2 -2
- package/scripts/epic/epic-index.ts +2 -3
- package/scripts/epic/epic-issue.ts +1 -15
- package/scripts/epic/epic-lane-offer.ts +20 -30
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +1 -3
- package/scripts/epic/epic-next-views.ts +0 -1
- package/scripts/epic/epic-next.ts +1 -10
- package/scripts/epic/epic-parse.ts +0 -1
- package/scripts/epic/epic-promote.ts +0 -9
- package/scripts/epic/epic-rank.ts +37 -0
- package/scripts/epic/epic-read.ts +1 -2
- package/scripts/epic/epic-reconcile.ts +1 -1
- package/scripts/epic/epic-reference.ts +1 -13
- package/scripts/epic/epic-relation-recheck.ts +1 -1
- package/scripts/epic/epic-relations.ts +1 -1
- package/scripts/epic/epic-remove.ts +1 -1
- package/scripts/epic/epic-report.ts +0 -1
- package/scripts/epic/epic-run.ts +2 -3
- package/scripts/epic/epic-shape.ts +1 -1
- package/scripts/epic/epic-solo-stale.ts +107 -0
- package/scripts/epic/epic-solo.ts +32 -30
- package/scripts/epic/epic-triage.ts +1 -1
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/epic/epic.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +53 -0
- package/scripts/{git → followup}/followup-issue-number.ts +1 -6
- package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
- package/scripts/{git → followup}/git-followup-finish.ts +1 -3
- package/scripts/{git → followup}/git-followup-flush.ts +2 -2
- package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
- package/scripts/{git → followup}/git-followup-label.ts +4 -4
- package/scripts/followup/git-followup-merged.ts +112 -0
- package/scripts/{git → followup}/git-followup-pending.ts +1 -1
- package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
- package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
- package/scripts/{git → followup}/git-pr-followup.ts +53 -16
- package/scripts/gate/core-budget.ts +3 -9
- package/scripts/gate/gate-plan.ts +7 -4
- package/scripts/gate/gate-report.ts +0 -6
- package/scripts/gate/gate-tree.ts +1 -1
- package/scripts/gate/pre-commit-type-check.ts +0 -6
- package/scripts/gate/project-checks.ts +7 -8
- package/scripts/gate/scoped-green.ts +0 -1
- package/scripts/gate/type-check-step.ts +1 -1
- package/scripts/gate/verification-gate.ts +0 -2
- package/scripts/gh/fix-gh-packages.ts +15 -12
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
- package/scripts/{git → gh}/git-gh-check.ts +2 -1
- package/scripts/{git → gh}/git-gh-exec.ts +1 -1
- package/scripts/{git → gh}/git-gh-failure.ts +1 -1
- package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
- package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
- package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
- package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
- package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
- package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
- package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
- package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
- package/scripts/{git → gh}/git-gh-pr.ts +3 -1
- package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
- package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
- package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
- package/scripts/{git → gh}/git-pr-checks.ts +2 -1
- package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
- package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
- package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
- package/scripts/{git → gh}/git-pr.ts +3 -3
- package/scripts/git/changed-file-scope.ts +0 -1
- package/scripts/git/git-branch.ts +3 -6
- package/scripts/git/git-command.ts +1 -1
- package/scripts/git/git-commit.ts +1 -1
- package/scripts/git/git-common-directory.ts +80 -24
- package/scripts/git/git-error.ts +66 -9
- package/scripts/git/git-execa-error.ts +6 -1
- package/scripts/git/git-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +24 -6
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push-transport.ts +12 -69
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-spawn.ts +79 -3
- package/scripts/git/git-ssh-keepalive.ts +74 -0
- package/scripts/git/git-staging.ts +1 -0
- package/scripts/git/git-status.ts +1 -1
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/gone-branch.ts +4 -2
- package/scripts/git/listing-cutoff.ts +1 -1
- package/scripts/git/main-merge.ts +1 -1
- package/scripts/git/main-sync.ts +19 -1
- package/scripts/git/parse-json-array.ts +0 -3
- package/scripts/git/repository-lock.ts +16 -16
- package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
- package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
- package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
- package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
- package/scripts/hooks/codex-hook-adapter.ts +0 -1
- package/scripts/hooks/edited-cspell.ts +1 -1
- package/scripts/hooks/format-edited-cli.ts +15 -0
- package/scripts/hooks/format-edited-file.ts +4 -9
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard-cli.ts +21 -0
- package/scripts/hooks/pretool-guard.ts +36 -19
- package/scripts/hooks/reserved-run.ts +1 -1
- package/scripts/hooks/step-zero-notice.ts +76 -0
- package/scripts/hooks/stop-guard.ts +47 -21
- package/scripts/init/claude-plugin-config.ts +4 -5
- package/scripts/init/hook-command-rewrite.ts +16 -8
- package/scripts/init/hook-launch.ts +41 -15
- package/scripts/init/init-basic.ts +2 -5
- package/scripts/init/init-logic.ts +7 -0
- package/scripts/init/init.ts +0 -3
- package/scripts/init/project-profile.ts +6 -11
- package/scripts/init/start-exec.ts +8 -2
- package/scripts/init/start-plan.ts +18 -5
- package/scripts/init/start-setup-pr.ts +52 -25
- package/scripts/init/start-steps.ts +42 -9
- package/scripts/init/start.ts +40 -10
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +3 -3
- package/scripts/issue/defect-rate.ts +1 -2
- package/scripts/{git → issue}/git-next-issues.ts +37 -8
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +19 -3
- package/scripts/issue/issue-classification.ts +1 -9
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +2 -2
- package/scripts/issue/issue-file-cli.ts +5 -5
- package/scripts/issue/issue-file.ts +2 -2
- package/scripts/issue/issue-fold-cli.ts +1 -1
- package/scripts/issue/issue-fold-existing-cli.ts +1 -1
- package/scripts/{git → issue}/issue-labels.ts +20 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/issue/issue-rank.ts +89 -0
- package/scripts/issue/issue-read-cli.ts +8 -47
- package/scripts/issue/issue-read.ts +0 -2
- package/scripts/issue/issue-report-failures.ts +80 -0
- package/scripts/issue/issue-scout-cli.ts +1 -7
- package/scripts/issue/issue-scout-closed.ts +2 -2
- package/scripts/issue/issue-scout.ts +0 -2
- package/scripts/issue/issue-state-cli.ts +5 -46
- package/scripts/issue/issue-state.ts +1 -5
- package/scripts/issue/markdown-section.ts +1 -1
- package/scripts/issue/measure-rerun-cli.ts +1 -1
- package/scripts/issue/reproduction-measure.ts +1 -1
- package/scripts/josh/cli-body.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +0 -3
- package/scripts/josh/josh-command-map.ts +2 -102
- package/scripts/josh/josh-commands-ai.ts +9 -102
- package/scripts/josh/josh-commands-backlog.ts +5 -1
- package/scripts/josh/josh-commands-development.ts +10 -3
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/josh/josh-commands-maintenance.ts +7 -0
- package/scripts/josh/josh-commands-project.ts +7 -1
- package/scripts/josh/josh-commands-run.ts +114 -0
- package/scripts/josh/josh-commands-versioning.ts +8 -0
- package/scripts/josh/josh-commands-workflow.ts +2 -2
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +3 -6
- package/scripts/lane/lane-capacity.ts +6 -3
- package/scripts/lane/lane-child-invocation.ts +20 -7
- package/scripts/lane/lane-child-marker.ts +16 -2
- package/scripts/lane/lane-cli.ts +33 -18
- package/scripts/lane/lane-close.ts +1 -3
- package/scripts/lane/lane-dispatch.ts +3 -4
- package/scripts/lane/lane-environment.ts +0 -9
- package/scripts/lane/lane-handoff.ts +38 -0
- package/scripts/lane/lane-launch-cli.ts +21 -11
- package/scripts/lane/lane-open.ts +0 -3
- package/scripts/lane/lane-output.ts +0 -1
- package/scripts/lane/lane-registry.ts +9 -0
- package/scripts/lane/lane-report.ts +10 -4
- package/scripts/lane/openai-lane-ship.ts +2 -0
- package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
- package/scripts/lane/openai-lane-supervisor.ts +6 -4
- package/scripts/lane/openai-review-broker.ts +3 -0
- package/scripts/lib/bounded-pool.ts +1 -0
- package/scripts/lib/json-value.ts +5 -4
- package/scripts/lib/poll.ts +3 -1
- package/scripts/lib/timed-fetch.ts +15 -0
- package/scripts/lib/timeouts.ts +13 -0
- package/scripts/{yaml → lib}/yaml-document.ts +3 -1
- package/scripts/{bytes → lines}/bytes-command.ts +0 -2
- package/scripts/lines/lines-command.ts +0 -1
- package/scripts/lint/lint-related-scope.ts +0 -1
- package/scripts/lint/lint-related.ts +1 -1
- package/scripts/{git → notify}/telegram-notify.ts +2 -2
- package/scripts/{git → notify}/telegram-test.ts +4 -4
- package/scripts/observations/observation-ledger-home.ts +0 -1
- package/scripts/observations/observation-ledger-line.ts +0 -1
- package/scripts/observations/observation-ledger-migrate.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +3 -3
- package/scripts/observations/observations-flush.ts +2 -2
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/package/package-scout-cli.ts +2 -7
- package/scripts/package/package-scout.ts +0 -2
- package/scripts/propagate/propagate-git-failure.ts +0 -1
- package/scripts/propagate/propagate-git.ts +0 -2
- package/scripts/propagate/propagate-plan.ts +185 -0
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -3
- package/scripts/propagate/propagate-steps.ts +19 -6
- package/scripts/propagate/propagate-targets.ts +13 -6
- package/scripts/propagate/propagate.ts +60 -46
- package/scripts/refactor/import-graph.ts +0 -1
- package/scripts/refactor/refactor-lint.ts +0 -2
- package/scripts/refactor/refactor-scan.ts +0 -1
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +1 -2
- package/scripts/registry-migration/migrate.ts +19 -9
- package/scripts/release/github-release-cli.ts +8 -6
- package/scripts/release/github-release-environment.ts +46 -0
- package/scripts/release/github-release.ts +151 -94
- package/scripts/release/release-history.ts +0 -1
- package/scripts/release/release-plan.ts +0 -1
- package/scripts/release/release-publish.ts +2 -3
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- package/scripts/repo/auto-merge-setting-logic.ts +1 -4
- package/scripts/repo/repo-setting.ts +1 -1
- package/scripts/repo/repository-labels.ts +3 -3
- package/scripts/repo/required-checks-logic.ts +206 -0
- package/scripts/repo/required-checks-report.ts +71 -0
- package/scripts/repo/ruleset-check-cli.ts +53 -0
- package/scripts/repo/ruleset-check.ts +147 -0
- package/scripts/report/report-lint-cli.ts +0 -4
- package/scripts/review/disposition-cli.ts +1 -1
- package/scripts/review/live-evidence.ts +1 -1
- package/scripts/review/review-attest-cli.ts +0 -6
- package/scripts/review/review-attest.ts +48 -16
- package/scripts/review/review-brief-cli.ts +72 -8
- package/scripts/review/review-brief.ts +67 -9
- package/scripts/review/review-diff-parts.ts +89 -0
- package/scripts/review/review-diff-write.ts +97 -0
- package/scripts/review/review-finding-ledger.ts +0 -1
- package/scripts/review/review-record-cli.ts +1 -1
- package/scripts/review/review-record.ts +0 -1
- package/scripts/review/review-round2-cli.ts +1 -1
- package/scripts/review/review-stamps.ts +6 -2
- package/scripts/review/review-tree.ts +14 -2
- package/scripts/rules/decision-oracle-stage.ts +18 -0
- package/scripts/rules/decision-oracle.ts +10 -7
- package/scripts/rules/delivered-rules.ts +9 -1
- package/scripts/rules/destructive-command.ts +119 -0
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/file-body.ts +0 -3
- package/scripts/rules/filing-cap.ts +0 -2
- package/scripts/rules/gh-api.ts +7 -2
- package/scripts/rules/git-argv.ts +18 -7
- package/scripts/rules/git-force.ts +0 -2
- package/scripts/rules/implementation-cut.ts +1 -2
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/issue-fold.ts +1 -2
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-carry-conflict.ts +1 -2
- package/scripts/rules/lane-park.ts +14 -8
- package/scripts/rules/last-prompt.ts +1 -0
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +0 -3
- package/scripts/rules/permission-guards.ts +14 -0
- package/scripts/rules/pre-gate-cut.ts +2 -2
- package/scripts/rules/protected-files.ts +74 -0
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +0 -3
- package/scripts/rules/rule-value-cli.ts +0 -1
- package/scripts/rules/shell-body-trigger.ts +0 -1
- package/scripts/rules/shell-segments.ts +0 -1
- package/scripts/rules/stop-rules.ts +13 -5
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +0 -1
- package/scripts/rules/worktree-guard.ts +26 -9
- package/scripts/run/run-carry-cli.ts +0 -2
- package/scripts/run/run-carry-stash.ts +2 -2
- package/scripts/run/run-carry-streak.ts +1 -1
- package/scripts/run/run-cut-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +1 -1
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +101 -24
- package/scripts/run/run-entry.ts +0 -1
- package/scripts/run/run-event-cli.ts +0 -2
- package/scripts/run/run-event-follow.ts +1 -0
- package/scripts/run/run-event-render.ts +1 -1
- package/scripts/run/run-event-scope.ts +53 -4
- package/scripts/run/run-event-stream.ts +0 -3
- package/scripts/run/run-event-watch.ts +1 -0
- package/scripts/run/run-halfrun-resume.ts +20 -7
- package/scripts/run/run-headless.ts +24 -8
- package/scripts/run/run-hold-cli.ts +33 -10
- package/scripts/run/run-hold.ts +25 -5
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +1 -1
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +5 -13
- package/scripts/run/run-merge-steps.ts +5 -5
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-next-cli.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +143 -0
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +2 -2
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-cli.ts +4 -7
- package/scripts/run/run-progress-clock.ts +6 -34
- package/scripts/run/run-progress-config.ts +0 -4
- package/scripts/run/run-progress-read.ts +3 -3
- package/scripts/run/run-progress.ts +22 -10
- package/scripts/run/run-prrun-resume.ts +117 -0
- package/scripts/run/run-report-cli.ts +1 -2
- package/scripts/run/run-report.ts +0 -1
- package/scripts/run/run-retrospective.ts +1 -1
- package/scripts/run/run-review-cli.ts +0 -3
- package/scripts/run/run-review-steps.ts +2 -0
- package/scripts/run/run-review.ts +0 -2
- package/scripts/run/run-ship-cli.ts +27 -77
- package/scripts/run/run-ship-detach.ts +1 -0
- package/scripts/run/run-ship-next.ts +106 -0
- package/scripts/run/run-ship-preflight.ts +87 -0
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +23 -30
- package/scripts/run/run-ship-review.ts +20 -0
- package/scripts/run/run-ship-scoped.ts +45 -0
- package/scripts/run/run-ship-stage.ts +5 -1
- package/scripts/run/run-ship-steps.ts +105 -0
- package/scripts/run/run-ship.ts +2 -1
- package/scripts/run/run-stage-read.ts +62 -0
- package/scripts/run/run-stage.ts +160 -0
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +21 -14
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stop-notify.ts +1 -3
- package/scripts/run/run-stranded-cli.ts +0 -4
- package/scripts/run/run-stranded-detect.ts +2 -2
- package/scripts/run/run-tail-cli.ts +17 -11
- package/scripts/run/run-tail.ts +2 -0
- package/scripts/run/run-tidy-lanes.ts +2 -1
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +4 -5
- package/scripts/run/run-wake-describe.ts +19 -1
- package/scripts/run/run-wake-loop.ts +2 -2
- package/scripts/run/run-wake.ts +2 -4
- package/scripts/run/run-watcher-guard-cli.ts +0 -4
- package/scripts/run/run-watcher-guard.ts +9 -7
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- package/scripts/safe-chain/project-config.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +0 -1
- package/scripts/security/security-audit-provision.ts +3 -2
- package/scripts/security/security-audit.ts +0 -1
- package/scripts/security/security-updates-logic.ts +0 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
- package/scripts/sonar/sonar-hotspots.ts +0 -1
- package/scripts/sonar/sonar-new-code-cli.ts +150 -0
- package/scripts/sonar/sonar-new-code.ts +79 -0
- package/scripts/sonar/sonar-project.ts +97 -0
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +2 -5
- package/scripts/sync/managed-config-scope-cli.ts +1 -1
- package/scripts/sync/skill-migration.ts +0 -1
- package/scripts/sync/sync-hook-safety.ts +2 -3
- package/scripts/sync/sync.ts +1 -8
- package/scripts/sync/template-source-logic.ts +0 -1
- package/scripts/sync/workflow-pin-logic.ts +16 -28
- package/scripts/test/test-declared-logic.ts +0 -1
- package/scripts/test/test-declared.ts +0 -2
- package/scripts/test/test-red-commit.ts +2 -2
- package/scripts/test/test-red.ts +14 -7
- package/scripts/test/test-type-logic.ts +1 -1
- package/scripts/test/unit-worker-share.ts +7 -16
- package/scripts/time-runtime/time-batch-guard.ts +1 -2
- package/scripts/time-runtime/time-bundle-call.ts +2 -3
- package/scripts/time-runtime/time-bundles.ts +0 -4
- package/scripts/time-runtime/time-density-hook.ts +0 -2
- package/scripts/time-runtime/time-followup-stage.ts +1 -1
- package/scripts/time-runtime/time-format.ts +0 -73
- package/scripts/time-runtime/time-round-trips.ts +0 -4
- package/scripts/time-runtime/time-single-check.ts +1 -1
- package/scripts/time-runtime/time-spans.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +1 -2
- package/scripts/ui/ui-routes-cli.ts +0 -5
- package/scripts/ui/ui-routes.ts +0 -5
- package/scripts/version/effective-upstream.ts +2 -2
- package/scripts/version/latest-corepack.ts +7 -9
- package/scripts/version/latest-scope-cli.ts +0 -2
- package/scripts/version/latest-update.ts +0 -2
- package/scripts/version/npm-registry.ts +97 -0
- package/scripts/version/publishable-range-check.ts +1 -1
- package/scripts/version/release-hold.ts +0 -4
- package/scripts/version/running-binary.ts +2 -2
- package/scripts/version/version-check-logic.ts +0 -2
- package/scripts/version/version-commands.ts +5 -4
- package/scripts/version/version-remote.ts +28 -14
- package/scripts/version/version-targets.ts +4 -4
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/dependabot-auto-merge.yml +5 -3
- package/templates/workflows/github-release.yml +81 -0
- package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
- package/prompts/collaboration-workflow/epic-audit.md +0 -5
- package/prompts/collaboration-workflow/epic-bundle.md +0 -5
- package/scripts/init/plugin-install-hint.ts +0 -47
- package/scripts/version/parse-json.ts +0 -13
- /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
- /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
- /package/scripts/{git → gh}/git-gh-command.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
- /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
- /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
- /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
- /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
- /package/scripts/{git → gh}/git-pr-error.ts +0 -0
- /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
- /package/scripts/{git → gh}/github-issue-url.ts +0 -0
- /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
- /package/scripts/{git → issue}/issue-reference.ts +0 -0
- /package/scripts/{git → lib}/animation-helpers.ts +0 -0
- /package/scripts/{git → lib}/git-animation.ts +0 -0
- /package/scripts/{git → notify}/git-notify.ts +0 -0
- /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { text } from 'node:stream/consumers'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
5
|
+
import { pretool_outcome_async } from './pretool-guard'
|
|
6
|
+
|
|
7
|
+
// The `PreToolUse` hook's entry, kept apart from the composition in `pretool-guard.ts`
|
|
8
|
+
// (joshuafolkken/kit#2922). The hook bundles are built with `splitting: true`, which moves a module
|
|
9
|
+
// imported by two entries into a shared chunk — and `codex-hook-adapter.ts` imports `pretool-guard.ts`.
|
|
10
|
+
// Its self-invoke went into that chunk, whose `import.meta.url` never equals the launched
|
|
11
|
+
// `dist/hooks/pretool-guard.js`, so the bundled hook ran no guard at all and every refusal failed open.
|
|
12
|
+
// An entry nothing imports keeps the self-invoke in the file that is actually launched.
|
|
13
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
14
|
+
if (process.stdin.isTTY) hook_decision.report_no_payload('pretool:guard')
|
|
15
|
+
else {
|
|
16
|
+
const raw_payload = await text(process.stdin)
|
|
17
|
+
|
|
18
|
+
hook_decision.load_environment_file()
|
|
19
|
+
hook_decision.emit_outcome(await pretool_outcome_async(raw_payload))
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
import { text } from 'node:stream/consumers'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
1
|
import { duplicate_read_outcome } from '#scripts/delegation/duplicate-read-guard'
|
|
5
2
|
import { investigation_refusal } from '#scripts/delegation/investigation-guard'
|
|
6
|
-
import {
|
|
3
|
+
import type { GuardOutcome } from '#scripts/josh/hook-decision'
|
|
7
4
|
import { delivered_rules } from '#scripts/rules/delivered-rules'
|
|
5
|
+
import { run_parent_cut_hook } from '#scripts/run/run-parent-cut-hook'
|
|
8
6
|
import { run_watcher_hook } from '#scripts/run/run-watcher-hook'
|
|
9
7
|
import { batch_outcome } from './batch-guard'
|
|
8
|
+
import { step_zero_notice } from './step-zero-notice'
|
|
10
9
|
|
|
11
10
|
// One PreToolUse process for the three guards that used to be three (joshuafolkken/kit#1930). A Bash
|
|
12
11
|
// call used to spawn `batch:guard`, `investigation:guard` and `rule:guard` separately — three pnpm
|
|
@@ -51,10 +50,20 @@ function with_duplicate_notice(combined: GuardOutcome, notice: string | undefine
|
|
|
51
50
|
return { reason: undefined, notice, fault: undefined }
|
|
52
51
|
}
|
|
53
52
|
|
|
53
|
+
// The Step 0 reminder is the last word (joshuafolkken/kit#2994): asked only where every guard stayed
|
|
54
|
+
// clear, so a refusal or another notice never spends its once-per-session stamp unseen.
|
|
55
|
+
function with_step_zero_notice(outcome: GuardOutcome, raw_payload: string): GuardOutcome {
|
|
56
|
+
if (!is_clear(outcome)) return outcome
|
|
57
|
+
|
|
58
|
+
const notice = step_zero_notice.notice(raw_payload)
|
|
59
|
+
|
|
60
|
+
return notice === undefined ? outcome : { reason: undefined, notice, fault: undefined }
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
// All guards run unconditionally, exactly as the separate PreToolUse entries did: each records its own
|
|
55
64
|
// once-per-run stamp, so short-circuiting on the first refusal would change which guard is allowed to
|
|
56
65
|
// fire on a later call.
|
|
57
|
-
function
|
|
66
|
+
function guard_outcome(raw_payload: string): GuardOutcome {
|
|
58
67
|
const batch = batch_outcome(raw_payload)
|
|
59
68
|
const investigation = investigation_refusal(raw_payload)
|
|
60
69
|
const duplicate = duplicate_read_outcome(raw_payload)
|
|
@@ -65,32 +74,40 @@ function pretool_outcome(raw_payload: string): GuardOutcome {
|
|
|
65
74
|
return with_duplicate_notice(combined, duplicate.notice)
|
|
66
75
|
}
|
|
67
76
|
|
|
77
|
+
// The synchronous verdict the Codex adapter asks for, with the Step 0 reminder as its last layer.
|
|
78
|
+
function pretool_outcome(raw_payload: string): GuardOutcome {
|
|
79
|
+
return with_step_zero_notice(guard_outcome(raw_payload), raw_payload)
|
|
80
|
+
}
|
|
81
|
+
|
|
68
82
|
// The watcher guard is the one composed rule that cannot answer synchronously — it reads the lane
|
|
69
83
|
// registry and the watcher's life record off disk (joshuafolkken/kit#2353). So it is asked after the
|
|
70
84
|
// synchronous guards and only where they stayed clear: a refusal from any of them wins first, exactly
|
|
71
85
|
// as `combine_outcomes` orders them, and the watcher's refusal fills a clear verdict rather than
|
|
72
86
|
// overriding one. It fires once per run itself (`run-watcher-hook.ts`), so a stale watcher refuses the
|
|
73
87
|
// first call but not the `pnpm josh run:progress --wait` that fixes it.
|
|
88
|
+
//
|
|
89
|
+
// **The parent hand-off guard is the second asynchronous rule, asked after the watcher's**
|
|
90
|
+
// (joshuafolkken/kit#2947). It reads the carry record to tell the `backlogrun` parent apart, so it sits
|
|
91
|
+
// beside the watcher rather than among the synchronous rows; a stale watcher is the cheaper fix and is
|
|
92
|
+
// surfaced first.
|
|
93
|
+
async function async_reason(raw_payload: string): Promise<string | undefined> {
|
|
94
|
+
const watcher = await run_watcher_hook.watcher_hook_reason(raw_payload)
|
|
95
|
+
|
|
96
|
+
return watcher ?? (await run_parent_cut_hook.parent_cut_reason(raw_payload))
|
|
97
|
+
}
|
|
98
|
+
|
|
74
99
|
async function pretool_outcome_async(raw_payload: string): Promise<GuardOutcome> {
|
|
75
|
-
const base =
|
|
100
|
+
const base = guard_outcome(raw_payload)
|
|
76
101
|
|
|
77
102
|
if (!is_clear(base)) return base
|
|
78
103
|
|
|
79
|
-
const reason = await
|
|
80
|
-
|
|
81
|
-
return reason === undefined ? base : { reason, notice: undefined, fault: undefined }
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const pretool_guard = { combine_outcomes, pretool_outcome, pretool_outcome_async }
|
|
104
|
+
const reason = await async_reason(raw_payload)
|
|
85
105
|
|
|
86
|
-
if (
|
|
87
|
-
if (process.stdin.isTTY) hook_decision.report_no_payload('pretool:guard')
|
|
88
|
-
else {
|
|
89
|
-
const raw_payload = await text(process.stdin)
|
|
106
|
+
if (reason !== undefined) return { reason, notice: undefined, fault: undefined }
|
|
90
107
|
|
|
91
|
-
|
|
92
|
-
hook_decision.emit_outcome(await pretool_outcome_async(raw_payload))
|
|
93
|
-
}
|
|
108
|
+
return with_step_zero_notice(base, raw_payload)
|
|
94
109
|
}
|
|
95
110
|
|
|
111
|
+
const pretool_guard = { combine_outcomes, pretool_outcome }
|
|
112
|
+
|
|
96
113
|
export { pretool_guard, pretool_outcome, pretool_outcome_async }
|
|
@@ -85,6 +85,6 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
85
85
|
process.exitCode = await run_reserved(process.argv.slice(FIRST_ARGUMENT_INDEX))
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
const reserved_run = { parse_arguments,
|
|
88
|
+
const reserved_run = { parse_arguments, run_reserved }
|
|
89
89
|
|
|
90
90
|
export { reserved_run }
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
3
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
4
|
+
import { test_declared_logic } from '#scripts/test/test-declared-logic'
|
|
5
|
+
|
|
6
|
+
// The Code Change Rules Step 0 reminder, delivered at the moment implementation code is about to be
|
|
7
|
+
// written rather than on every prompt (joshuafolkken/kit#2994). As a `UserPromptSubmit` echo it was
|
|
8
|
+
// injected into every turn — a question that writes nothing included — and re-read as accumulated
|
|
9
|
+
// context on each turn after it. The trigger the rule names is "before writing any implementation
|
|
10
|
+
// code", so the hook that delivers it is the one that sees that write: the first `Edit` / `Write` of a
|
|
11
|
+
// runtime file in the session.
|
|
12
|
+
//
|
|
13
|
+
// **A runtime file only.** What counts is `test_declared_logic.is_exempt`, the same classification
|
|
14
|
+
// `pnpm josh test:declared` answers at the commit, so a doc or prompt edit neither shows the notice nor
|
|
15
|
+
// spends it. A path outside the working tree (a memory file, a scratchpad) is not this project's code.
|
|
16
|
+
//
|
|
17
|
+
// **Once per session**, on a stamp keyed by the transcript like every other guard record here. A stamp
|
|
18
|
+
// that cannot be written stays silent rather than repeating the notice on every edit.
|
|
19
|
+
const STAMP_PREFIX = 'josh-step-zero-notice-'
|
|
20
|
+
const EDIT_TOOLS: ReadonlySet<string> = new Set(['Edit', 'Write'])
|
|
21
|
+
const PARENT_PREFIX = '..'
|
|
22
|
+
|
|
23
|
+
const NOTICE =
|
|
24
|
+
'Before writing any implementation code: present the two-layer work summary (Now / Change / Check, then every change with its test) once per Issue. Full rule: Code Change Rules Step 0 in CLAUDE.md.'
|
|
25
|
+
|
|
26
|
+
const STAMP = hook_decision.create_refusal_stamp(STAMP_PREFIX)
|
|
27
|
+
|
|
28
|
+
// A Codex `apply_patch` arrives translated with its first file as `file_path` and every file in
|
|
29
|
+
// `file_paths`, so a patch that leads with a doc and also writes code is still a runtime write.
|
|
30
|
+
function edited_paths(tool_input: unknown): Array<string> {
|
|
31
|
+
if (!json_value.is_record(tool_input)) return []
|
|
32
|
+
|
|
33
|
+
const { file_path, file_paths } = tool_input
|
|
34
|
+
const listed: ReadonlyArray<unknown> = Array.isArray(file_paths) ? file_paths : []
|
|
35
|
+
|
|
36
|
+
return [file_path, ...listed].filter(
|
|
37
|
+
(entry): entry is string => typeof entry === 'string' && entry.length > 0,
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function is_runtime_file(file_path: string, root: string): boolean {
|
|
42
|
+
const relative = path.relative(root, path.resolve(root, file_path))
|
|
43
|
+
|
|
44
|
+
if (relative.startsWith(PARENT_PREFIX) || path.isAbsolute(relative)) return false
|
|
45
|
+
|
|
46
|
+
return !test_declared_logic.is_exempt(relative.split(path.sep).join('/'))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function is_candidate(raw_payload: string, root: string): string | undefined {
|
|
50
|
+
const payload = hook_decision.parse_hook_payload(raw_payload)
|
|
51
|
+
|
|
52
|
+
if (payload === undefined || !EDIT_TOOLS.has(payload.tool_name)) return undefined
|
|
53
|
+
|
|
54
|
+
const has_runtime_file = edited_paths(payload.tool_input).some((file_path) =>
|
|
55
|
+
is_runtime_file(file_path, root),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return has_runtime_file ? payload.transcript_path : undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function notice(raw_payload: string, root: string = process.cwd()): string | undefined {
|
|
62
|
+
const transcript = is_candidate(raw_payload, root)
|
|
63
|
+
|
|
64
|
+
if (transcript === undefined) return undefined
|
|
65
|
+
|
|
66
|
+
const target = STAMP.path(transcript)
|
|
67
|
+
|
|
68
|
+
if (STAMP.last_ms(target) !== hook_decision.NEVER_MS) return undefined
|
|
69
|
+
if (!STAMP.record(target, Date.now())) return undefined
|
|
70
|
+
|
|
71
|
+
return NOTICE
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const step_zero_notice = { NOTICE, notice, stamp_path: STAMP.path }
|
|
75
|
+
|
|
76
|
+
export { step_zero_notice }
|
|
@@ -7,12 +7,15 @@ import { repo_party } from '#scripts/discovery/repo-party'
|
|
|
7
7
|
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
8
8
|
import { session_language } from '#scripts/josh/session-language'
|
|
9
9
|
import { lane_child_marker } from '#scripts/lane/lane-child-marker'
|
|
10
|
+
import { lane_handoff } from '#scripts/lane/lane-handoff'
|
|
10
11
|
import { filing_cap } from '#scripts/rules/filing-cap'
|
|
11
12
|
import { lane_background } from '#scripts/rules/lane-background'
|
|
12
13
|
import { lane_park } from '#scripts/rules/lane-park'
|
|
13
14
|
import { last_prompt } from '#scripts/rules/last-prompt'
|
|
14
15
|
import { stop_rules, type StopContext, type StopOutcome } from '#scripts/rules/stop-rules'
|
|
16
|
+
import { run_carry } from '#scripts/run/run-carry'
|
|
15
17
|
import { run_cut } from '#scripts/run/run-cut'
|
|
18
|
+
import { run_halfrun_resume } from '#scripts/run/run-halfrun-resume'
|
|
16
19
|
import { run_headless } from '#scripts/run/run-headless'
|
|
17
20
|
import { run_hold } from '#scripts/run/run-hold'
|
|
18
21
|
import { run_stranded_detect } from '#scripts/run/run-stranded-detect'
|
|
@@ -29,16 +32,17 @@ import { time_hook_transcript } from '#scripts/time-runtime/time-hook-transcript
|
|
|
29
32
|
// resolving (send the notify, release the hold) and `stop_hook_active` is the backstop, so failing
|
|
30
33
|
// open here costs at most a missed nudge, never a stuck run.
|
|
31
34
|
|
|
32
|
-
// The hold record for this working tree is still in place
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
+
// The hold record for this working tree is still in place, and whether it is a `prrun` stop's
|
|
36
|
+
// (joshuafolkken/kit#3023). `unreadable` reads as absent: the safe direction for a stop guard is not to
|
|
37
|
+
// block, and an unreadable record is not proof a run is holding.
|
|
38
|
+
async function hold_facts(): Promise<Pick<StopContext, 'hold_present' | 'prrun_stopped'>> {
|
|
35
39
|
const directory = await run_hold.worktree_directory()
|
|
40
|
+
const hold =
|
|
41
|
+
directory === undefined
|
|
42
|
+
? undefined
|
|
43
|
+
: run_halfrun_resume.hold_of(run_hold.read_hold(run_hold.hold_path(directory)))
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const read = run_hold.read_hold(run_hold.hold_path(directory))
|
|
40
|
-
|
|
41
|
-
return read.kind === 'held' || read.kind === 'stale'
|
|
45
|
+
return { hold_present: hold !== undefined, prrun_stopped: hold?.prrun_stop_head !== undefined }
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
// A `confirmation` notify sits on this run's transcript tail. The tail is derived exactly as the
|
|
@@ -67,7 +71,7 @@ async function build_context(
|
|
|
67
71
|
const tail = transcript_tail(transcript_path)
|
|
68
72
|
|
|
69
73
|
return {
|
|
70
|
-
|
|
74
|
+
...(await hold_facts()),
|
|
71
75
|
tree_clean: !(await run_hold.is_tree_dirty()),
|
|
72
76
|
notified: lane_park.mentions_confirmation_notify(tail),
|
|
73
77
|
message: payload_tail.message,
|
|
@@ -81,6 +85,7 @@ async function build_context(
|
|
|
81
85
|
lane_child: lane_child_marker.is_child_of(process.cwd()),
|
|
82
86
|
background_pending: lane_background.pending_background_ids(tail).length > 0,
|
|
83
87
|
agent_pending: lane_background.pending_agent_ids(tail).length > 0,
|
|
88
|
+
handed_off: lane_handoff.is_handed_off(process.cwd()),
|
|
84
89
|
session_lang: session_lang(),
|
|
85
90
|
}
|
|
86
91
|
}
|
|
@@ -106,22 +111,43 @@ async function outcome_of(raw_payload: string): Promise<StopOutcome> {
|
|
|
106
111
|
}
|
|
107
112
|
}
|
|
108
113
|
|
|
114
|
+
// A live carry record is in place — `carried` alone reads as a run. Both report checks below are about
|
|
115
|
+
// a carried run: the strand judge reads this very record and returns on anything but `carried`, and a
|
|
116
|
+
// stall needs a backlog driver, which begins one before its plan. A spent (`expired`) or `unreadable`
|
|
117
|
+
// record a crashed run left behind is no run either, so it does not re-arm the stall's backlog probe
|
|
118
|
+
// on every stop (joshuafolkken/kit#2995).
|
|
119
|
+
// A failed git read — outside a repository, `git rev-parse` exits non-zero — reads as no run, since this
|
|
120
|
+
// gate sits ahead of the checks' own swallowing and must not throw into the stop decision either.
|
|
121
|
+
async function has_run_record(): Promise<boolean> {
|
|
122
|
+
try {
|
|
123
|
+
const directory = await run_carry.repository_directory()
|
|
124
|
+
|
|
125
|
+
if (directory === undefined) return false
|
|
126
|
+
|
|
127
|
+
return run_carry.read_carry(run_carry.carry_path(directory)).kind === 'carried'
|
|
128
|
+
} catch {
|
|
129
|
+
return false
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// The stall check rides the Stop hook because the stop *is* the loop boundary: a run alive but not
|
|
134
|
+
// advancing ends turns without dispatching (joshuafolkken/kit#2359). The strand check rides the same
|
|
135
|
+
// boundary and is the step before the stall (joshuafolkken/kit#2375): it fires when the driver is gone
|
|
136
|
+
// — the budget handed off, the owner dead, no supervisor watching. Both only report and swallow their
|
|
137
|
+
// own failures, so neither can change the stop decision. An ordinary stop with no run record skips
|
|
138
|
+
// both, so it pays one directory read rather than their reads and a stale stream's backlog probe.
|
|
139
|
+
async function run_report_checks(): Promise<void> {
|
|
140
|
+
if (!(await has_run_record())) return
|
|
141
|
+
|
|
142
|
+
await backlog_stalled_detect.run_stall_check(backlog_ready.DEFAULT_PORTS)
|
|
143
|
+
await run_stranded_detect.run_stranded_check()
|
|
144
|
+
}
|
|
145
|
+
|
|
109
146
|
// Nothing reaches stdout on an ordinary stop, so what the harness parses stays empty unless the stop
|
|
110
147
|
// is being held — all three rules block, so a bare `#N` is reported the same way (joshuafolkken/kit#2247).
|
|
111
148
|
async function write_stop_decision(raw_payload: string): Promise<void> {
|
|
112
149
|
hook_decision.load_environment_file()
|
|
113
|
-
|
|
114
|
-
// The stall check rides the Stop hook because the stop *is* the loop boundary: a run alive but not
|
|
115
|
-
// advancing ends turns without dispatching (joshuafolkken/kit#2359). It only reports — leaves a
|
|
116
|
-
// marker, sends a notification — and swallows its own failures, so it can never change the decision
|
|
117
|
-
// below or hold the stop.
|
|
118
|
-
await backlog_stalled_detect.run_stall_check(backlog_ready.DEFAULT_PORTS)
|
|
119
|
-
|
|
120
|
-
// The strand check rides the same boundary for the same reason, and is the step before the stall
|
|
121
|
-
// (joshuafolkken/kit#2375): the stall detector needs a live driver that could dispatch, and this one
|
|
122
|
-
// fires when that driver is gone — the budget handed off, the owner dead, no supervisor watching. It
|
|
123
|
-
// too only reports and swallows its own failures, so it never touches the stop decision below.
|
|
124
|
-
await run_stranded_detect.run_stranded_check()
|
|
150
|
+
await run_report_checks()
|
|
125
151
|
|
|
126
152
|
const { reason } = await outcome_of(raw_payload)
|
|
127
153
|
|
|
@@ -13,9 +13,10 @@ const PLUGIN_ID = 'kit@kit'
|
|
|
13
13
|
const MARKETPLACE_PATH = './node_modules/@joshuafolkken/kit'
|
|
14
14
|
const CLAUDE_SETTINGS_DESTINATION = path.join('.claude', 'settings.json')
|
|
15
15
|
|
|
16
|
-
// `enabledPlugins` declares the plugin; `extraKnownMarketplaces` says where to find it.
|
|
17
|
-
//
|
|
18
|
-
//
|
|
16
|
+
// `enabledPlugins` declares the plugin; `extraKnownMarketplaces` says where to find it. Nothing needs
|
|
17
|
+
// installing: in a trusted workspace Claude Code registers the marketplace from this declaration and
|
|
18
|
+
// loads the skills — an interactive session from its first session, a headless one (`claude -p`) from
|
|
19
|
+
// its second (joshuafolkken/kit#2990).
|
|
19
20
|
const PLUGIN_SETTINGS: Record<string, unknown> = {
|
|
20
21
|
extraKnownMarketplaces: {
|
|
21
22
|
[MARKETPLACE_NAME]: { source: { source: 'directory', path: MARKETPLACE_PATH } },
|
|
@@ -39,11 +40,9 @@ function apply_plugin_config_for_destination(destination_path: string, content:
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
const claude_plugin_config = {
|
|
42
|
-
MARKETPLACE_NAME,
|
|
43
43
|
PLUGIN_ID,
|
|
44
44
|
MARKETPLACE_PATH,
|
|
45
45
|
CLAUDE_SETTINGS_DESTINATION,
|
|
46
|
-
PLUGIN_SETTINGS,
|
|
47
46
|
inject_plugin_config,
|
|
48
47
|
apply_plugin_config_for_destination,
|
|
49
48
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { GIT_LOCATION_VARIABLES } from '#scripts/git/git-location-environment'
|
|
2
1
|
import { claude_plugin_config } from './claude-plugin-config'
|
|
3
2
|
import { hook_launch } from './hook-launch'
|
|
4
3
|
|
|
@@ -27,8 +26,11 @@ const MISSING_INSTALL_NOTICE = 'kit hooks inactive: run pnpm install, then rerea
|
|
|
27
26
|
const MISSING_INSTALL_GUARD = `if [ ! -f ${CONSUMER_PACKAGE_MANIFEST} ]; then echo '${MISSING_INSTALL_NOTICE}' >&2; exit 0; fi; `
|
|
28
27
|
const CODEX_ADAPTER_BUNDLE = `node ${CONSUMER_HOOK_BUNDLE_DIR}codex-hook-adapter.js`
|
|
29
28
|
const CODEX_HOOKS_DESTINATION = '.codex/hooks.json'
|
|
30
|
-
|
|
31
|
-
const PROJECT_ROOT_PREFIX =
|
|
29
|
+
// The values below are matched inside raw JSON text, so the root prefix is taken in its escaped form.
|
|
30
|
+
const PROJECT_ROOT_PREFIX = JSON.stringify(hook_launch.PROJECT_ROOT_PREFIX).slice(1, -1)
|
|
31
|
+
// The installed package ships its bundles built, so they cannot be stale against a source the consumer
|
|
32
|
+
// never has: the ready gate kit's own commands pass (joshuafolkken/kit#2984) becomes a presence check.
|
|
33
|
+
const CONSUMER_READY_GATE = `[ -d ${CONSUMER_HOOK_BUNDLE_DIR} ]`
|
|
32
34
|
// Capture the value of every `"command"` field, escapes and all, so the rewrites below touch command
|
|
33
35
|
// values alone — never an echo reminder's prose or a `"description"` that merely mentions the string.
|
|
34
36
|
const COMMAND_FIELD = /("command":\s*")((?:[^"\\]|\\.)*)(")/gu
|
|
@@ -49,6 +51,8 @@ function rebase_bundle_directory(value: string): string {
|
|
|
49
51
|
// holds no `pnpm josh `), so the whole rewrite is safe to run more than once.
|
|
50
52
|
function rewrite_command_value(value: string): string {
|
|
51
53
|
const rewritten = rebase_bundle_directory(value)
|
|
54
|
+
.split(hook_launch.BUNDLE_READY_GATE)
|
|
55
|
+
.join(CONSUMER_READY_GATE)
|
|
52
56
|
.split(PNPM_JOSH_PREFIX)
|
|
53
57
|
.join(BUNDLE_INVOCATION)
|
|
54
58
|
.split(CODEX_ADAPTER_SOURCE)
|
|
@@ -60,12 +64,18 @@ function rewrite_command_value(value: string): string {
|
|
|
60
64
|
return `${MISSING_INSTALL_GUARD}${rewritten}`
|
|
61
65
|
}
|
|
62
66
|
|
|
67
|
+
// kit's own commands already start from the root (`hook-launch.ts`), and so does an already-rewritten
|
|
68
|
+
// value. The prefix is taken off before the rewrite and put back after it, so the install guard sits
|
|
69
|
+
// behind the `cd` it depends on and a second pass never doubles the prefix.
|
|
70
|
+
function without_root_prefix(value: string): string {
|
|
71
|
+
return value.startsWith(PROJECT_ROOT_PREFIX) ? value.slice(PROJECT_ROOT_PREFIX.length) : value
|
|
72
|
+
}
|
|
73
|
+
|
|
63
74
|
function rewrite_hook_commands(content: string, is_codex = false): string {
|
|
64
75
|
return content.replaceAll(COMMAND_FIELD, (_match, open: string, value: string, close: string) => {
|
|
65
|
-
const rewritten = rewrite_command_value(value)
|
|
76
|
+
const rewritten = rewrite_command_value(without_root_prefix(value))
|
|
66
77
|
const should_select_root = is_codex || rewritten.includes(claude_plugin_config.MARKETPLACE_PATH)
|
|
67
|
-
const prefix =
|
|
68
|
-
should_select_root && !rewritten.startsWith(PROJECT_ROOT_PREFIX) ? PROJECT_ROOT_PREFIX : ''
|
|
78
|
+
const prefix = should_select_root ? PROJECT_ROOT_PREFIX : ''
|
|
69
79
|
|
|
70
80
|
return `${open}${prefix}${rewritten}${close}`
|
|
71
81
|
})
|
|
@@ -89,8 +99,6 @@ function apply_hook_command_rewrite_for_destination(
|
|
|
89
99
|
|
|
90
100
|
const hook_command_rewrite = {
|
|
91
101
|
apply_hook_command_rewrite_for_destination,
|
|
92
|
-
BUNDLE_INVOCATION,
|
|
93
|
-
PNPM_JOSH_PREFIX,
|
|
94
102
|
rewrite_hook_commands,
|
|
95
103
|
}
|
|
96
104
|
|
|
@@ -1,31 +1,57 @@
|
|
|
1
|
+
import { GIT_LOCATION_VARIABLES } from '#scripts/git/git-location-environment'
|
|
2
|
+
|
|
1
3
|
// The shell command a Claude Code hook is launched with, so it starts without a `pnpm` wrapper — and,
|
|
2
4
|
// for a consumer, without the `dist/josh.js` dispatcher re-spawning `tsx` for the hook's `.ts`
|
|
3
5
|
// (joshuafolkken/kit#2023). Each hook is pre-built to its own `dist/hooks/<name>.js`
|
|
4
6
|
// (`scripts/build/build-hooks.ts`) and launched directly with `node`.
|
|
5
7
|
//
|
|
6
|
-
// **The
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
//
|
|
8
|
+
// **The command starts from the project root, never from wherever the session happens to be**
|
|
9
|
+
// (joshuafolkken/kit#2984). Every path after the prefix is relative, so a hook fired from a
|
|
10
|
+
// subdirectory would otherwise miss its bundle. The root is git's, with the location variables a git
|
|
11
|
+
// hook exports cleared first — the same resolution the consumer rewrite (`hook-command-rewrite.ts`)
|
|
12
|
+
// applies, so both sides stay one mechanism for Claude Code and Codex alike.
|
|
13
|
+
//
|
|
14
|
+
// **The bundle runs only once the ready gate passes** (`scripts/hooks/hook-bundle-ready.ts`): it
|
|
15
|
+
// rebuilds `dist/hooks/` when the source beside it has changed, so an edited guard is never shadowed by
|
|
16
|
+
// its old bundle. The gate failing — a checkout that cannot build — drops to the fallback, the live
|
|
17
|
+
// source. **An `if`/`else`, never `&&`/`||`**: a guard's refusal is a non-zero exit, and a
|
|
18
|
+
// `node … || pnpm josh …` chain would read that refusal as a missing bundle and run the hook twice.
|
|
19
|
+
|
|
15
20
|
const HOOK_DIST_DIR = 'dist/hooks'
|
|
21
|
+
const UNSET_OPTIONS = GIT_LOCATION_VARIABLES.map((name) => `-u ${name}`).join(' ')
|
|
22
|
+
const PROJECT_ROOT_PREFIX = `if project_root="$(env ${UNSET_OPTIONS} git rev-parse --show-toplevel 2>/dev/null)"; then unset ${GIT_LOCATION_VARIABLES.join(' ')}; else project_root="$(git rev-parse --show-toplevel)" || exit 1; fi; cd "$project_root" && `
|
|
23
|
+
// Plain `node` runs the gate's TypeScript directly; the flag keeps Node 22's type-stripping notice off
|
|
24
|
+
// every hook's stderr.
|
|
25
|
+
const BUNDLE_READY_GATE =
|
|
26
|
+
'node --disable-warning=ExperimentalWarning scripts/hooks/hook-bundle-ready.ts'
|
|
16
27
|
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
function launch_command(
|
|
20
|
-
return `if
|
|
28
|
+
// Run `primary_command` when `gate` exits 0, else `fallback_command` — both verbatim. Kept generic so
|
|
29
|
+
// a test can exercise the branch selection with stub commands rather than real hooks.
|
|
30
|
+
function launch_command(gate: string, primary_command: string, fallback_command: string): string {
|
|
31
|
+
return `if ${gate}; then ${primary_command}; else ${fallback_command}; fi`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// `invocation` is the hook's file under `dist/hooks` plus any arguments (e.g. `pretool-guard.js`);
|
|
35
|
+
// `fallback_command` runs the same hook from source.
|
|
36
|
+
function bundle_launch_command(invocation: string, fallback_command: string): string {
|
|
37
|
+
const primary = `node ${HOOK_DIST_DIR}/${invocation}`
|
|
38
|
+
|
|
39
|
+
return `${PROJECT_ROOT_PREFIX}${launch_command(BUNDLE_READY_GATE, primary, fallback_command)}`
|
|
21
40
|
}
|
|
22
41
|
|
|
23
42
|
// `bundle` is the hook's file under `dist/hooks` (e.g. `pretool-guard.js`); `command` is the josh
|
|
24
43
|
// subcommand the fallback runs (e.g. `pretool:guard`).
|
|
25
44
|
function hook_launch_command(bundle: string, command: string): string {
|
|
26
|
-
return
|
|
45
|
+
return bundle_launch_command(bundle, `pnpm josh ${command}`)
|
|
27
46
|
}
|
|
28
47
|
|
|
29
|
-
const hook_launch = {
|
|
48
|
+
const hook_launch = {
|
|
49
|
+
BUNDLE_READY_GATE,
|
|
50
|
+
bundle_launch_command,
|
|
51
|
+
HOOK_DIST_DIR,
|
|
52
|
+
hook_launch_command,
|
|
53
|
+
launch_command,
|
|
54
|
+
PROJECT_ROOT_PREFIX,
|
|
55
|
+
}
|
|
30
56
|
|
|
31
57
|
export { hook_launch }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { json_format } from '#scripts/config-merge/json-format'
|
|
2
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
2
3
|
import { z } from 'zod'
|
|
3
4
|
import { init_logic } from './init-logic'
|
|
4
5
|
import type { ProjectShape } from './project-profile'
|
|
@@ -6,10 +7,6 @@ import type { ProjectShape } from './project-profile'
|
|
|
6
7
|
const KIT_PACKAGE_NAME = '@joshuafolkken/kit'
|
|
7
8
|
const record_schema = z.record(z.string(), z.unknown())
|
|
8
9
|
|
|
9
|
-
function is_record(value: unknown): value is Record<string, unknown> {
|
|
10
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
10
|
interface BasicVersions {
|
|
14
11
|
kit: string
|
|
15
12
|
prettier: string
|
|
@@ -23,7 +20,7 @@ function with_recorded_profile(content: string, profile: ProjectShape['profile']
|
|
|
23
20
|
const parsed: unknown = JSON.parse(content)
|
|
24
21
|
const manifest = record_schema.parse(parsed)
|
|
25
22
|
const existing = manifest['josh']
|
|
26
|
-
const josh = is_record(existing) ? existing : {}
|
|
23
|
+
const josh = json_value.is_record(existing) ? existing : {}
|
|
27
24
|
|
|
28
25
|
manifest['josh'] = { ...josh, profile }
|
|
29
26
|
|
|
@@ -92,6 +92,10 @@ const AI_COPY_FILES: ReadonlyArray<string> = [
|
|
|
92
92
|
'.github/workflows/production.yml',
|
|
93
93
|
'.github/workflows/sonar-qube.yml',
|
|
94
94
|
'.github/workflows/pr-classification.yml',
|
|
95
|
+
// Called by `pr-classification.yml` as `uses: ./.github/actions/setup-pnpm`; without it the
|
|
96
|
+
// consumer's job cannot resolve the action and the Release classification check fails
|
|
97
|
+
// (joshuafolkken/kit#3013).
|
|
98
|
+
'.github/actions/setup-pnpm/action.yml',
|
|
95
99
|
'.github/pull_request_template.md',
|
|
96
100
|
'.github/release.yml',
|
|
97
101
|
'.github/dependabot.yml',
|
|
@@ -118,6 +122,9 @@ const AI_COPY_FILE_MAPPINGS: ReadonlyArray<FileCopyMapping> = [
|
|
|
118
122
|
src: 'templates/workflows/dependabot-auto-merge.yml',
|
|
119
123
|
dest: '.github/workflows/dependabot-auto-merge.yml',
|
|
120
124
|
},
|
|
125
|
+
// A template rather than a copy of kit's own file: kit releases from its publish.yml, so the file
|
|
126
|
+
// must not run in kit as well (joshuafolkken/kit#3007).
|
|
127
|
+
{ src: 'templates/workflows/github-release.yml', dest: '.github/workflows/github-release.yml' },
|
|
121
128
|
]
|
|
122
129
|
|
|
123
130
|
// Empty since joshuafolkken/kit#1879: the five skill directories kit used to copy whole
|
package/scripts/init/init.ts
CHANGED
|
@@ -22,7 +22,6 @@ import { init_install } from './init-install'
|
|
|
22
22
|
import { init_logic } from './init-logic'
|
|
23
23
|
import { PACKAGE_DIR, PROJECT_ROOT } from './init-paths'
|
|
24
24
|
import { kit_setup_state } from './kit-setup-state'
|
|
25
|
-
import { plugin_install_hint_module } from './plugin-install-hint'
|
|
26
25
|
import { project_profile, type ProjectProfile, type ProjectShape } from './project-profile'
|
|
27
26
|
|
|
28
27
|
const PACKAGE_JSON = 'package.json'
|
|
@@ -295,8 +294,6 @@ function run_ai_file_actions(shape: ProjectShape): void {
|
|
|
295
294
|
const name_with_owner = init_ai_copy.run_ai_copies(shape)
|
|
296
295
|
|
|
297
296
|
if (shape.has_github) report_repository_settings(name_with_owner)
|
|
298
|
-
|
|
299
|
-
if (shape.profile === 'full') plugin_install_hint_module.report_plugin_install_hint()
|
|
300
297
|
}
|
|
301
298
|
|
|
302
299
|
function initialize_project(shape: ProjectShape): void {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, type Dirent } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { repo_origin } from '#scripts/discovery/repo-origin'
|
|
4
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
4
5
|
import { KIT_PACKAGE_NAME } from '#scripts/version/kit-descriptor'
|
|
5
6
|
import { execaSync } from 'execa'
|
|
6
7
|
|
|
@@ -73,32 +74,26 @@ function read_manifest(root: string): Record<string, unknown> | undefined {
|
|
|
73
74
|
if (!existsSync(filename)) return undefined
|
|
74
75
|
const parsed: unknown = JSON.parse(readFileSync(filename, 'utf8'))
|
|
75
76
|
|
|
76
|
-
if (
|
|
77
|
-
throw new Error('package.json must contain an object')
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return parsed as Record<string, unknown>
|
|
81
|
-
}
|
|
77
|
+
if (!json_value.is_record(parsed)) throw new Error('package.json must contain an object')
|
|
82
78
|
|
|
83
|
-
|
|
84
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
79
|
+
return parsed
|
|
85
80
|
}
|
|
86
81
|
|
|
87
82
|
function recorded_profile(manifest: Record<string, unknown>): ProjectProfile | undefined {
|
|
88
83
|
const { josh } = manifest
|
|
89
84
|
|
|
90
|
-
return is_record(josh) ? parse_profile(josh['profile']) : undefined
|
|
85
|
+
return json_value.is_record(josh) ? parse_profile(josh['profile']) : undefined
|
|
91
86
|
}
|
|
92
87
|
|
|
93
88
|
function has_build_script(value: unknown): boolean {
|
|
94
|
-
return is_record(value) && ('build' in value || 'dev' in value)
|
|
89
|
+
return json_value.is_record(value) && ('build' in value || 'dev' in value)
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
// kit itself is not evidence of a Node toolchain: `pnpm add -D @joshuafolkken/kit` before
|
|
98
93
|
// `josh init` is the documented order, and it must still leave an `index.html` site on the basic
|
|
99
94
|
// profile (joshuafolkken/kit#2693).
|
|
100
95
|
function has_project_dependencies(value: unknown): boolean {
|
|
101
|
-
if (!is_record(value)) return false
|
|
96
|
+
if (!json_value.is_record(value)) return false
|
|
102
97
|
|
|
103
98
|
return Object.keys(value).some((name) => name !== KIT_PACKAGE_NAME)
|
|
104
99
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { git_gh_exec } from '#scripts/
|
|
1
|
+
import { git_gh_exec } from '#scripts/gh/git-gh-exec'
|
|
2
2
|
import { execaSync } from 'execa'
|
|
3
3
|
|
|
4
4
|
// The three spawn shapes every `josh start` step uses, shared by `start-steps.ts`, the setup pull
|
|
@@ -23,6 +23,12 @@ function run(command: string, args: ReadonlyArray<string>, root: string): void {
|
|
|
23
23
|
execaSync(command, args, { ...git_gh_exec.direct_environment(), cwd: root, stdio: 'inherit' })
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
// A caller's own initialize command stands in for the in-process `josh init`, so it keeps the
|
|
27
|
+
// environment that setup would have had — its install goes through a scanner's proxy as usual.
|
|
28
|
+
function run_local(command: string, args: ReadonlyArray<string>, root: string): void {
|
|
29
|
+
execaSync(command, args, { cwd: root, stdio: 'inherit' })
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const start_exec = { succeeds, read_output, run, run_local }
|
|
27
33
|
|
|
28
34
|
export { start_exec }
|