@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,26 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { readFileSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { codex_hooks } from '#scripts/agent/codex-hooks'
|
|
6
|
+
|
|
7
|
+
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
|
|
8
|
+
const CLAUDE_SETTINGS = path.join(REPO_ROOT, '.claude', 'settings.json')
|
|
9
|
+
const CODEX_HOOKS = path.join(REPO_ROOT, '.codex', 'hooks.json')
|
|
10
|
+
|
|
11
|
+
// Regenerate `.codex/hooks.json` from `.claude/settings.json` (joshuafolkken/kit#2997). The output is
|
|
12
|
+
// committed rather than gitignored: Codex reads it straight from a fresh clone of kit, before any
|
|
13
|
+
// build has run, and `josh init` / `josh sync` copy it to consumers from the package.
|
|
14
|
+
function build_codex_hooks(): string {
|
|
15
|
+
writeFileSync(CODEX_HOOKS, codex_hooks.codex_hooks_text(readFileSync(CLAUDE_SETTINGS, 'utf8')))
|
|
16
|
+
|
|
17
|
+
return CODEX_HOOKS
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function main(): void {
|
|
21
|
+
console.info(` ✔ ${build_codex_hooks()} built`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main()
|
|
25
|
+
|
|
26
|
+
export { build_codex_hooks, CLAUDE_SETTINGS, CODEX_HOOKS }
|
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
mkdirSync,
|
|
4
|
+
mkdtempSync,
|
|
5
|
+
readdirSync,
|
|
6
|
+
readFileSync,
|
|
7
|
+
renameSync,
|
|
8
|
+
rmSync,
|
|
9
|
+
writeFileSync,
|
|
10
|
+
} from 'node:fs'
|
|
3
11
|
import path from 'node:path'
|
|
4
12
|
import { fileURLToPath } from 'node:url'
|
|
13
|
+
import { hook_bundle_stamp } from '#scripts/build/hook-bundle-stamp'
|
|
5
14
|
import { error_text } from '#scripts/lib/error-message'
|
|
6
|
-
import { build } from 'esbuild'
|
|
15
|
+
import { build, type OnLoadArgs, type OutputFile, type Plugin, type PluginBuild } from 'esbuild'
|
|
7
16
|
|
|
8
17
|
const PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
|
|
9
18
|
const OUT_DIR = path.join(PACKAGE_DIR, 'dist', 'hooks')
|
|
19
|
+
const { STAMP_NAME } = hook_bundle_stamp
|
|
20
|
+
const CHUNK_PREFIX = 'chunk-'
|
|
21
|
+
const STAGING_PREFIX = '.hooks-staging-'
|
|
22
|
+
// esbuild compiles a plugin filter as a Go regexp, which rejects the `u` flag.
|
|
23
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
24
|
+
const ANY_PATH = /.*/
|
|
10
25
|
|
|
11
26
|
// Each Claude Code hook is bundled to its own `dist/hooks/<name>.js`, so a consumer (and kit itself)
|
|
12
27
|
// invokes `node dist/hooks/<name>.js` directly — no `pnpm` launch and no `tsx` re-spawn from the
|
|
@@ -20,6 +35,11 @@ const OUT_DIR = path.join(PACKAGE_DIR, 'dist', 'hooks')
|
|
|
20
35
|
// splitting keeps every entry in its own file with its own `import.meta.url`, so an imported guard's
|
|
21
36
|
// `import.meta.url` never equals `argv[1]` and only the file actually launched runs its main.
|
|
22
37
|
//
|
|
38
|
+
// **The flip side: an entry another entry imports loses its main** (joshuafolkken/kit#2922). Splitting
|
|
39
|
+
// moves a module two entries share into a chunk, so a launched hook whose own module is imported
|
|
40
|
+
// elsewhere becomes a re-export stub that runs nothing. Each launched hook is therefore a `*-cli.ts`
|
|
41
|
+
// file holding only the self-invoke, which no other module imports.
|
|
42
|
+
//
|
|
23
43
|
// `packages: 'external'` keeps bare dependencies as runtime imports the consumer resolves from kit's
|
|
24
44
|
// node_modules, exactly as the library bundles do, while kit's internal `#scripts/*` graph is inlined.
|
|
25
45
|
// No shebang banner is added: unlike `dist/josh.js` (the `bin.josh` entry, executed directly), a hook
|
|
@@ -35,9 +55,9 @@ interface HookBundle {
|
|
|
35
55
|
// `delivered-rules` (the fourth guard) has no self-invoke, so it stays inlined.
|
|
36
56
|
const HOOK_BUNDLES: ReadonlyArray<HookBundle> = [
|
|
37
57
|
{ source: 'scripts/hooks/codex-hook-adapter.ts', out: 'codex-hook-adapter' },
|
|
38
|
-
{ source: 'scripts/hooks/pretool-guard.ts', out: 'pretool-guard' },
|
|
58
|
+
{ source: 'scripts/hooks/pretool-guard-cli.ts', out: 'pretool-guard' },
|
|
39
59
|
{ source: 'scripts/hooks/stop-guard.ts', out: 'stop-guard' },
|
|
40
|
-
{ source: 'scripts/hooks/format-edited-
|
|
60
|
+
{ source: 'scripts/hooks/format-edited-cli.ts', out: 'format-edited' },
|
|
41
61
|
{ source: 'scripts/josh/session-language-cli.ts', out: 'session-lang' },
|
|
42
62
|
{ source: 'scripts/hooks/batch-guard.ts', out: 'batch-guard' },
|
|
43
63
|
{ source: 'scripts/delegation/investigation-guard.ts', out: 'investigation-guard' },
|
|
@@ -55,20 +75,76 @@ function outfile_for(bundle: HookBundle): string {
|
|
|
55
75
|
// The output directory is flat (every entry and chunk sits at its top level), so a file whose name
|
|
56
76
|
// this build did not emit is a leftover of an earlier one.
|
|
57
77
|
function prune_stale_outputs(out_directory: string, outputs: ReadonlyArray<string>): void {
|
|
58
|
-
const live = new Set(outputs.map((output) => path.basename(output)))
|
|
78
|
+
const live = new Set([...outputs.map((output) => path.basename(output)), STAMP_NAME])
|
|
59
79
|
|
|
60
80
|
for (const name of readdirSync(out_directory)) {
|
|
61
81
|
if (!live.has(name)) rmSync(path.join(out_directory, name), { recursive: true, force: true })
|
|
62
82
|
}
|
|
63
83
|
}
|
|
64
84
|
|
|
85
|
+
// Every file the build loads is read here, so the stamp digests the exact bytes that were bundled —
|
|
86
|
+
// a source edited mid-build is recorded as what it was, and the next launch rebuilds it.
|
|
87
|
+
function source_recorder(sources: Map<string, Uint8Array>): Plugin {
|
|
88
|
+
return {
|
|
89
|
+
name: 'hook-source-recorder',
|
|
90
|
+
setup(plugin_build: PluginBuild): void {
|
|
91
|
+
plugin_build.onLoad({ filter: ANY_PATH, namespace: 'file' }, function load(args: OnLoadArgs) {
|
|
92
|
+
const contents = readFileSync(args.path)
|
|
93
|
+
|
|
94
|
+
sources.set(path.relative(PACKAGE_DIR, args.path), contents)
|
|
95
|
+
|
|
96
|
+
return { contents, loader: 'default' }
|
|
97
|
+
})
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function is_chunk(file: OutputFile): boolean {
|
|
103
|
+
return path.basename(file.path).startsWith(CHUNK_PREFIX)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Shared chunks first, then the entries that import them: an entry swapped in before its chunks
|
|
107
|
+
// would fail to load in a hook launched at that moment.
|
|
108
|
+
function is_chunk_first(left: OutputFile, right: OutputFile): number {
|
|
109
|
+
return Number(is_chunk(right)) - Number(is_chunk(left))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Each file is written into a private staging directory and renamed into place, so a hook never
|
|
113
|
+
// reads a half-written bundle and two builds running side by side never write one file at once.
|
|
114
|
+
function place(staging: string, target: string, contents: Uint8Array | string): void {
|
|
115
|
+
const temporary = path.join(staging, path.basename(target))
|
|
116
|
+
|
|
117
|
+
writeFileSync(temporary, contents)
|
|
118
|
+
renameSync(temporary, target)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function place_build(out_directory: string, files: ReadonlyArray<OutputFile>, stamp: string): void {
|
|
122
|
+
mkdirSync(out_directory, { recursive: true })
|
|
123
|
+
const staging = mkdtempSync(path.join(path.dirname(out_directory), STAGING_PREFIX))
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
for (const file of files.toSorted(is_chunk_first)) place(staging, file.path, file.contents)
|
|
127
|
+
prune_stale_outputs(
|
|
128
|
+
out_directory,
|
|
129
|
+
files.map((file) => file.path),
|
|
130
|
+
)
|
|
131
|
+
place(staging, path.join(out_directory, STAMP_NAME), stamp)
|
|
132
|
+
} finally {
|
|
133
|
+
rmSync(staging, { recursive: true, force: true })
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
65
137
|
// With `splitting: true` every build emits freshly hashed `chunk-*.js` files, so without a cleanup
|
|
66
138
|
// the chunks of every earlier build pile up beside the live ones and ship in any local pack
|
|
67
|
-
// (joshuafolkken/kit#2885). The cleanup runs after the
|
|
68
|
-
// first: this checkout's own settings.json launches `node dist/hooks/<name>.js` on
|
|
69
|
-
// and an emptied directory would make a hook launched mid-build fail to load and its
|
|
139
|
+
// (joshuafolkken/kit#2885). The cleanup runs after the new files are in place rather than emptying
|
|
140
|
+
// the directory first: this checkout's own settings.json launches `node dist/hooks/<name>.js` on
|
|
141
|
+
// every tool call, and an emptied directory would make a hook launched mid-build fail to load and its
|
|
142
|
+
// guard fail open. The source digest is placed last (`hook-bundle-stamp.ts`), so a launch only reads
|
|
143
|
+
// the bundles as fresh once every one of them is in place (joshuafolkken/kit#2984).
|
|
70
144
|
async function build_hooks(out_directory: string = OUT_DIR): Promise<void> {
|
|
71
|
-
const
|
|
145
|
+
const sources = new Map<string, Uint8Array>()
|
|
146
|
+
const { outputFiles: files } = await build({
|
|
147
|
+
absWorkingDir: PACKAGE_DIR,
|
|
72
148
|
entryPoints: HOOK_BUNDLES.map((bundle) => entry_point(bundle)),
|
|
73
149
|
outdir: out_directory,
|
|
74
150
|
bundle: true,
|
|
@@ -77,10 +153,15 @@ async function build_hooks(out_directory: string = OUT_DIR): Promise<void> {
|
|
|
77
153
|
format: 'esm',
|
|
78
154
|
target: 'node22',
|
|
79
155
|
packages: 'external',
|
|
80
|
-
|
|
156
|
+
write: false,
|
|
157
|
+
plugins: [source_recorder(sources)],
|
|
81
158
|
})
|
|
159
|
+
const stamp = hook_bundle_stamp.stamp_text(
|
|
160
|
+
sources,
|
|
161
|
+
files.map((file) => file.path),
|
|
162
|
+
)
|
|
82
163
|
|
|
83
|
-
|
|
164
|
+
place_build(out_directory, files, stamp)
|
|
84
165
|
}
|
|
85
166
|
|
|
86
167
|
async function main(): Promise<void> {
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
5
|
+
|
|
6
|
+
// What a hook build was made from, so a later launch can tell whether `dist/hooks/` still matches the
|
|
7
|
+
// source it runs beside (joshuafolkken/kit#2984). `dist/` is git-ignored and rebuilt only by
|
|
8
|
+
// `pnpm build`, so without this record an edited guard keeps running its old bundle with nothing to
|
|
9
|
+
// say so — and a lane's bundles are copied from the main checkout, whose source can differ.
|
|
10
|
+
//
|
|
11
|
+
// **The record is a content digest, not a timestamp.** A copy (`lane-cache.ts`) or a fresh checkout
|
|
12
|
+
// rewrites every mtime while leaving the content alone, and a digest is the only comparison that
|
|
13
|
+
// neither rebuilds on that nor misses an edit that kept the old mtime.
|
|
14
|
+
//
|
|
15
|
+
// **The digest is taken from the bytes the build read, never re-read from disk afterwards.** A source
|
|
16
|
+
// edited while the build runs would otherwise be recorded as built, and its stale bundle read as fresh.
|
|
17
|
+
//
|
|
18
|
+
// This module is loaded by plain `node` on every hook launch (`scripts/hooks/hook-bundle-ready.ts`),
|
|
19
|
+
// so it imports `node:` built-ins and `#scripts/*` subpaths alone — nothing slow to load.
|
|
20
|
+
|
|
21
|
+
const STAMP_NAME = 'inputs.json'
|
|
22
|
+
const DIGEST_ALGORITHM = 'sha256'
|
|
23
|
+
const JSON_INDENT = '\t'
|
|
24
|
+
|
|
25
|
+
interface HookBundleStamp {
|
|
26
|
+
digest: string
|
|
27
|
+
inputs: Array<string>
|
|
28
|
+
outputs: Array<string>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Package-relative input path → the bytes the build read for it.
|
|
32
|
+
type HookSources = ReadonlyMap<string, Uint8Array>
|
|
33
|
+
|
|
34
|
+
// Code-unit order, so the digest does not depend on the locale of the machine that computes it.
|
|
35
|
+
function by_code_unit(left: string, right: string): number {
|
|
36
|
+
if (left === right) return 0
|
|
37
|
+
|
|
38
|
+
return left < right ? -1 : 1
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Inputs are hashed in sorted order with their names, so a rename or a reorder changes the digest.
|
|
42
|
+
function digest_of(sources: HookSources): string {
|
|
43
|
+
const hash = createHash(DIGEST_ALGORITHM)
|
|
44
|
+
|
|
45
|
+
for (const input of [...sources.keys()].toSorted(by_code_unit)) {
|
|
46
|
+
hash.update(`${input}\0`).update(sources.get(input) ?? new Uint8Array())
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return hash.digest('hex')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// The record for a build that read `sources` and emitted `outputs`, as the text to write.
|
|
53
|
+
function stamp_text(sources: HookSources, outputs: ReadonlyArray<string>): string {
|
|
54
|
+
const stamp: HookBundleStamp = {
|
|
55
|
+
digest: digest_of(sources),
|
|
56
|
+
inputs: [...sources.keys()],
|
|
57
|
+
outputs: outputs.map((output) => path.basename(output)),
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return `${JSON.stringify(stamp, undefined, JSON_INDENT)}\n`
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Undefined when an input is gone: a deleted input cannot match any digest.
|
|
64
|
+
function read_sources(
|
|
65
|
+
package_directory: string,
|
|
66
|
+
inputs: ReadonlyArray<string>,
|
|
67
|
+
): HookSources | undefined {
|
|
68
|
+
const sources = new Map<string, Uint8Array>()
|
|
69
|
+
|
|
70
|
+
for (const input of inputs) {
|
|
71
|
+
const file_path = path.join(package_directory, input)
|
|
72
|
+
if (!existsSync(file_path)) return undefined
|
|
73
|
+
sources.set(input, readFileSync(file_path))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return sources
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function is_string_array(value: unknown): value is Array<string> {
|
|
80
|
+
return Array.isArray(value) && value.every((item) => typeof item === 'string')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function is_stamp(value: unknown): value is HookBundleStamp {
|
|
84
|
+
if (!json_value.is_record(value) || typeof value['digest'] !== 'string') return false
|
|
85
|
+
|
|
86
|
+
return is_string_array(value['inputs']) && is_string_array(value['outputs'])
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// A record of any other shape — hand-edited, truncated, or from an older format — reads as no record.
|
|
90
|
+
function read_stamp(out_directory: string): HookBundleStamp | undefined {
|
|
91
|
+
const stamp_path = path.join(out_directory, STAMP_NAME)
|
|
92
|
+
if (!existsSync(stamp_path)) return undefined
|
|
93
|
+
const stamp = json_value.parse_or_undefined(readFileSync(stamp_path, 'utf8'))
|
|
94
|
+
|
|
95
|
+
return is_stamp(stamp) ? stamp : undefined
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Fresh only when the record exists, every output it lists is still there, and the listed inputs hash
|
|
99
|
+
// to the recorded digest — a missing or deleted input counts as stale.
|
|
100
|
+
function is_fresh(out_directory: string, package_directory: string): boolean {
|
|
101
|
+
const stamp = read_stamp(out_directory)
|
|
102
|
+
if (!stamp?.outputs.every((output) => existsSync(path.join(out_directory, output)))) return false
|
|
103
|
+
const sources = read_sources(package_directory, stamp.inputs)
|
|
104
|
+
|
|
105
|
+
return sources !== undefined && digest_of(sources) === stamp.digest
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const hook_bundle_stamp = { is_fresh, STAMP_NAME, stamp_text }
|
|
109
|
+
|
|
110
|
+
export type { HookSources }
|
|
111
|
+
export { hook_bundle_stamp }
|
|
@@ -41,7 +41,7 @@ function main(argv: ReadonlyArray<string>): void {
|
|
|
41
41
|
process.exitCode = run(argv)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const cases_cli = {
|
|
44
|
+
const cases_cli = { run }
|
|
45
45
|
|
|
46
46
|
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
47
47
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
// A local composite action is one directory under `.github/actions`, and GitHub resolves
|
|
4
|
+
// `uses: ./.github/actions/<name>` to that directory's `action.yml` (or `action.yaml`). Workflow
|
|
5
|
+
// scanners that read `.github/workflows` read these files too: `.github/actions/setup-pnpm` holds
|
|
6
|
+
// the pnpm/setup pin and the safe-chain installer pin kit's workflows used to carry inline
|
|
7
|
+
// (joshuafolkken/kit#2982).
|
|
8
|
+
const ACTIONS_DIRECTORY = '.github/actions'
|
|
9
|
+
const ACTION_FILE_NAMES = ['action.yml', 'action.yaml']
|
|
10
|
+
|
|
11
|
+
function as_is(relative_path: string): string {
|
|
12
|
+
return relative_path
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Relative paths, resolved for the file-system calls through `resolve` — the identity for a
|
|
16
|
+
// consumer's working directory, `package_path` for kit's own package.
|
|
17
|
+
function list(resolve: (relative_path: string) => string = as_is): Array<string> {
|
|
18
|
+
if (!existsSync(resolve(ACTIONS_DIRECTORY))) return []
|
|
19
|
+
|
|
20
|
+
return readdirSync(resolve(ACTIONS_DIRECTORY))
|
|
21
|
+
.toSorted((left, right) => left.localeCompare(right))
|
|
22
|
+
.flatMap((name) =>
|
|
23
|
+
ACTION_FILE_NAMES.map((file_name) => `${ACTIONS_DIRECTORY}/${name}/${file_name}`),
|
|
24
|
+
)
|
|
25
|
+
.filter((relative_path) => existsSync(resolve(relative_path)))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const composite_actions = { list }
|
|
29
|
+
|
|
30
|
+
export { composite_actions }
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs'
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
|
-
import { git_gh_exec } from '#scripts/
|
|
3
|
+
import { git_gh_exec } from '#scripts/gh/git-gh-exec'
|
|
4
4
|
import {
|
|
5
5
|
BREAKING_CHANGE_LABEL as BREAKING,
|
|
6
6
|
BUGFIX_LABEL as BUGFIX,
|
|
7
7
|
RELEASE_CLASSIFICATION_NAMES as CLASSIFICATION_LABELS,
|
|
8
8
|
ENHANCEMENT_LABEL,
|
|
9
9
|
type ReleaseClassification,
|
|
10
|
-
} from '#scripts/
|
|
10
|
+
} from '#scripts/issue/issue-labels'
|
|
11
11
|
import { error_text } from '#scripts/lib/error-message'
|
|
12
12
|
import { z } from 'zod'
|
|
13
13
|
|
|
@@ -144,4 +144,4 @@ export { pr_classification }
|
|
|
144
144
|
export {
|
|
145
145
|
RELEASE_CLASSIFICATION_NAMES as CLASSIFICATION_LABELS,
|
|
146
146
|
type ReleaseClassification,
|
|
147
|
-
} from '#scripts/
|
|
147
|
+
} from '#scripts/issue/issue-labels'
|
|
@@ -6,8 +6,17 @@
|
|
|
6
6
|
// Matches a consumer workflow destination, absolute or repo-relative, on either separator.
|
|
7
7
|
const WORKFLOW_DESTINATION_PATTERN = /(?:^|[/\\])\.github[/\\]workflows[/\\][^/\\]+\.ya?ml$/u
|
|
8
8
|
|
|
9
|
+
// A local composite action is a workflow file too: it pins actions of its own, the distributed
|
|
10
|
+
// `dependabot.yml` bumps it (`/.github/actions/*`), and the next sync writes it back — so it needs
|
|
11
|
+
// the same pins and the same managed stamp as the workflow that calls it (joshuafolkken/kit#3013).
|
|
12
|
+
const COMPOSITE_ACTION_DESTINATION_PATTERN =
|
|
13
|
+
/(?:^|[/\\])\.github[/\\]actions[/\\][^/\\]+[/\\]action\.ya?ml$/u
|
|
14
|
+
|
|
9
15
|
function is_workflow_destination(destination: string): boolean {
|
|
10
|
-
return
|
|
16
|
+
return (
|
|
17
|
+
WORKFLOW_DESTINATION_PATTERN.test(destination) ||
|
|
18
|
+
COMPOSITE_ACTION_DESTINATION_PATTERN.test(destination)
|
|
19
|
+
)
|
|
11
20
|
}
|
|
12
21
|
|
|
13
22
|
export { is_workflow_destination }
|
|
@@ -32,7 +32,7 @@ function main(argv: ReadonlyArray<string>): void {
|
|
|
32
32
|
process.exitCode = run(argv)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const clone_scan_cli = { USAGE,
|
|
35
|
+
const clone_scan_cli = { USAGE, run }
|
|
36
36
|
|
|
37
37
|
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
38
38
|
|
|
@@ -153,6 +153,6 @@ function format_report(groups: ReadonlyArray<CloneGroup>): string {
|
|
|
153
153
|
return [header, ...groups.map((group) => format_group(group))].join('\n')
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
const clone_scan = { CLEAN_VERDICT, CLONES_PREFIX, scan,
|
|
156
|
+
const clone_scan = { CLEAN_VERDICT, CLONES_PREFIX, scan, format_report }
|
|
157
157
|
|
|
158
158
|
export { clone_scan }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { string_array_schema } from '#scripts/lib/schemas'
|
|
2
|
-
import { yaml_document } from '#scripts/
|
|
2
|
+
import { yaml_document } from '#scripts/lib/yaml-document'
|
|
3
3
|
import { dump, type DumpOptions } from 'js-yaml'
|
|
4
4
|
import { list_patch, type ListEntryMatcher } from './list-patch'
|
|
5
5
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { globSync, readFileSync } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
3
4
|
import { z } from 'zod'
|
|
4
5
|
import { cost_transcript } from './cost-transcript'
|
|
5
6
|
import type { OverMeasurement } from './cost-verdict'
|
|
@@ -23,14 +24,6 @@ const TOKEN_COUNT_SCHEMA = z.looseObject({
|
|
|
23
24
|
|
|
24
25
|
type Environment = Readonly<Record<string, string | undefined>>
|
|
25
26
|
|
|
26
|
-
function decode(line: string): unknown {
|
|
27
|
-
try {
|
|
28
|
-
return JSON.parse(line)
|
|
29
|
-
} catch {
|
|
30
|
-
return undefined
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
27
|
function same_project(cwd: string, target: string): boolean {
|
|
35
28
|
return cost_transcript.session_cwd(cwd) === cost_transcript.session_cwd(target)
|
|
36
29
|
}
|
|
@@ -51,7 +44,7 @@ function measurement_from(
|
|
|
51
44
|
target: string,
|
|
52
45
|
thread_id: string,
|
|
53
46
|
): OverMeasurement | undefined {
|
|
54
|
-
const values = content.split('\n').map((line) =>
|
|
47
|
+
const values = content.split('\n').map((line) => json_value.parse_or_undefined(line))
|
|
55
48
|
const metadata = values.flatMap((value) => {
|
|
56
49
|
const parsed = SESSION_META_SCHEMA.safeParse(value)
|
|
57
50
|
|
|
@@ -305,11 +305,8 @@ const cost_cli = {
|
|
|
305
305
|
USAGE,
|
|
306
306
|
parse_options,
|
|
307
307
|
to_threshold,
|
|
308
|
-
load_corpus: cost_corpus.load_corpus,
|
|
309
|
-
attributed: cost_corpus.attributed,
|
|
310
308
|
run,
|
|
311
309
|
session_verdict,
|
|
312
|
-
main,
|
|
313
310
|
}
|
|
314
311
|
|
|
315
312
|
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
@@ -265,11 +265,9 @@ function mainline_records(pairs: ReadonlyArray<AttributedRecord>): Array<Array<U
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
const cost_corpus = {
|
|
268
|
-
accumulate_missing,
|
|
269
268
|
load_corpus,
|
|
270
269
|
attribute_corpus,
|
|
271
270
|
floor_for_issue,
|
|
272
|
-
dedupe_across_sessions,
|
|
273
271
|
attributed,
|
|
274
272
|
mainline_records,
|
|
275
273
|
}
|
|
@@ -84,7 +84,7 @@ function main(argv: ReadonlyArray<string>): void {
|
|
|
84
84
|
process.exitCode = run(argv)
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
const delegation_cli = {
|
|
87
|
+
const delegation_cli = { print_list, run }
|
|
88
88
|
|
|
89
89
|
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
90
90
|
|
|
@@ -92,6 +92,17 @@ const DELEGATABLE_STEPS: ReadonlyArray<DelegatableStep> = [
|
|
|
92
92
|
verifier:
|
|
93
93
|
'the parent opens the cited lines; a conclusion those lines do not support fails there, and reading a handful of cited regions costs far less than redoing the reading. The unit reports what the code does and never what to change — deciding that is `diagnosis`, which stays kept, so a unit returning a root cause would be delegating the rejected row under this name',
|
|
94
94
|
},
|
|
95
|
+
{
|
|
96
|
+
name: 'lane-failure-investigation',
|
|
97
|
+
// The `backlogrun` parent's counterpart of `investigation` (joshuafolkken/kit#2947). The parent
|
|
98
|
+
// orchestrates and never implements, yet it read a failed lane's logs, records and sources in its
|
|
99
|
+
// own context — about 150 grep / cat / sed calls on 2026-10-02 — and every later request of the
|
|
100
|
+
// batch re-read them. The verifier is `investigation`'s, and so is the boundary: the unit reports
|
|
101
|
+
// what happened, and what the parent does about it (park, re-dispatch, file) stays its own call.
|
|
102
|
+
does: "find out why a lane's child stopped, failed or conflicted — its output log, run records, PR checks and the files they name — and return the conclusion plus the `file:line` or log-line citations that support it, never the text read, so the batch parent's context stays the size its orchestration needs",
|
|
103
|
+
verifier:
|
|
104
|
+
'the parent opens the cited lines and re-reads the child with `pnpm josh issue:state`; a conclusion those do not support fails there. The unit reports what happened and never what to do — parking, re-dispatching or filing stays with the parent, so a wrong account is caught before it is acted on',
|
|
105
|
+
},
|
|
95
106
|
]
|
|
96
107
|
|
|
97
108
|
// Steps that were considered and are **not** delegatable, kept as a list rather than dropped: the
|
|
@@ -170,7 +181,6 @@ const delegation_policy = {
|
|
|
170
181
|
REJECTED_STEPS,
|
|
171
182
|
find_step,
|
|
172
183
|
verdict_for,
|
|
173
|
-
rejection_for,
|
|
174
184
|
reason_for,
|
|
175
185
|
}
|
|
176
186
|
|
|
@@ -216,14 +216,6 @@ const { deny_envelope, DISABLED_VALUES } = hook_decision
|
|
|
216
216
|
const duplicate_reads = {
|
|
217
217
|
REASON,
|
|
218
218
|
NOTICE,
|
|
219
|
-
SWITCH_ENV_KEY,
|
|
220
|
-
is_candidate,
|
|
221
|
-
is_rearmed,
|
|
222
|
-
is_redundant_reread,
|
|
223
|
-
is_refusable_call,
|
|
224
|
-
is_unchanged_reread,
|
|
225
|
-
last_read_ms,
|
|
226
|
-
read_target,
|
|
227
219
|
}
|
|
228
220
|
|
|
229
221
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
@@ -54,7 +54,7 @@ function main(argv: ReadonlyArray<string>): void {
|
|
|
54
54
|
process.exitCode = run(argv)
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const fanout_cli = {
|
|
57
|
+
const fanout_cli = { parse_unit, run }
|
|
58
58
|
|
|
59
59
|
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
60
60
|
|