@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
|
@@ -17,10 +17,12 @@ import {
|
|
|
17
17
|
filing_cap,
|
|
18
18
|
gh_failure,
|
|
19
19
|
git_command,
|
|
20
|
+
git_common_directory,
|
|
20
21
|
git_gh_api_path,
|
|
21
22
|
git_gh_exec,
|
|
22
23
|
has_any_label,
|
|
23
24
|
has_stderr_field,
|
|
25
|
+
issue_cite,
|
|
24
26
|
lane_background,
|
|
25
27
|
lane_park,
|
|
26
28
|
lane_registry,
|
|
@@ -31,37 +33,36 @@ import {
|
|
|
31
33
|
repo_party,
|
|
32
34
|
run_carry,
|
|
33
35
|
run_cut,
|
|
36
|
+
run_headless,
|
|
34
37
|
run_hold,
|
|
35
|
-
run_progress_clock,
|
|
36
38
|
run_tail,
|
|
37
|
-
run_watcher_guard,
|
|
38
39
|
shell_segments,
|
|
39
40
|
tail_commands
|
|
40
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-UD24EAIL.js";
|
|
41
42
|
import {
|
|
42
43
|
find_local_bin_upwards
|
|
43
44
|
} from "./chunk-3V37IID6.js";
|
|
44
45
|
import {
|
|
45
46
|
batch_outcome
|
|
46
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-IL27YTPH.js";
|
|
47
48
|
import {
|
|
48
49
|
investigation_refusal
|
|
49
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-KHWHKJOM.js";
|
|
50
51
|
import {
|
|
51
52
|
duplicate_read_outcome
|
|
52
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-3C4YCCEF.js";
|
|
53
54
|
import {
|
|
54
55
|
investigation_reads
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-7ZPFAVR7.js";
|
|
56
57
|
import {
|
|
57
58
|
lane_guard_policy,
|
|
58
59
|
time_batch_guard
|
|
59
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-O4LL4HTI.js";
|
|
60
61
|
import {
|
|
61
62
|
hook_decision,
|
|
62
63
|
lane_child_marker,
|
|
63
64
|
run_issue_number
|
|
64
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-E54KGFEQ.js";
|
|
65
66
|
import {
|
|
66
67
|
PLATFORM_TEMP_ROOT,
|
|
67
68
|
cost_attribute,
|
|
@@ -73,14 +74,10 @@ import {
|
|
|
73
74
|
lane_paths,
|
|
74
75
|
stamp_file,
|
|
75
76
|
time_shell
|
|
76
|
-
} from "./chunk-
|
|
77
|
-
|
|
78
|
-
// scripts/hooks/pretool-guard.ts
|
|
79
|
-
import { text } from "node:stream/consumers";
|
|
80
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
77
|
+
} from "./chunk-NKOG3XAV.js";
|
|
81
78
|
|
|
82
79
|
// scripts/rules/direct-filing.ts
|
|
83
|
-
var DIRECT_FILING_REASON = '\u26D4 direct filing: an Issue is filed with `pnpm josh issue:file "<title>" --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>]`, never with `gh api \u2026/issues` or `gh issue create`. The command runs every filing step in order \u2014 the duplicate scout, the body lint and its classification labels, the depth and `route:` labels, the `## Origin` check when filing into another repository, and `epic:bundle` after the create \u2014 so none of them is a step to remember. When the scout prints candidates it holds the filing: read each, then reissue with `--distinct <N,\u2026>` for the ones that are separate deliverables. Reference: `docs/josh-commands.md` \u2192 "`josh issue:file`". **This rule fires on every occurrence, not once per run.**';
|
|
80
|
+
var DIRECT_FILING_REASON = '\u26D4 direct filing: an Issue is filed with `pnpm josh issue:file "<title>" --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>]`, never with `gh api \u2026/issues` or `gh issue create`. The command runs every filing step in order \u2014 the duplicate scout, the body lint and its classification labels, the depth and `route:` labels, the `## Origin` check when filing into another repository, and `epic:bundle` after the create \u2014 so none of them is a step to remember. When the scout prints candidates it holds the filing: read each, then reissue with `--distinct <N,\u2026>` for the ones that are separate deliverables. Reference: `docs/josh-commands-automation.md` \u2192 "`josh issue:file`". **This rule fires on every occurrence, not once per run.**';
|
|
84
81
|
function is_any_filing(command) {
|
|
85
82
|
return bash_triggers.is_direct_filing(command) || bash_triggers.is_issue_filing(command);
|
|
86
83
|
}
|
|
@@ -138,17 +135,19 @@ function next_state(previous, key, now_ms) {
|
|
|
138
135
|
if (previous?.key === key) return previous;
|
|
139
136
|
return { key, unchanged_since_ms: now_ms };
|
|
140
137
|
}
|
|
141
|
-
function format_child(child) {
|
|
138
|
+
function format_child(child, cite) {
|
|
142
139
|
const labels = child.labels.length > 0 ? child.labels.join(",") : "(no labels)";
|
|
143
|
-
return
|
|
140
|
+
return `${cite(child.issue)} ${labels} PR:${child.pr_state}`;
|
|
144
141
|
}
|
|
145
|
-
function format_children(children) {
|
|
142
|
+
function format_children(children, repo) {
|
|
146
143
|
if (children.length === 0) return NO_CHILD_YET;
|
|
147
|
-
|
|
144
|
+
const cite = issue_cite.citer(repo, new Map(children.map((child) => [child.issue, child.title])));
|
|
145
|
+
return children.map((child) => format_child(child, cite)).join(" \xB7 ");
|
|
148
146
|
}
|
|
149
|
-
function format_lanes(lanes) {
|
|
147
|
+
function format_lanes(lanes, repo) {
|
|
150
148
|
if (lanes.length === 0) return NO_LANES;
|
|
151
|
-
|
|
149
|
+
const cite = issue_cite.citer(repo, /* @__PURE__ */ new Map());
|
|
150
|
+
return lanes.map((lane) => `${cite(lane.issue)}:${lane.state}`).join(" ");
|
|
152
151
|
}
|
|
153
152
|
function format_record(record_age_ms) {
|
|
154
153
|
return record_age_ms === void 0 ? "unread" : `+${format_minutes(record_age_ms)}`;
|
|
@@ -173,8 +172,8 @@ function format_line(observations, timing) {
|
|
|
173
172
|
observed_at: format_observed_at(timing.now_ms),
|
|
174
173
|
quiet: format_minutes(timing.now_ms - timing.quiet_since_ms),
|
|
175
174
|
unchanged: format_minutes(timing.now_ms - timing.unchanged_since_ms),
|
|
176
|
-
children: format_children(observations.children),
|
|
177
|
-
lanes: format_lanes(observations.lanes),
|
|
175
|
+
children: format_children(observations.children, observations.repo),
|
|
176
|
+
lanes: format_lanes(observations.lanes, observations.repo),
|
|
178
177
|
load: observations.load_average.toFixed(1),
|
|
179
178
|
record: format_record(observations.record_age_ms),
|
|
180
179
|
next: format_next_report(timing.now_ms, timing.interval_ms)
|
|
@@ -204,7 +203,6 @@ var run_progress = {
|
|
|
204
203
|
format_line,
|
|
205
204
|
format_next_line,
|
|
206
205
|
format_next_report,
|
|
207
|
-
format_record,
|
|
208
206
|
format_report,
|
|
209
207
|
is_due,
|
|
210
208
|
minutes_from,
|
|
@@ -212,16 +210,139 @@ var run_progress = {
|
|
|
212
210
|
observation_key
|
|
213
211
|
};
|
|
214
212
|
|
|
213
|
+
// scripts/run/run-progress-clock.ts
|
|
214
|
+
import { z } from "zod";
|
|
215
|
+
var PROGRESS_PREFIX = "josh-run-progress-";
|
|
216
|
+
var LIFE_PREFIX = "josh-run-progress-life-";
|
|
217
|
+
var LOG_SUFFIX = ".log";
|
|
218
|
+
var LOG_KEEP = 12;
|
|
219
|
+
var MS_PER_MINUTE2 = 6e4;
|
|
220
|
+
var LOG_STALE_MINUTES = 90;
|
|
221
|
+
var LOG_STALE_MS = LOG_STALE_MINUTES * MS_PER_MINUTE2;
|
|
222
|
+
var BLOCK_SEPARATOR = "\n\n";
|
|
223
|
+
var report_stamp_schema = z.object({ reported_at: z.string(), line: z.string().optional() });
|
|
224
|
+
function parse_stamp(raw) {
|
|
225
|
+
const parsed = report_stamp_schema.safeParse(JSON.parse(raw));
|
|
226
|
+
if (!parsed.success) return void 0;
|
|
227
|
+
const reported_at = Date.parse(parsed.data.reported_at);
|
|
228
|
+
return Number.isNaN(reported_at) ? void 0 : reported_at;
|
|
229
|
+
}
|
|
230
|
+
function read_last_line(target) {
|
|
231
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
232
|
+
if (raw === void 0) return void 0;
|
|
233
|
+
try {
|
|
234
|
+
return report_stamp_schema.safeParse(JSON.parse(raw)).data?.line;
|
|
235
|
+
} catch {
|
|
236
|
+
return void 0;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function read_last_report(target) {
|
|
240
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
241
|
+
if (raw === void 0) return void 0;
|
|
242
|
+
try {
|
|
243
|
+
return parse_stamp(raw);
|
|
244
|
+
} catch {
|
|
245
|
+
return void 0;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function log_path_of(target) {
|
|
249
|
+
return `${target}${LOG_SUFFIX}`;
|
|
250
|
+
}
|
|
251
|
+
function is_log_stale(target, now_ms) {
|
|
252
|
+
const previous_ms = read_last_report(target);
|
|
253
|
+
return previous_ms === void 0 || now_ms - previous_ms > LOG_STALE_MS;
|
|
254
|
+
}
|
|
255
|
+
function recent_blocks(log_target2, is_fresh) {
|
|
256
|
+
if (is_fresh) return [];
|
|
257
|
+
const raw = stamp_file.read_stamp_text(log_target2);
|
|
258
|
+
if (raw === void 0) return [];
|
|
259
|
+
return raw.split(BLOCK_SEPARATOR).map((block) => block.trimEnd()).filter((block) => block.length > 0);
|
|
260
|
+
}
|
|
261
|
+
function append_line(log_target2, reported_at, line, is_fresh) {
|
|
262
|
+
const block = `${reported_at}
|
|
263
|
+
${line}`;
|
|
264
|
+
const blocks = [...recent_blocks(log_target2, is_fresh), block].slice(-LOG_KEEP);
|
|
265
|
+
stamp_file.write_text_stamp(log_target2, `${blocks.join(BLOCK_SEPARATOR)}
|
|
266
|
+
`);
|
|
267
|
+
}
|
|
268
|
+
function mark(target, now_ms, line) {
|
|
269
|
+
const reported_at = new Date(now_ms).toISOString();
|
|
270
|
+
const kept = line ?? read_last_line(target);
|
|
271
|
+
if (line !== void 0) {
|
|
272
|
+
append_line(log_path_of(target), reported_at, line, is_log_stale(target, now_ms));
|
|
273
|
+
}
|
|
274
|
+
stamp_file.write_stamp(target, kept === void 0 ? { reported_at } : { reported_at, line: kept });
|
|
275
|
+
}
|
|
276
|
+
function stamp_target_of(git_directory) {
|
|
277
|
+
return stamp_file.stamp_path(PROGRESS_PREFIX, git_directory);
|
|
278
|
+
}
|
|
279
|
+
function life_target_of(git_directory) {
|
|
280
|
+
return stamp_file.stamp_path(LIFE_PREFIX, git_directory);
|
|
281
|
+
}
|
|
282
|
+
var life_schema = z.object({ alive: z.literal(true), pinged_at: z.string().optional() });
|
|
283
|
+
function begin_life(target) {
|
|
284
|
+
stamp_file.write_stamp(target, { alive: true, pinged_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
285
|
+
}
|
|
286
|
+
function ping_life(target) {
|
|
287
|
+
begin_life(target);
|
|
288
|
+
}
|
|
289
|
+
function parse_pinged_at(raw) {
|
|
290
|
+
const parsed = life_schema.safeParse(JSON.parse(raw));
|
|
291
|
+
if (!parsed.success || parsed.data.pinged_at === void 0) return void 0;
|
|
292
|
+
const pinged_ms = Date.parse(parsed.data.pinged_at);
|
|
293
|
+
return Number.isNaN(pinged_ms) ? void 0 : pinged_ms;
|
|
294
|
+
}
|
|
295
|
+
function is_life_fresh(target, threshold_ms) {
|
|
296
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
297
|
+
if (raw === void 0) return false;
|
|
298
|
+
try {
|
|
299
|
+
const pinged_ms = parse_pinged_at(raw);
|
|
300
|
+
return pinged_ms !== void 0 && Date.now() - pinged_ms < threshold_ms;
|
|
301
|
+
} catch {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function is_life_ended(target) {
|
|
306
|
+
return stamp_file.read_stamp_text(target) === void 0;
|
|
307
|
+
}
|
|
308
|
+
function end_life(target) {
|
|
309
|
+
stamp_file.remove_stamp(target);
|
|
310
|
+
}
|
|
311
|
+
function stamp_target_sync() {
|
|
312
|
+
const directory = git_common_directory.own();
|
|
313
|
+
return directory === void 0 ? void 0 : stamp_target_of(directory);
|
|
314
|
+
}
|
|
315
|
+
function read_last_report_sync() {
|
|
316
|
+
const target = stamp_target_sync();
|
|
317
|
+
return target === void 0 ? void 0 : read_last_report(target);
|
|
318
|
+
}
|
|
319
|
+
var run_progress_clock = {
|
|
320
|
+
LIFE_PREFIX,
|
|
321
|
+
LOG_KEEP,
|
|
322
|
+
LOG_STALE_MS,
|
|
323
|
+
begin_life,
|
|
324
|
+
end_life,
|
|
325
|
+
is_life_ended,
|
|
326
|
+
is_life_fresh,
|
|
327
|
+
life_target_of,
|
|
328
|
+
log_path_of,
|
|
329
|
+
mark,
|
|
330
|
+
parse_stamp,
|
|
331
|
+
ping_life,
|
|
332
|
+
read_last_line,
|
|
333
|
+
read_last_report,
|
|
334
|
+
read_last_report_sync,
|
|
335
|
+
stamp_target_of
|
|
336
|
+
};
|
|
337
|
+
|
|
215
338
|
// scripts/run/run-progress-config.ts
|
|
216
339
|
import { readFileSync } from "node:fs";
|
|
217
340
|
import path from "node:path";
|
|
218
|
-
import { z } from "zod";
|
|
341
|
+
import { z as z2 } from "zod";
|
|
219
342
|
var PACKAGE_FILE = "package.json";
|
|
220
|
-
var CONFIG_FIELD = "josh";
|
|
221
|
-
var INTERVAL_FIELD = "progress_interval_minutes";
|
|
222
343
|
var MAX_DEPTH = 10;
|
|
223
|
-
var package_schema =
|
|
224
|
-
josh:
|
|
344
|
+
var package_schema = z2.object({
|
|
345
|
+
josh: z2.object({ progress_interval_minutes: z2.number().positive() }).optional()
|
|
225
346
|
});
|
|
226
347
|
function ancestors_of(start) {
|
|
227
348
|
const directories = [];
|
|
@@ -258,8 +379,6 @@ function configured_interval_ms(directory = process.cwd()) {
|
|
|
258
379
|
return resolve_interval_ms(void 0, directory);
|
|
259
380
|
}
|
|
260
381
|
var run_progress_config = {
|
|
261
|
-
CONFIG_FIELD,
|
|
262
|
-
INTERVAL_FIELD,
|
|
263
382
|
PACKAGE_FILE,
|
|
264
383
|
configured_interval_ms,
|
|
265
384
|
read_package_minutes,
|
|
@@ -406,10 +525,7 @@ var ROW2 = {
|
|
|
406
525
|
var file_body = {
|
|
407
526
|
FILE_BODY_REASON,
|
|
408
527
|
ROW: ROW2,
|
|
409
|
-
carries_a_file_body
|
|
410
|
-
is_in_place_perl,
|
|
411
|
-
is_interpreter_write,
|
|
412
|
-
writes_existing_file
|
|
528
|
+
carries_a_file_body
|
|
413
529
|
};
|
|
414
530
|
|
|
415
531
|
// scripts/rules/gh-api.ts
|
|
@@ -424,8 +540,11 @@ var REPO_GROUP = 2;
|
|
|
424
540
|
function is_gh_api(segment) {
|
|
425
541
|
return GH_API_COMMAND.test(segment);
|
|
426
542
|
}
|
|
543
|
+
function method_of(segment) {
|
|
544
|
+
return API_METHOD.exec(segment)?.[1]?.toUpperCase();
|
|
545
|
+
}
|
|
427
546
|
function is_read(segment) {
|
|
428
|
-
const method =
|
|
547
|
+
const method = method_of(segment);
|
|
429
548
|
if (method !== void 0) return method.toUpperCase() === READ_METHOD;
|
|
430
549
|
return !API_FIELD.test(segment);
|
|
431
550
|
}
|
|
@@ -437,7 +556,7 @@ function repo_target(segment) {
|
|
|
437
556
|
if (match === null) return void 0;
|
|
438
557
|
return { owner: match[OWNER_GROUP] ?? "", repo: match[REPO_GROUP] ?? "" };
|
|
439
558
|
}
|
|
440
|
-
var gh_api = {
|
|
559
|
+
var gh_api = { GH_FLAGS, is_gh_api, is_read, is_write, method_of, repo_target };
|
|
441
560
|
|
|
442
561
|
// scripts/rules/git-argv.ts
|
|
443
562
|
var ENV_ASSIGNMENT = /^[A-Za-z_]\w*=/u;
|
|
@@ -447,7 +566,8 @@ var WRAPPER_WORDS = /* @__PURE__ */ new Set([
|
|
|
447
566
|
"exec",
|
|
448
567
|
"run",
|
|
449
568
|
"sudo",
|
|
450
|
-
"command"
|
|
569
|
+
"command",
|
|
570
|
+
"env"
|
|
451
571
|
]);
|
|
452
572
|
var SUBSHELL_OPEN = "(";
|
|
453
573
|
var VALUE_TAKING_GLOBALS = /* @__PURE__ */ new Set([
|
|
@@ -487,11 +607,15 @@ function after_globals(words, start) {
|
|
|
487
607
|
}
|
|
488
608
|
return index;
|
|
489
609
|
}
|
|
490
|
-
function
|
|
610
|
+
function arguments_of(segment, command) {
|
|
491
611
|
const words = words_of(segment);
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
|
|
612
|
+
const command_index = after_wrapper(words);
|
|
613
|
+
return words[command_index] === command ? words.slice(command_index + NEXT) : void 0;
|
|
614
|
+
}
|
|
615
|
+
function parse(segment) {
|
|
616
|
+
const words = arguments_of(segment, GIT_COMMAND);
|
|
617
|
+
if (words === void 0) return void 0;
|
|
618
|
+
const subcommand_index = after_globals(words, 0);
|
|
495
619
|
return { subcommand: words[subcommand_index], args: words.slice(subcommand_index + NEXT) };
|
|
496
620
|
}
|
|
497
621
|
var SHORT_CLUSTER = /^-[A-Za-z]+$/u;
|
|
@@ -503,7 +627,7 @@ function short_cluster_has(token, letters) {
|
|
|
503
627
|
}
|
|
504
628
|
return false;
|
|
505
629
|
}
|
|
506
|
-
var git_argv = { parse, short_cluster_has
|
|
630
|
+
var git_argv = { arguments_of, parse, short_cluster_has };
|
|
507
631
|
|
|
508
632
|
// scripts/rules/git-force.ts
|
|
509
633
|
var FORCE_LONG_PREFIX = "--force";
|
|
@@ -542,9 +666,7 @@ var ROW3 = {
|
|
|
542
666
|
var git_force = {
|
|
543
667
|
GIT_FORCE_REASON,
|
|
544
668
|
ROW: ROW3,
|
|
545
|
-
|
|
546
|
-
is_force_or_delete,
|
|
547
|
-
is_force_or_delete_push
|
|
669
|
+
is_force_or_delete
|
|
548
670
|
};
|
|
549
671
|
|
|
550
672
|
// scripts/cost-runtime/cost-cli.ts
|
|
@@ -554,30 +676,23 @@ import { parseArgs } from "node:util";
|
|
|
554
676
|
// scripts/cost-runtime/codex-usage.ts
|
|
555
677
|
import { globSync, readFileSync as readFileSync2 } from "node:fs";
|
|
556
678
|
import path2 from "node:path";
|
|
557
|
-
import { z as
|
|
679
|
+
import { z as z3 } from "zod";
|
|
558
680
|
var THREAD_ID_PATTERN = /^[A-Za-z0-9-]+$/u;
|
|
559
|
-
var SESSION_META_SCHEMA =
|
|
560
|
-
type:
|
|
561
|
-
payload:
|
|
681
|
+
var SESSION_META_SCHEMA = z3.looseObject({
|
|
682
|
+
type: z3.literal("session_meta"),
|
|
683
|
+
payload: z3.looseObject({ id: z3.string(), cwd: z3.string() })
|
|
562
684
|
});
|
|
563
|
-
var TOTAL_USAGE_SCHEMA =
|
|
564
|
-
var TOKEN_COUNT_SCHEMA =
|
|
565
|
-
type:
|
|
566
|
-
payload:
|
|
567
|
-
type:
|
|
568
|
-
info:
|
|
685
|
+
var TOTAL_USAGE_SCHEMA = z3.looseObject({ input_tokens: z3.number().nonnegative() });
|
|
686
|
+
var TOKEN_COUNT_SCHEMA = z3.looseObject({
|
|
687
|
+
type: z3.literal("event_msg"),
|
|
688
|
+
payload: z3.looseObject({
|
|
689
|
+
type: z3.literal("token_count"),
|
|
690
|
+
info: z3.looseObject({
|
|
569
691
|
total_token_usage: TOTAL_USAGE_SCHEMA,
|
|
570
692
|
last_token_usage: TOTAL_USAGE_SCHEMA
|
|
571
693
|
})
|
|
572
694
|
})
|
|
573
695
|
});
|
|
574
|
-
function decode(line) {
|
|
575
|
-
try {
|
|
576
|
-
return JSON.parse(line);
|
|
577
|
-
} catch {
|
|
578
|
-
return void 0;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
696
|
function same_project(cwd, target) {
|
|
582
697
|
return cost_transcript.session_cwd(cwd) === cost_transcript.session_cwd(target);
|
|
583
698
|
}
|
|
@@ -585,7 +700,7 @@ function billed_per_request(usages) {
|
|
|
585
700
|
return usages.map((usage) => usage.last_token_usage.input_tokens);
|
|
586
701
|
}
|
|
587
702
|
function measurement_from(content, target, thread_id) {
|
|
588
|
-
const values = content.split("\n").map((line) =>
|
|
703
|
+
const values = content.split("\n").map((line) => json_value.parse_or_undefined(line));
|
|
589
704
|
const metadata = values.flatMap((value) => {
|
|
590
705
|
const parsed = SESSION_META_SCHEMA.safeParse(value);
|
|
591
706
|
return parsed.success ? [parsed.data] : [];
|
|
@@ -736,11 +851,9 @@ function mainline_records(pairs) {
|
|
|
736
851
|
return [...groups.values()];
|
|
737
852
|
}
|
|
738
853
|
var cost_corpus = {
|
|
739
|
-
accumulate_missing,
|
|
740
854
|
load_corpus,
|
|
741
855
|
attribute_corpus,
|
|
742
856
|
floor_for_issue,
|
|
743
|
-
dedupe_across_sessions,
|
|
744
857
|
attributed,
|
|
745
858
|
mainline_records
|
|
746
859
|
};
|
|
@@ -830,8 +943,8 @@ function selected_threshold(values) {
|
|
|
830
943
|
function threshold_option(over) {
|
|
831
944
|
return over === void 0 ? {} : { over };
|
|
832
945
|
}
|
|
833
|
-
function path_option(
|
|
834
|
-
return
|
|
946
|
+
function path_option(path10) {
|
|
947
|
+
return path10 === void 0 ? {} : { path: path10 };
|
|
835
948
|
}
|
|
836
949
|
function to_options(values) {
|
|
837
950
|
if (values.cut === true && values.over !== void 0) return void 0;
|
|
@@ -947,11 +1060,8 @@ var cost_cli = {
|
|
|
947
1060
|
USAGE,
|
|
948
1061
|
parse_options,
|
|
949
1062
|
to_threshold,
|
|
950
|
-
load_corpus: cost_corpus.load_corpus,
|
|
951
|
-
attributed: cost_corpus.attributed,
|
|
952
1063
|
run,
|
|
953
|
-
session_verdict
|
|
954
|
-
main
|
|
1064
|
+
session_verdict
|
|
955
1065
|
};
|
|
956
1066
|
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET));
|
|
957
1067
|
|
|
@@ -970,16 +1080,13 @@ function format_share(part, whole) {
|
|
|
970
1080
|
return `${(part / whole * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`;
|
|
971
1081
|
}
|
|
972
1082
|
var cost_format = {
|
|
973
|
-
USD_DECIMALS,
|
|
974
|
-
PERCENT_SCALE,
|
|
975
|
-
PERCENT_DECIMALS,
|
|
976
1083
|
format_usd,
|
|
977
1084
|
format_tokens,
|
|
978
1085
|
format_share
|
|
979
1086
|
};
|
|
980
1087
|
|
|
981
1088
|
// scripts/rules/implementation-cut-verdict.ts
|
|
982
|
-
import { z as
|
|
1089
|
+
import { z as z4 } from "zod";
|
|
983
1090
|
var VERDICT_CACHE_PREFIX = "josh-impl-cut-verdict-";
|
|
984
1091
|
var VERDICT_REUSE_MS = 5e3;
|
|
985
1092
|
var VERDICT_VALUES = [
|
|
@@ -987,7 +1094,7 @@ var VERDICT_VALUES = [
|
|
|
987
1094
|
"under",
|
|
988
1095
|
"unmeasurable"
|
|
989
1096
|
];
|
|
990
|
-
var cache_schema =
|
|
1097
|
+
var cache_schema = z4.object({ read_at_ms: z4.number(), verdict: z4.enum(VERDICT_VALUES) });
|
|
991
1098
|
function cache_path(directory) {
|
|
992
1099
|
return stamp_file.stamp_path(VERDICT_CACHE_PREFIX, directory);
|
|
993
1100
|
}
|
|
@@ -1083,7 +1190,6 @@ var implementation_cut = {
|
|
|
1083
1190
|
REISSUE_WINDOW_MS,
|
|
1084
1191
|
ROW: ROW4,
|
|
1085
1192
|
decide: decide2,
|
|
1086
|
-
is_edit_tool,
|
|
1087
1193
|
is_over_threshold_edit,
|
|
1088
1194
|
is_reissued_refusal,
|
|
1089
1195
|
takes_the_impl_cut,
|
|
@@ -1159,20 +1265,20 @@ var lane_carry_conflict = {
|
|
|
1159
1265
|
};
|
|
1160
1266
|
|
|
1161
1267
|
// scripts/agent/interactive-ask.ts
|
|
1162
|
-
import { z as
|
|
1268
|
+
import { z as z5 } from "zod";
|
|
1163
1269
|
var INTERACTIVE_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion"]);
|
|
1164
1270
|
function is_interactive_tool(name) {
|
|
1165
1271
|
return INTERACTIVE_TOOLS.has(name);
|
|
1166
1272
|
}
|
|
1167
|
-
var OPTION_SCHEMA =
|
|
1168
|
-
var QUESTION_SCHEMA =
|
|
1169
|
-
question:
|
|
1170
|
-
options:
|
|
1273
|
+
var OPTION_SCHEMA = z5.looseObject({ label: z5.string().optional() });
|
|
1274
|
+
var QUESTION_SCHEMA = z5.looseObject({
|
|
1275
|
+
question: z5.string().optional(),
|
|
1276
|
+
options: z5.array(OPTION_SCHEMA).optional()
|
|
1171
1277
|
});
|
|
1172
|
-
var ASK_INPUT_SCHEMA =
|
|
1173
|
-
var DENIAL_SCHEMA =
|
|
1174
|
-
tool_name:
|
|
1175
|
-
tool_input:
|
|
1278
|
+
var ASK_INPUT_SCHEMA = z5.looseObject({ questions: z5.array(QUESTION_SCHEMA).optional() });
|
|
1279
|
+
var DENIAL_SCHEMA = z5.looseObject({
|
|
1280
|
+
tool_name: z5.string().optional(),
|
|
1281
|
+
tool_input: z5.unknown().optional()
|
|
1176
1282
|
});
|
|
1177
1283
|
var UNKNOWN_QUESTION = "(question text unavailable)";
|
|
1178
1284
|
var OPTION_SEPARATOR = " / ";
|
|
@@ -1182,8 +1288,8 @@ function labels_of(question) {
|
|
|
1182
1288
|
}
|
|
1183
1289
|
function render_question(question) {
|
|
1184
1290
|
const labels = labels_of(question);
|
|
1185
|
-
const
|
|
1186
|
-
return labels.length === 0 ?
|
|
1291
|
+
const text = question.question ?? UNKNOWN_QUESTION;
|
|
1292
|
+
return labels.length === 0 ? text : `${text} [${labels.join(OPTION_SEPARATOR)}]`;
|
|
1187
1293
|
}
|
|
1188
1294
|
function interactive_input(raw) {
|
|
1189
1295
|
const denial = DENIAL_SCHEMA.safeParse(raw);
|
|
@@ -1198,7 +1304,7 @@ function refused_ask_of(permission_denials) {
|
|
|
1198
1304
|
if (questions.length === 0) return void 0;
|
|
1199
1305
|
return questions.map((question) => render_question(question)).join(QUESTION_SEPARATOR);
|
|
1200
1306
|
}
|
|
1201
|
-
var interactive_ask = {
|
|
1307
|
+
var interactive_ask = { is_interactive_tool, refused_ask_of };
|
|
1202
1308
|
|
|
1203
1309
|
// scripts/rules/lane-interactive-ask.ts
|
|
1204
1310
|
function is_interactive_ask(call, is_lane_child = lane_child_marker.is_child_of(process.cwd())) {
|
|
@@ -1257,6 +1363,108 @@ var lane_switch_main = {
|
|
|
1257
1363
|
switch_targets
|
|
1258
1364
|
};
|
|
1259
1365
|
|
|
1366
|
+
// scripts/run/run-stage.ts
|
|
1367
|
+
var KICKOFF = "kickoff";
|
|
1368
|
+
var HALFRUN = "halfrun";
|
|
1369
|
+
var PRRUN = "prrun";
|
|
1370
|
+
var FULLRUN = "fullrun";
|
|
1371
|
+
var COMMANDS = [KICKOFF, HALFRUN, PRRUN, FULLRUN];
|
|
1372
|
+
var DEFAULT_COMMAND = FULLRUN;
|
|
1373
|
+
var FRESH = "fresh";
|
|
1374
|
+
var PLANNED = "planned";
|
|
1375
|
+
var HALFRUN_STOPPED = "halfrun-stopped";
|
|
1376
|
+
var PRRUN_STOPPED = "prrun-stopped";
|
|
1377
|
+
var MERGED = "merged";
|
|
1378
|
+
var STATES = [FRESH, PLANNED, HALFRUN_STOPPED, PRRUN_STOPPED, MERGED];
|
|
1379
|
+
var REACHED = "reached";
|
|
1380
|
+
var STARTS = {
|
|
1381
|
+
[FRESH]: "plan",
|
|
1382
|
+
[PLANNED]: "implement",
|
|
1383
|
+
[HALFRUN_STOPPED]: "gate",
|
|
1384
|
+
[PRRUN_STOPPED]: "followup",
|
|
1385
|
+
[MERGED]: REACHED
|
|
1386
|
+
};
|
|
1387
|
+
var START_TOKENS = [...new Set(Object.values(STARTS))];
|
|
1388
|
+
var ENDS = {
|
|
1389
|
+
[KICKOFF]: "plan posted",
|
|
1390
|
+
[HALFRUN]: "gated, before the commit",
|
|
1391
|
+
[PRRUN]: "green, mergeable PR",
|
|
1392
|
+
[FULLRUN]: "merged"
|
|
1393
|
+
};
|
|
1394
|
+
var NEXT_PREFIX = "Next: ";
|
|
1395
|
+
var NEXT_SEPARATOR = " | ";
|
|
1396
|
+
var STATE_HEADER = "Issue state";
|
|
1397
|
+
var CELL_ARROW = " \u2192 ";
|
|
1398
|
+
var REACHED_CELL = "reached \u2014 report and stop";
|
|
1399
|
+
function to_command(value) {
|
|
1400
|
+
return COMMANDS.find((command) => command === value);
|
|
1401
|
+
}
|
|
1402
|
+
function state_of(facts) {
|
|
1403
|
+
if (facts.is_closed) return MERGED;
|
|
1404
|
+
if (facts.is_prrun_stopped) return PRRUN_STOPPED;
|
|
1405
|
+
if (facts.is_halfrun_stopped) return HALFRUN_STOPPED;
|
|
1406
|
+
return facts.is_planned ? PLANNED : FRESH;
|
|
1407
|
+
}
|
|
1408
|
+
function decide3(state, command) {
|
|
1409
|
+
const is_reached = STATES.indexOf(state) > COMMANDS.indexOf(command);
|
|
1410
|
+
const start = is_reached ? REACHED : STARTS[state];
|
|
1411
|
+
return { state, command, start, end: ENDS[command], is_reached };
|
|
1412
|
+
}
|
|
1413
|
+
function next_commands(command) {
|
|
1414
|
+
return COMMANDS.slice(COMMANDS.indexOf(command) + 1);
|
|
1415
|
+
}
|
|
1416
|
+
function next_line(command, issue) {
|
|
1417
|
+
const commands = next_commands(command).map((next) => `${next} #${issue}`);
|
|
1418
|
+
return `${NEXT_PREFIX}${commands.join(NEXT_SEPARATOR)}`;
|
|
1419
|
+
}
|
|
1420
|
+
function format_decision(issue, decision) {
|
|
1421
|
+
const fields = [`at: ${decision.state}`, `to: ${decision.command}`, `start: ${decision.start}`];
|
|
1422
|
+
return `stage #${issue} \u2014 ${fields.join(" \xB7 ")}`;
|
|
1423
|
+
}
|
|
1424
|
+
function cell(state, command) {
|
|
1425
|
+
const decision = decide3(state, command);
|
|
1426
|
+
return decision.is_reached ? REACHED_CELL : `${decision.start}${CELL_ARROW}${decision.end}`;
|
|
1427
|
+
}
|
|
1428
|
+
function table_rows() {
|
|
1429
|
+
const header = [STATE_HEADER, ...COMMANDS.map((command) => `\`${command}\``)];
|
|
1430
|
+
const rows = STATES.map((state) => [
|
|
1431
|
+
`\`${state}\``,
|
|
1432
|
+
...COMMANDS.map((command) => cell(state, command))
|
|
1433
|
+
]);
|
|
1434
|
+
return [header, ...rows];
|
|
1435
|
+
}
|
|
1436
|
+
var run_stage = {
|
|
1437
|
+
COMMANDS,
|
|
1438
|
+
DEFAULT_COMMAND,
|
|
1439
|
+
FRESH,
|
|
1440
|
+
HALFRUN,
|
|
1441
|
+
HALFRUN_STOPPED,
|
|
1442
|
+
KICKOFF,
|
|
1443
|
+
MERGED,
|
|
1444
|
+
PLANNED,
|
|
1445
|
+
PRRUN,
|
|
1446
|
+
PRRUN_STOPPED,
|
|
1447
|
+
REACHED,
|
|
1448
|
+
START_TOKENS,
|
|
1449
|
+
STATES,
|
|
1450
|
+
decide: decide3,
|
|
1451
|
+
format_decision,
|
|
1452
|
+
next_commands,
|
|
1453
|
+
next_line,
|
|
1454
|
+
state_of,
|
|
1455
|
+
table_rows,
|
|
1456
|
+
to_command
|
|
1457
|
+
};
|
|
1458
|
+
|
|
1459
|
+
// scripts/rules/decision-oracle-stage.ts
|
|
1460
|
+
var RUN_ENTRY_ORACLE = {
|
|
1461
|
+
name: "run:entry",
|
|
1462
|
+
decision: "Where a run on an issue starts, and whether the typed command has already been reached",
|
|
1463
|
+
args: "<N> [--to kickoff|halfrun|prrun|fullrun]",
|
|
1464
|
+
vocabulary: run_stage.START_TOKENS,
|
|
1465
|
+
single_source: ".claude/skills/workflow-commands/SKILL.md \u2192 \xA72k"
|
|
1466
|
+
};
|
|
1467
|
+
|
|
1260
1468
|
// scripts/rules/decision-oracle.ts
|
|
1261
1469
|
var CHAIN_RULE_MD = ".claude/skills/workflow-commands/chain-rule.md";
|
|
1262
1470
|
var BACKLOGRUN_PROGRESS_MD = ".claude/skills/workflow-commands/backlogrun-progress.md";
|
|
@@ -1264,11 +1472,11 @@ var SKILL_2E = ".claude/skills/workflow-commands/SKILL.md \u2192 \xA72e";
|
|
|
1264
1472
|
var SPLIT_ASSESSMENT_QUESTION = ".claude/skills/workflow-commands/split-assessment.md \u2192 The question";
|
|
1265
1473
|
var PRE_GATE_CUT_MD = ".claude/skills/workflow-commands/pre-gate-cut.md";
|
|
1266
1474
|
var BACKLOGRUN_MD = ".claude/skills/workflow-commands/backlogrun.md";
|
|
1267
|
-
var RUN_MERGE_REFERENCE = "docs/josh-commands.md \u2192 `josh run:merge`";
|
|
1268
|
-
var EPIC_NEXT_REFERENCE = "docs/josh-commands.md \u2192 `josh epic:next`";
|
|
1269
|
-
var BACKLOG_BUDGET_REFERENCE = "docs/josh-commands.md \u2192 `josh backlog:budget`";
|
|
1270
|
-
var RUN_LIVENESS_REFERENCE = "docs/josh-commands.md \u2192 `josh run:liveness`";
|
|
1271
|
-
var AUTO_OK_NEXT_REFERENCE = "docs/josh-commands.md \u2192 `josh auto-ok:next`";
|
|
1475
|
+
var RUN_MERGE_REFERENCE = "docs/josh-commands-automation.md \u2192 `josh run:merge`";
|
|
1476
|
+
var EPIC_NEXT_REFERENCE = "docs/josh-commands-automation.md \u2192 `josh epic:next`";
|
|
1477
|
+
var BACKLOG_BUDGET_REFERENCE = "docs/josh-commands-automation.md \u2192 `josh backlog:budget`";
|
|
1478
|
+
var RUN_LIVENESS_REFERENCE = "docs/josh-commands-automation.md \u2192 `josh run:liveness`";
|
|
1479
|
+
var AUTO_OK_NEXT_REFERENCE = "docs/josh-commands-automation.md \u2192 `josh auto-ok:next`";
|
|
1272
1480
|
var RUN_CUT_CMD = "run:cut";
|
|
1273
1481
|
var REQUIRED = "required";
|
|
1274
1482
|
var SKIP = "skip";
|
|
@@ -1520,15 +1728,16 @@ var DECISION_ORACLES = [
|
|
|
1520
1728
|
decision: "Whether an epic's declaration matches its recorded relations, and the repair when it does not",
|
|
1521
1729
|
args: "--reconcile <E>",
|
|
1522
1730
|
vocabulary: [RECONCILED, NOTHING_TO_RECONCILE],
|
|
1523
|
-
single_source: "docs/josh-commands.md \u2192 `josh epic --reconcile`"
|
|
1731
|
+
single_source: "docs/josh-commands-automation.md \u2192 `josh epic --reconcile`"
|
|
1524
1732
|
},
|
|
1525
1733
|
{
|
|
1526
1734
|
name: "lane:list",
|
|
1527
1735
|
decision: "Whether each in-progress issue holds a live lane, and the two-directional difference",
|
|
1528
1736
|
args: "",
|
|
1529
1737
|
vocabulary: [LIVE, STOPPED, UNKNOWN],
|
|
1530
|
-
single_source: "docs/josh-commands.md \u2192 The `in-progress` / lane difference"
|
|
1531
|
-
}
|
|
1738
|
+
single_source: "docs/josh-commands-automation.md \u2192 The `in-progress` / lane difference"
|
|
1739
|
+
},
|
|
1740
|
+
RUN_ENTRY_ORACLE
|
|
1532
1741
|
];
|
|
1533
1742
|
function get_command(oracle) {
|
|
1534
1743
|
return oracle.command ?? oracle.name;
|
|
@@ -1591,6 +1800,7 @@ var NOT_NAMED = /* @__PURE__ */ new Map([
|
|
|
1591
1800
|
["epic:next", READ],
|
|
1592
1801
|
["run:merge", PHASE],
|
|
1593
1802
|
["run:step", SELF],
|
|
1803
|
+
["run:entry", SELF],
|
|
1594
1804
|
["refactor:scan", PHASE],
|
|
1595
1805
|
["split:assess", PHASE],
|
|
1596
1806
|
["sonar:hotspots", READ],
|
|
@@ -1643,7 +1853,337 @@ function row_for(oracle, firing_point) {
|
|
|
1643
1853
|
};
|
|
1644
1854
|
}
|
|
1645
1855
|
var ROWS = oracle_firing.firing_oracles().map(({ oracle, firing_point }) => row_for(oracle, firing_point));
|
|
1646
|
-
var oracle_consulted = { ROWS,
|
|
1856
|
+
var oracle_consulted = { ROWS, reason_for };
|
|
1857
|
+
|
|
1858
|
+
// scripts/rules/destructive-command.ts
|
|
1859
|
+
var RM_COMMAND = "rm";
|
|
1860
|
+
var RECURSIVE_LONG = "--recursive";
|
|
1861
|
+
var RECURSIVE_LETTERS = "rR";
|
|
1862
|
+
var FORCE_LONG = "--force";
|
|
1863
|
+
var FORCE_LETTER = "f";
|
|
1864
|
+
function has_flag(args, long, letters) {
|
|
1865
|
+
return args.some((argument) => argument === long || git_argv.short_cluster_has(argument, letters));
|
|
1866
|
+
}
|
|
1867
|
+
function is_recursive_forced_rm(segment) {
|
|
1868
|
+
const args = git_argv.arguments_of(segment, RM_COMMAND);
|
|
1869
|
+
if (args === void 0) return false;
|
|
1870
|
+
return has_flag(args, RECURSIVE_LONG, RECURSIVE_LETTERS) && has_flag(args, FORCE_LONG, FORCE_LETTER);
|
|
1871
|
+
}
|
|
1872
|
+
var GH_COMMAND = "gh";
|
|
1873
|
+
var REPO_GROUP2 = "repo";
|
|
1874
|
+
var REPO_REMOVALS = /* @__PURE__ */ new Set(["delete", "archive"]);
|
|
1875
|
+
var REPO_EDIT = "edit";
|
|
1876
|
+
var VISIBILITY_FLAG = "--visibility";
|
|
1877
|
+
var PR_GROUP = "pr";
|
|
1878
|
+
var PR_CLOSE = "close";
|
|
1879
|
+
function is_destructive_repo_action(action, args) {
|
|
1880
|
+
if (REPO_REMOVALS.has(action)) return true;
|
|
1881
|
+
return action === REPO_EDIT && args.some((argument) => argument.startsWith(VISIBILITY_FLAG));
|
|
1882
|
+
}
|
|
1883
|
+
function is_destructive_gh_command(args) {
|
|
1884
|
+
const [group, action = ""] = args;
|
|
1885
|
+
if (group === PR_GROUP) return action === PR_CLOSE;
|
|
1886
|
+
return group === REPO_GROUP2 && is_destructive_repo_action(action, args);
|
|
1887
|
+
}
|
|
1888
|
+
var DELETE_METHOD = "DELETE";
|
|
1889
|
+
var REPOSITORY_PATH = "repos/";
|
|
1890
|
+
var ISSUE_LABEL_PATH = /^['"]?\/?repos\/[^/\s'"]+\/[^/\s'"]+\/issues\/\d+\/labels\/[^/\s'"]+['"]?$/u;
|
|
1891
|
+
function is_destructive_api_call(args) {
|
|
1892
|
+
const call = [GH_COMMAND, ...args].join(" ");
|
|
1893
|
+
if (!gh_api.is_gh_api(call) || gh_api.method_of(call) !== DELETE_METHOD) return false;
|
|
1894
|
+
return args.some(
|
|
1895
|
+
(argument) => argument.includes(REPOSITORY_PATH) && !ISSUE_LABEL_PATH.test(argument)
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
function is_destructive_gh(segment) {
|
|
1899
|
+
const args = git_argv.arguments_of(segment, GH_COMMAND);
|
|
1900
|
+
if (args === void 0) return false;
|
|
1901
|
+
return is_destructive_gh_command(args) || is_destructive_api_call(args);
|
|
1902
|
+
}
|
|
1903
|
+
function is_destructive_segment2(segment) {
|
|
1904
|
+
return is_recursive_forced_rm(segment) || is_destructive_gh(segment);
|
|
1905
|
+
}
|
|
1906
|
+
function is_destructive_command(command) {
|
|
1907
|
+
return shell_segments.segments_of(command).some((segment) => is_destructive_segment2(segment));
|
|
1908
|
+
}
|
|
1909
|
+
var DESTRUCTIVE_COMMAND_REASON = "\u26D4 destructive command: a recursive forced `rm` (`rm -rf`, `rm -fr`, `rm -r -f`, `rm --recursive --force`), `gh repo delete` / `archive`, `gh repo edit --visibility`, `gh pr close`, or a `gh api -X DELETE repos/\u2026` call deletes or closes something that cannot be restored, which is Tier C and needs explicit current-turn user instruction (`prompts/collaboration-workflow/operating-rules.md`). The `.claude/settings.json` deny list matches prefix globs, so it misses these spellings; this row reads the argv instead. Remove a file or directory one path at a time without `-f`, or ask the user to run the command in their own terminal. `gh issue close` and removing a label from an Issue (`DELETE repos/<o>/<r>/issues/<N>/labels/<name>`) are not refused. **This rule fires on every occurrence, not once per run.**";
|
|
1910
|
+
var ROW10 = {
|
|
1911
|
+
id: "destructive-command",
|
|
1912
|
+
is_trigger: bash_triggers.on_bash_command(is_destructive_command),
|
|
1913
|
+
reason: DESTRUCTIVE_COMMAND_REASON,
|
|
1914
|
+
decide: () => true
|
|
1915
|
+
};
|
|
1916
|
+
var destructive_command = { DESTRUCTIVE_COMMAND_REASON, ROW: ROW10, is_destructive_command };
|
|
1917
|
+
|
|
1918
|
+
// scripts/rules/worktree-guard.ts
|
|
1919
|
+
var CHECKOUT_SUBCOMMAND = "checkout";
|
|
1920
|
+
var RESTORE_SUBCOMMAND = "restore";
|
|
1921
|
+
var STASH_SUBCOMMAND = "stash";
|
|
1922
|
+
var PATHSPEC_SEPARATOR = "--";
|
|
1923
|
+
function is_worktree_checkout(args) {
|
|
1924
|
+
return args.includes(PATHSPEC_SEPARATOR);
|
|
1925
|
+
}
|
|
1926
|
+
var STAGED_LONG = "--staged";
|
|
1927
|
+
var STAGED_LETTER = "S";
|
|
1928
|
+
var WORKTREE_LONG = "--worktree";
|
|
1929
|
+
var WORKTREE_LETTER = "W";
|
|
1930
|
+
function touches_worktree(args) {
|
|
1931
|
+
const is_staged = args.some(
|
|
1932
|
+
(argument) => argument === STAGED_LONG || git_argv.short_cluster_has(argument, STAGED_LETTER)
|
|
1933
|
+
);
|
|
1934
|
+
const is_worktree = args.some(
|
|
1935
|
+
(argument) => argument === WORKTREE_LONG || git_argv.short_cluster_has(argument, WORKTREE_LETTER)
|
|
1936
|
+
);
|
|
1937
|
+
return !is_staged || is_worktree;
|
|
1938
|
+
}
|
|
1939
|
+
var PUSH_STASH = "push";
|
|
1940
|
+
var MESSAGE_LONG = "--message";
|
|
1941
|
+
var MESSAGE_SHORT_LETTER = "m";
|
|
1942
|
+
var READ_ONLY_STASH = /* @__PURE__ */ new Set(["list", "show"]);
|
|
1943
|
+
function has_message(args) {
|
|
1944
|
+
return args.some(
|
|
1945
|
+
(argument) => argument === MESSAGE_LONG || argument.startsWith(`${MESSAGE_LONG}=`) || git_argv.short_cluster_has(argument, MESSAGE_SHORT_LETTER)
|
|
1946
|
+
);
|
|
1947
|
+
}
|
|
1948
|
+
function is_unauthorized_stash(args) {
|
|
1949
|
+
const [stash_subcommand, ...rest] = args;
|
|
1950
|
+
if (stash_subcommand === void 0) return true;
|
|
1951
|
+
if (READ_ONLY_STASH.has(stash_subcommand)) return false;
|
|
1952
|
+
if (stash_subcommand === PUSH_STASH) return !has_message(rest);
|
|
1953
|
+
return true;
|
|
1954
|
+
}
|
|
1955
|
+
var CLEAN_SUBCOMMAND = "clean";
|
|
1956
|
+
var FORCE_LONG2 = "--force";
|
|
1957
|
+
var FORCE_LETTER2 = "f";
|
|
1958
|
+
function is_forced_clean(args) {
|
|
1959
|
+
return args.some(
|
|
1960
|
+
(argument) => argument === FORCE_LONG2 || git_argv.short_cluster_has(argument, FORCE_LETTER2)
|
|
1961
|
+
);
|
|
1962
|
+
}
|
|
1963
|
+
var JUDGED_SUBCOMMANDS = /* @__PURE__ */ new Map([
|
|
1964
|
+
[CHECKOUT_SUBCOMMAND, is_worktree_checkout],
|
|
1965
|
+
[RESTORE_SUBCOMMAND, touches_worktree],
|
|
1966
|
+
[CLEAN_SUBCOMMAND, is_forced_clean],
|
|
1967
|
+
[STASH_SUBCOMMAND, is_unauthorized_stash]
|
|
1968
|
+
]);
|
|
1969
|
+
function is_unauthorized_segment(segment) {
|
|
1970
|
+
const call = git_argv.parse(segment);
|
|
1971
|
+
if (call === void 0) return false;
|
|
1972
|
+
return JUDGED_SUBCOMMANDS.get(call.subcommand ?? "")?.(call.args) === true;
|
|
1973
|
+
}
|
|
1974
|
+
function is_unauthorized_worktree_change(command) {
|
|
1975
|
+
return shell_segments.segments_of(command).some((segment) => is_unauthorized_segment(segment));
|
|
1976
|
+
}
|
|
1977
|
+
var WORKTREE_MUTATION_REASON = '\u26D4 unauthorized working-tree change: `git checkout -- <path>`, `git restore <path>`, a forced `git clean` and an unauthorized `git stash` discard work or mutate the repository-wide stash every work tree shares, and none is on the `.claude/settings.json` deny list (`operating-rules.md`). Do not run them on your own judgement. A commit goes through `pnpm josh git`; a stash pop goes through `pnpm josh stash:pop "<message>"`, never a positional `git stash pop` a shared stack lets another lane divert. A stash push is authorized only inside a documented flow and only with a findable message \u2014 `git stash push -u -m "<message>"` \u2014 which this row allows; a bare `git stash`, a message-less push, or `pop` / `apply` / `drop` is refused. **This rule fires on every occurrence, not once per run.**';
|
|
1978
|
+
var ROW11 = {
|
|
1979
|
+
id: "worktree-mutation",
|
|
1980
|
+
is_trigger: bash_triggers.on_bash_command(is_unauthorized_worktree_change),
|
|
1981
|
+
reason: WORKTREE_MUTATION_REASON,
|
|
1982
|
+
decide: () => true
|
|
1983
|
+
};
|
|
1984
|
+
var worktree_guard = {
|
|
1985
|
+
ROW: ROW11,
|
|
1986
|
+
WORKTREE_MUTATION_REASON,
|
|
1987
|
+
is_unauthorized_worktree_change,
|
|
1988
|
+
touches_worktree
|
|
1989
|
+
};
|
|
1990
|
+
|
|
1991
|
+
// scripts/rules/index-guard.ts
|
|
1992
|
+
var INDEX_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
1993
|
+
"add",
|
|
1994
|
+
"commit",
|
|
1995
|
+
"mv",
|
|
1996
|
+
"reset",
|
|
1997
|
+
"rm",
|
|
1998
|
+
"stage"
|
|
1999
|
+
]);
|
|
2000
|
+
var RESTORE_SUBCOMMAND2 = "restore";
|
|
2001
|
+
function is_index_restore(args) {
|
|
2002
|
+
return !worktree_guard.touches_worktree(args);
|
|
2003
|
+
}
|
|
2004
|
+
function is_index_segment(segment) {
|
|
2005
|
+
const call = git_argv.parse(segment);
|
|
2006
|
+
if (call === void 0) return false;
|
|
2007
|
+
if (INDEX_SUBCOMMANDS.has(call.subcommand ?? "")) return true;
|
|
2008
|
+
return call.subcommand === RESTORE_SUBCOMMAND2 && is_index_restore(call.args);
|
|
2009
|
+
}
|
|
2010
|
+
function is_index_mutation(command) {
|
|
2011
|
+
return shell_segments.segments_of(command).some((segment) => is_index_segment(segment));
|
|
2012
|
+
}
|
|
2013
|
+
var INDEX_MUTATION_REASON = '\u26D4 git index mutation: `git add` / `stage` / `commit` / `reset` / `rm` / `mv` and `git restore --staged` overwrite the user\'s staged snapshot, which `CLAUDE.md` \u2192 Git Rules forbids on your own judgement (`prompts/collaboration-workflow/operating-rules.md` \u2192 "git index \u3092\u52DD\u624B\u306B\u5909\u66F4\u3057\u306A\u3044"). The `.claude/settings.json` deny list matches prefix globs, so it misses `git -C . commit`, `git -c k=v commit` and `env git commit`; this row reads the argv instead, so the spelling does not matter. A commit goes through `pnpm josh git -y`; any other staging needs explicit current-turn user instruction, run by the user in their own terminal. **This rule fires on every occurrence, not once per run.**';
|
|
2014
|
+
var ROW12 = {
|
|
2015
|
+
id: "index-mutation",
|
|
2016
|
+
is_trigger: bash_triggers.on_bash_command(is_index_mutation),
|
|
2017
|
+
reason: INDEX_MUTATION_REASON,
|
|
2018
|
+
decide: () => true
|
|
2019
|
+
};
|
|
2020
|
+
var index_guard = { INDEX_MUTATION_REASON, ROW: ROW12, is_index_mutation };
|
|
2021
|
+
|
|
2022
|
+
// scripts/rules/protected-files.ts
|
|
2023
|
+
import path5 from "node:path";
|
|
2024
|
+
|
|
2025
|
+
// scripts/doctor/doctor-consumer.ts
|
|
2026
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
2027
|
+
import path4 from "node:path";
|
|
2028
|
+
|
|
2029
|
+
// scripts/lib/spawn-exit.ts
|
|
2030
|
+
function read_spawn_stdout(result) {
|
|
2031
|
+
return result.stdout ?? "";
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
// scripts/version/kit-descriptor.ts
|
|
2035
|
+
var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
|
|
2036
|
+
|
|
2037
|
+
// scripts/doctor/doctor-consumer.ts
|
|
2038
|
+
import { execaSync } from "execa";
|
|
2039
|
+
import { z as z6 } from "zod";
|
|
2040
|
+
var NODE_MODULES = "node_modules";
|
|
2041
|
+
var SETTINGS_PATH = path4.join(".claude", "settings.json");
|
|
2042
|
+
var CLAUDE_MD = "CLAUDE.md";
|
|
2043
|
+
var PLUGIN_ID = "kit@kit";
|
|
2044
|
+
var CLAUDE_MD_POINTER = `@${NODE_MODULES}/${KIT_PACKAGE_NAME}/dist/${CLAUDE_MD}`;
|
|
2045
|
+
var SECRETLINT_BIN = path4.join(NODE_MODULES, ".bin", "secretlint");
|
|
2046
|
+
var GIT_TIMEOUT_MS = 2e3;
|
|
2047
|
+
var manifest_schema = z6.object({
|
|
2048
|
+
name: z6.string().optional(),
|
|
2049
|
+
dependencies: z6.record(z6.string(), z6.string()).optional(),
|
|
2050
|
+
devDependencies: z6.record(z6.string(), z6.string()).optional()
|
|
2051
|
+
});
|
|
2052
|
+
var settings_schema = z6.object({
|
|
2053
|
+
enabledPlugins: z6.record(z6.string(), z6.boolean()).optional()
|
|
2054
|
+
});
|
|
2055
|
+
var STATE_OK = "ok";
|
|
2056
|
+
var STATE_TARGET_MISSING = "target-missing";
|
|
2057
|
+
var STATE_MISSING = "missing";
|
|
2058
|
+
function parse_manifest(root) {
|
|
2059
|
+
const content = file_reader.read_if_readable(path4.join(root, "package.json"));
|
|
2060
|
+
if (content === void 0) return void 0;
|
|
2061
|
+
const parsed = manifest_schema.safeParse(json_value.parse_or_undefined(content));
|
|
2062
|
+
return parsed.success ? parsed.data : void 0;
|
|
2063
|
+
}
|
|
2064
|
+
function lists_kit_dependency(manifest) {
|
|
2065
|
+
if (manifest === void 0) return false;
|
|
2066
|
+
return Object.hasOwn(manifest.dependencies ?? {}, KIT_PACKAGE_NAME) || Object.hasOwn(manifest.devDependencies ?? {}, KIT_PACKAGE_NAME);
|
|
2067
|
+
}
|
|
2068
|
+
function is_kit_consumer(root) {
|
|
2069
|
+
const manifest = parse_manifest(root);
|
|
2070
|
+
if (manifest?.name === KIT_PACKAGE_NAME) return false;
|
|
2071
|
+
return lists_kit_dependency(manifest) || existsSync2(path4.join(root, NODE_MODULES, KIT_PACKAGE_NAME));
|
|
2072
|
+
}
|
|
2073
|
+
function is_plugin_declared(root) {
|
|
2074
|
+
const content = file_reader.read_if_readable(path4.join(root, SETTINGS_PATH));
|
|
2075
|
+
if (content === void 0) return false;
|
|
2076
|
+
const parsed = settings_schema.safeParse(json_value.parse_or_undefined(content));
|
|
2077
|
+
return parsed.success && parsed.data.enabledPlugins?.[PLUGIN_ID] === true;
|
|
2078
|
+
}
|
|
2079
|
+
function configured_hooks_path(root) {
|
|
2080
|
+
const result = execaSync("git", ["-C", root, "config", "--get", "core.hooksPath"], {
|
|
2081
|
+
reject: false,
|
|
2082
|
+
timeout: GIT_TIMEOUT_MS
|
|
2083
|
+
});
|
|
2084
|
+
const value = read_spawn_stdout(result).trim();
|
|
2085
|
+
return value === "" ? void 0 : value;
|
|
2086
|
+
}
|
|
2087
|
+
function claude_md_state(root) {
|
|
2088
|
+
const content = file_reader.read_if_readable(path4.join(root, CLAUDE_MD));
|
|
2089
|
+
if (content === void 0) return STATE_MISSING;
|
|
2090
|
+
if (!content.includes(CLAUDE_MD_POINTER)) return STATE_OK;
|
|
2091
|
+
return existsSync2(path4.join(root, NODE_MODULES, KIT_PACKAGE_NAME, "dist", CLAUDE_MD)) ? STATE_OK : STATE_TARGET_MISSING;
|
|
2092
|
+
}
|
|
2093
|
+
function is_secretlint_runnable(root) {
|
|
2094
|
+
return existsSync2(path4.join(root, SECRETLINT_BIN));
|
|
2095
|
+
}
|
|
2096
|
+
function status_line(is_ok, ok_text, warn_text) {
|
|
2097
|
+
return is_ok ? ` \u2713 ${ok_text}` : ` \u26A0 ${warn_text}`;
|
|
2098
|
+
}
|
|
2099
|
+
function plugin_line(is_declared2) {
|
|
2100
|
+
return status_line(
|
|
2101
|
+
is_declared2,
|
|
2102
|
+
"kit plugin declared (skills load in a trusted workspace; headless from its second session)",
|
|
2103
|
+
"kit plugin not declared in .claude/settings.json \u2014 run `pnpm josh sync`"
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
function hooks_path_line(hooks_path) {
|
|
2107
|
+
return status_line(
|
|
2108
|
+
hooks_path === void 0,
|
|
2109
|
+
"git hooks install normally (core.hooksPath unset)",
|
|
2110
|
+
`core.hooksPath is set (${hooks_path ?? ""}) \u2014 lefthook installs no git hooks; unset it`
|
|
2111
|
+
);
|
|
2112
|
+
}
|
|
2113
|
+
function claude_md_line(state) {
|
|
2114
|
+
if (state === STATE_OK) return " \u2713 CLAUDE.md resolves to the installed kit rules";
|
|
2115
|
+
if (state === STATE_TARGET_MISSING) {
|
|
2116
|
+
return " \u26A0 CLAUDE.md points at rules that are not installed \u2014 run `pnpm install`";
|
|
2117
|
+
}
|
|
2118
|
+
return " \u26A0 CLAUDE.md is missing \u2014 run `pnpm josh init`";
|
|
2119
|
+
}
|
|
2120
|
+
function secretlint_line(is_runnable) {
|
|
2121
|
+
return status_line(
|
|
2122
|
+
is_runnable,
|
|
2123
|
+
"secretlint is runnable",
|
|
2124
|
+
"secretlint is not installed \u2014 run `pnpm install`"
|
|
2125
|
+
);
|
|
2126
|
+
}
|
|
2127
|
+
function consumer_setup_lines(root) {
|
|
2128
|
+
return [
|
|
2129
|
+
plugin_line(is_plugin_declared(root)),
|
|
2130
|
+
hooks_path_line(configured_hooks_path(root)),
|
|
2131
|
+
claude_md_line(claude_md_state(root)),
|
|
2132
|
+
secretlint_line(is_secretlint_runnable(root))
|
|
2133
|
+
];
|
|
2134
|
+
}
|
|
2135
|
+
function report_consumer_setup(root) {
|
|
2136
|
+
if (!is_kit_consumer(root)) return;
|
|
2137
|
+
console.info("");
|
|
2138
|
+
console.info("Consumer setup:");
|
|
2139
|
+
for (const line of consumer_setup_lines(root)) console.info(line);
|
|
2140
|
+
}
|
|
2141
|
+
var doctor_consumer = {
|
|
2142
|
+
claude_md_line,
|
|
2143
|
+
claude_md_state,
|
|
2144
|
+
hooks_path_line,
|
|
2145
|
+
is_kit_consumer,
|
|
2146
|
+
is_plugin_declared,
|
|
2147
|
+
is_secretlint_runnable,
|
|
2148
|
+
plugin_line,
|
|
2149
|
+
report_consumer_setup,
|
|
2150
|
+
secretlint_line
|
|
2151
|
+
};
|
|
2152
|
+
|
|
2153
|
+
// scripts/rules/protected-files.ts
|
|
2154
|
+
var READ_TOOL = "Read";
|
|
2155
|
+
var EDIT_TOOLS2 = /* @__PURE__ */ new Set(["Edit", "Write"]);
|
|
2156
|
+
var ENVIRONMENT_FILE = ".env";
|
|
2157
|
+
var SETTINGS_FILE = path5.join(".claude", "settings.json");
|
|
2158
|
+
function file_path_of(call) {
|
|
2159
|
+
if (!json_value.is_record(call.input)) return "";
|
|
2160
|
+
const value = call.input["file_path"];
|
|
2161
|
+
return typeof value === "string" ? value : "";
|
|
2162
|
+
}
|
|
2163
|
+
function is_environment_read(call) {
|
|
2164
|
+
return call.name === READ_TOOL && path5.basename(file_path_of(call)) === ENVIRONMENT_FILE;
|
|
2165
|
+
}
|
|
2166
|
+
function is_consumer_settings_edit(call, is_kit_consumer2) {
|
|
2167
|
+
if (!EDIT_TOOLS2.has(call.name)) return false;
|
|
2168
|
+
const file_path = path5.resolve(file_path_of(call));
|
|
2169
|
+
if (!file_path.endsWith(`${path5.sep}${SETTINGS_FILE}`)) return false;
|
|
2170
|
+
return is_kit_consumer2(path5.dirname(path5.dirname(file_path)));
|
|
2171
|
+
}
|
|
2172
|
+
function is_protected_file_call(call, is_kit_consumer2 = doctor_consumer.is_kit_consumer) {
|
|
2173
|
+
return is_environment_read(call) || is_consumer_settings_edit(call, is_kit_consumer2);
|
|
2174
|
+
}
|
|
2175
|
+
var PROTECTED_FILE_REASON = '\u26D4 protected file: `.env` holds the Telegram bot token, so reading it puts a secret in the transcript \u2014 the scripts that need it load it in their own process. `.claude/settings.json` in a consumer repository is the deny list and the hooks every other rule rests on, so a run must not rewrite it; `josh sync` owns it, and a change belongs upstream in kit (`CLAUDE.md` \u2192 "Route distributed-doc / config changes upstream to kit"). Leave both files alone, or ask the user. **This rule fires on every occurrence, not once per run.**';
|
|
2176
|
+
var ROW13 = {
|
|
2177
|
+
id: "protected-file",
|
|
2178
|
+
is_trigger: is_protected_file_call,
|
|
2179
|
+
reason: PROTECTED_FILE_REASON,
|
|
2180
|
+
decide: () => true
|
|
2181
|
+
};
|
|
2182
|
+
var protected_files = { ROW: ROW13, is_protected_file_call };
|
|
2183
|
+
|
|
2184
|
+
// scripts/rules/permission-guards.ts
|
|
2185
|
+
var ROWS2 = [index_guard.ROW, destructive_command.ROW, protected_files.ROW];
|
|
2186
|
+
var permission_guards = { ROWS: ROWS2 };
|
|
1647
2187
|
|
|
1648
2188
|
// scripts/rules/piped-verification.ts
|
|
1649
2189
|
var VERIFICATION_COMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -1713,7 +2253,7 @@ function is_poll_loop(command) {
|
|
|
1713
2253
|
return LOOP_KEYWORD2.test(plain) && SLEEP_COMMAND.test(plain);
|
|
1714
2254
|
}
|
|
1715
2255
|
var POLL_LOOP_REASON = '\u26D4 output poll loop: this hand-writes a `while`/`until` wait loop over a command\'s output, a marker file or a process \u2014 with a `sleep` or, worse, without one \u2014 and the loop does not know when the command finished. A regex that never matches waits to the harness block limit; one that matches a mid-run line exits too early \u2014 either way the command exit is not what ends the wait, and each pass spends a full-context round trip (joshuafolkken/kit#2371 measured about 45 minutes, 13% of six lanes, lost to exactly this). Do not poll the output file. A command known to take minutes \u2014 `pnpm josh gate`, `pnpm josh followup`, `pnpm josh format` \u2014 is started detached from the first with `run_in_background` set, and the harness re-invokes you when it exits: its completion notification is what ends the wait, on the task exit rather than a regex or the block limit. So issue the long command in the background and end the turn \u2014 do not arm a loop; the wake-up brings you back. To glance at interim output, `Read` the output file once, never in a sleep loop. If you are waiting on CI, `pnpm josh followup` waits on it for you. The procedure is `.claude/skills/workflow-commands/background-commands.md`, "A command that can take minutes is issued in the background". **This rule fires on every occurrence, not once per run.**';
|
|
1716
|
-
var
|
|
2256
|
+
var ROW14 = {
|
|
1717
2257
|
id: "poll-loop",
|
|
1718
2258
|
is_trigger: bash_triggers.on_bash_command(is_poll_loop),
|
|
1719
2259
|
reason: POLL_LOOP_REASON,
|
|
@@ -1721,7 +2261,7 @@ var ROW10 = {
|
|
|
1721
2261
|
};
|
|
1722
2262
|
var poll_loop = {
|
|
1723
2263
|
POLL_LOOP_REASON,
|
|
1724
|
-
ROW:
|
|
2264
|
+
ROW: ROW14,
|
|
1725
2265
|
is_poll_loop
|
|
1726
2266
|
};
|
|
1727
2267
|
|
|
@@ -1841,13 +2381,13 @@ function posts_at_path_literally(command) {
|
|
|
1841
2381
|
return RAW_FIELD_BODY_AT.test(command);
|
|
1842
2382
|
}
|
|
1843
2383
|
var RAW_FIELD_BODY_REASON = "\u26D4 literal @path body: this passes `body=@<path>` to `gh api` with a raw field flag (`-f` / `--raw-field`), which sends the value verbatim \u2014 the string `@<path>` is posted as the comment, not the file it points at. `-F` / `--field` is the flag that reads the file, and the two spellings differ by one character while `gh` exits 0 and returns a comment URL either way, so the break is invisible until a person reads the issue (joshuafolkken/kit#2304 lost two park comments this way). Post an issue or PR comment with `pnpm josh issue:comment <N> --body-file <path>` \u2014 the one spelling, which cannot take the wrong flag. The rule and the safe forms are in `prompts/collaboration-workflow/shell-body.md`. This rule fires on every occurrence, not once per run.";
|
|
1844
|
-
var
|
|
2384
|
+
var ROW15 = {
|
|
1845
2385
|
id: "raw-field-body",
|
|
1846
2386
|
is_trigger: bash_triggers.on_bash_command(posts_at_path_literally),
|
|
1847
2387
|
reason: RAW_FIELD_BODY_REASON,
|
|
1848
2388
|
decide: () => true
|
|
1849
2389
|
};
|
|
1850
|
-
var raw_field_body = { RAW_FIELD_BODY_REASON, ROW:
|
|
2390
|
+
var raw_field_body = { RAW_FIELD_BODY_REASON, ROW: ROW15, posts_at_path_literally };
|
|
1851
2391
|
|
|
1852
2392
|
// scripts/rules/rule-body-guard.ts
|
|
1853
2393
|
var EDIT_TOOL = "Edit";
|
|
@@ -1860,8 +2400,8 @@ function is_rule_document(file_path) {
|
|
|
1860
2400
|
}
|
|
1861
2401
|
var LINK_TARGET = /\]\([^)]*\)/gu;
|
|
1862
2402
|
var BARE_URL = /https?:\/\/\S+/gu;
|
|
1863
|
-
function prose_of(
|
|
1864
|
-
return
|
|
2403
|
+
function prose_of(text) {
|
|
2404
|
+
return text.replaceAll(LINK_TARGET, "]()").replaceAll(BARE_URL, "");
|
|
1865
2405
|
}
|
|
1866
2406
|
var MIN_APPENDED_PROSE = 120;
|
|
1867
2407
|
function adds_rule_prose(old_text, new_text) {
|
|
@@ -1918,7 +2458,7 @@ function runs_placement_oracle(command) {
|
|
|
1918
2458
|
(names) => shell_segments.segments_of(command).some((segment) => shell_segments.is_josh_command(segment, names))
|
|
1919
2459
|
);
|
|
1920
2460
|
}
|
|
1921
|
-
var
|
|
2461
|
+
var ROW16 = {
|
|
1922
2462
|
id: "rule-body",
|
|
1923
2463
|
is_trigger: writes_rule_prose,
|
|
1924
2464
|
reason: RULE_BODY_REASON,
|
|
@@ -1927,12 +2467,9 @@ var ROW12 = {
|
|
|
1927
2467
|
};
|
|
1928
2468
|
var rule_body_guard = {
|
|
1929
2469
|
RULE_BODY_REASON,
|
|
1930
|
-
ROW:
|
|
1931
|
-
adds_rule_prose,
|
|
2470
|
+
ROW: ROW16,
|
|
1932
2471
|
answered_placement,
|
|
1933
2472
|
is_rule_document,
|
|
1934
|
-
prose_of,
|
|
1935
|
-
runs_placement_oracle,
|
|
1936
2473
|
writes_rule_prose
|
|
1937
2474
|
};
|
|
1938
2475
|
|
|
@@ -2002,7 +2539,6 @@ var SHELL_BODY_REASON = "\u26D4 shell-evaluated body: this command carries a bod
|
|
|
2002
2539
|
var shell_body_trigger = {
|
|
2003
2540
|
SHELL_BODY_REASON,
|
|
2004
2541
|
carries_a_body,
|
|
2005
|
-
is_safe_body_form,
|
|
2006
2542
|
is_shell_evaluated_body,
|
|
2007
2543
|
keeps_body_safe
|
|
2008
2544
|
};
|
|
@@ -2011,18 +2547,13 @@ var shell_body_trigger = {
|
|
|
2011
2547
|
import { execFileSync } from "node:child_process";
|
|
2012
2548
|
|
|
2013
2549
|
// scripts/gate/project-checks.ts
|
|
2014
|
-
import { existsSync as
|
|
2015
|
-
import
|
|
2016
|
-
|
|
2017
|
-
// scripts/init/project-profile.ts
|
|
2018
|
-
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync3 } from "node:fs";
|
|
2019
|
-
import path4 from "node:path";
|
|
2020
|
-
|
|
2021
|
-
// scripts/version/kit-descriptor.ts
|
|
2022
|
-
var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
|
|
2550
|
+
import { existsSync as existsSync4, globSync as globSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
2551
|
+
import path7 from "node:path";
|
|
2023
2552
|
|
|
2024
2553
|
// scripts/init/project-profile.ts
|
|
2025
|
-
import {
|
|
2554
|
+
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3 } from "node:fs";
|
|
2555
|
+
import path6 from "node:path";
|
|
2556
|
+
import { execaSync as execaSync2 } from "execa";
|
|
2026
2557
|
var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".svelte-kit"]);
|
|
2027
2558
|
var WEB_EXTENSIONS = /* @__PURE__ */ new Set([".html", ".css", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
2028
2559
|
var TYPESCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx"]);
|
|
@@ -2054,26 +2585,21 @@ function requested_profile(args, usage = "josh init [--profile basic|full]") {
|
|
|
2054
2585
|
throw new Error("Profile must be basic or full");
|
|
2055
2586
|
}
|
|
2056
2587
|
function read_manifest(root) {
|
|
2057
|
-
const filename =
|
|
2058
|
-
if (!
|
|
2588
|
+
const filename = path6.join(root, "package.json");
|
|
2589
|
+
if (!existsSync3(filename)) return void 0;
|
|
2059
2590
|
const parsed = JSON.parse(readFileSync3(filename, "utf8"));
|
|
2060
|
-
if (
|
|
2061
|
-
throw new Error("package.json must contain an object");
|
|
2062
|
-
}
|
|
2591
|
+
if (!json_value.is_record(parsed)) throw new Error("package.json must contain an object");
|
|
2063
2592
|
return parsed;
|
|
2064
2593
|
}
|
|
2065
|
-
function is_record(value) {
|
|
2066
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2067
|
-
}
|
|
2068
2594
|
function recorded_profile(manifest) {
|
|
2069
2595
|
const { josh } = manifest;
|
|
2070
|
-
return is_record(josh) ? parse_profile(josh["profile"]) : void 0;
|
|
2596
|
+
return json_value.is_record(josh) ? parse_profile(josh["profile"]) : void 0;
|
|
2071
2597
|
}
|
|
2072
2598
|
function has_build_script(value) {
|
|
2073
|
-
return is_record(value) && ("build" in value || "dev" in value);
|
|
2599
|
+
return json_value.is_record(value) && ("build" in value || "dev" in value);
|
|
2074
2600
|
}
|
|
2075
2601
|
function has_project_dependencies(value) {
|
|
2076
|
-
if (!is_record(value)) return false;
|
|
2602
|
+
if (!json_value.is_record(value)) return false;
|
|
2077
2603
|
return Object.keys(value).some((name) => name !== KIT_PACKAGE_NAME);
|
|
2078
2604
|
}
|
|
2079
2605
|
function inferred_profile(manifest) {
|
|
@@ -2099,9 +2625,9 @@ function should_visit(entry) {
|
|
|
2099
2625
|
function scan_directory(directory, pending) {
|
|
2100
2626
|
const entries = readdirSync(directory, { withFileTypes: true });
|
|
2101
2627
|
pending.push(
|
|
2102
|
-
...entries.filter((entry) => should_visit(entry)).map((entry) =>
|
|
2628
|
+
...entries.filter((entry) => should_visit(entry)).map((entry) => path6.join(directory, entry.name))
|
|
2103
2629
|
);
|
|
2104
|
-
return entries.filter((entry) => entry.isFile()).map((entry) =>
|
|
2630
|
+
return entries.filter((entry) => entry.isFile()).map((entry) => path6.extname(entry.name));
|
|
2105
2631
|
}
|
|
2106
2632
|
function file_extensions(root) {
|
|
2107
2633
|
const pending = [root];
|
|
@@ -2118,7 +2644,7 @@ function scan_files(root) {
|
|
|
2118
2644
|
return { has_web, has_typescript };
|
|
2119
2645
|
}
|
|
2120
2646
|
function has_github_remote(root) {
|
|
2121
|
-
const result =
|
|
2647
|
+
const result = execaSync2("git", ["config", "--get", "remote.origin.url"], {
|
|
2122
2648
|
cwd: root,
|
|
2123
2649
|
reject: false
|
|
2124
2650
|
});
|
|
@@ -2127,7 +2653,7 @@ function has_github_remote(root) {
|
|
|
2127
2653
|
function inspect_project(root, requested) {
|
|
2128
2654
|
const profile = resolve_profile(root, requested);
|
|
2129
2655
|
const files = scan_files(root);
|
|
2130
|
-
const has_git =
|
|
2656
|
+
const has_git = existsSync3(path6.join(root, ".git"));
|
|
2131
2657
|
return { ...profile, ...files, has_git, has_github: has_git && has_github_remote(root) };
|
|
2132
2658
|
}
|
|
2133
2659
|
var project_profile = {
|
|
@@ -2142,7 +2668,7 @@ var project_profile = {
|
|
|
2142
2668
|
var SKIP_MARKER = "\u2014 skipping";
|
|
2143
2669
|
|
|
2144
2670
|
// scripts/gate/project-checks.ts
|
|
2145
|
-
import { z as
|
|
2671
|
+
import { z as z7 } from "zod";
|
|
2146
2672
|
var PACKAGE_JSON = "package.json";
|
|
2147
2673
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
2148
2674
|
"node_modules",
|
|
@@ -2177,11 +2703,11 @@ var CSPELL_CONFIGS = [
|
|
|
2177
2703
|
];
|
|
2178
2704
|
var TYPE_CONFIGS = ["tsconfig.json", "jsconfig.json"];
|
|
2179
2705
|
var DEPENDENCY_FIELDS = ["dependencies", "devDependencies"];
|
|
2180
|
-
var object_schema =
|
|
2706
|
+
var object_schema = z7.record(z7.string(), z7.unknown());
|
|
2181
2707
|
function project_root(directory) {
|
|
2182
2708
|
let current = directory;
|
|
2183
|
-
while (!
|
|
2184
|
-
const parent =
|
|
2709
|
+
while (!existsSync4(path7.join(current, PACKAGE_JSON))) {
|
|
2710
|
+
const parent = path7.dirname(current);
|
|
2185
2711
|
if (parent === current) return directory;
|
|
2186
2712
|
current = parent;
|
|
2187
2713
|
}
|
|
@@ -2194,24 +2720,23 @@ function has_files(directory, pattern) {
|
|
|
2194
2720
|
return globSync2(pattern, { cwd: project_root(directory), exclude: is_ignored }).length > 0;
|
|
2195
2721
|
}
|
|
2196
2722
|
function has_config(directory, names) {
|
|
2197
|
-
return names.some((name) =>
|
|
2723
|
+
return names.some((name) => existsSync4(path7.join(project_root(directory), name)));
|
|
2198
2724
|
}
|
|
2199
2725
|
function has_bin(directory, bin_name) {
|
|
2200
2726
|
return find_local_bin_upwards(directory, bin_name) !== void 0;
|
|
2201
2727
|
}
|
|
2202
2728
|
function josh_settings(manifest) {
|
|
2203
|
-
|
|
2204
|
-
return manifest.josh;
|
|
2729
|
+
return json_value.is_record(manifest) ? manifest["josh"] : void 0;
|
|
2205
2730
|
}
|
|
2206
2731
|
function is_basic_manifest(manifest) {
|
|
2207
2732
|
const josh = josh_settings(manifest);
|
|
2208
|
-
if (
|
|
2209
|
-
return project_profile.parse_profile(josh
|
|
2733
|
+
if (!json_value.is_record(josh)) return false;
|
|
2734
|
+
return project_profile.parse_profile(josh["profile"]) === "basic";
|
|
2210
2735
|
}
|
|
2211
2736
|
function read_manifest2(directory) {
|
|
2212
2737
|
try {
|
|
2213
|
-
const manifest_path =
|
|
2214
|
-
return
|
|
2738
|
+
const manifest_path = path7.join(project_root(directory), PACKAGE_JSON);
|
|
2739
|
+
return json_value.parse_or_undefined(readFileSync4(manifest_path, "utf8"));
|
|
2215
2740
|
} catch {
|
|
2216
2741
|
return void 0;
|
|
2217
2742
|
}
|
|
@@ -2231,8 +2756,8 @@ function missing_tool_reason(directory, package_name, bin_name) {
|
|
|
2231
2756
|
if (has_bin(directory, bin_name) || is_declared(directory, package_name)) return void 0;
|
|
2232
2757
|
return `${package_name} is not installed`;
|
|
2233
2758
|
}
|
|
2234
|
-
function skip_notice(
|
|
2235
|
-
return `josh ${
|
|
2759
|
+
function skip_notice(check4, reason) {
|
|
2760
|
+
return `josh ${check4}: ${reason} ${SKIP_MARKER} ${check4}.`;
|
|
2236
2761
|
}
|
|
2237
2762
|
function type_check_skip_reason(directory) {
|
|
2238
2763
|
if (!is_basic(directory)) return void 0;
|
|
@@ -2254,8 +2779,6 @@ function eslint_skip_reason(directory) {
|
|
|
2254
2779
|
var project_checks = {
|
|
2255
2780
|
CSPELL_CONFIGS,
|
|
2256
2781
|
ESLINT_CONFIGS,
|
|
2257
|
-
SCRIPT_FILES,
|
|
2258
|
-
TYPE_CONFIGS,
|
|
2259
2782
|
TYPE_FILES,
|
|
2260
2783
|
WEB_FILES,
|
|
2261
2784
|
eslint_skip_reason,
|
|
@@ -2293,46 +2816,45 @@ var BASIC_REQUIRED_SUFFIXES = [
|
|
|
2293
2816
|
".toml"
|
|
2294
2817
|
];
|
|
2295
2818
|
function normalize(paths) {
|
|
2296
|
-
return paths.map((
|
|
2819
|
+
return paths.map((path10) => path10.trim()).filter((path10) => path10 !== "");
|
|
2297
2820
|
}
|
|
2298
|
-
function is_test_file(
|
|
2299
|
-
return TEST_SUFFIXES.some((suffix) =>
|
|
2821
|
+
function is_test_file(path10) {
|
|
2822
|
+
return TEST_SUFFIXES.some((suffix) => path10.endsWith(suffix));
|
|
2300
2823
|
}
|
|
2301
|
-
function is_basic_manual(
|
|
2302
|
-
const lower =
|
|
2824
|
+
function is_basic_manual(path10, is_basic2) {
|
|
2825
|
+
const lower = path10.toLowerCase();
|
|
2303
2826
|
return is_basic2 && BASIC_REQUIRED_SUFFIXES.every((suffix) => !lower.endsWith(suffix));
|
|
2304
2827
|
}
|
|
2305
|
-
function is_basic_visual(
|
|
2306
|
-
const lower =
|
|
2828
|
+
function is_basic_visual(path10) {
|
|
2829
|
+
const lower = path10.toLowerCase();
|
|
2307
2830
|
return BASIC_VISUAL_SUFFIXES.some((suffix) => lower.endsWith(suffix));
|
|
2308
2831
|
}
|
|
2309
|
-
function is_exempt(
|
|
2310
|
-
if (EXEMPT_PATHS.includes(
|
|
2311
|
-
return EXEMPT_SUFFIXES.some((suffix) =>
|
|
2832
|
+
function is_exempt(path10, is_basic2 = false) {
|
|
2833
|
+
if (EXEMPT_PATHS.includes(path10) || is_basic_manual(path10, is_basic2)) return true;
|
|
2834
|
+
return EXEMPT_SUFFIXES.some((suffix) => path10.endsWith(suffix)) || EXEMPT_PREFIXES.some((prefix) => path10.startsWith(prefix));
|
|
2312
2835
|
}
|
|
2313
|
-
function is_runtime(
|
|
2314
|
-
return !is_test_file(
|
|
2836
|
+
function is_runtime(path10, is_basic2 = false) {
|
|
2837
|
+
return !is_test_file(path10) && !is_exempt(path10, is_basic2);
|
|
2315
2838
|
}
|
|
2316
2839
|
function verdict_for(paths, is_basic2 = false) {
|
|
2317
2840
|
const changed = normalize(paths);
|
|
2318
|
-
if (changed.some((
|
|
2319
|
-
if (changed.some((
|
|
2841
|
+
if (changed.some((path10) => is_test_file(path10))) return "satisfied";
|
|
2842
|
+
if (changed.some((path10) => is_runtime(path10, is_basic2))) return "required";
|
|
2320
2843
|
return "exempt";
|
|
2321
2844
|
}
|
|
2322
2845
|
function runtime_files(paths, is_basic2 = false) {
|
|
2323
|
-
return normalize(paths).filter((
|
|
2846
|
+
return normalize(paths).filter((path10) => is_runtime(path10, is_basic2));
|
|
2324
2847
|
}
|
|
2325
2848
|
function exempt_files(paths, is_basic2 = false) {
|
|
2326
|
-
return normalize(paths).filter((
|
|
2849
|
+
return normalize(paths).filter((path10) => is_exempt(path10, is_basic2));
|
|
2327
2850
|
}
|
|
2328
2851
|
function manual_check_files(paths, is_basic2) {
|
|
2329
|
-
return normalize(paths).filter((
|
|
2852
|
+
return normalize(paths).filter((path10) => is_exempt(path10, is_basic2) && !is_exempt(path10));
|
|
2330
2853
|
}
|
|
2331
2854
|
var test_declared_logic = {
|
|
2332
2855
|
EXEMPT_PATHS,
|
|
2333
2856
|
EXEMPT_PREFIXES,
|
|
2334
2857
|
EXEMPT_SUFFIXES,
|
|
2335
|
-
TEST_SUFFIXES,
|
|
2336
2858
|
exempt_files,
|
|
2337
2859
|
is_basic_visual,
|
|
2338
2860
|
is_exempt,
|
|
@@ -2393,8 +2915,8 @@ function is_untested_commit(call) {
|
|
|
2393
2915
|
return test_declared_changed.current_verdict() === "required";
|
|
2394
2916
|
}
|
|
2395
2917
|
var REASON = '\u26D4 test declared: this commits a runtime code change with no test beside it \u2014 `pnpm josh test:declared` reads the working tree as `required` (a changed file that is neither a test \u2014 `*.test.ts` / `*.e2e.ts` \u2014 nor a mechanically-exempt non-runtime path). `CLAUDE.md` \u2192 Code Change Rules requires a test for ALL code changes: a bug fix gets a regression test, a refactor gets tests pinning behavior first, logic gets a unit test, an observable UI/timing change gets an E2E. Add the declared test and reissue this commit. **If the change genuinely touches no executable runtime path** it is the pre-approved non-runtime exception \u2014 declare it in your Step 0 work summary with the reason it is exempt (non-executable config, a cosmetic asset swap) and reissue; the exception is a presentation, not a stop. Run `pnpm josh test:declared` to see the files it names. The procedure is `prompts/collaboration-workflow/rule-delivery.md` \u2192 "\u914D\u9001\u3055\u308C\u3066\u3044\u308B\u898F\u5247". This fires once per run, so reissuing will not repeat on the call in hand.';
|
|
2396
|
-
var
|
|
2397
|
-
var test_declared_commit = { REASON, ROW:
|
|
2918
|
+
var ROW17 = { id: "test-declared", is_trigger: is_untested_commit, reason: REASON };
|
|
2919
|
+
var test_declared_commit = { REASON, ROW: ROW17 };
|
|
2398
2920
|
|
|
2399
2921
|
// scripts/rules/third-party-write.ts
|
|
2400
2922
|
function is_third_party_write_segment(segment, session_owner) {
|
|
@@ -2410,87 +2932,24 @@ function writes_third_party(command, resolve_owner = repo_party.current_owner) {
|
|
|
2410
2932
|
return targets.some((segment) => is_third_party_write_segment(segment, session_owner));
|
|
2411
2933
|
}
|
|
2412
2934
|
var THIRD_PARTY_WRITE_REASON = '\u26D4 third-party write: this `gh api` call writes to a repository whose owner is not this session \u2014 a tracker we do not own is Tier C, and every write there (Issue, comment, PR, Discussion, review) needs explicit current-turn user instruction; typing the target, or holding a correct diagnosis, is not that instruction (`CLAUDE.md` \u2192 "Third-party repositories are Tier C", `prompts/collaboration-workflow/upstream-interrupt.md`). Confirm the party with `pnpm josh repo:party <owner/repo>` \u2014 owner equality, computed not judged. A read (`-X GET`, or no field flag) passes untouched; only a write (`-f`/`-F`/`--field`/`--raw-field`/`--input`, or `-X POST|PATCH|PUT|DELETE`) is refused. Record the finding on our own Issue and draft the artifact for a person to post \u2014 do not publish it yourself. **This rule fires on every occurrence, not once per run.**';
|
|
2413
|
-
var
|
|
2935
|
+
var ROW18 = {
|
|
2414
2936
|
id: "third-party-write",
|
|
2415
2937
|
is_trigger: bash_triggers.on_bash_command((command) => writes_third_party(command)),
|
|
2416
2938
|
reason: THIRD_PARTY_WRITE_REASON,
|
|
2417
2939
|
decide: () => true
|
|
2418
2940
|
};
|
|
2419
2941
|
var third_party_write = {
|
|
2420
|
-
ROW:
|
|
2942
|
+
ROW: ROW18,
|
|
2421
2943
|
THIRD_PARTY_WRITE_REASON,
|
|
2422
|
-
is_third_party_write_segment,
|
|
2423
2944
|
writes_third_party
|
|
2424
2945
|
};
|
|
2425
2946
|
|
|
2426
|
-
// scripts/rules/worktree-guard.ts
|
|
2427
|
-
var CHECKOUT_SUBCOMMAND = "checkout";
|
|
2428
|
-
var RESTORE_SUBCOMMAND = "restore";
|
|
2429
|
-
var STASH_SUBCOMMAND = "stash";
|
|
2430
|
-
var PATHSPEC_SEPARATOR = "--";
|
|
2431
|
-
function is_worktree_checkout(args) {
|
|
2432
|
-
return args.includes(PATHSPEC_SEPARATOR);
|
|
2433
|
-
}
|
|
2434
|
-
var STAGED_LONG = "--staged";
|
|
2435
|
-
var STAGED_LETTER = "S";
|
|
2436
|
-
var WORKTREE_LONG = "--worktree";
|
|
2437
|
-
var WORKTREE_LETTER = "W";
|
|
2438
|
-
function touches_worktree(args) {
|
|
2439
|
-
const is_staged = args.some(
|
|
2440
|
-
(argument) => argument === STAGED_LONG || git_argv.short_cluster_has(argument, STAGED_LETTER)
|
|
2441
|
-
);
|
|
2442
|
-
const is_worktree = args.some(
|
|
2443
|
-
(argument) => argument === WORKTREE_LONG || git_argv.short_cluster_has(argument, WORKTREE_LETTER)
|
|
2444
|
-
);
|
|
2445
|
-
return !is_staged || is_worktree;
|
|
2446
|
-
}
|
|
2447
|
-
var PUSH_STASH = "push";
|
|
2448
|
-
var MESSAGE_LONG = "--message";
|
|
2449
|
-
var MESSAGE_SHORT_LETTER = "m";
|
|
2450
|
-
var READ_ONLY_STASH = /* @__PURE__ */ new Set(["list", "show"]);
|
|
2451
|
-
function has_message(args) {
|
|
2452
|
-
return args.some(
|
|
2453
|
-
(argument) => argument === MESSAGE_LONG || argument.startsWith(`${MESSAGE_LONG}=`) || git_argv.short_cluster_has(argument, MESSAGE_SHORT_LETTER)
|
|
2454
|
-
);
|
|
2455
|
-
}
|
|
2456
|
-
function is_unauthorized_stash(args) {
|
|
2457
|
-
const [stash_subcommand, ...rest] = args;
|
|
2458
|
-
if (stash_subcommand === void 0) return true;
|
|
2459
|
-
if (READ_ONLY_STASH.has(stash_subcommand)) return false;
|
|
2460
|
-
if (stash_subcommand === PUSH_STASH) return !has_message(rest);
|
|
2461
|
-
return true;
|
|
2462
|
-
}
|
|
2463
|
-
function is_unauthorized_segment(segment) {
|
|
2464
|
-
const call = git_argv.parse(segment);
|
|
2465
|
-
if (call === void 0) return false;
|
|
2466
|
-
if (call.subcommand === CHECKOUT_SUBCOMMAND) return is_worktree_checkout(call.args);
|
|
2467
|
-
if (call.subcommand === RESTORE_SUBCOMMAND) return touches_worktree(call.args);
|
|
2468
|
-
return call.subcommand === STASH_SUBCOMMAND && is_unauthorized_stash(call.args);
|
|
2469
|
-
}
|
|
2470
|
-
function is_unauthorized_worktree_change(command) {
|
|
2471
|
-
return shell_segments.segments_of(command).some((segment) => is_unauthorized_segment(segment));
|
|
2472
|
-
}
|
|
2473
|
-
var WORKTREE_MUTATION_REASON = '\u26D4 unauthorized working-tree change: `git checkout -- <path>`, `git restore <path>` and an unauthorized `git stash` mutate the working tree or the repository-wide stash every work tree shares, and none is on the `.claude/settings.json` deny list (`operating-rules.md`). Do not run them on your own judgement. A commit goes through `pnpm josh git`; a stash pop goes through `pnpm josh stash:pop "<message>"`, never a positional `git stash pop` a shared stack lets another lane divert. A stash push is authorized only inside a documented flow and only with a findable message \u2014 `git stash push -u -m "<message>"` \u2014 which this row allows; a bare `git stash`, a message-less push, or `pop` / `apply` / `drop` is refused. **This rule fires on every occurrence, not once per run.**';
|
|
2474
|
-
var ROW15 = {
|
|
2475
|
-
id: "worktree-mutation",
|
|
2476
|
-
is_trigger: bash_triggers.on_bash_command(is_unauthorized_worktree_change),
|
|
2477
|
-
reason: WORKTREE_MUTATION_REASON,
|
|
2478
|
-
decide: () => true
|
|
2479
|
-
};
|
|
2480
|
-
var worktree_guard = {
|
|
2481
|
-
ROW: ROW15,
|
|
2482
|
-
WORKTREE_MUTATION_REASON,
|
|
2483
|
-
is_unauthorized_stash,
|
|
2484
|
-
is_unauthorized_worktree_change,
|
|
2485
|
-
is_worktree_checkout,
|
|
2486
|
-
touches_worktree
|
|
2487
|
-
};
|
|
2488
|
-
|
|
2489
2947
|
// scripts/rules/delivered-rules.ts
|
|
2490
2948
|
var SWITCH_ENV_KEY = "JOSH_RULE_GUARD";
|
|
2491
2949
|
var STAMP_PREFIX = "josh-rule-guard-";
|
|
2492
2950
|
var { is_issue_filing, on_bash_command } = bash_triggers;
|
|
2493
|
-
var
|
|
2951
|
+
var WIP_CAP = 30;
|
|
2952
|
+
var WIP_CAP_REASON = `\u26D4 backlog WIP cap: count the target repository's open Issues before filing. With more than ${String(WIP_CAP)} open, close one first; nothing honestly closable means do not file. Two filings are exempt and proceed while stating the overage \u2014 one the run is blocked by, and an interrupt, decided by three tests rather than judgement: a verification answers wrongly, a documented workflow cannot complete, or data is lost or written outside the repository. Meeting none of the three, the finding is discretionary and waits. The count command and both procedures are in \`prompts/collaboration-workflow/wip-cap.md\`. Reissue this call once you have counted \u2014 it fires once per run and cannot repeat on the call in hand.`;
|
|
2494
2953
|
var ISSUE_VIEW_COMMAND = new RegExp(String.raw`^gh\s+${gh_api.GH_FLAGS}issue\s+view\s`, "u");
|
|
2495
2954
|
var ISSUE_BODY_PATH = /repos\/[^\s'"]*\/issues\/\d+(?=$|["'\s])/u;
|
|
2496
2955
|
var FETCHES_COMMENTS = /--comments\b|--json\s[\w,]*\bcomments\b|\/comments\b/u;
|
|
@@ -2727,6 +3186,10 @@ var DELIVERED_RULES = [
|
|
|
2727
3186
|
git_force.ROW,
|
|
2728
3187
|
worktree_guard.ROW,
|
|
2729
3188
|
file_body.ROW,
|
|
3189
|
+
// **The deny-list bypasses closed by argv and path rather than glob** (joshuafolkken/kit#2983) — an
|
|
3190
|
+
// index mutation, a recursive forced `rm` or destructive `gh` call, and a protected file. Each
|
|
3191
|
+
// claims a command or file no row above does and refuses every occurrence (`permission-guards.ts`).
|
|
3192
|
+
...permission_guards.ROWS,
|
|
2730
3193
|
// **The hand-written wait loop a lane child improvises over a backgrounded command's output**
|
|
2731
3194
|
// (joshuafolkken/kit#2371). `early-heartbeat` refuses a bare `sleep` and stands down on any loop
|
|
2732
3195
|
// keyword; this is the loop it left — a `while`/`until` that sleeps between probes of an output
|
|
@@ -2819,12 +3282,12 @@ function is_first_delivery(tail, call, delivered_at_ms, run2) {
|
|
|
2819
3282
|
return delivered_at_ms === hook_decision.NEVER_MS && !will_batch_guard_refuse(tail, call, run2);
|
|
2820
3283
|
}
|
|
2821
3284
|
function delivery_decision(rule) {
|
|
2822
|
-
const { decide:
|
|
2823
|
-
if (
|
|
3285
|
+
const { decide: decide6, already_satisfied } = rule;
|
|
3286
|
+
if (decide6 === void 0 && already_satisfied === void 0) return is_first_delivery;
|
|
2824
3287
|
return function should_block(tail, call, delivered_at_ms, run2) {
|
|
2825
3288
|
if (already_satisfied?.(tail, call) === true) return false;
|
|
2826
|
-
if (
|
|
2827
|
-
return
|
|
3289
|
+
if (decide6 === void 0) return true;
|
|
3290
|
+
return decide6(call, run2, !will_batch_guard_refuse(tail, call, run2), delivered_at_ms);
|
|
2828
3291
|
};
|
|
2829
3292
|
}
|
|
2830
3293
|
function guard_of(rule) {
|
|
@@ -2870,6 +3333,7 @@ var delivered_rules = {
|
|
|
2870
3333
|
SHELL_BODY_REASON: SHELL_BODY_REASON2,
|
|
2871
3334
|
SWITCH_ENV_KEY,
|
|
2872
3335
|
THIRD_PARTY_WRITE_REASON: third_party_write.THIRD_PARTY_WRITE_REASON,
|
|
3336
|
+
WIP_CAP,
|
|
2873
3337
|
WIP_CAP_REASON,
|
|
2874
3338
|
WORKTREE_MUTATION_REASON: worktree_guard.WORKTREE_MUTATION_REASON,
|
|
2875
3339
|
delivery,
|
|
@@ -2880,12 +3344,12 @@ var delivered_rules = {
|
|
|
2880
3344
|
};
|
|
2881
3345
|
|
|
2882
3346
|
// scripts/run/run-watcher-hook.ts
|
|
2883
|
-
import { z as
|
|
3347
|
+
import { z as z19 } from "zod";
|
|
2884
3348
|
|
|
2885
3349
|
// scripts/run/run-progress-read.ts
|
|
2886
3350
|
import { loadavg } from "node:os";
|
|
2887
3351
|
|
|
2888
|
-
// scripts/
|
|
3352
|
+
// scripts/gh/git-gh-helpers.ts
|
|
2889
3353
|
function parse_pr_state_string(result) {
|
|
2890
3354
|
const trimmed = result.trim();
|
|
2891
3355
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
@@ -2908,95 +3372,94 @@ function handle_pr_create_error(error) {
|
|
|
2908
3372
|
}
|
|
2909
3373
|
var git_gh_helpers = {
|
|
2910
3374
|
parse_pr_state_string,
|
|
2911
|
-
is_pr_already_exists_message,
|
|
2912
3375
|
get_error_message_with_stderr,
|
|
2913
3376
|
handle_pr_create_error
|
|
2914
3377
|
};
|
|
2915
3378
|
|
|
2916
|
-
// scripts/git/git-gh-issue-rest.ts
|
|
2917
|
-
import { z as z7 } from "zod";
|
|
2918
|
-
|
|
2919
|
-
// scripts/git/git-gh-rest-state.ts
|
|
2920
|
-
var MERGED_STATE = "MERGED";
|
|
2921
|
-
function to_gh_state(state) {
|
|
2922
|
-
return state?.toUpperCase();
|
|
2923
|
-
}
|
|
2924
|
-
|
|
2925
3379
|
// scripts/git/schemas.ts
|
|
2926
|
-
import { z as
|
|
2927
|
-
var package_name_schema =
|
|
2928
|
-
var rollup_item_schema =
|
|
3380
|
+
import { z as z8 } from "zod";
|
|
3381
|
+
var package_name_schema = z8.object({ name: z8.string().min(1) });
|
|
3382
|
+
var rollup_item_schema = z8.looseObject({
|
|
2929
3383
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
|
|
2930
|
-
__typename:
|
|
2931
|
-
state:
|
|
2932
|
-
status:
|
|
2933
|
-
conclusion:
|
|
2934
|
-
name:
|
|
2935
|
-
context:
|
|
3384
|
+
__typename: z8.string().optional(),
|
|
3385
|
+
state: z8.string().optional(),
|
|
3386
|
+
status: z8.string().optional(),
|
|
3387
|
+
conclusion: z8.string().optional(),
|
|
3388
|
+
name: z8.string().optional(),
|
|
3389
|
+
context: z8.string().optional()
|
|
2936
3390
|
});
|
|
2937
|
-
var pr_raw_schema =
|
|
2938
|
-
statusCheckRollup:
|
|
2939
|
-
mergeStateStatus:
|
|
2940
|
-
reviewDecision:
|
|
3391
|
+
var pr_raw_schema = z8.object({
|
|
3392
|
+
statusCheckRollup: z8.array(rollup_item_schema).optional(),
|
|
3393
|
+
mergeStateStatus: z8.string().optional(),
|
|
3394
|
+
reviewDecision: z8.string().optional()
|
|
2941
3395
|
});
|
|
2942
|
-
var pull_comment_schema =
|
|
2943
|
-
body:
|
|
2944
|
-
html_url:
|
|
2945
|
-
user:
|
|
3396
|
+
var pull_comment_schema = z8.object({
|
|
3397
|
+
body: z8.string().optional(),
|
|
3398
|
+
html_url: z8.string().optional(),
|
|
3399
|
+
user: z8.object({ login: z8.string().optional() }).optional()
|
|
2946
3400
|
});
|
|
2947
|
-
var ai_review_pull_comment_schema =
|
|
2948
|
-
body:
|
|
2949
|
-
url:
|
|
2950
|
-
author:
|
|
3401
|
+
var ai_review_pull_comment_schema = z8.object({
|
|
3402
|
+
body: z8.string().optional(),
|
|
3403
|
+
url: z8.string().optional(),
|
|
3404
|
+
author: z8.object({ login: z8.string().optional() }).optional()
|
|
2951
3405
|
});
|
|
2952
|
-
var pr_info_schema =
|
|
2953
|
-
mergeable:
|
|
2954
|
-
mergeStateStatus:
|
|
2955
|
-
state:
|
|
3406
|
+
var pr_info_schema = z8.object({
|
|
3407
|
+
mergeable: z8.union([z8.boolean(), z8.string()]).nullable().optional(),
|
|
3408
|
+
mergeStateStatus: z8.string().nullable().optional(),
|
|
3409
|
+
state: z8.string().optional()
|
|
2956
3410
|
});
|
|
2957
|
-
var epic_issue_schema =
|
|
2958
|
-
number:
|
|
2959
|
-
body:
|
|
3411
|
+
var epic_issue_schema = z8.object({
|
|
3412
|
+
number: z8.number(),
|
|
3413
|
+
body: z8.string().optional()
|
|
2960
3414
|
});
|
|
2961
|
-
var blocking_issue_schema =
|
|
2962
|
-
number:
|
|
2963
|
-
state:
|
|
2964
|
-
repository_url:
|
|
3415
|
+
var blocking_issue_schema = z8.object({
|
|
3416
|
+
number: z8.number(),
|
|
3417
|
+
state: z8.string().optional(),
|
|
3418
|
+
repository_url: z8.string().optional()
|
|
2965
3419
|
});
|
|
2966
|
-
var blocked_by_schema =
|
|
2967
|
-
nodes:
|
|
2968
|
-
totalCount:
|
|
3420
|
+
var blocked_by_schema = z8.object({
|
|
3421
|
+
nodes: z8.array(blocking_issue_schema).default([]),
|
|
3422
|
+
totalCount: z8.number().optional()
|
|
2969
3423
|
}).optional();
|
|
2970
|
-
var epic_child_schema =
|
|
2971
|
-
state:
|
|
3424
|
+
var epic_child_schema = z8.object({
|
|
3425
|
+
state: z8.string().optional(),
|
|
2972
3426
|
blockedBy: blocked_by_schema
|
|
2973
3427
|
});
|
|
2974
|
-
var rest_comment_schema =
|
|
2975
|
-
body:
|
|
2976
|
-
html_url:
|
|
2977
|
-
user:
|
|
3428
|
+
var rest_comment_schema = z8.looseObject({
|
|
3429
|
+
body: z8.string().nullish(),
|
|
3430
|
+
html_url: z8.string().optional(),
|
|
3431
|
+
user: z8.looseObject({ login: z8.string().optional() }).nullish()
|
|
2978
3432
|
});
|
|
2979
|
-
var issue_label_schema =
|
|
2980
|
-
var epic_subject_schema =
|
|
2981
|
-
number:
|
|
2982
|
-
state:
|
|
2983
|
-
labels:
|
|
2984
|
-
body:
|
|
3433
|
+
var issue_label_schema = z8.object({ name: z8.string() });
|
|
3434
|
+
var epic_subject_schema = z8.object({
|
|
3435
|
+
number: z8.number(),
|
|
3436
|
+
state: z8.string().optional(),
|
|
3437
|
+
labels: z8.array(issue_label_schema).optional(),
|
|
3438
|
+
body: z8.string().optional()
|
|
2985
3439
|
});
|
|
2986
|
-
var open_issue_schema =
|
|
2987
|
-
number:
|
|
2988
|
-
title:
|
|
2989
|
-
labels:
|
|
2990
|
-
createdAt:
|
|
3440
|
+
var open_issue_schema = z8.object({
|
|
3441
|
+
number: z8.number(),
|
|
3442
|
+
title: z8.string(),
|
|
3443
|
+
labels: z8.array(issue_label_schema).optional(),
|
|
3444
|
+
createdAt: z8.string(),
|
|
2991
3445
|
blockedBy: blocked_by_schema
|
|
2992
3446
|
});
|
|
2993
3447
|
|
|
2994
|
-
// scripts/
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3448
|
+
// scripts/gh/git-gh-issue-rest.ts
|
|
3449
|
+
import { z as z9 } from "zod";
|
|
3450
|
+
|
|
3451
|
+
// scripts/gh/git-gh-rest-state.ts
|
|
3452
|
+
var MERGED_STATE = "MERGED";
|
|
3453
|
+
function to_gh_state(state) {
|
|
3454
|
+
return state?.toUpperCase();
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
// scripts/gh/git-gh-issue-rest.ts
|
|
3458
|
+
var rest_issue_schema = z9.looseObject({
|
|
3459
|
+
number: z9.number(),
|
|
3460
|
+
issue_dependencies_summary: z9.looseObject({ total_blocked_by: z9.number().optional() }).nullish(),
|
|
2998
3461
|
// Present only on a pull request, which this endpoint serves as readily as an issue.
|
|
2999
|
-
pull_request:
|
|
3462
|
+
pull_request: z9.looseObject({ merged_at: z9.string().nullish() }).nullish()
|
|
3000
3463
|
});
|
|
3001
3464
|
var REPOSITORY_URL = /\/repos\/([\w.-]+\/[\w.-]+)$/u;
|
|
3002
3465
|
var REPOSITORY_URL_GROUP = 1;
|
|
@@ -3090,7 +3553,7 @@ var git_gh_issue_rest = {
|
|
|
3090
3553
|
to_field_text
|
|
3091
3554
|
};
|
|
3092
3555
|
|
|
3093
|
-
// scripts/
|
|
3556
|
+
// scripts/gh/git-gh-reachability.ts
|
|
3094
3557
|
var RATE_LIMITED_STATUS = 429;
|
|
3095
3558
|
var SERVER_ERROR_FLOOR = 500;
|
|
3096
3559
|
function is_retryable_status(status) {
|
|
@@ -3103,7 +3566,7 @@ function classify_status(status) {
|
|
|
3103
3566
|
}
|
|
3104
3567
|
var gh_reachability = { classify_status };
|
|
3105
3568
|
|
|
3106
|
-
// scripts/
|
|
3569
|
+
// scripts/gh/git-gh-issue-read.ts
|
|
3107
3570
|
async function read_blocked_by_listing(issue_number, repo, exact_total) {
|
|
3108
3571
|
const json = await git_gh_exec.exec_gh_api({
|
|
3109
3572
|
path: `${git_gh_api_path.blocked_by_api_path(issue_number, repo)}${git_gh_api_path.FULL_PAGE_QUERY}`
|
|
@@ -3209,9 +3672,9 @@ async function issue_get_labels_and_body(issue_number) {
|
|
|
3209
3672
|
return await issue_view_json(issue_number, "number,state,labels,body");
|
|
3210
3673
|
}
|
|
3211
3674
|
async function issue_list_comments(issue_number) {
|
|
3212
|
-
const
|
|
3675
|
+
const path10 = `${git_gh_api_path.issue_comments_api_path(issue_number)}${git_gh_api_path.FULL_PAGE_QUERY}`;
|
|
3213
3676
|
try {
|
|
3214
|
-
return await git_gh_exec.exec_gh_api({ path:
|
|
3677
|
+
return await git_gh_exec.exec_gh_api({ path: path10, should_paginate: true });
|
|
3215
3678
|
} catch {
|
|
3216
3679
|
return void 0;
|
|
3217
3680
|
}
|
|
@@ -3252,7 +3715,7 @@ var git_gh_issue_read = {
|
|
|
3252
3715
|
issue_list_comments
|
|
3253
3716
|
};
|
|
3254
3717
|
|
|
3255
|
-
// scripts/
|
|
3718
|
+
// scripts/gh/git-gh-issue-list.ts
|
|
3256
3719
|
var PER_PAGE = 100;
|
|
3257
3720
|
var FIRST_PAGE = 1;
|
|
3258
3721
|
var DEFAULT_STATE = "open";
|
|
@@ -3286,8 +3749,8 @@ function is_selected(rest, request) {
|
|
|
3286
3749
|
return !git_gh_issue_rest.is_pull_request(rest) && matches_body(rest, request.body_term);
|
|
3287
3750
|
}
|
|
3288
3751
|
async function fetch_page(request, page) {
|
|
3289
|
-
const
|
|
3290
|
-
const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path:
|
|
3752
|
+
const path10 = listing_path(request, page);
|
|
3753
|
+
const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path: path10 }));
|
|
3291
3754
|
return {
|
|
3292
3755
|
selected: rows.filter((row) => is_selected(row, request)),
|
|
3293
3756
|
is_full: rows.length >= PER_PAGE
|
|
@@ -3337,9 +3800,9 @@ var git_gh_issue_list = {
|
|
|
3337
3800
|
issue_list
|
|
3338
3801
|
};
|
|
3339
3802
|
|
|
3340
|
-
// scripts/
|
|
3803
|
+
// scripts/gh/git-gh-issue-write.ts
|
|
3341
3804
|
var PATCH_METHOD = "PATCH";
|
|
3342
|
-
var
|
|
3805
|
+
var DELETE_METHOD2 = "DELETE";
|
|
3343
3806
|
var HTML_URL_FILTER = ".html_url";
|
|
3344
3807
|
var ID_FILTER = ".id";
|
|
3345
3808
|
var LABELS_SEGMENT = "/labels";
|
|
@@ -3427,7 +3890,7 @@ async function issue_remove_label(issue_number, label) {
|
|
|
3427
3890
|
const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`;
|
|
3428
3891
|
await git_gh_exec.exec_gh_api({
|
|
3429
3892
|
path: `${labels_path}/${encodeURIComponent(label)}`,
|
|
3430
|
-
method:
|
|
3893
|
+
method: DELETE_METHOD2
|
|
3431
3894
|
});
|
|
3432
3895
|
}
|
|
3433
3896
|
async function read_issue_id(issue_number) {
|
|
@@ -3456,7 +3919,7 @@ async function issue_remove_blocked_by(issue_number, blocker) {
|
|
|
3456
3919
|
const relations_path = git_gh_api_path.blocked_by_api_path(issue_number);
|
|
3457
3920
|
await git_gh_exec.exec_gh_api({
|
|
3458
3921
|
path: `${relations_path}/${String(issue_id)}`,
|
|
3459
|
-
method:
|
|
3922
|
+
method: DELETE_METHOD2
|
|
3460
3923
|
});
|
|
3461
3924
|
});
|
|
3462
3925
|
}
|
|
@@ -3474,7 +3937,7 @@ var git_gh_issue_write = {
|
|
|
3474
3937
|
issue_remove_blocked_by
|
|
3475
3938
|
};
|
|
3476
3939
|
|
|
3477
|
-
// scripts/
|
|
3940
|
+
// scripts/gh/git-gh-issue.ts
|
|
3478
3941
|
var NUMBER_AND_BODY_FIELDS = "number,body";
|
|
3479
3942
|
var BACKLOG_SCAN_FIELDS = `number,title,body,${BLOCKED_BY_COUNT_FIELD}`;
|
|
3480
3943
|
var NUMBER_TITLE_AND_LABELS_FIELDS = "number,title,labels";
|
|
@@ -3530,18 +3993,18 @@ var git_gh_issue = {
|
|
|
3530
3993
|
// scripts/ci/pr-classification.ts
|
|
3531
3994
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
3532
3995
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3533
|
-
import { z as
|
|
3996
|
+
import { z as z10 } from "zod";
|
|
3534
3997
|
var CLASSIFICATION_SET = new Set(RELEASE_CLASSIFICATION_NAMES);
|
|
3535
3998
|
var ISSUE_BUG_LABEL = "bug";
|
|
3536
3999
|
var DECLARATION_PREFIX = "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: ";
|
|
3537
4000
|
var DECLARATION = new RegExp(`^${DECLARATION_PREFIX}(.+)$`, "gmu");
|
|
3538
4001
|
var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
|
|
3539
|
-
var LABEL =
|
|
3540
|
-
var USER =
|
|
3541
|
-
var PULL_REQUEST =
|
|
3542
|
-
var EVENT =
|
|
4002
|
+
var LABEL = z10.object({ name: z10.string() });
|
|
4003
|
+
var USER = z10.object({ login: z10.string() });
|
|
4004
|
+
var PULL_REQUEST = z10.object({ number: z10.number(), user: USER });
|
|
4005
|
+
var EVENT = z10.object({
|
|
3543
4006
|
pull_request: PULL_REQUEST,
|
|
3544
|
-
repository:
|
|
4007
|
+
repository: z10.object({ full_name: z10.string() })
|
|
3545
4008
|
});
|
|
3546
4009
|
function classification_error(labels, author) {
|
|
3547
4010
|
const legacy = labels.filter((label) => LEGACY_LABELS.has(label.toLowerCase()));
|
|
@@ -3564,7 +4027,7 @@ function release_candidates(candidates) {
|
|
|
3564
4027
|
return candidates.filter((candidate) => candidate !== ENHANCEMENT_LABEL);
|
|
3565
4028
|
}
|
|
3566
4029
|
function issue_candidates(issue_json) {
|
|
3567
|
-
const issue =
|
|
4030
|
+
const issue = z10.object({ labels: z10.array(LABEL), body: z10.string().nullable() }).parse(JSON.parse(issue_json));
|
|
3568
4031
|
const names = issue.labels.map((label) => label.name.toLowerCase());
|
|
3569
4032
|
const declared = [...(issue.body ?? "").matchAll(DECLARATION)].map((match) => match[1] ?? "");
|
|
3570
4033
|
const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
|
|
@@ -3587,9 +4050,9 @@ function select_issue_classification(issue_json) {
|
|
|
3587
4050
|
return label;
|
|
3588
4051
|
}
|
|
3589
4052
|
function fetch_current_labels(repository, pull_number) {
|
|
3590
|
-
const
|
|
4053
|
+
const path10 = `repos/${repository}/issues/${String(pull_number)}/labels`;
|
|
3591
4054
|
try {
|
|
3592
|
-
const names = git_gh_exec.exec_gh_api_sync({ path:
|
|
4055
|
+
const names = git_gh_exec.exec_gh_api_sync({ path: path10, jq_filter: ".[].name" });
|
|
3593
4056
|
return names.split("\n").filter((name) => name !== "");
|
|
3594
4057
|
} catch (error) {
|
|
3595
4058
|
const detail = error_text.message_of(error);
|
|
@@ -3638,32 +4101,32 @@ async function poll_until(is_done, options) {
|
|
|
3638
4101
|
}
|
|
3639
4102
|
var poll = { poll_until, sleep };
|
|
3640
4103
|
|
|
3641
|
-
// scripts/
|
|
3642
|
-
import { z as
|
|
4104
|
+
// scripts/gh/git-gh-pr.ts
|
|
4105
|
+
import { z as z14 } from "zod";
|
|
3643
4106
|
|
|
3644
|
-
// scripts/
|
|
3645
|
-
import { z as
|
|
3646
|
-
var rest_repo_schema =
|
|
3647
|
-
var rest_pull_side_schema =
|
|
3648
|
-
var rest_pull_schema =
|
|
3649
|
-
number:
|
|
3650
|
-
html_url:
|
|
3651
|
-
body:
|
|
3652
|
-
state:
|
|
3653
|
-
merged:
|
|
3654
|
-
merged_at:
|
|
3655
|
-
mergeable:
|
|
3656
|
-
mergeable_state:
|
|
4107
|
+
// scripts/gh/git-gh-pr-rest.ts
|
|
4108
|
+
import { z as z11 } from "zod";
|
|
4109
|
+
var rest_repo_schema = z11.looseObject({ full_name: z11.string().optional() }).nullish();
|
|
4110
|
+
var rest_pull_side_schema = z11.looseObject({ repo: rest_repo_schema });
|
|
4111
|
+
var rest_pull_schema = z11.looseObject({
|
|
4112
|
+
number: z11.number(),
|
|
4113
|
+
html_url: z11.string().optional(),
|
|
4114
|
+
body: z11.string().nullish(),
|
|
4115
|
+
state: z11.string().optional(),
|
|
4116
|
+
merged: z11.boolean().nullish(),
|
|
4117
|
+
merged_at: z11.string().nullish(),
|
|
4118
|
+
mergeable: z11.boolean().nullish(),
|
|
4119
|
+
mergeable_state: z11.string().optional(),
|
|
3657
4120
|
// `sha` is the head commit, which is what both halves of the merge-gate rollup are keyed by —
|
|
3658
4121
|
// REST hangs the check runs and the status contexts off the commit rather than off the pull
|
|
3659
4122
|
// request (joshuafolkken/kit#1028).
|
|
3660
|
-
head:
|
|
4123
|
+
head: z11.looseObject({ ref: z11.string().optional(), sha: z11.string().optional(), repo: rest_repo_schema }).nullish(),
|
|
3661
4124
|
base: rest_pull_side_schema.nullish(),
|
|
3662
4125
|
// `node_id` is what the GraphQL auto-merge mutation addresses a pull request by, and `auto_merge`
|
|
3663
4126
|
// is `null` until auto-merge is enabled — both read by `git-gh-pr-auto-merge.ts`
|
|
3664
4127
|
// (joshuafolkken/kit#2497).
|
|
3665
|
-
node_id:
|
|
3666
|
-
auto_merge:
|
|
4128
|
+
node_id: z11.string().optional(),
|
|
4129
|
+
auto_merge: z11.looseObject({}).nullish()
|
|
3667
4130
|
});
|
|
3668
4131
|
var NOT_A_PULL_MESSAGE = "gh api answered something other than a pull request object";
|
|
3669
4132
|
var NOT_A_PULL_LISTING_MESSAGE = "gh api answered something other than a pull request listing";
|
|
@@ -3723,7 +4186,7 @@ var git_gh_pr_rest = {
|
|
|
3723
4186
|
to_pr_comments
|
|
3724
4187
|
};
|
|
3725
4188
|
|
|
3726
|
-
// scripts/
|
|
4189
|
+
// scripts/gh/git-gh-pr-read.ts
|
|
3727
4190
|
var pr_number_by_branch = /* @__PURE__ */ new Map();
|
|
3728
4191
|
var LOOKUP_QUERY = "state=all&sort=created&direction=desc&per_page=100";
|
|
3729
4192
|
var COMMENTS_QUERY = FULL_PAGE_QUERY;
|
|
@@ -3810,6 +4273,15 @@ async function pr_get_url(branch_name) {
|
|
|
3810
4273
|
if (pull?.html_url === void 0) return void 0;
|
|
3811
4274
|
return git_gh_helpers.parse_pr_state_string(pull.html_url);
|
|
3812
4275
|
}
|
|
4276
|
+
async function pr_get_merge_state(branch_name) {
|
|
4277
|
+
const pull = await read_pull_of_branch(branch_name);
|
|
4278
|
+
if (pull === void 0) return void 0;
|
|
4279
|
+
return {
|
|
4280
|
+
is_merged: git_gh_pr_rest.is_merged(pull),
|
|
4281
|
+
merged_at: pull.merged_at ?? void 0,
|
|
4282
|
+
head_sha: pull.head?.sha
|
|
4283
|
+
};
|
|
4284
|
+
}
|
|
3813
4285
|
async function pr_get_body(branch_name) {
|
|
3814
4286
|
const pull = await read_pull_of_branch(branch_name);
|
|
3815
4287
|
const body = pull?.body;
|
|
@@ -3823,9 +4295,9 @@ async function pr_view(branch_name) {
|
|
|
3823
4295
|
async function read_comments(branch_name, to_path, to_json) {
|
|
3824
4296
|
const pr_number = await resolve_pr_number(branch_name);
|
|
3825
4297
|
if (pr_number === void 0) return void 0;
|
|
3826
|
-
const
|
|
4298
|
+
const path10 = `${to_path(String(pr_number))}${COMMENTS_QUERY}`;
|
|
3827
4299
|
try {
|
|
3828
|
-
return to_json(await git_gh_exec.exec_gh_api({ path:
|
|
4300
|
+
return to_json(await git_gh_exec.exec_gh_api({ path: path10, should_paginate: true }));
|
|
3829
4301
|
} catch {
|
|
3830
4302
|
return void 0;
|
|
3831
4303
|
}
|
|
@@ -3847,20 +4319,21 @@ var git_gh_pr_read = {
|
|
|
3847
4319
|
pr_get_number,
|
|
3848
4320
|
pr_get_url,
|
|
3849
4321
|
pr_get_body,
|
|
4322
|
+
pr_get_merge_state,
|
|
3850
4323
|
pr_view,
|
|
3851
4324
|
pr_get_comments,
|
|
3852
4325
|
pr_get_review_comments
|
|
3853
4326
|
};
|
|
3854
4327
|
|
|
3855
|
-
// scripts/
|
|
3856
|
-
import { z as
|
|
4328
|
+
// scripts/gh/git-gh-pr-review.ts
|
|
4329
|
+
import { z as z12 } from "zod";
|
|
3857
4330
|
var REVIEW_APPROVED = "APPROVED";
|
|
3858
4331
|
var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
|
|
3859
4332
|
var REVIEW_NONE = "";
|
|
3860
4333
|
var STATE_CHANGING_REVIEWS = /* @__PURE__ */ new Set([REVIEW_APPROVED, REVIEW_CHANGES_REQUESTED]);
|
|
3861
|
-
var rest_review_schema =
|
|
3862
|
-
state:
|
|
3863
|
-
user:
|
|
4334
|
+
var rest_review_schema = z12.looseObject({
|
|
4335
|
+
state: z12.string().optional(),
|
|
4336
|
+
user: z12.looseObject({ login: z12.string().optional() }).nullish()
|
|
3864
4337
|
});
|
|
3865
4338
|
var NOT_A_REVIEW_LISTING = "gh api answered something other than a review listing";
|
|
3866
4339
|
function parse_rest_reviews(reviews_json) {
|
|
@@ -3890,21 +4363,21 @@ function to_review_decision(reviews_json) {
|
|
|
3890
4363
|
if (latest.has(REVIEW_CHANGES_REQUESTED)) return REVIEW_CHANGES_REQUESTED;
|
|
3891
4364
|
return latest.has(REVIEW_APPROVED) ? REVIEW_APPROVED : REVIEW_NONE;
|
|
3892
4365
|
}
|
|
3893
|
-
var git_gh_pr_review = { to_review_decision
|
|
4366
|
+
var git_gh_pr_review = { to_review_decision };
|
|
3894
4367
|
|
|
3895
|
-
// scripts/
|
|
3896
|
-
import { z as
|
|
4368
|
+
// scripts/gh/git-gh-pr-rollup.ts
|
|
4369
|
+
import { z as z13 } from "zod";
|
|
3897
4370
|
var STATUS_CONTEXT_TYPE_NAME = "StatusContext";
|
|
3898
4371
|
var TYPE_NAME_KEY = "__typename";
|
|
3899
|
-
var rollup_element_schema =
|
|
3900
|
-
var check_runs_page_schema =
|
|
4372
|
+
var rollup_element_schema = z13.looseObject({});
|
|
4373
|
+
var check_runs_page_schema = z13.looseObject({
|
|
3901
4374
|
// Required, not optional: GitHub always names the key, and accepting a page without one would
|
|
3902
4375
|
// answer an empty rollup — which `git-pr-followup.ts` reports as "this branch has no checks".
|
|
3903
|
-
check_runs:
|
|
4376
|
+
check_runs: z13.array(rollup_element_schema)
|
|
3904
4377
|
});
|
|
3905
|
-
var id_holder_schema =
|
|
3906
|
-
var status_page_schema =
|
|
3907
|
-
statuses:
|
|
4378
|
+
var id_holder_schema = z13.object({ id: z13.number() });
|
|
4379
|
+
var status_page_schema = z13.looseObject({
|
|
4380
|
+
statuses: z13.array(rollup_element_schema)
|
|
3908
4381
|
});
|
|
3909
4382
|
var NOT_A_CHECK_RUNS_LISTING = "gh api answered something other than a check run listing";
|
|
3910
4383
|
var NOT_A_STATUS_LISTING = "gh api answered something other than a commit status listing";
|
|
@@ -3965,23 +4438,21 @@ function to_status_check_rollup(input) {
|
|
|
3965
4438
|
];
|
|
3966
4439
|
}
|
|
3967
4440
|
var git_gh_pr_rollup = {
|
|
3968
|
-
to_check_run_items,
|
|
3969
|
-
to_status_context_items,
|
|
3970
4441
|
to_status_check_rollup
|
|
3971
4442
|
};
|
|
3972
4443
|
|
|
3973
|
-
// scripts/
|
|
4444
|
+
// scripts/gh/git-gh-pr-snapshot.ts
|
|
3974
4445
|
var NO_HEAD_SHA_MESSAGE = "gh api answered a pull request with no head commit";
|
|
3975
|
-
async function read_object_pages(
|
|
4446
|
+
async function read_object_pages(path10) {
|
|
3976
4447
|
return await git_gh_exec.exec_gh_api({
|
|
3977
|
-
path: `${
|
|
4448
|
+
path: `${path10}${FULL_PAGE_QUERY}`,
|
|
3978
4449
|
should_paginate: true,
|
|
3979
4450
|
should_slurp: true
|
|
3980
4451
|
});
|
|
3981
4452
|
}
|
|
3982
|
-
async function read_array_pages(
|
|
4453
|
+
async function read_array_pages(path10) {
|
|
3983
4454
|
return await git_gh_exec.exec_gh_api({
|
|
3984
|
-
path: `${
|
|
4455
|
+
path: `${path10}${FULL_PAGE_QUERY}`,
|
|
3985
4456
|
should_paginate: true
|
|
3986
4457
|
});
|
|
3987
4458
|
}
|
|
@@ -3998,8 +4469,8 @@ async function read_status_check_rollup(commit_sha) {
|
|
|
3998
4469
|
return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json });
|
|
3999
4470
|
}
|
|
4000
4471
|
async function pr_get_review_decision(pr_number) {
|
|
4001
|
-
const
|
|
4002
|
-
return git_gh_pr_review.to_review_decision(await read_array_pages(
|
|
4472
|
+
const path10 = git_gh_api_path.pull_reviews_api_path(String(pr_number));
|
|
4473
|
+
return git_gh_pr_review.to_review_decision(await read_array_pages(path10));
|
|
4003
4474
|
}
|
|
4004
4475
|
async function build_checks_fields(pull) {
|
|
4005
4476
|
return {
|
|
@@ -4029,7 +4500,7 @@ var git_gh_pr_snapshot = {
|
|
|
4029
4500
|
pr_get_review_decision
|
|
4030
4501
|
};
|
|
4031
4502
|
|
|
4032
|
-
// scripts/
|
|
4503
|
+
// scripts/gh/git-gh-pr.ts
|
|
4033
4504
|
var HTML_URL_FILTER2 = ".html_url";
|
|
4034
4505
|
var PUT_METHOD = "PUT";
|
|
4035
4506
|
var PATCH_METHOD2 = "PATCH";
|
|
@@ -4040,7 +4511,7 @@ var MERGE_READ_BACK_ATTEMPTS = 3;
|
|
|
4040
4511
|
var MERGE_READ_BACK_INTERVAL_MS = 1e3;
|
|
4041
4512
|
var PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u;
|
|
4042
4513
|
var LABELS_SEGMENT2 = "/labels";
|
|
4043
|
-
var PR_LABELS =
|
|
4514
|
+
var PR_LABELS = z14.array(z14.object({ name: z14.string() }));
|
|
4044
4515
|
async function add_pr_classification(number, label) {
|
|
4045
4516
|
await git_gh_exec.exec_gh_api({
|
|
4046
4517
|
path: `${git_gh_api_path.issue_api_path(number)}${LABELS_SEGMENT2}`,
|
|
@@ -4145,7 +4616,7 @@ var git_gh_pr = {
|
|
|
4145
4616
|
pr_update_body
|
|
4146
4617
|
};
|
|
4147
4618
|
|
|
4148
|
-
// scripts/
|
|
4619
|
+
// scripts/gh/git-gh-pr-auto-merge.ts
|
|
4149
4620
|
var GRAPHQL_PATH = "graphql";
|
|
4150
4621
|
var OPEN_PULLS_QUERY = `${git_gh_api_path.FULL_PAGE_QUERY}&state=open`;
|
|
4151
4622
|
var MISSING_NODE_ID_MESSAGE = "gh api answered a pull request without a node_id";
|
|
@@ -4191,7 +4662,7 @@ var git_gh_pr_auto_merge = {
|
|
|
4191
4662
|
pr_list_open_with_head_prefix
|
|
4192
4663
|
};
|
|
4193
4664
|
|
|
4194
|
-
// scripts/
|
|
4665
|
+
// scripts/gh/git-gh-repo.ts
|
|
4195
4666
|
async function repo_get_name_with_owner() {
|
|
4196
4667
|
try {
|
|
4197
4668
|
const result = await git_gh_exec.exec_gh_api({
|
|
@@ -4207,7 +4678,7 @@ var git_gh_repo = {
|
|
|
4207
4678
|
repo_get_name_with_owner
|
|
4208
4679
|
};
|
|
4209
4680
|
|
|
4210
|
-
// scripts/
|
|
4681
|
+
// scripts/gh/git-pr-checks-parse.ts
|
|
4211
4682
|
var CHECK_STATUS_PASS = "pass";
|
|
4212
4683
|
var CHECK_STATUS_PENDING = "pending";
|
|
4213
4684
|
var CHECK_STATUS_FAIL = "fail";
|
|
@@ -4251,20 +4722,13 @@ function read_rollup_array(parsed) {
|
|
|
4251
4722
|
if (!result.success) return [];
|
|
4252
4723
|
return result.data.statusCheckRollup ?? [];
|
|
4253
4724
|
}
|
|
4254
|
-
function parse_json_safe(raw_json) {
|
|
4255
|
-
try {
|
|
4256
|
-
return JSON.parse(raw_json);
|
|
4257
|
-
} catch {
|
|
4258
|
-
return void 0;
|
|
4259
|
-
}
|
|
4260
|
-
}
|
|
4261
4725
|
function parse_rollup_item(item) {
|
|
4262
4726
|
const name = read_string(item[KEY_NAME]) ?? read_string(item[KEY_CONTEXT]);
|
|
4263
4727
|
if (name === void 0) return void 0;
|
|
4264
4728
|
return { name, status: parse_rollup_status(item) };
|
|
4265
4729
|
}
|
|
4266
4730
|
function parse_rollup_checks(raw_json) {
|
|
4267
|
-
const parsed =
|
|
4731
|
+
const parsed = json_value.parse_or_undefined(raw_json);
|
|
4268
4732
|
const rollup = read_rollup_array(parsed);
|
|
4269
4733
|
const checks = [];
|
|
4270
4734
|
for (const item of rollup) {
|
|
@@ -4274,7 +4738,7 @@ function parse_rollup_checks(raw_json) {
|
|
|
4274
4738
|
return checks;
|
|
4275
4739
|
}
|
|
4276
4740
|
function parse_pr_state_snapshot(raw_json) {
|
|
4277
|
-
const parsed =
|
|
4741
|
+
const parsed = json_value.parse_or_undefined(raw_json);
|
|
4278
4742
|
const result = pr_raw_schema.safeParse(parsed);
|
|
4279
4743
|
const data = result.success ? result.data : void 0;
|
|
4280
4744
|
return {
|
|
@@ -4284,14 +4748,14 @@ function parse_pr_state_snapshot(raw_json) {
|
|
|
4284
4748
|
};
|
|
4285
4749
|
}
|
|
4286
4750
|
|
|
4287
|
-
// scripts/
|
|
4751
|
+
// scripts/gh/git-pr-checks-eval.ts
|
|
4288
4752
|
var DEFAULT_REQUIRED_CHECKS = ["SonarQube"];
|
|
4289
4753
|
var CODERABBIT_CHECK_NAME = "CodeRabbit";
|
|
4290
4754
|
var REQUIRED_CHECKS_ENV_VAR = "JOSH_REQUIRED_CHECKS";
|
|
4291
4755
|
function parse_required_checks() {
|
|
4292
4756
|
const raw = process.env[REQUIRED_CHECKS_ENV_VAR];
|
|
4293
4757
|
if (!raw) return DEFAULT_REQUIRED_CHECKS;
|
|
4294
|
-
return raw.split(",").map((
|
|
4758
|
+
return raw.split(",").map((check4) => check4.trim()).filter((check4) => check4.length > 0);
|
|
4295
4759
|
}
|
|
4296
4760
|
var REQUIRED_CHECKS = parse_required_checks();
|
|
4297
4761
|
var MERGE_STATE_CLEAN = "CLEAN";
|
|
@@ -4308,7 +4772,7 @@ function is_required_match(check_name, required_name) {
|
|
|
4308
4772
|
return check_name.startsWith(`${required_name}${CHECK_SUITE_SEPARATOR}`);
|
|
4309
4773
|
}
|
|
4310
4774
|
function find_required_check(checks, required_name) {
|
|
4311
|
-
return checks.find((
|
|
4775
|
+
return checks.find((check4) => is_required_match(check4.name, required_name));
|
|
4312
4776
|
}
|
|
4313
4777
|
function read_required_statuses(checks) {
|
|
4314
4778
|
return REQUIRED_CHECKS.map(
|
|
@@ -4338,19 +4802,19 @@ function is_coderabbit_check(check_name) {
|
|
|
4338
4802
|
}
|
|
4339
4803
|
function is_unstable_only_from_coderabbit(snapshot) {
|
|
4340
4804
|
if (snapshot.merge_state_status !== MERGE_STATE_UNSTABLE) return false;
|
|
4341
|
-
const non_passing = snapshot.rollup.filter((
|
|
4805
|
+
const non_passing = snapshot.rollup.filter((check4) => check4.status !== CHECK_STATUS_PASS);
|
|
4342
4806
|
if (non_passing.length === 0) return false;
|
|
4343
|
-
return non_passing.every((
|
|
4807
|
+
return non_passing.every((check4) => is_coderabbit_check(check4.name));
|
|
4344
4808
|
}
|
|
4345
4809
|
function is_required_check(check_name) {
|
|
4346
4810
|
return REQUIRED_CHECKS.some((required) => is_required_match(check_name, required));
|
|
4347
4811
|
}
|
|
4348
|
-
function is_blocking_failure(
|
|
4349
|
-
if (
|
|
4350
|
-
return !is_coderabbit_check(
|
|
4812
|
+
function is_blocking_failure(check4) {
|
|
4813
|
+
if (check4.status !== CHECK_STATUS_FAIL) return false;
|
|
4814
|
+
return !is_coderabbit_check(check4.name) || is_required_check(check4.name);
|
|
4351
4815
|
}
|
|
4352
4816
|
function collect_blocking_failures(snapshot) {
|
|
4353
|
-
return snapshot.rollup.filter((
|
|
4817
|
+
return snapshot.rollup.filter((check4) => is_blocking_failure(check4)).map((check4) => check4.name);
|
|
4354
4818
|
}
|
|
4355
4819
|
function is_mergeable_state(snapshot) {
|
|
4356
4820
|
if (is_merge_state_clean(snapshot.merge_state_status)) return true;
|
|
@@ -4386,7 +4850,7 @@ function is_review_decision_decisive(snapshot) {
|
|
|
4386
4850
|
return evaluate_pr_state(snapshot) !== "pending";
|
|
4387
4851
|
}
|
|
4388
4852
|
|
|
4389
|
-
// scripts/
|
|
4853
|
+
// scripts/gh/git-pr-checks.ts
|
|
4390
4854
|
var SECONDS_TO_MS = 1e3;
|
|
4391
4855
|
var CHECK_WAIT_INTERVAL_MS = 1e4;
|
|
4392
4856
|
var DEFAULT_TIMEOUT_SECONDS = 1920;
|
|
@@ -4489,25 +4953,25 @@ async function default_fetch_pr_state(branch_name, should_read_review_decision =
|
|
|
4489
4953
|
return { ...snapshot, review_decision: read_string(decision) };
|
|
4490
4954
|
}
|
|
4491
4955
|
|
|
4492
|
-
// scripts/
|
|
4956
|
+
// scripts/gh/git-pr-checks-watch.ts
|
|
4493
4957
|
var PR_CHECKS_WATCH_TIMEOUT_MS = 12e4;
|
|
4494
4958
|
var WATCH_TIMED_OUT_NOTE = "\u23F1\uFE0F pr checks --watch timed out.";
|
|
4495
4959
|
var NO_CHECKS_MESSAGE = "gh api reported no checks on the branch";
|
|
4496
4960
|
var CHECKS_FAILED_MESSAGE = "gh api reported a failing check on the branch";
|
|
4497
|
-
function is_awaited_check(
|
|
4498
|
-
return !is_coderabbit_check(
|
|
4961
|
+
function is_awaited_check(check4) {
|
|
4962
|
+
return !is_coderabbit_check(check4.name) || is_required_check(check4.name);
|
|
4499
4963
|
}
|
|
4500
4964
|
function evaluate_checks_settled(snapshot) {
|
|
4501
|
-
const awaited = snapshot.rollup.filter((
|
|
4965
|
+
const awaited = snapshot.rollup.filter((check4) => is_awaited_check(check4));
|
|
4502
4966
|
const considered = awaited.length === 0 ? snapshot.rollup : awaited;
|
|
4503
|
-
if (considered.length === 0 || considered.some((
|
|
4967
|
+
if (considered.length === 0 || considered.some((check4) => check4.status === CHECK_STATUS_PENDING)) {
|
|
4504
4968
|
return "pending";
|
|
4505
4969
|
}
|
|
4506
|
-
return snapshot.rollup.some((
|
|
4970
|
+
return snapshot.rollup.some((check4) => check4.status === CHECK_STATUS_FAIL) ? "failure" : "success";
|
|
4507
4971
|
}
|
|
4508
4972
|
function describe_checks_failure(snapshot) {
|
|
4509
|
-
const failed = snapshot.rollup.filter((
|
|
4510
|
-
return `${CHECKS_FAILED_MESSAGE}: ${failed.map((
|
|
4973
|
+
const failed = snapshot.rollup.filter((check4) => check4.status === CHECK_STATUS_FAIL);
|
|
4974
|
+
return `${CHECKS_FAILED_MESSAGE}: ${failed.map((check4) => check4.name).join(", ")}`;
|
|
4511
4975
|
}
|
|
4512
4976
|
var SHOULD_NEVER_READ_REVIEW_DECISION = () => false;
|
|
4513
4977
|
var CHECKS_SETTLED_EVALUATOR = {
|
|
@@ -4545,7 +5009,7 @@ async function pr_checks_watch(branch_name) {
|
|
|
4545
5009
|
}
|
|
4546
5010
|
var git_pr_checks_watch = { pr_checks_watch };
|
|
4547
5011
|
|
|
4548
|
-
// scripts/
|
|
5012
|
+
// scripts/gh/git-gh-command.ts
|
|
4549
5013
|
var git_gh_command = {
|
|
4550
5014
|
...git_gh_pr,
|
|
4551
5015
|
...git_gh_pr_auto_merge,
|
|
@@ -4610,7 +5074,6 @@ var epic_busy = {
|
|
|
4610
5074
|
unreadable_message,
|
|
4611
5075
|
truncated_message,
|
|
4612
5076
|
busy_reason,
|
|
4613
|
-
format_holders,
|
|
4614
5077
|
is_parked,
|
|
4615
5078
|
parse_listing,
|
|
4616
5079
|
read_repository
|
|
@@ -4619,28 +5082,28 @@ var epic_busy = {
|
|
|
4619
5082
|
// scripts/run/run-liveness.ts
|
|
4620
5083
|
import { readFileSync as readFileSync6, realpathSync, statSync } from "node:fs";
|
|
4621
5084
|
import { homedir, tmpdir } from "node:os";
|
|
4622
|
-
import
|
|
5085
|
+
import path8 from "node:path";
|
|
4623
5086
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
4624
5087
|
|
|
4625
5088
|
// scripts/agent/agent-event.ts
|
|
4626
|
-
import { z as
|
|
5089
|
+
import { z as z16 } from "zod";
|
|
4627
5090
|
|
|
4628
5091
|
// scripts/agent/claude-result-event.ts
|
|
4629
|
-
import { z as
|
|
4630
|
-
var RESULT_EVENT_SCHEMA =
|
|
4631
|
-
type:
|
|
4632
|
-
is_error:
|
|
4633
|
-
subtype:
|
|
4634
|
-
num_turns:
|
|
4635
|
-
permission_denials:
|
|
4636
|
-
result:
|
|
4637
|
-
session_id:
|
|
4638
|
-
usage:
|
|
5092
|
+
import { z as z15 } from "zod";
|
|
5093
|
+
var RESULT_EVENT_SCHEMA = z15.looseObject({
|
|
5094
|
+
type: z15.literal("result"),
|
|
5095
|
+
is_error: z15.unknown().optional(),
|
|
5096
|
+
subtype: z15.unknown().optional(),
|
|
5097
|
+
num_turns: z15.unknown().optional(),
|
|
5098
|
+
permission_denials: z15.unknown().optional(),
|
|
5099
|
+
result: z15.unknown().optional(),
|
|
5100
|
+
session_id: z15.unknown().optional(),
|
|
5101
|
+
usage: z15.unknown().optional()
|
|
4639
5102
|
});
|
|
4640
|
-
var USAGE_SCHEMA =
|
|
4641
|
-
input_tokens:
|
|
4642
|
-
cache_read_input_tokens:
|
|
4643
|
-
output_tokens:
|
|
5103
|
+
var USAGE_SCHEMA = z15.looseObject({
|
|
5104
|
+
input_tokens: z15.unknown().optional(),
|
|
5105
|
+
cache_read_input_tokens: z15.unknown().optional(),
|
|
5106
|
+
output_tokens: z15.unknown().optional()
|
|
4644
5107
|
});
|
|
4645
5108
|
function usable_reason(value) {
|
|
4646
5109
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
@@ -4661,7 +5124,7 @@ function usage_of(value) {
|
|
|
4661
5124
|
};
|
|
4662
5125
|
return Object.values(usage).some((count) => count !== void 0) ? usage : void 0;
|
|
4663
5126
|
}
|
|
4664
|
-
function
|
|
5127
|
+
function decode(value) {
|
|
4665
5128
|
const parsed = RESULT_EVENT_SCHEMA.safeParse(value);
|
|
4666
5129
|
if (!parsed.success) return void 0;
|
|
4667
5130
|
const is_error = parsed.data.is_error === true;
|
|
@@ -4676,34 +5139,34 @@ function decode2(value) {
|
|
|
4676
5139
|
usage: usage_of(parsed.data.usage)
|
|
4677
5140
|
};
|
|
4678
5141
|
}
|
|
4679
|
-
var claude_result_event = { decode
|
|
5142
|
+
var claude_result_event = { decode };
|
|
4680
5143
|
|
|
4681
5144
|
// scripts/agent/agent-event.ts
|
|
4682
|
-
var TEXT_BLOCK_SCHEMA =
|
|
4683
|
-
var CLAUDE_MESSAGE_SCHEMA =
|
|
4684
|
-
var CLAUDE_INIT_SCHEMA =
|
|
4685
|
-
var CLAUDE_ASSISTANT_SCHEMA =
|
|
4686
|
-
type:
|
|
5145
|
+
var TEXT_BLOCK_SCHEMA = z16.looseObject({ type: z16.literal("text"), text: z16.string() });
|
|
5146
|
+
var CLAUDE_MESSAGE_SCHEMA = z16.looseObject({ content: z16.array(z16.unknown()).optional() });
|
|
5147
|
+
var CLAUDE_INIT_SCHEMA = z16.looseObject({ type: z16.literal("system"), subtype: z16.literal("init") });
|
|
5148
|
+
var CLAUDE_ASSISTANT_SCHEMA = z16.looseObject({
|
|
5149
|
+
type: z16.literal("assistant"),
|
|
4687
5150
|
message: CLAUDE_MESSAGE_SCHEMA
|
|
4688
5151
|
});
|
|
4689
|
-
var USAGE_SCHEMA2 =
|
|
4690
|
-
input_tokens:
|
|
4691
|
-
cached_input_tokens:
|
|
4692
|
-
output_tokens:
|
|
5152
|
+
var USAGE_SCHEMA2 = z16.looseObject({
|
|
5153
|
+
input_tokens: z16.number().optional(),
|
|
5154
|
+
cached_input_tokens: z16.number().optional(),
|
|
5155
|
+
output_tokens: z16.number().optional()
|
|
4693
5156
|
});
|
|
4694
|
-
var CODEX_START_SCHEMA =
|
|
4695
|
-
var CODEX_PROGRESS_SCHEMA =
|
|
4696
|
-
type:
|
|
4697
|
-
item:
|
|
5157
|
+
var CODEX_START_SCHEMA = z16.looseObject({ type: z16.enum(["thread.started", "turn.started"]) });
|
|
5158
|
+
var CODEX_PROGRESS_SCHEMA = z16.looseObject({
|
|
5159
|
+
type: z16.enum(["item.started", "item.updated", "item.completed"]),
|
|
5160
|
+
item: z16.looseObject({ type: z16.string(), text: z16.string().optional() }).optional()
|
|
4698
5161
|
});
|
|
4699
|
-
var CODEX_COMPLETE_SCHEMA =
|
|
4700
|
-
type:
|
|
5162
|
+
var CODEX_COMPLETE_SCHEMA = z16.looseObject({
|
|
5163
|
+
type: z16.literal("turn.completed"),
|
|
4701
5164
|
usage: USAGE_SCHEMA2.optional()
|
|
4702
5165
|
});
|
|
4703
|
-
var CODEX_FAILURE_SCHEMA =
|
|
4704
|
-
type:
|
|
4705
|
-
error:
|
|
4706
|
-
message:
|
|
5166
|
+
var CODEX_FAILURE_SCHEMA = z16.looseObject({
|
|
5167
|
+
type: z16.enum(["turn.failed", "error"]),
|
|
5168
|
+
error: z16.looseObject({ message: z16.string().optional() }).optional(),
|
|
5169
|
+
message: z16.string().optional()
|
|
4707
5170
|
});
|
|
4708
5171
|
var EMPTY_STATE = {
|
|
4709
5172
|
provider: void 0,
|
|
@@ -4719,7 +5182,7 @@ function usable_text(value) {
|
|
|
4719
5182
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
4720
5183
|
}
|
|
4721
5184
|
function claude_progress(content) {
|
|
4722
|
-
return content.map((block) => TEXT_BLOCK_SCHEMA.safeParse(block)).filter((parsed) => parsed.success).map((parsed) => parsed.data.text).findLast((
|
|
5185
|
+
return content.map((block) => TEXT_BLOCK_SCHEMA.safeParse(block)).filter((parsed) => parsed.success).map((parsed) => parsed.data.text).findLast((text) => text.trim() !== "");
|
|
4723
5186
|
}
|
|
4724
5187
|
function claude_result(value, state) {
|
|
4725
5188
|
const result = claude_result_event.decode(value);
|
|
@@ -4794,7 +5257,7 @@ function describe(state) {
|
|
|
4794
5257
|
var agent_event = { describe, read };
|
|
4795
5258
|
|
|
4796
5259
|
// scripts/issue/issue-state.ts
|
|
4797
|
-
import { z as
|
|
5260
|
+
import { z as z17 } from "zod";
|
|
4798
5261
|
var NO_LABELS = "(none)";
|
|
4799
5262
|
var LABEL_SEPARATOR = ", ";
|
|
4800
5263
|
var STATE_LABEL = "state: ";
|
|
@@ -4804,9 +5267,9 @@ var YES = "yes";
|
|
|
4804
5267
|
var NO = "no";
|
|
4805
5268
|
var ISSUE_LABEL = "issue: ";
|
|
4806
5269
|
var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
|
|
4807
|
-
var label_schema =
|
|
4808
|
-
var issue_state_schema =
|
|
4809
|
-
state:
|
|
5270
|
+
var label_schema = z17.looseObject({ name: z17.string() });
|
|
5271
|
+
var issue_state_schema = z17.looseObject({
|
|
5272
|
+
state: z17.string(),
|
|
4810
5273
|
labels: label_schema.array().optional()
|
|
4811
5274
|
});
|
|
4812
5275
|
function parse_issue_state(json) {
|
|
@@ -4838,10 +5301,6 @@ ${format_issue_state(state)}`;
|
|
|
4838
5301
|
}
|
|
4839
5302
|
var issue_state = {
|
|
4840
5303
|
NO_LABELS,
|
|
4841
|
-
STATE_LABEL,
|
|
4842
|
-
LABELS_LABEL,
|
|
4843
|
-
HUMAN_REVIEW_LABEL_LINE,
|
|
4844
|
-
ISSUE_LABEL,
|
|
4845
5304
|
parse_issue_state,
|
|
4846
5305
|
format_issue_state,
|
|
4847
5306
|
format_attributed_issue_state
|
|
@@ -4856,7 +5315,7 @@ var PROCESS_ALIVE = "alive";
|
|
|
4856
5315
|
var PROCESS_UNKNOWN = "unknown";
|
|
4857
5316
|
var DEFAULT_SILENT_MINUTES = 30;
|
|
4858
5317
|
var DEFAULT_GAP_SECONDS = 5;
|
|
4859
|
-
var
|
|
5318
|
+
var MS_PER_MINUTE3 = 6e4;
|
|
4860
5319
|
var MS_PER_SECOND2 = 1e3;
|
|
4861
5320
|
var OPEN_STATE3 = "OPEN";
|
|
4862
5321
|
var STATE_FIELDS = "state,labels";
|
|
@@ -4904,7 +5363,7 @@ function to_advice(verdict, has_work_to_stash) {
|
|
|
4904
5363
|
if (verdict === UNDETERMINED_VERDICT) return UNDETERMINED_ADVICE;
|
|
4905
5364
|
return has_work_to_stash ? STOPPED_DIRTY_ADVICE : STOPPED_CLEAN_ADVICE;
|
|
4906
5365
|
}
|
|
4907
|
-
function
|
|
5366
|
+
function decide4(traces) {
|
|
4908
5367
|
const verdict = to_verdict(traces);
|
|
4909
5368
|
const has_work_to_stash = verdict === STOPPED_VERDICT && traces.is_tree_dirty;
|
|
4910
5369
|
return {
|
|
@@ -4927,12 +5386,12 @@ var ALLOWED_ROOTS = [
|
|
|
4927
5386
|
)
|
|
4928
5387
|
];
|
|
4929
5388
|
function is_within(candidate, root) {
|
|
4930
|
-
const relative =
|
|
4931
|
-
return relative !== "" && !relative.startsWith("..") && !
|
|
5389
|
+
const relative = path8.relative(root, candidate);
|
|
5390
|
+
return relative !== "" && !relative.startsWith("..") && !path8.isAbsolute(relative);
|
|
4932
5391
|
}
|
|
4933
5392
|
function to_safe_path(output_path) {
|
|
4934
|
-
const normalized2 =
|
|
4935
|
-
if (!
|
|
5393
|
+
const normalized2 = path8.normalize(output_path);
|
|
5394
|
+
if (!path8.isAbsolute(normalized2)) return void 0;
|
|
4936
5395
|
return ALLOWED_ROOTS.some((root) => is_within(normalized2, root)) ? normalized2 : void 0;
|
|
4937
5396
|
}
|
|
4938
5397
|
function sample_output(output_path) {
|
|
@@ -4986,7 +5445,7 @@ async function read_traces(request) {
|
|
|
4986
5445
|
gap_ms: request.gap_ms ?? DEFAULT_GAP_SECONDS * MS_PER_SECOND2,
|
|
4987
5446
|
now_ms: Date.now(),
|
|
4988
5447
|
output_path: request.output_path,
|
|
4989
|
-
silent_window_ms: request.silent_window_ms ?? DEFAULT_SILENT_MINUTES *
|
|
5448
|
+
silent_window_ms: request.silent_window_ms ?? DEFAULT_SILENT_MINUTES * MS_PER_MINUTE3
|
|
4990
5449
|
}),
|
|
4991
5450
|
run_hold.is_tree_dirty()
|
|
4992
5451
|
]);
|
|
@@ -5003,14 +5462,13 @@ async function read_traces(request) {
|
|
|
5003
5462
|
}
|
|
5004
5463
|
async function check(request) {
|
|
5005
5464
|
run_issue_number.require_issue_number(request.issue);
|
|
5006
|
-
return
|
|
5465
|
+
return decide4(await read_traces(request));
|
|
5007
5466
|
}
|
|
5008
5467
|
var run_liveness = {
|
|
5009
5468
|
check,
|
|
5010
|
-
decide:
|
|
5469
|
+
decide: decide4,
|
|
5011
5470
|
describe_agent_state,
|
|
5012
5471
|
read_child_settled,
|
|
5013
|
-
read_agent_state,
|
|
5014
5472
|
read_output_frozen,
|
|
5015
5473
|
sample_output,
|
|
5016
5474
|
to_safe_path
|
|
@@ -5041,9 +5499,10 @@ function event_column(lane) {
|
|
|
5041
5499
|
const state = run_liveness.describe_agent_state(lane.output);
|
|
5042
5500
|
return state ?? "agent -";
|
|
5043
5501
|
}
|
|
5044
|
-
|
|
5502
|
+
var PLAIN_CITE = issue_cite.citer(void 0, /* @__PURE__ */ new Map());
|
|
5503
|
+
function describe_lane(lane, cite = PLAIN_CITE) {
|
|
5045
5504
|
return [
|
|
5046
|
-
|
|
5505
|
+
cite(lane.issue),
|
|
5047
5506
|
`seat ${value_or_unknown(lane.seat)}`,
|
|
5048
5507
|
`dev ${value_or_unknown(lane.development_port)}`,
|
|
5049
5508
|
`preview ${value_or_unknown(lane.preview_port)}`,
|
|
@@ -5055,9 +5514,9 @@ function describe_lane(lane) {
|
|
|
5055
5514
|
event_column(lane)
|
|
5056
5515
|
].join(COLUMN_SEPARATOR);
|
|
5057
5516
|
}
|
|
5058
|
-
function describe_lanes(lanes) {
|
|
5517
|
+
function describe_lanes(lanes, cite = PLAIN_CITE) {
|
|
5059
5518
|
if (lanes.length === 0) return NO_LANES2;
|
|
5060
|
-
return lanes.map((lane) => describe_lane(lane)).join("\n");
|
|
5519
|
+
return lanes.map((lane) => describe_lane(lane, cite)).join("\n");
|
|
5061
5520
|
}
|
|
5062
5521
|
function describe_ports(lane) {
|
|
5063
5522
|
if (lane.seat === void 0) return "no lane seat could be read";
|
|
@@ -5078,7 +5537,7 @@ var lane_report = {
|
|
|
5078
5537
|
};
|
|
5079
5538
|
|
|
5080
5539
|
// scripts/run/run-preflight.ts
|
|
5081
|
-
import { z as
|
|
5540
|
+
import { z as z18 } from "zod";
|
|
5082
5541
|
var CLEAN_VERDICT = "clean";
|
|
5083
5542
|
var RECLAIM_VERDICT = "reclaim";
|
|
5084
5543
|
var RESUME_VERDICT = "resume";
|
|
@@ -5088,7 +5547,7 @@ var OPEN_PR = "open";
|
|
|
5088
5547
|
var MERGED_PR = "merged";
|
|
5089
5548
|
var CLOSED_PR = "closed";
|
|
5090
5549
|
var NO_CHILD_WORK = { branch_name: void 0, pr_state: NO_PR };
|
|
5091
|
-
var pr_info_schema2 =
|
|
5550
|
+
var pr_info_schema2 = z18.object({ state: z18.string().optional() });
|
|
5092
5551
|
var GH_PR_STATES = /* @__PURE__ */ new Map([
|
|
5093
5552
|
["CLOSED", CLOSED_PR],
|
|
5094
5553
|
["MERGED", MERGED_PR],
|
|
@@ -5099,7 +5558,7 @@ var CLEAN_ADVICE = "Start the child.";
|
|
|
5099
5558
|
var RESUME_ADVICE = "Reuse the branch and run the whole verification gate from the start \u2014 refactor, `pnpm josh gate`, `/code-review` \u2014 never only the part the interrupted run had not reached. Nobody verified what it already committed.";
|
|
5100
5559
|
var PARK_ADVICE = "Park the child: add `needs-decision` and comment what was found. Do not delete the branch, do not reopen the pull request, and do not commit on top of it.";
|
|
5101
5560
|
var STASH_LABEL_PREFIX = "run:hold reclaimed before #";
|
|
5102
|
-
var {
|
|
5561
|
+
var { require_issue_number } = run_issue_number;
|
|
5103
5562
|
var UNREADABLE_PR_MESSAGE = "The pull request could not be read for branch ";
|
|
5104
5563
|
function needs_reclaim(tree) {
|
|
5105
5564
|
return tree.is_dirty || tree.branch !== tree.default_branch;
|
|
@@ -5157,7 +5616,7 @@ function to_advice2(verdict, issue, tree) {
|
|
|
5157
5616
|
if (verdict === PARK_VERDICT) return PARK_ADVICE;
|
|
5158
5617
|
return CLEAN_ADVICE;
|
|
5159
5618
|
}
|
|
5160
|
-
function
|
|
5619
|
+
function decide5(tree, child, issue) {
|
|
5161
5620
|
const verdict = to_verdict2(tree, child);
|
|
5162
5621
|
return {
|
|
5163
5622
|
advice: to_advice2(verdict, issue, tree),
|
|
@@ -5258,30 +5717,23 @@ async function read_child_state(issue) {
|
|
|
5258
5717
|
async function check2(issue) {
|
|
5259
5718
|
require_issue_number(issue);
|
|
5260
5719
|
const tree = await read_tree_state();
|
|
5261
|
-
if (needs_reclaim(tree)) return
|
|
5262
|
-
return
|
|
5720
|
+
if (needs_reclaim(tree)) return decide5(tree, NO_CHILD_WORK, issue);
|
|
5721
|
+
return decide5(tree, await read_child_state(issue), issue);
|
|
5263
5722
|
}
|
|
5264
5723
|
var run_preflight = {
|
|
5265
|
-
CLEAN_ADVICE,
|
|
5266
|
-
CLEAN_REASON,
|
|
5267
5724
|
CLEAN_VERDICT,
|
|
5268
|
-
ISSUE_NUMBER_PATTERN,
|
|
5269
|
-
PARK_ADVICE,
|
|
5270
|
-
PARK_VERDICT,
|
|
5271
|
-
RECLAIM_VERDICT,
|
|
5272
5725
|
RESUME_ADVICE,
|
|
5273
|
-
RESUME_VERDICT,
|
|
5274
5726
|
MERGED_PR,
|
|
5275
5727
|
STASH_LABEL_PREFIX,
|
|
5276
5728
|
check: check2,
|
|
5277
|
-
decide:
|
|
5729
|
+
decide: decide5,
|
|
5278
5730
|
read_child_state,
|
|
5279
5731
|
read_pr_state: read_pr_state2,
|
|
5280
5732
|
to_pr_state: to_pr_state2
|
|
5281
5733
|
};
|
|
5282
5734
|
|
|
5283
5735
|
// scripts/run/run-progress-read.ts
|
|
5284
|
-
var {
|
|
5736
|
+
var { mark: mark2, parse_stamp: parse_stamp2, read_last_report: read_last_report2 } = run_progress_clock;
|
|
5285
5737
|
var FIRST_LOAD_AVERAGE = 0;
|
|
5286
5738
|
var IDLE_READ = { kind: "idle" };
|
|
5287
5739
|
var UNREADABLE_READ = { kind: "unreadable" };
|
|
@@ -5304,7 +5756,7 @@ function to_labels(issue) {
|
|
|
5304
5756
|
async function to_child(issue) {
|
|
5305
5757
|
const number = String(issue.number);
|
|
5306
5758
|
const child = await run_preflight.read_child_state(number);
|
|
5307
|
-
return { issue: number, labels: to_labels(issue), pr_state: child.pr_state };
|
|
5759
|
+
return { issue: number, title: issue.title, labels: to_labels(issue), pr_state: child.pr_state };
|
|
5308
5760
|
}
|
|
5309
5761
|
async function read_children(repo) {
|
|
5310
5762
|
const read2 = await epic_busy.read_repository(repo);
|
|
@@ -5349,6 +5801,7 @@ async function read_observations(request) {
|
|
|
5349
5801
|
if (children === void 0) return UNREADABLE_READ;
|
|
5350
5802
|
if (children.length === 0 && !await has_run_started(lanes)) return IDLE_READ;
|
|
5351
5803
|
const observations = {
|
|
5804
|
+
repo: request.repo,
|
|
5352
5805
|
children,
|
|
5353
5806
|
lanes,
|
|
5354
5807
|
load_average: loadavg()[FIRST_LOAD_AVERAGE] ?? 0,
|
|
@@ -5357,24 +5810,46 @@ async function read_observations(request) {
|
|
|
5357
5810
|
return { kind: "observed", observations };
|
|
5358
5811
|
}
|
|
5359
5812
|
var run_progress_read = {
|
|
5360
|
-
PROGRESS_PREFIX,
|
|
5361
5813
|
has_run_started,
|
|
5362
5814
|
live_target,
|
|
5363
5815
|
log_target,
|
|
5364
|
-
mark,
|
|
5365
|
-
parse_stamp,
|
|
5816
|
+
mark: mark2,
|
|
5817
|
+
parse_stamp: parse_stamp2,
|
|
5366
5818
|
read_children,
|
|
5367
|
-
read_last_report,
|
|
5819
|
+
read_last_report: read_last_report2,
|
|
5368
5820
|
read_lanes,
|
|
5369
5821
|
read_observations,
|
|
5370
5822
|
read_record_age,
|
|
5371
5823
|
stamp_target
|
|
5372
5824
|
};
|
|
5373
5825
|
|
|
5826
|
+
// scripts/run/run-watcher-guard.ts
|
|
5827
|
+
var WATCHER_TICK_MS = 3e4;
|
|
5828
|
+
var TICK_MULTIPLIER = 3;
|
|
5829
|
+
var MS_PER_SECOND3 = 1e3;
|
|
5830
|
+
var STALE_THRESHOLD_MS = WATCHER_TICK_MS * TICK_MULTIPLIER;
|
|
5831
|
+
var STALE_THRESHOLD_S = STALE_THRESHOLD_MS / MS_PER_SECOND3;
|
|
5832
|
+
var STALE_NOTE = `Lane children are in-flight but the progress watcher has not pinged in the last ${String(STALE_THRESHOLD_S)}s \u2014 run \`pnpm josh run:progress --wait\` in the background before proceeding`;
|
|
5833
|
+
var OK_RESULT = { kind: "ok" };
|
|
5834
|
+
async function owes_watcher() {
|
|
5835
|
+
if (!await run_headless.is_backlog_parent()) return false;
|
|
5836
|
+
return await lane_registry.has_lanes_in_flight();
|
|
5837
|
+
}
|
|
5838
|
+
async function check3(life_target) {
|
|
5839
|
+
if (!await owes_watcher()) return OK_RESULT;
|
|
5840
|
+
if (run_progress_clock.is_life_fresh(life_target, STALE_THRESHOLD_MS)) return OK_RESULT;
|
|
5841
|
+
return { kind: "stale", note: STALE_NOTE };
|
|
5842
|
+
}
|
|
5843
|
+
var run_watcher_guard = {
|
|
5844
|
+
STALE_NOTE,
|
|
5845
|
+
STALE_THRESHOLD_MS,
|
|
5846
|
+
check: check3
|
|
5847
|
+
};
|
|
5848
|
+
|
|
5374
5849
|
// scripts/run/run-watcher-hook.ts
|
|
5375
5850
|
var SWITCH_ENV_KEY2 = "JOSH_WATCHER_GUARD";
|
|
5376
5851
|
var STAMP_PREFIX2 = "josh-watcher-guard-";
|
|
5377
|
-
var payload_schema =
|
|
5852
|
+
var payload_schema = z19.object({ transcript_path: z19.string().min(1) });
|
|
5378
5853
|
function transcript_of(raw_payload) {
|
|
5379
5854
|
try {
|
|
5380
5855
|
const parsed = payload_schema.safeParse(JSON.parse(raw_payload));
|
|
@@ -5403,7 +5878,95 @@ async function watcher_hook_reason(raw_payload, now_ms = Date.now()) {
|
|
|
5403
5878
|
if (transcript === void 0) return void 0;
|
|
5404
5879
|
return await stale_reason(transcript, now_ms);
|
|
5405
5880
|
}
|
|
5406
|
-
var run_watcher_hook = {
|
|
5881
|
+
var run_watcher_hook = { transcript_of, watcher_hook_reason };
|
|
5882
|
+
|
|
5883
|
+
// scripts/run/run-parent-cut-hook.ts
|
|
5884
|
+
var SWITCH_ENV_KEY3 = "JOSH_PARENT_CUT_GUARD";
|
|
5885
|
+
var STAMP_PREFIX3 = "josh-parent-cut-guard-";
|
|
5886
|
+
var QUIET_WINDOW_MS = 6e5;
|
|
5887
|
+
function current_state3() {
|
|
5888
|
+
return {
|
|
5889
|
+
carry: async () => await run_headless.driving_carry(),
|
|
5890
|
+
verdict: () => implementation_cut_verdict.reused_verdict(() => cost_cli.session_verdict())
|
|
5891
|
+
};
|
|
5892
|
+
}
|
|
5893
|
+
var THRESHOLD_TEXT2 = `${cost_format.format_tokens(CONTEXT_CUT_THRESHOLD)}-token`;
|
|
5894
|
+
var PARENT_CUT_REASON = `\u26D4 backlogrun parent hand-off: this session drives a \`backlogrun\` (it owns the live carry record) and its recent-context cost has crossed the shared ${THRESHOLD_TEXT2} threshold between merges, so every later request re-reads the accumulated context (joshuafolkken/kit#2947). Take the hand-off now rather than at the next merge: follow \`.claude/skills/workflow-commands/backlogrun-progress.md\` \u2192 "The hand-off" from its \`over\` branch \u2014 open no new lane and take no new child, read \`pnpm josh lane:list\`, make sure every lane in flight records an output path, then run \`pnpm josh run:carry --cut --owner "$PPID"\` and, unless it answers \`capped\`, \`pnpm josh run:wake\`, post the progress comment and end the turn. A lane nobody can poll means the cut does not happen; carry on and this asks again later. Reissue this call when the hand-off is done or cannot be taken \u2014 the guard stays quiet for a while after it refuses, so the hand-off calls themselves are not refused.`;
|
|
5895
|
+
async function is_due2(state) {
|
|
5896
|
+
const carry = await state.carry();
|
|
5897
|
+
if (carry === void 0 || run_carry.is_at_cut_cap(carry)) return false;
|
|
5898
|
+
return state.verdict() === cost_verdict.OVER_VERDICT;
|
|
5899
|
+
}
|
|
5900
|
+
function is_quiet(target, now_ms) {
|
|
5901
|
+
const last_ms = hook_decision.create_refusal_stamp(STAMP_PREFIX3).last_ms(target);
|
|
5902
|
+
return last_ms !== hook_decision.NEVER_MS && now_ms - last_ms < QUIET_WINDOW_MS;
|
|
5903
|
+
}
|
|
5904
|
+
async function refusal_for(transcript, now_ms, state) {
|
|
5905
|
+
const stamp = hook_decision.create_refusal_stamp(STAMP_PREFIX3);
|
|
5906
|
+
const target = stamp.path(transcript);
|
|
5907
|
+
if (is_quiet(target, now_ms) || !await is_due2(state)) return void 0;
|
|
5908
|
+
return stamp.record(target, now_ms) ? PARENT_CUT_REASON : void 0;
|
|
5909
|
+
}
|
|
5910
|
+
function is_unit_call(raw_payload) {
|
|
5911
|
+
try {
|
|
5912
|
+
return (hook_decision.parse_hook_payload(raw_payload)?.agent_id ?? "") !== "";
|
|
5913
|
+
} catch {
|
|
5914
|
+
return false;
|
|
5915
|
+
}
|
|
5916
|
+
}
|
|
5917
|
+
function is_exempt2(raw_payload) {
|
|
5918
|
+
return !hook_decision.is_switch_enabled(SWITCH_ENV_KEY3) || is_unit_call(raw_payload);
|
|
5919
|
+
}
|
|
5920
|
+
async function parent_cut_reason(raw_payload, now_ms = Date.now(), state = current_state3()) {
|
|
5921
|
+
if (is_exempt2(raw_payload)) return void 0;
|
|
5922
|
+
const transcript = run_watcher_hook.transcript_of(raw_payload);
|
|
5923
|
+
if (transcript === void 0) return void 0;
|
|
5924
|
+
return await refusal_for(transcript, now_ms, state);
|
|
5925
|
+
}
|
|
5926
|
+
var run_parent_cut_hook = {
|
|
5927
|
+
PARENT_CUT_REASON,
|
|
5928
|
+
QUIET_WINDOW_MS,
|
|
5929
|
+
SWITCH_ENV_KEY: SWITCH_ENV_KEY3,
|
|
5930
|
+
parent_cut_reason
|
|
5931
|
+
};
|
|
5932
|
+
|
|
5933
|
+
// scripts/hooks/step-zero-notice.ts
|
|
5934
|
+
import path9 from "node:path";
|
|
5935
|
+
var STAMP_PREFIX4 = "josh-step-zero-notice-";
|
|
5936
|
+
var EDIT_TOOLS3 = /* @__PURE__ */ new Set(["Edit", "Write"]);
|
|
5937
|
+
var PARENT_PREFIX = "..";
|
|
5938
|
+
var NOTICE = "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.";
|
|
5939
|
+
var STAMP = hook_decision.create_refusal_stamp(STAMP_PREFIX4);
|
|
5940
|
+
function edited_paths(tool_input) {
|
|
5941
|
+
if (!json_value.is_record(tool_input)) return [];
|
|
5942
|
+
const { file_path, file_paths } = tool_input;
|
|
5943
|
+
const listed = Array.isArray(file_paths) ? file_paths : [];
|
|
5944
|
+
return [file_path, ...listed].filter(
|
|
5945
|
+
(entry) => typeof entry === "string" && entry.length > 0
|
|
5946
|
+
);
|
|
5947
|
+
}
|
|
5948
|
+
function is_runtime_file(file_path, root) {
|
|
5949
|
+
const relative = path9.relative(root, path9.resolve(root, file_path));
|
|
5950
|
+
if (relative.startsWith(PARENT_PREFIX) || path9.isAbsolute(relative)) return false;
|
|
5951
|
+
return !test_declared_logic.is_exempt(relative.split(path9.sep).join("/"));
|
|
5952
|
+
}
|
|
5953
|
+
function is_candidate(raw_payload, root) {
|
|
5954
|
+
const payload = hook_decision.parse_hook_payload(raw_payload);
|
|
5955
|
+
if (payload === void 0 || !EDIT_TOOLS3.has(payload.tool_name)) return void 0;
|
|
5956
|
+
const has_runtime_file = edited_paths(payload.tool_input).some(
|
|
5957
|
+
(file_path) => is_runtime_file(file_path, root)
|
|
5958
|
+
);
|
|
5959
|
+
return has_runtime_file ? payload.transcript_path : void 0;
|
|
5960
|
+
}
|
|
5961
|
+
function notice(raw_payload, root = process.cwd()) {
|
|
5962
|
+
const transcript = is_candidate(raw_payload, root);
|
|
5963
|
+
if (transcript === void 0) return void 0;
|
|
5964
|
+
const target = STAMP.path(transcript);
|
|
5965
|
+
if (STAMP.last_ms(target) !== hook_decision.NEVER_MS) return void 0;
|
|
5966
|
+
if (!STAMP.record(target, Date.now())) return void 0;
|
|
5967
|
+
return NOTICE;
|
|
5968
|
+
}
|
|
5969
|
+
var step_zero_notice = { NOTICE, notice, stamp_path: STAMP.path };
|
|
5407
5970
|
|
|
5408
5971
|
// scripts/hooks/pretool-guard.ts
|
|
5409
5972
|
function combine_outcomes(batch, extra_reason) {
|
|
@@ -5416,11 +5979,16 @@ function combine_outcomes(batch, extra_reason) {
|
|
|
5416
5979
|
function is_clear(outcome) {
|
|
5417
5980
|
return outcome.reason === void 0 && outcome.notice === void 0 && outcome.fault === void 0;
|
|
5418
5981
|
}
|
|
5419
|
-
function with_duplicate_notice(combined,
|
|
5420
|
-
if (
|
|
5421
|
-
return { reason: void 0, notice, fault: void 0 };
|
|
5982
|
+
function with_duplicate_notice(combined, notice2) {
|
|
5983
|
+
if (notice2 === void 0 || !is_clear(combined)) return combined;
|
|
5984
|
+
return { reason: void 0, notice: notice2, fault: void 0 };
|
|
5422
5985
|
}
|
|
5423
|
-
function
|
|
5986
|
+
function with_step_zero_notice(outcome, raw_payload) {
|
|
5987
|
+
if (!is_clear(outcome)) return outcome;
|
|
5988
|
+
const notice2 = step_zero_notice.notice(raw_payload);
|
|
5989
|
+
return notice2 === void 0 ? outcome : { reason: void 0, notice: notice2, fault: void 0 };
|
|
5990
|
+
}
|
|
5991
|
+
function guard_outcome(raw_payload) {
|
|
5424
5992
|
const batch = batch_outcome(raw_payload);
|
|
5425
5993
|
const investigation = investigation_refusal(raw_payload);
|
|
5426
5994
|
const duplicate = duplicate_read_outcome(raw_payload);
|
|
@@ -5429,24 +5997,23 @@ function pretool_outcome(raw_payload) {
|
|
|
5429
5997
|
const combined = combine_outcomes(batch, investigation ?? duplicate_refusal ?? rule);
|
|
5430
5998
|
return with_duplicate_notice(combined, duplicate.notice);
|
|
5431
5999
|
}
|
|
6000
|
+
function pretool_outcome(raw_payload) {
|
|
6001
|
+
return with_step_zero_notice(guard_outcome(raw_payload), raw_payload);
|
|
6002
|
+
}
|
|
6003
|
+
async function async_reason(raw_payload) {
|
|
6004
|
+
const watcher = await run_watcher_hook.watcher_hook_reason(raw_payload);
|
|
6005
|
+
return watcher ?? await run_parent_cut_hook.parent_cut_reason(raw_payload);
|
|
6006
|
+
}
|
|
5432
6007
|
async function pretool_outcome_async(raw_payload) {
|
|
5433
|
-
const base =
|
|
6008
|
+
const base = guard_outcome(raw_payload);
|
|
5434
6009
|
if (!is_clear(base)) return base;
|
|
5435
|
-
const reason = await
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
var pretool_guard = { combine_outcomes, pretool_outcome, pretool_outcome_async };
|
|
5439
|
-
if (process.argv[1] === fileURLToPath3(import.meta.url)) {
|
|
5440
|
-
if (process.stdin.isTTY) hook_decision.report_no_payload("pretool:guard");
|
|
5441
|
-
else {
|
|
5442
|
-
const raw_payload = await text(process.stdin);
|
|
5443
|
-
hook_decision.load_environment_file();
|
|
5444
|
-
hook_decision.emit_outcome(await pretool_outcome_async(raw_payload));
|
|
5445
|
-
}
|
|
6010
|
+
const reason = await async_reason(raw_payload);
|
|
6011
|
+
if (reason !== void 0) return { reason, notice: void 0, fault: void 0 };
|
|
6012
|
+
return with_step_zero_notice(base, raw_payload);
|
|
5446
6013
|
}
|
|
6014
|
+
var pretool_guard = { combine_outcomes, pretool_outcome };
|
|
5447
6015
|
|
|
5448
6016
|
export {
|
|
5449
|
-
pretool_outcome,
|
|
5450
6017
|
pretool_outcome_async,
|
|
5451
6018
|
pretool_guard
|
|
5452
6019
|
};
|