@joshuafolkken/kit 1.1166.0 → 1.1229.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/.claude-plugin/plugin.json +1 -1
- package/.claude/settings.json +2 -2
- package/.claude/skills/dependency-update/SKILL.md +4 -8
- package/.claude/skills/epic-commands/SKILL.md +2 -2
- package/.claude/skills/epic-commands/epic-bundle.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +2 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +6 -4
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -5
- package/.claude/skills/workflow-commands/backlogrun-park.md +29 -9
- package/.claude/skills/workflow-commands/backlogrun-progress.md +7 -2
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
- package/.claude/skills/workflow-commands/backlogrun-steps.md +24 -15
- package/.claude/skills/workflow-commands/chain-rule.md +1 -1
- package/.claude/skills/workflow-commands/delegation.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +5 -0
- package/.claude/skills/workflow-commands/fullrun-steps.md +1 -1
- package/.claude/skills/workflow-commands/halfrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
- package/.claude/skills/workflow-commands/pre-gate-cut.md +10 -5
- package/.claude/skills/workflow-commands/prerequisite.md +2 -2
- package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +1 -1
- package/.codex/hooks.json +2 -2
- package/.cursorrules +6 -41
- package/.github/actions/setup-node/action.yml +1 -1
- package/.github/workflows/auto-tag.yml +3 -4
- package/.github/workflows/ci.yml +47 -33
- package/.github/workflows/dependabot-auto-merge.yml +13 -6
- package/.github/workflows/publish.yml +48 -4
- package/.github/workflows/sonar-qube.yml +3 -0
- package/.pnpmfile.mjs +4 -3
- package/.prettierignore +8 -2
- package/CLAUDE.md +18 -20
- package/README.md +26 -19
- package/SECURITY.md +15 -1
- package/dist/CLAUDE.md +18 -20
- package/dist/commands/document-section-cli.js +734 -0
- package/dist/hooks/audit-provision.js +346 -0
- package/dist/hooks/batch-guard.js +5 -4
- package/dist/hooks/{chunk-DYAVAM6S.js → chunk-55HHG5PX.js} +1405 -631
- package/dist/hooks/{chunk-A6P7PN7P.js → chunk-5VMKCCC4.js} +25 -10
- package/dist/hooks/chunk-5VNDSNG3.js +12 -0
- package/dist/hooks/{chunk-5KTCMCOT.js → chunk-6HJJXRBX.js} +4 -2
- package/dist/hooks/chunk-CDY4NFQG.js +15 -0
- package/dist/hooks/chunk-ELCN5LCH.js +135 -0
- package/dist/hooks/{chunk-ENA7P5FB.js → chunk-F56MFS4B.js} +3 -3
- package/dist/hooks/{chunk-ANJ2WGFD.js → chunk-FIVDHQGT.js} +7 -6
- package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
- package/dist/hooks/{chunk-GU5MATVE.js → chunk-JUDKDCDP.js} +499 -389
- package/dist/hooks/{chunk-ZDZ555YH.js → chunk-NV2JRZZO.js} +743 -909
- package/dist/hooks/{chunk-V2BTOZHT.js → chunk-RNWHN5BP.js} +3 -3
- package/dist/hooks/{chunk-URJA6XY4.js → chunk-TQNPDZNH.js} +4 -4
- package/dist/hooks/{chunk-GYNGP7HI.js → chunk-VC3PZPZO.js} +1 -1
- package/dist/hooks/codex-hook-adapter.js +14 -12
- package/dist/hooks/duplicate-read-guard.js +6 -5
- package/dist/hooks/format-edited.js +4 -3
- package/dist/hooks/inputs.json +232 -210
- package/dist/hooks/investigation-guard.js +6 -5
- package/dist/hooks/pretool-guard.js +12 -10
- package/dist/hooks/session-lang.js +2 -4
- package/dist/hooks/stop-guard.js +81 -59
- package/dist/josh.js +872 -75
- package/dist/version/index.d.ts +7 -2
- package/dist/version/index.js +152 -75
- package/eslint/base.js +23 -1
- package/eslint/rules/code-quality.js +3 -0
- package/eslint/rules/early-return-one-liner.js +98 -0
- package/eslint/rules/unicorn.js +16 -1
- package/package.json +7 -6
- package/pnpm-workspace.yaml +9 -4
- package/prettier/basic.d.ts +3 -1
- package/prettier/index.d.ts +3 -1
- package/prettier/static.d.ts +3 -1
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +4 -4
- package/prompts/collaboration-workflow/glossary.md +1 -1
- package/prompts/collaboration-workflow/operating-rules.md +17 -9
- package/prompts/collaboration-workflow/overview.md +2 -2
- package/prompts/collaboration-workflow/principles.md +14 -12
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +1 -1
- package/prompts/collaboration-workflow/rule-delivery.md +6 -6
- package/prompts/collaboration-workflow/shell-body.md +6 -6
- package/prompts/collaboration-workflow/turn-batching.md +1 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +12 -2
- package/prompts/collaboration-workflow/wip-cap.md +10 -10
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +1 -1
- package/scripts/agent/agent-headless.ts +29 -0
- package/scripts/agent/agent-launch-environment.ts +6 -2
- package/scripts/agent/codex-agent-argv.ts +2 -1
- package/scripts/auto-ok/auto-ok-cli.ts +1 -1
- package/scripts/backlog/backlog-arrival.ts +3 -3
- package/scripts/backlog/backlog-budget.ts +1 -1
- package/scripts/backlog/backlog-drive-args.ts +135 -0
- package/scripts/backlog/backlog-drive-cli.ts +11 -137
- package/scripts/backlog/backlog-drive-launch.ts +39 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +3 -5
- package/scripts/backlog/backlog-drive-named.ts +3 -3
- package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
- package/scripts/backlog/backlog-drive-owner.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +1 -1
- package/scripts/backlog/backlog-drive-retrospective.ts +1 -1
- package/scripts/backlog/backlog-drive.ts +1 -1
- package/scripts/backlog/backlog-next.ts +31 -9
- package/scripts/backlog/backlog-offer-cli.ts +6 -6
- package/scripts/backlog/backlog-offer.ts +1 -1
- package/scripts/backlog/backlog-plan-cli.ts +7 -6
- package/scripts/backlog/backlog-pool.ts +57 -11
- package/scripts/backlog/backlog-rank.ts +18 -9
- package/scripts/backlog/backlog-ready.ts +1 -1
- package/scripts/backlog/backlog-restructure.ts +152 -0
- package/scripts/backlog/backlog-scope.ts +1 -1
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +1 -1
- package/scripts/backlog/backlog-waves.ts +15 -17
- package/scripts/build/build-codex-hooks.ts +3 -1
- package/scripts/build/build-commands.ts +66 -0
- package/scripts/build/build-hooks.ts +2 -1
- package/scripts/build/build-library.ts +12 -3
- package/scripts/build/build.ts +70 -0
- package/scripts/build/local-bin.ts +3 -13
- package/scripts/cost-runtime/context-cut-threshold.ts +1 -9
- package/scripts/cost-runtime/cost-verdict.ts +15 -28
- package/scripts/delegation/investigation-reads.ts +3 -1
- package/scripts/discovery/repo-origin.ts +5 -5
- package/scripts/doctor/doctor-consumer.ts +2 -2
- package/scripts/doctor/doctor-io.ts +2 -3
- package/scripts/document/capped-print-part.ts +30 -0
- package/scripts/document/capped-print.ts +3 -4
- package/scripts/document/document-byte-budget.ts +11 -2
- package/scripts/document/document-scan.ts +117 -0
- package/scripts/document/document-section.ts +143 -16
- package/scripts/document/entry-read-budget.ts +5 -3
- package/scripts/document/entry-read-set.ts +10 -89
- package/scripts/document/read-set-cost.ts +98 -0
- package/scripts/epic/epic-add-body.ts +1 -0
- package/scripts/epic/epic-audit-checks.ts +1 -1
- package/scripts/epic/epic-audit-rationale.ts +4 -3
- package/scripts/epic/epic-bundle-cli.ts +14 -3
- package/scripts/epic/epic-bundle-poll.ts +41 -0
- package/scripts/epic/epic-busy.ts +1 -1
- package/scripts/epic/epic-candidate-confirm.ts +3 -2
- package/scripts/epic/epic-classify.ts +1 -1
- package/scripts/epic/epic-cli-argv.ts +78 -46
- package/scripts/epic/epic-cli-remove.ts +11 -19
- package/scripts/epic/epic-cli.ts +74 -73
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +1 -1
- package/scripts/epic/epic-cross-repo.ts +5 -5
- package/scripts/epic/epic-graph.ts +1 -1
- package/scripts/epic/epic-index.ts +1 -1
- package/scripts/epic/epic-issue.ts +2 -6
- package/scripts/epic/epic-lane-offer.ts +2 -2
- package/scripts/epic/epic-next.ts +29 -42
- package/scripts/epic/epic-solo-stale.ts +1 -1
- package/scripts/epic/epic-triage.ts +8 -4
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/followup/git-followup-finish.ts +2 -2
- package/scripts/followup/git-followup-label.ts +2 -2
- package/scripts/followup/git-followup-merged.ts +2 -2
- package/scripts/followup/git-followup-stages.ts +9 -0
- package/scripts/followup/git-pr-followup-checks.ts +142 -0
- package/scripts/followup/git-pr-followup.ts +5 -130
- package/scripts/gate/core-budget.ts +69 -1
- package/scripts/gate/gate-plan.ts +47 -7
- package/scripts/gate/gate-skip.ts +38 -7
- package/scripts/gate/hook-gate-reuse.ts +12 -10
- package/scripts/gate/pre-commit-type-check.ts +4 -1
- package/scripts/gate/project-checks.ts +6 -9
- package/scripts/gate/type-check-step.ts +2 -3
- package/scripts/gate/verification-gate.ts +27 -8
- package/scripts/gh/git-gh-api-path.ts +2 -2
- package/scripts/gh/git-gh-issue-rest.ts +3 -3
- package/scripts/gh/git-gh-issue-write.ts +53 -7
- package/scripts/gh/git-gh-issue.ts +5 -3
- package/scripts/gh/git-gh-pr-read.ts +68 -19
- package/scripts/gh/git-gh-pr-rest.ts +1 -1
- package/scripts/gh/git-gh-pr.ts +5 -1
- package/scripts/gh/git-pr-ai-review.ts +1 -1
- package/scripts/gh/git-pr-checks-eval.ts +9 -3
- package/scripts/gh/git-pr-checks-parse.ts +1 -1
- package/scripts/gh/git-pr-checks-watch.ts +6 -5
- package/scripts/gh/git-pr-checks.ts +18 -6
- package/scripts/gh/git-pr-coderabbit.ts +1 -1
- package/scripts/gh/git-pr-error.ts +1 -3
- package/scripts/gh/git-pr.ts +9 -13
- package/scripts/gh/github-issue-url.ts +2 -2
- package/scripts/git/constants.ts +12 -6
- package/scripts/git/git-command.ts +20 -218
- package/scripts/git/git-diff-reads.ts +225 -0
- package/scripts/git/git-error.ts +4 -12
- package/scripts/git/git-pre-push-hook.ts +139 -0
- package/scripts/git/git-prompt.ts +2 -6
- package/scripts/git/{schemas.ts → git-schemas.ts} +2 -0
- package/scripts/git/git-spawn-sync.ts +3 -1
- package/scripts/git/git-spawn.ts +1 -1
- package/scripts/git/git-staging.ts +4 -6
- package/scripts/git/git-status.ts +3 -9
- package/scripts/git/main-merge.ts +57 -21
- package/scripts/hooks/codex-hook-adapter.ts +1 -1
- package/scripts/hooks/edited-cspell.ts +2 -4
- package/scripts/hooks/format-edited-file.ts +3 -12
- package/scripts/hooks/pre-push-unit.ts +31 -9
- package/scripts/hooks/reserved-run.ts +2 -2
- package/scripts/hooks/run-hook.sh +5 -4
- package/scripts/hooks/stop-guard.ts +5 -3
- package/scripts/init/init-actions.ts +0 -5
- package/scripts/init/init-ai-copy.ts +13 -2
- package/scripts/init/init-logic-json-merge.ts +19 -0
- package/scripts/init/init-logic-secretlint.ts +7 -7
- package/scripts/init/init-logic-workspace.ts +41 -2
- package/scripts/init/init-logic.ts +16 -26
- package/scripts/init/init.ts +5 -15
- package/scripts/init/initial-commit.ts +4 -4
- package/scripts/init/kit-development-versions.ts +40 -0
- package/scripts/init/kit-setup-state.ts +2 -2
- package/scripts/init/start-exec.ts +68 -19
- package/scripts/init/start-setup-pr.ts +9 -9
- package/scripts/init/start-steps.ts +6 -10
- package/scripts/issue/defect-rate-cli.ts +1 -1
- package/scripts/issue/git-next-issues.ts +1 -1
- package/scripts/issue/issue-auto-ok.ts +1 -1
- package/scripts/issue/issue-backlinks-cli.ts +2 -2
- package/scripts/issue/issue-backlinks.ts +9 -9
- package/scripts/issue/issue-comment-cli.ts +19 -13
- package/scripts/issue/issue-file-cli.ts +45 -18
- package/scripts/issue/issue-file.ts +24 -1
- package/scripts/issue/issue-scout-closed.ts +1 -1
- package/scripts/issue/issue-state-cli.ts +30 -74
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-command-types.ts +11 -0
- package/scripts/josh/josh-commands-ai.ts +4 -4
- package/scripts/josh/josh-commands-backlog.ts +4 -1
- package/scripts/josh/josh-commands-development.ts +11 -1
- package/scripts/josh/josh-commands-document.ts +1 -0
- package/scripts/josh/josh-commands-lane.ts +22 -0
- package/scripts/josh/josh-commands-maintenance.ts +4 -4
- package/scripts/josh/josh-commands-run.ts +12 -7
- package/scripts/josh/josh-in-process.ts +28 -9
- package/scripts/josh/josh-logic.ts +33 -15
- package/scripts/josh/process-identity.ts +1 -3
- package/scripts/josh/session-language-cli.ts +3 -4
- package/scripts/lane/lane-await.ts +5 -1
- package/scripts/lane/lane-child-invocation.ts +2 -2
- package/scripts/lane/lane-cli.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +14 -10
- package/scripts/lane/lane-environment.ts +5 -1
- package/scripts/lane/lane-handoff.ts +1 -1
- package/scripts/lane/lane-install.ts +2 -13
- package/scripts/lane/lane-launch-cli.ts +35 -3
- package/scripts/lane/lane-ledger.ts +145 -0
- package/scripts/lane/lane-leftover.ts +1 -1
- package/scripts/lane/lane-load.ts +108 -0
- package/scripts/lane/lane-measure-cli.ts +149 -0
- package/scripts/lane/lane-occupancy.ts +3 -0
- package/scripts/lane/lane-reap.ts +1 -3
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-stats.ts +224 -0
- package/scripts/lane/lane-vacant.ts +36 -0
- package/scripts/lane/openai-lane-ship.ts +2 -2
- package/scripts/lane/openai-lane-supervisor-owner.ts +180 -0
- package/scripts/lane/openai-lane-supervisor.ts +7 -165
- package/scripts/lane/openai-review-broker.ts +2 -4
- package/scripts/lib/ancestor-directories.ts +35 -0
- package/scripts/lib/animation-helpers.ts +2 -2
- package/scripts/lib/buffered-process.ts +3 -7
- package/scripts/lib/cli-flags.ts +71 -1
- package/scripts/lib/spawn-exit.ts +2 -2
- package/scripts/lib/timeouts.ts +35 -2
- package/scripts/lines/line-budget.ts +4 -6
- package/scripts/notify/telegram-notify.ts +26 -1
- package/scripts/notify/telegram-test.ts +6 -0
- package/scripts/observations/observation-ledger-line.ts +6 -6
- package/scripts/observations/observation-ledger-migrate.ts +55 -4
- package/scripts/observations/observation-ledger.ts +26 -7
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/propagate/propagate-git.ts +1 -1
- package/scripts/propagate/propagate-publish.ts +2 -2
- package/scripts/propagate/propagate-steps.ts +20 -15
- package/scripts/propagate/propagate.ts +36 -27
- package/scripts/refactor/import-graph.ts +18 -1
- package/scripts/refactor/refactor-lint.ts +4 -4
- package/scripts/repo/repository-labels.ts +2 -2
- package/scripts/repo/required-checks-logic.ts +1 -3
- package/scripts/review/live-evidence.ts +2 -4
- package/scripts/review/review-brief-cli.ts +1 -1
- package/scripts/review/review-finding-ledger.ts +1 -1
- package/scripts/review/review-findings-cli.ts +1 -3
- package/scripts/rules/decision-oracle-batch.ts +128 -0
- package/scripts/rules/decision-oracle-tokens.ts +21 -0
- package/scripts/rules/decision-oracle.ts +8 -120
- package/scripts/rules/delivered-rules.ts +26 -182
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/early-heartbeat.ts +3 -3
- package/scripts/rules/git-argv.ts +1 -1
- package/scripts/rules/git-force.ts +1 -1
- package/scripts/rules/implementation-cut.ts +2 -2
- package/scripts/rules/index-guard.ts +1 -1
- package/scripts/rules/issue-comments.ts +118 -0
- package/scripts/rules/{issue-fold.ts → issue-fold-rule.ts} +2 -2
- package/scripts/rules/lane-background.ts +2 -2
- package/scripts/rules/lane-park.ts +18 -0
- package/scripts/rules/lane-split-park.ts +128 -0
- package/scripts/rules/oracle-firing.ts +1 -1
- package/scripts/rules/poll-loop.ts +1 -1
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +59 -4
- package/scripts/rules/{run-tail.ts → run-tail-rule.ts} +2 -2
- package/scripts/rules/shell-body-trigger.ts +1 -1
- package/scripts/rules/stop-rules.ts +18 -7
- package/scripts/rules/test-declared-commit.ts +4 -4
- package/scripts/rules/wip-cap.ts +63 -0
- package/scripts/run/{run-carry-args.ts → carry/run-carry-args.ts} +37 -13
- package/scripts/run/{run-carry-change.ts → carry/run-carry-change.ts} +29 -7
- package/scripts/run/{run-carry-cli.ts → carry/run-carry-cli.ts} +4 -6
- package/scripts/run/{run-carry.ts → carry/run-carry.ts} +12 -6
- package/scripts/run/{run-cut-args.ts → cut/run-cut-args.ts} +1 -1
- package/scripts/run/{run-cut-cli.ts → cut/run-cut-cli.ts} +3 -3
- package/scripts/run/{run-cut-report.ts → cut/run-cut-report.ts} +2 -2
- package/scripts/run/{run-cut.ts → cut/run-cut.ts} +1 -1
- package/scripts/run/{run-entry-cli.ts → entry/run-entry-cli.ts} +11 -11
- package/scripts/run/{run-entry.ts → entry/run-entry.ts} +2 -2
- package/scripts/run/{run-event-scope.ts → event/run-event-scope.ts} +1 -1
- package/scripts/run/{run-event-stream-emit.ts → event/run-event-stream-emit.ts} +1 -1
- package/scripts/run/{run-event-stream.ts → event/run-event-stream.ts} +16 -2
- package/scripts/run/{run-hold-cli.ts → hold/run-hold-cli.ts} +5 -5
- package/scripts/run/{run-merge-cli.ts → merge/run-merge-cli.ts} +10 -5
- package/scripts/run/{run-merge-steps.ts → merge/run-merge-steps.ts} +53 -5
- package/scripts/run/{run-merge.ts → merge/run-merge.ts} +1 -1
- package/scripts/run/{run-progress-cli.ts → progress/run-progress-cli.ts} +1 -1
- package/scripts/run/{run-progress-config.ts → progress/run-progress-config.ts} +2 -17
- package/scripts/run/{run-progress-read.ts → progress/run-progress-read.ts} +5 -5
- package/scripts/run/{run-progress.ts → progress/run-progress.ts} +1 -1
- package/scripts/run/{run-review-steps.ts → review/run-review-steps.ts} +2 -3
- package/scripts/run/run-ending.ts +2 -2
- package/scripts/run/run-halfrun-resume.ts +6 -1
- package/scripts/run/run-headless.ts +1 -1
- package/scripts/run/run-invocation.ts +85 -84
- package/scripts/run/run-liveness.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +1 -1
- package/scripts/run/run-preflight.ts +6 -6
- package/scripts/run/run-prep-cli.ts +1 -1
- package/scripts/run/run-prrun-resume.ts +1 -1
- package/scripts/run/run-report-cli.ts +4 -4
- package/scripts/run/run-report.ts +2 -2
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +3 -3
- package/scripts/run/run-step.ts +2 -2
- package/scripts/run/run-stop-notify.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +4 -4
- package/scripts/run/run-stranded.ts +2 -2
- package/scripts/run/run-watcher-guard-cli.ts +1 -1
- package/scripts/run/run-watcher-guard.ts +5 -3
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/run/{run-ship-cli.ts → ship/run-ship-cli.ts} +29 -8
- package/scripts/run/{run-ship-detach.ts → ship/run-ship-detach.ts} +3 -3
- package/scripts/run/ship/run-ship-lock.ts +50 -0
- package/scripts/run/{run-ship-next.ts → ship/run-ship-next.ts} +13 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +66 -0
- package/scripts/run/{run-ship-preflight.ts → ship/run-ship-preflight.ts} +6 -2
- package/scripts/run/{run-ship-probe.ts → ship/run-ship-probe.ts} +2 -2
- package/scripts/run/{run-ship-return.ts → ship/run-ship-return.ts} +10 -6
- package/scripts/run/{run-ship-review-steps.ts → ship/run-ship-review-steps.ts} +3 -3
- package/scripts/run/{run-ship-scoped.ts → ship/run-ship-scoped.ts} +10 -1
- package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +13 -0
- package/scripts/run/{run-ship-steps.ts → ship/run-ship-steps.ts} +15 -8
- package/scripts/run/ship/run-ship-stop-text.ts +13 -0
- package/scripts/run/ship/run-ship-sync.ts +128 -0
- package/scripts/run/{run-ship.ts → ship/run-ship.ts} +6 -0
- package/scripts/run/{run-tidy-lanes.ts → tidy/run-tidy-lanes.ts} +1 -1
- package/scripts/run/{run-wake-cli.ts → wake/run-wake-cli.ts} +31 -9
- package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +3 -3
- package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +99 -17
- package/scripts/run/{run-wake-handoff.ts → wake/run-wake-handoff.ts} +1 -1
- package/scripts/run/{run-wake-loop.ts → wake/run-wake-loop.ts} +8 -2
- package/scripts/run/wake/run-wake-restart.ts +58 -0
- package/scripts/run/{run-wake-session.ts → wake/run-wake-session.ts} +3 -3
- package/scripts/run/{run-wake.ts → wake/run-wake.ts} +1 -1
- package/scripts/safe-chain/preinstall-command.ts +20 -21
- package/scripts/safe-chain/project-config.ts +19 -15
- package/scripts/sync/sync-ai-files.ts +1 -1
- package/scripts/sync/sync-configs.ts +2 -1
- package/scripts/sync/sync.ts +15 -2
- package/scripts/test/test-red-logic.ts +17 -2
- package/scripts/test/test-red.ts +8 -7
- package/scripts/test/unit-worker-share.ts +1 -0
- package/scripts/time-runtime/time-background.ts +5 -1
- package/scripts/time-runtime/time-instant.ts +3 -1
- package/scripts/time-runtime/time-spans.ts +6 -139
- package/scripts/time-runtime/time-tool-call.ts +160 -0
- package/scripts/time-runtime/time-transcript-line.ts +27 -1
- package/scripts/version/effective-upstream.ts +2 -20
- package/scripts/version/latest-corepack.ts +17 -17
- package/scripts/version/latest-regression.ts +1 -1
- package/scripts/version/latest-update.ts +4 -4
- package/scripts/version/npm-registry.ts +20 -5
- package/scripts/version/publishable-range-check.ts +2 -2
- package/scripts/version/publishable-range.ts +1 -1
- package/scripts/version/release-age.ts +48 -38
- package/scripts/version/release-hold.ts +1 -1
- package/scripts/version/safe-chain-version-update.ts +40 -0
- package/scripts/version/upgrade-shell-command.ts +48 -8
- package/scripts/version/version-check-logic.ts +23 -14
- package/scripts/version/version-commands.ts +23 -11
- package/scripts/version/version-remote.ts +28 -13
- package/templates/pnpm-workspace.basic.yaml +4 -0
- package/templates/workflows/dependabot-auto-merge.yml +5 -5
- package/templates/workflows/github-release.yml +2 -0
- package/scripts/build/build-config-merge.ts +0 -27
- package/scripts/build/build-managed-marker.ts +0 -27
- package/scripts/build/build-self-sync-guard.ts +0 -27
- package/scripts/build/build-version.ts +0 -26
- package/scripts/version/preinstall-version-update.ts +0 -86
- /package/scripts/overrides/{schemas.ts → overrides-schemas.ts} +0 -0
- /package/scripts/run/{run-carry-conversation.ts → carry/run-carry-conversation.ts} +0 -0
- /package/scripts/run/{run-carry-reclaim.ts → carry/run-carry-reclaim.ts} +0 -0
- /package/scripts/run/{run-carry-stash.ts → carry/run-carry-stash.ts} +0 -0
- /package/scripts/run/{run-carry-streak.ts → carry/run-carry-streak.ts} +0 -0
- /package/scripts/run/{run-cut-handoff.ts → cut/run-cut-handoff.ts} +0 -0
- /package/scripts/run/{run-entry-stop.ts → entry/run-entry-stop.ts} +0 -0
- /package/scripts/run/{run-event-cli.ts → event/run-event-cli.ts} +0 -0
- /package/scripts/run/{run-event-follow.ts → event/run-event-follow.ts} +0 -0
- /package/scripts/run/{run-event-render.ts → event/run-event-render.ts} +0 -0
- /package/scripts/run/{run-event-watch.ts → event/run-event-watch.ts} +0 -0
- /package/scripts/run/{run-hold.ts → hold/run-hold.ts} +0 -0
- /package/scripts/run/{run-progress-args.ts → progress/run-progress-args.ts} +0 -0
- /package/scripts/run/{run-progress-clock.ts → progress/run-progress-clock.ts} +0 -0
- /package/scripts/run/{run-review-cli.ts → review/run-review-cli.ts} +0 -0
- /package/scripts/run/{run-review.ts → review/run-review.ts} +0 -0
- /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
- /package/scripts/run/{run-tidy-cli.ts → tidy/run-tidy-cli.ts} +0 -0
- /package/scripts/run/{run-tidy-stashes.ts → tidy/run-tidy-stashes.ts} +0 -0
- /package/scripts/run/{run-tidy.ts → tidy/run-tidy.ts} +0 -0
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ENV_FILE_NAME
|
|
3
3
|
} from "./chunk-RKUAD3I6.js";
|
|
4
|
+
import {
|
|
5
|
+
PLATFORM_TEMP_ROOT,
|
|
6
|
+
PROBE_TIMEOUT_MS,
|
|
7
|
+
stamp_file
|
|
8
|
+
} from "./chunk-ELCN5LCH.js";
|
|
4
9
|
|
|
5
10
|
// scripts/lib/json-value.ts
|
|
6
11
|
function parse_or_undefined(text) {
|
|
@@ -176,6 +181,9 @@ var BACKLOG_COMMANDS = {
|
|
|
176
181
|
},
|
|
177
182
|
"backlog:stalled": {
|
|
178
183
|
script: "scripts/backlog/backlog-stalled-cli.ts",
|
|
184
|
+
// A stall sends one Telegram warning (joshuafolkken/kit#3357). The `Stop` hook calls the detector
|
|
185
|
+
// directly, so this flag costs only the manual command its in-process dispatch.
|
|
186
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
179
187
|
description: "Report whether ready backlog work is sitting undispatched with a free lane and no recent dispatch",
|
|
180
188
|
category: "AI tools",
|
|
181
189
|
reference: ["", "automation", ["network"]]
|
|
@@ -194,7 +202,8 @@ var DOCUMENT_COMMANDS = {
|
|
|
194
202
|
script: "scripts/document/document-section-cli.ts",
|
|
195
203
|
description: 'Print one section of a markdown document, for a `file.md` \u2192 "Heading" reference',
|
|
196
204
|
category: "AI tools",
|
|
197
|
-
reference: ["<file> <heading>", "automation", ["none"]]
|
|
205
|
+
reference: ["<file> <heading>", "automation", ["none"]],
|
|
206
|
+
is_bundled: true
|
|
198
207
|
},
|
|
199
208
|
"read:set": {
|
|
200
209
|
script: "scripts/document/read-set-cli.ts",
|
|
@@ -311,6 +320,10 @@ var ISSUE_COMMANDS = {
|
|
|
311
320
|
var LANE_SCRIPT = "scripts/lane/lane-cli.ts";
|
|
312
321
|
var LANE_ARGUMENTS = { script: LANE_SCRIPT, tsx_arguments: OPTIONAL_ENV_FILE_FLAGS };
|
|
313
322
|
var ISSUE_WITH_OPTIONS = "<issue> [options]";
|
|
323
|
+
var MEASURE_ARGUMENTS = {
|
|
324
|
+
script: "scripts/lane/lane-measure-cli.ts",
|
|
325
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
|
|
326
|
+
};
|
|
314
327
|
var LANE_COMMANDS = {
|
|
315
328
|
"lane:open": {
|
|
316
329
|
...LANE_ARGUMENTS,
|
|
@@ -366,11 +379,27 @@ var LANE_COMMANDS = {
|
|
|
366
379
|
description: "Collapse a backlogrun lane-start event into one call: open the lane, pop and re-install on the first, dispatch the child",
|
|
367
380
|
category: "AI tools",
|
|
368
381
|
reference: ["<issue> [--stash <message>]", "automation", ["files", "git", "processes"]]
|
|
382
|
+
},
|
|
383
|
+
// The lane-limit measurement (joshuafolkken/kit#3355): `.env` is read so `lane:stats` labels the row
|
|
384
|
+
// with the `JOSH_LANE_LIMIT` a person set there.
|
|
385
|
+
"lane:sample": {
|
|
386
|
+
...MEASURE_ARGUMENTS,
|
|
387
|
+
description: "Record the machine load (load average, swap, free memory, working lanes) to the lane ledger",
|
|
388
|
+
category: "AI tools",
|
|
389
|
+
reference: ["[--every <seconds>]", "maintainer", ["files"]],
|
|
390
|
+
default_script_arguments: ["sample"]
|
|
391
|
+
},
|
|
392
|
+
"lane:stats": {
|
|
393
|
+
...MEASURE_ARGUMENTS,
|
|
394
|
+
description: "Print one table row of lane throughput, gate duration and machine load over a period",
|
|
395
|
+
category: "AI tools",
|
|
396
|
+
reference: ["--period <days> [--limit <lane-limit>]", "maintainer", ["none"]],
|
|
397
|
+
default_script_arguments: ["stats"]
|
|
369
398
|
}
|
|
370
399
|
};
|
|
371
400
|
|
|
372
401
|
// scripts/josh/josh-commands-run.ts
|
|
373
|
-
var RUN_HOLD_SCRIPT = "scripts/run/run-hold-cli.ts";
|
|
402
|
+
var RUN_HOLD_SCRIPT = "scripts/run/hold/run-hold-cli.ts";
|
|
374
403
|
var RUN_COMMANDS = {
|
|
375
404
|
"run:hold": {
|
|
376
405
|
script: RUN_HOLD_SCRIPT,
|
|
@@ -386,19 +415,22 @@ var RUN_COMMANDS = {
|
|
|
386
415
|
default_script_arguments: ["--release"]
|
|
387
416
|
},
|
|
388
417
|
"run:tidy": {
|
|
389
|
-
script: "scripts/run/run-tidy-cli.ts",
|
|
418
|
+
script: "scripts/run/tidy/run-tidy-cli.ts",
|
|
390
419
|
description: "Close merged lanes and drop stashes whose issues are all merged",
|
|
391
420
|
category: "AI tools",
|
|
392
421
|
reference: ["", "automation", ["git", "network", "files"]]
|
|
393
422
|
},
|
|
394
423
|
"run:carry": {
|
|
395
|
-
script: "scripts/run/run-carry-cli.ts",
|
|
424
|
+
script: "scripts/run/carry/run-carry-cli.ts",
|
|
425
|
+
// `--stopped` sends the stop confirmation, so the Telegram credentials come from `.env` as for
|
|
426
|
+
// `run:wake` below (joshuafolkken/kit#3357).
|
|
427
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
396
428
|
description: "Carry one invocation\u2019s budget across its own session cuts",
|
|
397
429
|
category: "AI tools",
|
|
398
430
|
reference: ["<operation> [arguments...]", "automation", ["files"]]
|
|
399
431
|
},
|
|
400
432
|
"run:wake": {
|
|
401
|
-
script: "scripts/run/run-wake-cli.ts",
|
|
433
|
+
script: "scripts/run/wake/run-wake-cli.ts",
|
|
402
434
|
// `.env` rather than the ambient environment:
|
|
403
435
|
// the failure warning needs the Telegram credentials, the same
|
|
404
436
|
// reasons `notify` and `followup` carry these flags.
|
|
@@ -408,7 +440,7 @@ var RUN_COMMANDS = {
|
|
|
408
440
|
reference: ["[options]", "automation", ["processes", "notifications"]]
|
|
409
441
|
},
|
|
410
442
|
"run:cut": {
|
|
411
|
-
script: "scripts/run/run-cut-cli.ts",
|
|
443
|
+
script: "scripts/run/cut/run-cut-cli.ts",
|
|
412
444
|
description: "Cut a lane child before the gate and resume a fresh process",
|
|
413
445
|
category: "AI tools",
|
|
414
446
|
reference: ["[--resume] <issue> [--impl] [--handoff <path>]", "automation", ["files"]]
|
|
@@ -426,7 +458,7 @@ var RUN_COMMANDS = {
|
|
|
426
458
|
reference: ["<issue> --output <path> [--repo <owner/repo>]", "automation", ["network"]]
|
|
427
459
|
},
|
|
428
460
|
"run:progress": {
|
|
429
|
-
script: "scripts/run/run-progress-cli.ts",
|
|
461
|
+
script: "scripts/run/progress/run-progress-cli.ts",
|
|
430
462
|
description: "Report an unattended run\u2019s progress once it has gone quiet for an interval",
|
|
431
463
|
category: "AI tools",
|
|
432
464
|
reference: [
|
|
@@ -445,7 +477,9 @@ var RUN_COMMANDS = {
|
|
|
445
477
|
// read the budget, gather the issue reads and decide the pre-implementation step. `run:hold`,
|
|
446
478
|
// `cost --cut`, `run:prep` and `run:step` were four round trips re-billing a lane's full context each.
|
|
447
479
|
"run:entry": {
|
|
448
|
-
script: "scripts/run/run-entry-cli.ts",
|
|
480
|
+
script: "scripts/run/entry/run-entry-cli.ts",
|
|
481
|
+
// A `busy` hold or an `over` budget sends the stop confirmation (joshuafolkken/kit#3357).
|
|
482
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
449
483
|
description: "Open a run in one call: claim the tree, read the budget, bundle the reads, decide the pre-implementation step",
|
|
450
484
|
category: "AI tools",
|
|
451
485
|
reference: ["<issue> [--to <command>]", "automation", ["git", "network", "files"]]
|
|
@@ -609,13 +643,13 @@ var AI_COMMANDS = {
|
|
|
609
643
|
reference: ["[<owner/repo>]", "automation", ["none"]]
|
|
610
644
|
},
|
|
611
645
|
"run:merge": {
|
|
612
|
-
script: "scripts/run/run-merge-cli.ts",
|
|
646
|
+
script: "scripts/run/merge/run-merge-cli.ts",
|
|
613
647
|
description: "Collapse a backlogrun merge event into one call: confirm the child, do the post-merge steps, offer the next child",
|
|
614
648
|
category: "AI tools",
|
|
615
649
|
reference: [ISSUE_WITH_OPTIONS2, "automation", ["git", "network"]]
|
|
616
650
|
},
|
|
617
651
|
"run:review": {
|
|
618
|
-
script: "scripts/run/run-review-cli.ts",
|
|
652
|
+
script: "scripts/run/review/run-review-cli.ts",
|
|
619
653
|
description: "Start the gate in the background and print the /code-review brief in one call so the two overlap (--join to join the gate and check its verdict)",
|
|
620
654
|
category: "AI tools",
|
|
621
655
|
reference: ["[--join]", "automation", ["processes", "files"]]
|
|
@@ -634,7 +668,7 @@ var AI_COMMANDS = {
|
|
|
634
668
|
// (`run:tail`) were four round trips re-billing the run's full context each. It stops at the first
|
|
635
669
|
// failed step and names it, so the run reads only the step to fix.
|
|
636
670
|
ship: {
|
|
637
|
-
script: "scripts/run/run-ship-cli.ts",
|
|
671
|
+
script: "scripts/run/ship/run-ship-cli.ts",
|
|
638
672
|
description: "Ship a change in one call: gate, commit/push/PR, the CI-wait merge and the report bookkeeping, stopping at the first failed step",
|
|
639
673
|
category: "AI tools",
|
|
640
674
|
reference: [
|
|
@@ -644,7 +678,7 @@ var AI_COMMANDS = {
|
|
|
644
678
|
]
|
|
645
679
|
},
|
|
646
680
|
"run:event": {
|
|
647
|
-
script: "scripts/run/run-event-cli.ts",
|
|
681
|
+
script: "scripts/run/event/run-event-cli.ts",
|
|
648
682
|
description: "Append to, read or watch the run\u2019s append-only event stream (--append <kind> <text> | --from|--follow <n> | --watch [<n>] | --last)",
|
|
649
683
|
category: "AI tools",
|
|
650
684
|
reference: [
|
|
@@ -704,6 +738,614 @@ var CLONE_COMMANDS = {
|
|
|
704
738
|
}
|
|
705
739
|
};
|
|
706
740
|
|
|
741
|
+
// scripts/gate/core-budget.ts
|
|
742
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
743
|
+
import { readdirSync as readdirSync2 } from "node:fs";
|
|
744
|
+
import { availableParallelism as availableParallelism2 } from "node:os";
|
|
745
|
+
import path3 from "node:path";
|
|
746
|
+
|
|
747
|
+
// scripts/josh/process-identity.ts
|
|
748
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
749
|
+
import { randomUUID } from "node:crypto";
|
|
750
|
+
import { readFileSync, rmSync } from "node:fs";
|
|
751
|
+
import { createServer } from "node:net";
|
|
752
|
+
import path from "node:path";
|
|
753
|
+
var PS_COMMAND = "/bin/ps";
|
|
754
|
+
var FORMAT_FLAG = "-o";
|
|
755
|
+
var START_TIME_FORMAT = "lstart=";
|
|
756
|
+
var PID_FLAG = "-p";
|
|
757
|
+
var PROBE_ENVIRONMENT = { TZ: "UTC", LC_ALL: "C" };
|
|
758
|
+
var LIVENESS_SIGNAL = 0;
|
|
759
|
+
var LOWEST_REAL_PID = 1;
|
|
760
|
+
var PROC_START_FIELD_INDEX = 19;
|
|
761
|
+
var BEACON_SCHEME = "socket:";
|
|
762
|
+
var BEACON_SUFFIX = ".sock";
|
|
763
|
+
var BEACON_PREFIX = `josh-process-identity-${String(process.getuid?.() ?? "")}-`;
|
|
764
|
+
var BEACON_ID_LENGTH = 36;
|
|
765
|
+
var BEACON_ID_PATTERN = /^[\da-f-]+$/u;
|
|
766
|
+
var WINDOWS_PLATFORM = "win32";
|
|
767
|
+
var SOCKET_PROBE_SOURCE = "const net=require('node:net');const socket=net.createConnection(process.argv[1]);socket.once('connect',()=>process.exit(0));socket.once('error',()=>process.exit(1));socket.setTimeout(1000,()=>process.exit(1));";
|
|
768
|
+
var beacons = /* @__PURE__ */ new Map();
|
|
769
|
+
var exit_cleanup = { is_registered: false };
|
|
770
|
+
function is_live_pid(pid) {
|
|
771
|
+
if (pid < LOWEST_REAL_PID) return false;
|
|
772
|
+
try {
|
|
773
|
+
process.kill(pid, LIVENESS_SIGNAL);
|
|
774
|
+
return true;
|
|
775
|
+
} catch {
|
|
776
|
+
return false;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
function read_proc_start(pid) {
|
|
780
|
+
try {
|
|
781
|
+
const stat = readFileSync(`/proc/${String(pid)}/stat`, "utf8");
|
|
782
|
+
const fields = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/u);
|
|
783
|
+
const start = fields[PROC_START_FIELD_INDEX];
|
|
784
|
+
return start === void 0 ? void 0 : `proc:${start}`;
|
|
785
|
+
} catch {
|
|
786
|
+
return void 0;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function read_ps_start(pid) {
|
|
790
|
+
try {
|
|
791
|
+
const printed = execFileSync(
|
|
792
|
+
PS_COMMAND,
|
|
793
|
+
[FORMAT_FLAG, START_TIME_FORMAT, PID_FLAG, String(pid)],
|
|
794
|
+
{
|
|
795
|
+
encoding: "utf8",
|
|
796
|
+
timeout: PROBE_TIMEOUT_MS,
|
|
797
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
798
|
+
env: PROBE_ENVIRONMENT
|
|
799
|
+
}
|
|
800
|
+
).trim();
|
|
801
|
+
return printed.length > 0 ? printed : void 0;
|
|
802
|
+
} catch {
|
|
803
|
+
return void 0;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
var START_PROBES = { read_proc_start, read_ps_start };
|
|
807
|
+
function safe_probe(probe, pid) {
|
|
808
|
+
try {
|
|
809
|
+
return probe(pid);
|
|
810
|
+
} catch {
|
|
811
|
+
return void 0;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
function read_start(pid, probes = START_PROBES) {
|
|
815
|
+
return safe_probe(probes.read_proc_start, pid) ?? safe_probe(probes.read_ps_start, pid);
|
|
816
|
+
}
|
|
817
|
+
function close_beacon(token) {
|
|
818
|
+
const server = beacons.get(token);
|
|
819
|
+
if (server === void 0) return;
|
|
820
|
+
beacons.delete(token);
|
|
821
|
+
server.close();
|
|
822
|
+
rmSync(token.slice(BEACON_SCHEME.length), { force: true });
|
|
823
|
+
}
|
|
824
|
+
function close_beacons() {
|
|
825
|
+
for (const token of beacons.keys()) close_beacon(token);
|
|
826
|
+
}
|
|
827
|
+
function ensure_exit_cleanup() {
|
|
828
|
+
if (exit_cleanup.is_registered) return;
|
|
829
|
+
exit_cleanup.is_registered = true;
|
|
830
|
+
process.once("exit", close_beacons);
|
|
831
|
+
}
|
|
832
|
+
function ignore_beacon_error() {
|
|
833
|
+
}
|
|
834
|
+
function bind_beacon(target) {
|
|
835
|
+
return createServer().on("error", ignore_beacon_error).listen(target);
|
|
836
|
+
}
|
|
837
|
+
function try_bind_beacon(bind, target) {
|
|
838
|
+
try {
|
|
839
|
+
const server = bind(target);
|
|
840
|
+
return server.listening ? server : void 0;
|
|
841
|
+
} catch {
|
|
842
|
+
return void 0;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
function open_beacon(bind = bind_beacon) {
|
|
846
|
+
const target = path.join(PLATFORM_TEMP_ROOT, `${BEACON_PREFIX}${randomUUID()}${BEACON_SUFFIX}`);
|
|
847
|
+
const token = `${BEACON_SCHEME}${target}`;
|
|
848
|
+
const server = try_bind_beacon(bind, target);
|
|
849
|
+
if (server === void 0) return void 0;
|
|
850
|
+
server.unref();
|
|
851
|
+
beacons.set(token, server);
|
|
852
|
+
ensure_exit_cleanup();
|
|
853
|
+
return token;
|
|
854
|
+
}
|
|
855
|
+
function resolve_own_start(probes = START_PROBES, platform = process.platform) {
|
|
856
|
+
const start = read_start(process.pid, probes);
|
|
857
|
+
if (start !== void 0 || platform === WINDOWS_PLATFORM) return start;
|
|
858
|
+
return open_beacon();
|
|
859
|
+
}
|
|
860
|
+
function is_valid_beacon_name(name) {
|
|
861
|
+
if (!name.startsWith(BEACON_PREFIX) || !name.endsWith(BEACON_SUFFIX)) return false;
|
|
862
|
+
const id = name.slice(BEACON_PREFIX.length, -BEACON_SUFFIX.length);
|
|
863
|
+
return id.length === BEACON_ID_LENGTH && BEACON_ID_PATTERN.test(id);
|
|
864
|
+
}
|
|
865
|
+
function beacon_target(token) {
|
|
866
|
+
if (!token.startsWith(BEACON_SCHEME)) return void 0;
|
|
867
|
+
const target = token.slice(BEACON_SCHEME.length);
|
|
868
|
+
if (path.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
|
|
869
|
+
return is_valid_beacon_name(path.basename(target)) ? target : void 0;
|
|
870
|
+
}
|
|
871
|
+
function is_live_beacon(target) {
|
|
872
|
+
return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
|
|
873
|
+
stdio: "ignore",
|
|
874
|
+
timeout: PROBE_TIMEOUT_MS
|
|
875
|
+
}).status === 0;
|
|
876
|
+
}
|
|
877
|
+
function has_matching_start(pid, recorded_start, read) {
|
|
878
|
+
const observed = read(pid);
|
|
879
|
+
return observed === void 0 ? void 0 : observed === recorded_start;
|
|
880
|
+
}
|
|
881
|
+
function matches_recorded_start(pid, recorded_start, read) {
|
|
882
|
+
const target = beacon_target(recorded_start);
|
|
883
|
+
return target === void 0 ? has_matching_start(pid, recorded_start, read) : is_live_beacon(target);
|
|
884
|
+
}
|
|
885
|
+
var own_probe = /* @__PURE__ */ new Map();
|
|
886
|
+
function own_start() {
|
|
887
|
+
if (!own_probe.has(process.pid)) own_probe.set(process.pid, resolve_own_start());
|
|
888
|
+
return own_probe.get(process.pid);
|
|
889
|
+
}
|
|
890
|
+
function own_fields() {
|
|
891
|
+
const start = own_start();
|
|
892
|
+
return { pid: process.pid, ...start !== void 0 && { process_start: start } };
|
|
893
|
+
}
|
|
894
|
+
function is_same_process(pid, recorded_start, read = read_start) {
|
|
895
|
+
if (pid === void 0 || !is_live_pid(pid)) return false;
|
|
896
|
+
if (recorded_start === void 0) return void 0;
|
|
897
|
+
return matches_recorded_start(pid, recorded_start, read);
|
|
898
|
+
}
|
|
899
|
+
function is_own_process(pid, recorded_start) {
|
|
900
|
+
return pid === process.pid && recorded_start === own_start();
|
|
901
|
+
}
|
|
902
|
+
var process_identity = {
|
|
903
|
+
close_beacon,
|
|
904
|
+
is_live_pid,
|
|
905
|
+
is_own_process,
|
|
906
|
+
is_same_process,
|
|
907
|
+
open_beacon,
|
|
908
|
+
own_fields,
|
|
909
|
+
own_start,
|
|
910
|
+
read_start,
|
|
911
|
+
resolve_own_start
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
// scripts/josh/process-owner.ts
|
|
915
|
+
import { z as z2 } from "zod";
|
|
916
|
+
var process_owner_schema = z2.object({ pid: z2.number(), process_start: z2.string().optional() });
|
|
917
|
+
|
|
918
|
+
// scripts/test/unit-worker-share.ts
|
|
919
|
+
import { readdirSync } from "node:fs";
|
|
920
|
+
import { availableParallelism } from "node:os";
|
|
921
|
+
import path2 from "node:path";
|
|
922
|
+
var RUN_PREFIX = "josh-unit-running-";
|
|
923
|
+
var WORKER_FLAG = "--maxWorkers";
|
|
924
|
+
var WORKER_FLAGS = [WORKER_FLAG, "--max-workers"];
|
|
925
|
+
var MIN_WORKERS = 1;
|
|
926
|
+
var SOLO_RUNS = 1;
|
|
927
|
+
function marker_path(pid = process.pid) {
|
|
928
|
+
return stamp_file.stamp_path(RUN_PREFIX, String(pid));
|
|
929
|
+
}
|
|
930
|
+
function is_running(marker) {
|
|
931
|
+
return process_identity.is_same_process(marker.pid, marker.process_start) !== false;
|
|
932
|
+
}
|
|
933
|
+
function read_marker(source) {
|
|
934
|
+
const raw = stamp_file.read_stamp_text(source);
|
|
935
|
+
if (raw === void 0) return void 0;
|
|
936
|
+
const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw));
|
|
937
|
+
return parsed.success ? parsed.data : void 0;
|
|
938
|
+
}
|
|
939
|
+
function marker_files(directory = PLATFORM_TEMP_ROOT) {
|
|
940
|
+
try {
|
|
941
|
+
return readdirSync(directory).filter((name) => name.startsWith(RUN_PREFIX));
|
|
942
|
+
} catch {
|
|
943
|
+
return [];
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
function sweep_marker(source) {
|
|
947
|
+
try {
|
|
948
|
+
stamp_file.remove_stamp(source);
|
|
949
|
+
} catch {
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
function is_marker_live(source) {
|
|
953
|
+
const marker = read_marker(source);
|
|
954
|
+
if (marker === void 0) return false;
|
|
955
|
+
if (is_running(marker)) return true;
|
|
956
|
+
sweep_marker(source);
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
959
|
+
function live_run_count(directory = PLATFORM_TEMP_ROOT) {
|
|
960
|
+
return marker_files(directory).filter((name) => is_marker_live(path2.join(directory, name))).length;
|
|
961
|
+
}
|
|
962
|
+
var NESTED_KEY = "JOSH_UNIT_RUN_MARKED";
|
|
963
|
+
var NESTED_VALUE = "1";
|
|
964
|
+
function is_nested_run() {
|
|
965
|
+
return process.env[NESTED_KEY] === NESTED_VALUE;
|
|
966
|
+
}
|
|
967
|
+
function resolve_unit_workers(available_cores, runs2) {
|
|
968
|
+
if (runs2 <= SOLO_RUNS) return void 0;
|
|
969
|
+
return Math.max(MIN_WORKERS, Math.floor(available_cores / runs2));
|
|
970
|
+
}
|
|
971
|
+
function current_share(available_cores = availableParallelism(), live_runs = live_run_count()) {
|
|
972
|
+
const own_run2 = is_nested_run() ? 0 : SOLO_RUNS;
|
|
973
|
+
return resolve_unit_workers(available_cores, live_runs + own_run2);
|
|
974
|
+
}
|
|
975
|
+
function is_worker_flag(argument) {
|
|
976
|
+
return WORKER_FLAGS.some((flag) => argument === flag || argument.startsWith(`${flag}=`));
|
|
977
|
+
}
|
|
978
|
+
function worker_arguments(vitest_arguments, share) {
|
|
979
|
+
if (share === void 0) return [];
|
|
980
|
+
if (vitest_arguments.some((argument) => is_worker_flag(argument))) return [];
|
|
981
|
+
return [`${WORKER_FLAG}=${String(share)}`];
|
|
982
|
+
}
|
|
983
|
+
function mark_run_started(target) {
|
|
984
|
+
try {
|
|
985
|
+
stamp_file.write_stamp(target, process_identity.own_fields());
|
|
986
|
+
} catch {
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
async function with_run_marker(run) {
|
|
990
|
+
if (is_nested_run()) return await run();
|
|
991
|
+
const target = marker_path();
|
|
992
|
+
mark_run_started(target);
|
|
993
|
+
process.env[NESTED_KEY] = NESTED_VALUE;
|
|
994
|
+
try {
|
|
995
|
+
return await run();
|
|
996
|
+
} finally {
|
|
997
|
+
process.env[NESTED_KEY] = "";
|
|
998
|
+
stamp_file.remove_stamp(target);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
var unit_worker_share = {
|
|
1002
|
+
MIN_WORKERS,
|
|
1003
|
+
NESTED_KEY,
|
|
1004
|
+
NESTED_VALUE,
|
|
1005
|
+
RUN_PREFIX,
|
|
1006
|
+
SOLO_RUNS,
|
|
1007
|
+
current_share,
|
|
1008
|
+
is_nested_run,
|
|
1009
|
+
live_run_count,
|
|
1010
|
+
marker_path,
|
|
1011
|
+
read_marker,
|
|
1012
|
+
resolve_unit_workers,
|
|
1013
|
+
with_run_marker,
|
|
1014
|
+
worker_arguments
|
|
1015
|
+
};
|
|
1016
|
+
|
|
1017
|
+
// scripts/gate/core-budget.ts
|
|
1018
|
+
import { z as z3 } from "zod";
|
|
1019
|
+
var RESERVED_PREFIX = "josh-core-reserved-";
|
|
1020
|
+
var RESERVED_SUFFIX = ".json";
|
|
1021
|
+
var POLL_INTERVAL_MS = 50;
|
|
1022
|
+
var WAIT_CAP_MS = 12e4;
|
|
1023
|
+
var MIN_BUDGET = 1;
|
|
1024
|
+
var CORE_WEIGHTS = {
|
|
1025
|
+
lint: 2,
|
|
1026
|
+
type_check: 1,
|
|
1027
|
+
spell_check: 1,
|
|
1028
|
+
eslint_scan: 1
|
|
1029
|
+
};
|
|
1030
|
+
var HELD_KEY = "JOSH_CORE_RESERVED";
|
|
1031
|
+
var HELD_VALUE = "1";
|
|
1032
|
+
var reservation_schema = process_owner_schema.extend({
|
|
1033
|
+
weight: z3.number(),
|
|
1034
|
+
claimed_at: z3.number()
|
|
1035
|
+
});
|
|
1036
|
+
function marker_name(key) {
|
|
1037
|
+
return `${RESERVED_PREFIX}${key}${RESERVED_SUFFIX}`;
|
|
1038
|
+
}
|
|
1039
|
+
function is_running2(reservation) {
|
|
1040
|
+
return process_identity.is_same_process(reservation.pid, reservation.process_start) !== false;
|
|
1041
|
+
}
|
|
1042
|
+
function read_reservation(source) {
|
|
1043
|
+
const raw = stamp_file.read_stamp_text(source);
|
|
1044
|
+
if (raw === void 0) return void 0;
|
|
1045
|
+
try {
|
|
1046
|
+
const parsed = reservation_schema.safeParse(JSON.parse(raw));
|
|
1047
|
+
return parsed.success ? parsed.data : void 0;
|
|
1048
|
+
} catch {
|
|
1049
|
+
return void 0;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
function sweep_marker2(source) {
|
|
1053
|
+
try {
|
|
1054
|
+
stamp_file.remove_stamp(source);
|
|
1055
|
+
} catch {
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
function live_reservation(source) {
|
|
1059
|
+
const reservation = read_reservation(source);
|
|
1060
|
+
if (reservation === void 0) return void 0;
|
|
1061
|
+
if (is_running2(reservation)) return reservation;
|
|
1062
|
+
sweep_marker2(source);
|
|
1063
|
+
return void 0;
|
|
1064
|
+
}
|
|
1065
|
+
function marker_files2(directory) {
|
|
1066
|
+
try {
|
|
1067
|
+
return readdirSync2(directory).filter((name) => name.startsWith(RESERVED_PREFIX));
|
|
1068
|
+
} catch {
|
|
1069
|
+
return [];
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
function live_reservations(directory = PLATFORM_TEMP_ROOT) {
|
|
1073
|
+
return marker_files2(directory).flatMap((name) => {
|
|
1074
|
+
const reservation = live_reservation(path3.join(directory, name));
|
|
1075
|
+
return reservation === void 0 ? [] : { key: name, reservation };
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
function compare_claim(left, right) {
|
|
1079
|
+
const by_time = left.reservation.claimed_at - right.reservation.claimed_at;
|
|
1080
|
+
return by_time === 0 ? left.key.localeCompare(right.key) : by_time;
|
|
1081
|
+
}
|
|
1082
|
+
function admitted_keys(reservations, budget) {
|
|
1083
|
+
const admitted = /* @__PURE__ */ new Set();
|
|
1084
|
+
let cumulative = 0;
|
|
1085
|
+
for (const [index, entry] of reservations.toSorted(compare_claim).entries()) {
|
|
1086
|
+
cumulative += entry.reservation.weight;
|
|
1087
|
+
if (index !== 0 && cumulative > budget) break;
|
|
1088
|
+
admitted.add(entry.key);
|
|
1089
|
+
}
|
|
1090
|
+
return admitted;
|
|
1091
|
+
}
|
|
1092
|
+
function is_admitted(key, reservations, budget) {
|
|
1093
|
+
return admitted_keys(reservations, budget).has(key);
|
|
1094
|
+
}
|
|
1095
|
+
function admitted_load(reservations, budget) {
|
|
1096
|
+
const admitted = admitted_keys(reservations, budget);
|
|
1097
|
+
return reservations.filter((entry) => admitted.has(entry.key)).reduce((total, entry) => total + entry.reservation.weight, 0);
|
|
1098
|
+
}
|
|
1099
|
+
function normalize_budget(budget) {
|
|
1100
|
+
return Number.isFinite(budget) ? Math.max(MIN_BUDGET, Math.floor(budget)) : MIN_BUDGET;
|
|
1101
|
+
}
|
|
1102
|
+
async function default_sleep(ms) {
|
|
1103
|
+
await new Promise((resolve) => {
|
|
1104
|
+
setTimeout(resolve, ms);
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
function write_reservation(target, weight, claimed_at) {
|
|
1108
|
+
stamp_file.write_stamp(target, { ...process_identity.own_fields(), weight, claimed_at });
|
|
1109
|
+
}
|
|
1110
|
+
function resolve_timing(options) {
|
|
1111
|
+
return {
|
|
1112
|
+
now: options.now ?? Date.now,
|
|
1113
|
+
sleep: options.sleep ?? default_sleep,
|
|
1114
|
+
poll_interval_ms: options.poll_interval_ms ?? POLL_INTERVAL_MS
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
async function await_admission(context) {
|
|
1118
|
+
while (!is_admitted(context.key, live_reservations(context.directory), context.budget)) {
|
|
1119
|
+
if (context.now() >= context.deadline) return;
|
|
1120
|
+
await context.sleep(context.poll_interval_ms);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
async function reserve(weight, options = {}) {
|
|
1124
|
+
const timing = resolve_timing(options);
|
|
1125
|
+
const directory = options.directory ?? PLATFORM_TEMP_ROOT;
|
|
1126
|
+
const budget = normalize_budget(options.budget ?? availableParallelism2());
|
|
1127
|
+
const claimed_at = timing.now();
|
|
1128
|
+
const name = marker_name(randomUUID2());
|
|
1129
|
+
const target = path3.join(directory, name);
|
|
1130
|
+
write_reservation(target, weight, claimed_at);
|
|
1131
|
+
await await_admission({
|
|
1132
|
+
...timing,
|
|
1133
|
+
key: name,
|
|
1134
|
+
directory,
|
|
1135
|
+
budget,
|
|
1136
|
+
deadline: claimed_at + (options.wait_cap_ms ?? WAIT_CAP_MS)
|
|
1137
|
+
});
|
|
1138
|
+
return { target };
|
|
1139
|
+
}
|
|
1140
|
+
function release(handle) {
|
|
1141
|
+
sweep_marker2(handle.target);
|
|
1142
|
+
}
|
|
1143
|
+
async function with_core_reservation(weight, run, options = {}) {
|
|
1144
|
+
const handle = await reserve(weight, options);
|
|
1145
|
+
try {
|
|
1146
|
+
return await run();
|
|
1147
|
+
} finally {
|
|
1148
|
+
release(handle);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
function is_held() {
|
|
1152
|
+
return process.env[HELD_KEY] === HELD_VALUE;
|
|
1153
|
+
}
|
|
1154
|
+
function set_held_mark(value) {
|
|
1155
|
+
process.env[HELD_KEY] = value;
|
|
1156
|
+
}
|
|
1157
|
+
async function with_held_mark(run) {
|
|
1158
|
+
const previous = process.env[HELD_KEY] ?? "";
|
|
1159
|
+
set_held_mark(HELD_VALUE);
|
|
1160
|
+
try {
|
|
1161
|
+
return await run();
|
|
1162
|
+
} finally {
|
|
1163
|
+
set_held_mark(previous);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
async function with_command_reservation(weight, run, options = {}) {
|
|
1167
|
+
if (is_held() || unit_worker_share.is_nested_run()) return await run();
|
|
1168
|
+
return await with_core_reservation(weight, async () => await with_held_mark(run), options);
|
|
1169
|
+
}
|
|
1170
|
+
var core_budget = {
|
|
1171
|
+
CORE_WEIGHTS,
|
|
1172
|
+
HELD_KEY,
|
|
1173
|
+
HELD_VALUE,
|
|
1174
|
+
RESERVED_PREFIX,
|
|
1175
|
+
admitted_keys,
|
|
1176
|
+
admitted_load,
|
|
1177
|
+
is_held,
|
|
1178
|
+
live_reservations,
|
|
1179
|
+
release,
|
|
1180
|
+
reserve,
|
|
1181
|
+
with_command_reservation,
|
|
1182
|
+
with_core_reservation,
|
|
1183
|
+
with_held_mark
|
|
1184
|
+
};
|
|
1185
|
+
|
|
1186
|
+
// scripts/gate/gate-plan.ts
|
|
1187
|
+
import { availableParallelism as availableParallelism3 } from "node:os";
|
|
1188
|
+
|
|
1189
|
+
// scripts/lib/status-icons.ts
|
|
1190
|
+
var FAIL_ICON = "\u2717";
|
|
1191
|
+
var PASS_ICON = "\u2714";
|
|
1192
|
+
var status_icons = { FAIL_ICON, PASS_ICON };
|
|
1193
|
+
|
|
1194
|
+
// scripts/josh/josh-verdict.ts
|
|
1195
|
+
var { FAIL_ICON: FAIL_ICON2, PASS_ICON: PASS_ICON2 } = status_icons;
|
|
1196
|
+
var GATE_SUBJECT = "verification gate";
|
|
1197
|
+
var GATE_PASSED_PREFIX = `${PASS_ICON2} ${GATE_SUBJECT} passed`;
|
|
1198
|
+
var GATE_FAILED_PREFIX = `${FAIL_ICON2} ${GATE_SUBJECT} failed`;
|
|
1199
|
+
var PASSED_VERDICT = "passed";
|
|
1200
|
+
var FAILED_VERDICT = "failed";
|
|
1201
|
+
function format_gate_passed(step_count, total) {
|
|
1202
|
+
return `${GATE_PASSED_PREFIX} (${step_count} checks) in ${total}.`;
|
|
1203
|
+
}
|
|
1204
|
+
function format_gate_failed(failed_labels, total) {
|
|
1205
|
+
return `${GATE_FAILED_PREFIX}: ${failed_labels} (${total})`;
|
|
1206
|
+
}
|
|
1207
|
+
var GATE_OPENING_PREFIX = "plan: ";
|
|
1208
|
+
var GATE_OPENING_MARK = " checks at once";
|
|
1209
|
+
function is_gate_opening(line) {
|
|
1210
|
+
const trimmed = line.trimStart();
|
|
1211
|
+
return trimmed.startsWith(GATE_OPENING_PREFIX) && trimmed.includes(GATE_OPENING_MARK);
|
|
1212
|
+
}
|
|
1213
|
+
function read_verdict(line) {
|
|
1214
|
+
const trimmed = line.trimStart();
|
|
1215
|
+
if (trimmed.startsWith(GATE_FAILED_PREFIX)) return FAILED_VERDICT;
|
|
1216
|
+
if (trimmed.startsWith(GATE_PASSED_PREFIX)) return PASSED_VERDICT;
|
|
1217
|
+
return void 0;
|
|
1218
|
+
}
|
|
1219
|
+
var josh_verdict = {
|
|
1220
|
+
PASSED_VERDICT,
|
|
1221
|
+
FAILED_VERDICT,
|
|
1222
|
+
format_gate_passed,
|
|
1223
|
+
format_gate_failed,
|
|
1224
|
+
GATE_OPENING_MARK,
|
|
1225
|
+
GATE_OPENING_PREFIX,
|
|
1226
|
+
is_gate_opening,
|
|
1227
|
+
read_verdict
|
|
1228
|
+
};
|
|
1229
|
+
|
|
1230
|
+
// scripts/gate/gate-plan.ts
|
|
1231
|
+
var LINT_LABEL = "lint";
|
|
1232
|
+
var TYPE_CHECK_LABEL = "check";
|
|
1233
|
+
var UNIT_LABEL = "test:unit";
|
|
1234
|
+
var BEHAVIOR_LABEL = "behavior";
|
|
1235
|
+
var WARNING_CHECKER_LABELS = [LINT_LABEL, TYPE_CHECK_LABEL];
|
|
1236
|
+
var STATIC_CHECKS = [
|
|
1237
|
+
{ label: LINT_LABEL, target: "lint", reserved_cores: core_budget.CORE_WEIGHTS.lint },
|
|
1238
|
+
{
|
|
1239
|
+
label: TYPE_CHECK_LABEL,
|
|
1240
|
+
target: "check",
|
|
1241
|
+
reserved_cores: core_budget.CORE_WEIGHTS.type_check
|
|
1242
|
+
},
|
|
1243
|
+
{ label: "cspell", target: "cspell:dot", reserved_cores: core_budget.CORE_WEIGHTS.spell_check },
|
|
1244
|
+
{ label: BEHAVIOR_LABEL, target: BEHAVIOR_LABEL, reserved_cores: 0 },
|
|
1245
|
+
// **The unused-member check reserves no core** (joshuafolkken/kit#2987): it builds one TypeScript
|
|
1246
|
+
// program and walks it for about 5s, and it is over well before lint and the type check. A
|
|
1247
|
+
// reservation would only take a place from the four-core CI runner's fan-out and a worker from the
|
|
1248
|
+
// unit suite for the whole gate.
|
|
1249
|
+
{ label: "exports", target: "exports:unused", reserved_cores: 0 }
|
|
1250
|
+
];
|
|
1251
|
+
var GATE_CHECKS = [
|
|
1252
|
+
...STATIC_CHECKS,
|
|
1253
|
+
{ label: UNIT_LABEL, target: UNIT_LABEL, reserved_cores: 0 }
|
|
1254
|
+
];
|
|
1255
|
+
function select_gate_checks(is_unit_included) {
|
|
1256
|
+
return is_unit_included ? GATE_CHECKS : STATIC_CHECKS;
|
|
1257
|
+
}
|
|
1258
|
+
function has_unit_check(checks) {
|
|
1259
|
+
return checks.some((check) => check.label === UNIT_LABEL);
|
|
1260
|
+
}
|
|
1261
|
+
var RESERVED_CORES = STATIC_CHECKS.reduce(
|
|
1262
|
+
(total, check) => total + check.reserved_cores,
|
|
1263
|
+
0
|
|
1264
|
+
);
|
|
1265
|
+
var MEASURED_CORES = 11;
|
|
1266
|
+
var MIN_CONCURRENCY = 1;
|
|
1267
|
+
var MIN_SHARED_CORES = 1;
|
|
1268
|
+
function shared_cores(available_cores, concurrent_runs) {
|
|
1269
|
+
const runs2 = Number.isFinite(concurrent_runs) ? Math.max(unit_worker_share.SOLO_RUNS, concurrent_runs) : unit_worker_share.SOLO_RUNS;
|
|
1270
|
+
return Math.max(MIN_SHARED_CORES, Math.floor(available_cores / runs2));
|
|
1271
|
+
}
|
|
1272
|
+
function resolve_concurrency(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS, checks = GATE_CHECKS) {
|
|
1273
|
+
const share = shared_cores(available_cores, concurrent_runs);
|
|
1274
|
+
let admitted = 0;
|
|
1275
|
+
let reserved = 0;
|
|
1276
|
+
for (const check of checks) {
|
|
1277
|
+
reserved += check.reserved_cores;
|
|
1278
|
+
if (reserved > share) break;
|
|
1279
|
+
admitted += 1;
|
|
1280
|
+
}
|
|
1281
|
+
return Math.max(MIN_CONCURRENCY, admitted);
|
|
1282
|
+
}
|
|
1283
|
+
function resolve_unit_worker_cap(available_cores, concurrent_runs = unit_worker_share.SOLO_RUNS) {
|
|
1284
|
+
const share = unit_worker_share.resolve_unit_workers(available_cores, concurrent_runs);
|
|
1285
|
+
if (share !== void 0) return share;
|
|
1286
|
+
if (available_cores < MEASURED_CORES) return void 0;
|
|
1287
|
+
return available_cores - RESERVED_CORES;
|
|
1288
|
+
}
|
|
1289
|
+
function solo_unit_weight(available_cores) {
|
|
1290
|
+
return Math.max(0, available_cores - RESERVED_CORES);
|
|
1291
|
+
}
|
|
1292
|
+
function check_weight(check, plan, available_cores) {
|
|
1293
|
+
if (check.label !== UNIT_LABEL) return check.reserved_cores;
|
|
1294
|
+
return plan.unit_worker_cap ?? solo_unit_weight(available_cores);
|
|
1295
|
+
}
|
|
1296
|
+
function direct_unit_weight(available_cores = availableParallelism3(), live_runs = unit_worker_share.live_run_count()) {
|
|
1297
|
+
const weight = unit_worker_share.current_share(available_cores, live_runs) ?? solo_unit_weight(available_cores);
|
|
1298
|
+
return Math.max(unit_worker_share.MIN_WORKERS, weight);
|
|
1299
|
+
}
|
|
1300
|
+
function plan_of(concurrency, unit_worker_cap, checks = GATE_CHECKS) {
|
|
1301
|
+
return { checks, concurrency, unit_worker_cap };
|
|
1302
|
+
}
|
|
1303
|
+
function resolve_gate_plan(available_cores = availableParallelism3(), concurrent_runs = unit_worker_share.SOLO_RUNS, is_unit_included = true) {
|
|
1304
|
+
const checks = select_gate_checks(is_unit_included);
|
|
1305
|
+
return {
|
|
1306
|
+
checks,
|
|
1307
|
+
concurrency: resolve_concurrency(available_cores, concurrent_runs, checks),
|
|
1308
|
+
unit_worker_cap: is_unit_included ? resolve_unit_worker_cap(available_cores, concurrent_runs) : void 0
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
function format_machine(available_cores, concurrent_runs) {
|
|
1312
|
+
const cores = `${String(available_cores)} cores`;
|
|
1313
|
+
if (concurrent_runs <= unit_worker_share.SOLO_RUNS) return cores;
|
|
1314
|
+
return `${cores}, ${String(concurrent_runs)} unit runs`;
|
|
1315
|
+
}
|
|
1316
|
+
function format_unit_cap(plan) {
|
|
1317
|
+
if (!has_unit_check(plan.checks)) return `${UNIT_LABEL} elsewhere`;
|
|
1318
|
+
if (plan.unit_worker_cap === void 0) return `${UNIT_LABEL} unrestricted`;
|
|
1319
|
+
return `${UNIT_LABEL} at ${String(plan.unit_worker_cap)} workers`;
|
|
1320
|
+
}
|
|
1321
|
+
function format_gate_plan(plan, available_cores = availableParallelism3(), concurrent_runs = unit_worker_share.SOLO_RUNS) {
|
|
1322
|
+
const cap = format_unit_cap(plan);
|
|
1323
|
+
const count = `${String(plan.concurrency)} of ${String(plan.checks.length)}`;
|
|
1324
|
+
const width = `${count}${josh_verdict.GATE_OPENING_MARK}`;
|
|
1325
|
+
const machine = format_machine(available_cores, concurrent_runs);
|
|
1326
|
+
return `${josh_verdict.GATE_OPENING_PREFIX}${width}, ${cap} (${machine})`;
|
|
1327
|
+
}
|
|
1328
|
+
var gate_plan = {
|
|
1329
|
+
GATE_CHECKS,
|
|
1330
|
+
LINT_LABEL,
|
|
1331
|
+
MEASURED_CORES,
|
|
1332
|
+
RESERVED_CORES,
|
|
1333
|
+
STATIC_CHECKS,
|
|
1334
|
+
TYPE_CHECK_LABEL,
|
|
1335
|
+
UNIT_LABEL,
|
|
1336
|
+
WARNING_CHECKER_LABELS,
|
|
1337
|
+
check_weight,
|
|
1338
|
+
direct_unit_weight,
|
|
1339
|
+
format_gate_plan,
|
|
1340
|
+
format_machine,
|
|
1341
|
+
has_unit_check,
|
|
1342
|
+
plan_of,
|
|
1343
|
+
resolve_concurrency,
|
|
1344
|
+
resolve_gate_plan,
|
|
1345
|
+
resolve_unit_worker_cap,
|
|
1346
|
+
select_gate_checks
|
|
1347
|
+
};
|
|
1348
|
+
|
|
707
1349
|
// scripts/josh/josh-commands-development.ts
|
|
708
1350
|
var FILE_ARGUMENTS = "[files...]";
|
|
709
1351
|
var REQUIRED_FILE_ARGUMENTS = "<files...>";
|
|
@@ -727,25 +1369,29 @@ var DEV_COMMANDS = {
|
|
|
727
1369
|
script: "scripts/lint/lint-parallel.ts",
|
|
728
1370
|
description: "Check code with prettier and eslint (skips a tool a basic project lacks)",
|
|
729
1371
|
category: "Development",
|
|
730
|
-
reference: ["", "developer", ["processes"]]
|
|
1372
|
+
reference: ["", "developer", ["processes"]],
|
|
1373
|
+
core_weight: core_budget.CORE_WEIGHTS.lint
|
|
731
1374
|
},
|
|
732
1375
|
"lint:related": {
|
|
733
1376
|
script: "scripts/lint/lint-related.ts",
|
|
734
1377
|
description: "Check only the changed files with prettier and eslint (whole tree on fallback)",
|
|
735
1378
|
category: "Development",
|
|
736
|
-
reference: [FILE_ARGUMENTS, "developer", ["processes"]]
|
|
1379
|
+
reference: [FILE_ARGUMENTS, "developer", ["processes"]],
|
|
1380
|
+
core_weight: core_budget.CORE_WEIGHTS.lint
|
|
737
1381
|
},
|
|
738
1382
|
lines: {
|
|
739
1383
|
script: "scripts/lines/lines-command.ts",
|
|
740
1384
|
description: "Print a file's code lines against the max-lines limit and the headroom left",
|
|
741
1385
|
category: "Development",
|
|
742
|
-
reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]]
|
|
1386
|
+
reference: [REQUIRED_FILE_ARGUMENTS, "developer", ["none"]],
|
|
1387
|
+
core_weight: core_budget.CORE_WEIGHTS.eslint_scan
|
|
743
1388
|
},
|
|
744
1389
|
"refactor:scan": {
|
|
745
1390
|
script: "scripts/refactor/refactor-scan-cli.ts",
|
|
746
1391
|
description: "List refactoring candidates in the changed scope by category and answer clear/candidates",
|
|
747
1392
|
category: "Development",
|
|
748
|
-
reference: ["", "automation", ["processes"]]
|
|
1393
|
+
reference: ["", "automation", ["processes"]],
|
|
1394
|
+
core_weight: core_budget.CORE_WEIGHTS.eslint_scan
|
|
749
1395
|
},
|
|
750
1396
|
bytes: {
|
|
751
1397
|
script: "scripts/lines/bytes-command.ts",
|
|
@@ -824,7 +1470,8 @@ var DEV_COMMANDS = {
|
|
|
824
1470
|
script: "scripts/lint/cspell-cached.ts",
|
|
825
1471
|
description: "Run spell check including dotfiles",
|
|
826
1472
|
category: "Development",
|
|
827
|
-
reference: ["", "developer", ["processes"]]
|
|
1473
|
+
reference: ["", "developer", ["processes"]],
|
|
1474
|
+
core_weight: core_budget.CORE_WEIGHTS.spell_check
|
|
828
1475
|
},
|
|
829
1476
|
behavior: {
|
|
830
1477
|
script: "scripts/behavior/behavior-cli.ts",
|
|
@@ -842,13 +1489,15 @@ var DEV_COMMANDS = {
|
|
|
842
1489
|
script: "scripts/test/test-unit-guard.ts",
|
|
843
1490
|
description: "Run unit tests with Vitest (skips when Vitest is absent; fails when it has no tests)",
|
|
844
1491
|
category: "Development",
|
|
845
|
-
reference: [FILTER_ARGUMENTS, "developer", ["processes"]]
|
|
1492
|
+
reference: [FILTER_ARGUMENTS, "developer", ["processes"]],
|
|
1493
|
+
core_weight: gate_plan.direct_unit_weight
|
|
846
1494
|
},
|
|
847
1495
|
"test:related": {
|
|
848
1496
|
script: "scripts/test/test-related.ts",
|
|
849
1497
|
description: "Run only the unit tests related to the changed files (full suite on fallback)",
|
|
850
1498
|
category: "Development",
|
|
851
|
-
reference: [FILE_ARGUMENTS, "developer", ["processes"]]
|
|
1499
|
+
reference: [FILE_ARGUMENTS, "developer", ["processes"]],
|
|
1500
|
+
core_weight: gate_plan.direct_unit_weight
|
|
852
1501
|
},
|
|
853
1502
|
"test:declared": {
|
|
854
1503
|
script: "scripts/test/test-declared.ts",
|
|
@@ -858,7 +1507,7 @@ var DEV_COMMANDS = {
|
|
|
858
1507
|
},
|
|
859
1508
|
"test:red": {
|
|
860
1509
|
script: "scripts/test/test-red.ts",
|
|
861
|
-
description: "Run the changed unit tests against the pre-fix tree (merge-base worktree) and report red/green/no-test",
|
|
1510
|
+
description: "Run the changed unit tests against the pre-fix tree (merge-base worktree) and report red/green/no-test/test-only",
|
|
862
1511
|
category: "Development",
|
|
863
1512
|
reference: ["", "developer", ["git", "processes"]]
|
|
864
1513
|
},
|
|
@@ -891,7 +1540,8 @@ var DEV_COMMANDS = {
|
|
|
891
1540
|
script: "scripts/gate/type-check-command.ts",
|
|
892
1541
|
description: "Type-check with tsc (skips a basic project with no TypeScript to check)",
|
|
893
1542
|
category: "Development",
|
|
894
|
-
reference: ["[arguments...]", "developer", ["processes"]]
|
|
1543
|
+
reference: ["[arguments...]", "developer", ["processes"]],
|
|
1544
|
+
core_weight: core_budget.CORE_WEIGHTS.type_check
|
|
895
1545
|
},
|
|
896
1546
|
port: {
|
|
897
1547
|
script: "scripts/ports/port-command.ts",
|
|
@@ -988,7 +1638,7 @@ var MAINTENANCE_COMMANDS = {
|
|
|
988
1638
|
script: "scripts/overrides/overrides-check.ts",
|
|
989
1639
|
description: "Check pnpm overrides for drift",
|
|
990
1640
|
category: "Maintenance",
|
|
991
|
-
reference: ["[--save]", "
|
|
1641
|
+
reference: ["[--save]", "developer", ["files"]]
|
|
992
1642
|
},
|
|
993
1643
|
audit: {
|
|
994
1644
|
script: "scripts/security/security-audit.ts",
|
|
@@ -1016,7 +1666,7 @@ var MAINTENANCE_COMMANDS = {
|
|
|
1016
1666
|
],
|
|
1017
1667
|
description: "Update pnpm, dependencies, and run security audit",
|
|
1018
1668
|
category: "Maintenance",
|
|
1019
|
-
reference: ["", "
|
|
1669
|
+
reference: ["", "developer", ["files", "network", "processes"]],
|
|
1020
1670
|
argument_targets: ["latest:corepack", "latest:update", "audit"]
|
|
1021
1671
|
},
|
|
1022
1672
|
"latest:scope": {
|
|
@@ -1039,13 +1689,13 @@ var MAINTENANCE_COMMANDS = {
|
|
|
1039
1689
|
script: "scripts/version/latest-corepack.ts",
|
|
1040
1690
|
description: "Update pnpm on the current major while preserving the integrity pin",
|
|
1041
1691
|
category: "Maintenance",
|
|
1042
|
-
reference: ["", "
|
|
1692
|
+
reference: ["", "developer", ["files", "network"]]
|
|
1043
1693
|
},
|
|
1044
1694
|
"latest:update": {
|
|
1045
1695
|
script: "scripts/version/latest-update.ts",
|
|
1046
1696
|
description: "Update all dependencies to latest",
|
|
1047
1697
|
category: "Maintenance",
|
|
1048
|
-
reference: ["", "
|
|
1698
|
+
reference: ["", "developer", ["files", "network"]]
|
|
1049
1699
|
}
|
|
1050
1700
|
};
|
|
1051
1701
|
|
|
@@ -1359,7 +2009,9 @@ var ALIASES = {
|
|
|
1359
2009
|
rtr: "retrospective",
|
|
1360
2010
|
rvf: "review:findings",
|
|
1361
2011
|
ruv: "rule:value",
|
|
1362
|
-
ev: "eval"
|
|
2012
|
+
ev: "eval",
|
|
2013
|
+
lsm: "lane:sample",
|
|
2014
|
+
lst: "lane:stats"
|
|
1363
2015
|
};
|
|
1364
2016
|
function canonical_command(name) {
|
|
1365
2017
|
if (!Object.hasOwn(ALIASES, name)) return name;
|
|
@@ -1488,7 +2140,7 @@ var time_shell = {
|
|
|
1488
2140
|
// scripts/time-runtime/time-background.ts
|
|
1489
2141
|
var NO_BACKGROUND = "";
|
|
1490
2142
|
var NO_FINISH = 0;
|
|
1491
|
-
var LAUNCH_PATTERN = /running in background with ID
|
|
2143
|
+
var LAUNCH_PATTERN = /(?:running in background with ID:|moved to the background \(ID:)\s*([\w-]+)/iu;
|
|
1492
2144
|
var AGENT_LAUNCH_PATTERN = /^Async agent launched[\s\S]*?\bagentId:\s*([\w-]+)/u;
|
|
1493
2145
|
var FINISH_PATTERN = /^<task-notification>[\s\S]*?<task-id>([\w-]+)<\/task-id>/u;
|
|
1494
2146
|
var OUTPUT_PATTERN = /tasks\/([\w-]+)\.output/u;
|
|
@@ -1581,74 +2233,542 @@ var time_background = {
|
|
|
1581
2233
|
unread_phases
|
|
1582
2234
|
};
|
|
1583
2235
|
|
|
1584
|
-
// scripts/
|
|
1585
|
-
|
|
1586
|
-
var
|
|
1587
|
-
var
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
var
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
2236
|
+
// scripts/git/git-schemas.ts
|
|
2237
|
+
import { z as z4 } from "zod";
|
|
2238
|
+
var package_name_schema = z4.object({ name: z4.string().min(1) });
|
|
2239
|
+
var rollup_item_schema = z4.looseObject({
|
|
2240
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
|
|
2241
|
+
__typename: z4.string().optional(),
|
|
2242
|
+
state: z4.string().optional(),
|
|
2243
|
+
status: z4.string().optional(),
|
|
2244
|
+
conclusion: z4.string().optional(),
|
|
2245
|
+
name: z4.string().optional(),
|
|
2246
|
+
context: z4.string().optional()
|
|
2247
|
+
});
|
|
2248
|
+
var pr_raw_schema = z4.object({
|
|
2249
|
+
statusCheckRollup: z4.array(rollup_item_schema).optional(),
|
|
2250
|
+
mergeStateStatus: z4.string().optional(),
|
|
2251
|
+
reviewDecision: z4.string().optional()
|
|
2252
|
+
});
|
|
2253
|
+
var pull_comment_schema = z4.object({
|
|
2254
|
+
body: z4.string().optional(),
|
|
2255
|
+
html_url: z4.string().optional(),
|
|
2256
|
+
user: z4.object({ login: z4.string().optional() }).optional()
|
|
2257
|
+
});
|
|
2258
|
+
var ai_review_pull_comment_schema = z4.object({
|
|
2259
|
+
body: z4.string().optional(),
|
|
2260
|
+
url: z4.string().optional(),
|
|
2261
|
+
author: z4.object({ login: z4.string().optional() }).optional()
|
|
2262
|
+
});
|
|
2263
|
+
var pr_info_schema = z4.object({
|
|
2264
|
+
mergeable: z4.union([z4.boolean(), z4.string()]).nullable().optional(),
|
|
2265
|
+
mergeStateStatus: z4.string().nullable().optional(),
|
|
2266
|
+
state: z4.string().optional()
|
|
2267
|
+
});
|
|
2268
|
+
var epic_issue_schema = z4.object({
|
|
2269
|
+
number: z4.number(),
|
|
2270
|
+
body: z4.string().optional()
|
|
2271
|
+
});
|
|
2272
|
+
var blocking_issue_schema = z4.object({
|
|
2273
|
+
number: z4.number(),
|
|
2274
|
+
state: z4.string().optional(),
|
|
2275
|
+
repository_url: z4.string().optional()
|
|
2276
|
+
});
|
|
2277
|
+
var blocked_by_schema = z4.object({
|
|
2278
|
+
nodes: z4.array(blocking_issue_schema).default([]),
|
|
2279
|
+
totalCount: z4.number().optional()
|
|
2280
|
+
}).optional();
|
|
2281
|
+
var epic_child_schema = z4.object({
|
|
2282
|
+
state: z4.string().optional(),
|
|
2283
|
+
blockedBy: blocked_by_schema
|
|
2284
|
+
});
|
|
2285
|
+
var rest_comment_schema = z4.looseObject({
|
|
2286
|
+
body: z4.string().nullish(),
|
|
2287
|
+
html_url: z4.string().optional(),
|
|
2288
|
+
user: z4.looseObject({ login: z4.string().optional() }).nullish()
|
|
2289
|
+
});
|
|
2290
|
+
var issue_label_schema = z4.object({ name: z4.string() });
|
|
2291
|
+
var epic_subject_schema = z4.object({
|
|
2292
|
+
number: z4.number(),
|
|
2293
|
+
state: z4.string().optional(),
|
|
2294
|
+
labels: z4.array(issue_label_schema).optional(),
|
|
2295
|
+
body: z4.string().optional()
|
|
2296
|
+
});
|
|
2297
|
+
var open_issue_schema = z4.object({
|
|
2298
|
+
number: z4.number(),
|
|
2299
|
+
title: z4.string(),
|
|
2300
|
+
labels: z4.array(issue_label_schema).optional(),
|
|
2301
|
+
createdAt: z4.string(),
|
|
2302
|
+
blockedBy: blocked_by_schema,
|
|
2303
|
+
// Present only on the pickup listing, which reads it for the restructures each issue declares.
|
|
2304
|
+
body: z4.string().optional()
|
|
2305
|
+
});
|
|
2306
|
+
|
|
2307
|
+
// scripts/gh/git-pr-checks-parse.ts
|
|
2308
|
+
var CHECK_STATUS_PASS = "pass";
|
|
2309
|
+
var CHECK_STATUS_PENDING = "pending";
|
|
2310
|
+
var CHECK_STATUS_FAIL = "fail";
|
|
2311
|
+
var CHECK_STATUS_MISSING = "missing";
|
|
2312
|
+
var PASSING_CONCLUSIONS = /* @__PURE__ */ new Set(["success", "skipped", "neutral"]);
|
|
2313
|
+
var KEY_TYPE_NAME = "__typename";
|
|
2314
|
+
var KEY_STATE = "state";
|
|
2315
|
+
var KEY_STATUS = "status";
|
|
2316
|
+
var KEY_CONCLUSION = "conclusion";
|
|
2317
|
+
var KEY_NAME = "name";
|
|
2318
|
+
var KEY_CONTEXT = "context";
|
|
2319
|
+
function read_string(value) {
|
|
2320
|
+
if (typeof value !== "string") return void 0;
|
|
2321
|
+
const trimmed = value.trim();
|
|
2322
|
+
if (trimmed.length === 0) return void 0;
|
|
2323
|
+
return trimmed;
|
|
2324
|
+
}
|
|
2325
|
+
var PENDING_STATUS_STATES = /* @__PURE__ */ new Set(["pending", "expected"]);
|
|
2326
|
+
function parse_status_context(item) {
|
|
2327
|
+
const state = read_string(item[KEY_STATE])?.toLowerCase();
|
|
2328
|
+
if (state === "success") return CHECK_STATUS_PASS;
|
|
2329
|
+
if (state !== void 0 && PENDING_STATUS_STATES.has(state)) return CHECK_STATUS_PENDING;
|
|
2330
|
+
return CHECK_STATUS_FAIL;
|
|
2331
|
+
}
|
|
2332
|
+
function is_passing_conclusion(item) {
|
|
2333
|
+
const conclusion = read_string(item[KEY_CONCLUSION])?.toLowerCase();
|
|
2334
|
+
return conclusion !== void 0 && PASSING_CONCLUSIONS.has(conclusion);
|
|
2335
|
+
}
|
|
2336
|
+
function parse_check_run(item) {
|
|
2337
|
+
const status = read_string(item[KEY_STATUS])?.toLowerCase();
|
|
2338
|
+
if (status !== "completed") return CHECK_STATUS_PENDING;
|
|
2339
|
+
return is_passing_conclusion(item) ? CHECK_STATUS_PASS : CHECK_STATUS_FAIL;
|
|
2340
|
+
}
|
|
2341
|
+
function parse_rollup_status(item) {
|
|
2342
|
+
const type_name = read_string(item[KEY_TYPE_NAME]);
|
|
2343
|
+
if (type_name === "StatusContext") return parse_status_context(item);
|
|
2344
|
+
return parse_check_run(item);
|
|
2345
|
+
}
|
|
2346
|
+
function read_rollup_array(parsed) {
|
|
2347
|
+
const result = pr_raw_schema.safeParse(parsed);
|
|
2348
|
+
if (!result.success) return [];
|
|
2349
|
+
return result.data.statusCheckRollup ?? [];
|
|
2350
|
+
}
|
|
2351
|
+
function parse_rollup_item(item) {
|
|
2352
|
+
const name = read_string(item[KEY_NAME]) ?? read_string(item[KEY_CONTEXT]);
|
|
2353
|
+
if (name === void 0) return void 0;
|
|
2354
|
+
return { name, status: parse_rollup_status(item) };
|
|
2355
|
+
}
|
|
2356
|
+
function parse_rollup_checks(raw_json) {
|
|
2357
|
+
const parsed = json_value.parse_or_undefined(raw_json);
|
|
2358
|
+
const rollup = read_rollup_array(parsed);
|
|
2359
|
+
const checks = [];
|
|
2360
|
+
for (const item of rollup) {
|
|
2361
|
+
const parsed_item = parse_rollup_item(item);
|
|
2362
|
+
if (parsed_item !== void 0) checks.push(parsed_item);
|
|
2363
|
+
}
|
|
2364
|
+
return checks;
|
|
2365
|
+
}
|
|
2366
|
+
function parse_pr_state_snapshot(raw_json) {
|
|
2367
|
+
const parsed = json_value.parse_or_undefined(raw_json);
|
|
2368
|
+
const result = pr_raw_schema.safeParse(parsed);
|
|
2369
|
+
const data = result.success ? result.data : void 0;
|
|
2370
|
+
return {
|
|
2371
|
+
rollup: parse_rollup_checks(raw_json),
|
|
2372
|
+
merge_state_status: read_string(data?.mergeStateStatus),
|
|
2373
|
+
review_decision: read_string(data?.reviewDecision)
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
// scripts/gh/git-pr-checks-eval.ts
|
|
2378
|
+
var DEFAULT_REQUIRED_CHECKS = ["SonarQube"];
|
|
2379
|
+
var CODERABBIT_CHECK_NAME = "CodeRabbit";
|
|
2380
|
+
var REQUIRED_CHECKS_ENV_VAR = "JOSH_REQUIRED_CHECKS";
|
|
2381
|
+
function parse_required_checks() {
|
|
2382
|
+
const raw = process.env[REQUIRED_CHECKS_ENV_VAR];
|
|
2383
|
+
if (!raw) return DEFAULT_REQUIRED_CHECKS;
|
|
2384
|
+
return raw.split(",").map((check) => check.trim()).filter((check) => check.length > 0);
|
|
2385
|
+
}
|
|
2386
|
+
var REQUIRED_CHECKS = parse_required_checks();
|
|
2387
|
+
var MERGE_STATE_CLEAN = "CLEAN";
|
|
2388
|
+
var MERGE_STATE_UNSTABLE = "UNSTABLE";
|
|
2389
|
+
var MERGE_STATE_DIRTY = "DIRTY";
|
|
2390
|
+
var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
|
|
2391
|
+
var CHECK_SUITE_SEPARATOR = " / ";
|
|
2392
|
+
var FAILURE_MESSAGE_PREFIX = "PR checks failed";
|
|
2393
|
+
var FAILURE_REASON_REVIEW = "review requested changes";
|
|
2394
|
+
var FAILURE_REASON_CHECKS = "failed checks";
|
|
2395
|
+
var FAILURE_REASON_CONFLICT = "merge conflict";
|
|
2396
|
+
function is_required_match(check_name, required_name) {
|
|
2397
|
+
if (check_name === required_name) return true;
|
|
2398
|
+
return check_name.startsWith(`${required_name}${CHECK_SUITE_SEPARATOR}`);
|
|
2399
|
+
}
|
|
2400
|
+
function find_required_check(checks, required_name) {
|
|
2401
|
+
return checks.find((check) => is_required_match(check.name, required_name));
|
|
2402
|
+
}
|
|
2403
|
+
function read_required_statuses(checks) {
|
|
2404
|
+
return REQUIRED_CHECKS.map(
|
|
2405
|
+
(name) => find_required_check(checks, name)?.status ?? CHECK_STATUS_MISSING
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
function is_review_blocked(review_decision) {
|
|
2409
|
+
return review_decision === REVIEW_CHANGES_REQUESTED;
|
|
2410
|
+
}
|
|
2411
|
+
function is_merge_conflict(merge_state_status) {
|
|
2412
|
+
return merge_state_status === MERGE_STATE_DIRTY;
|
|
2413
|
+
}
|
|
2414
|
+
function evaluate_failure_state(input) {
|
|
2415
|
+
if (is_merge_conflict(input.merge_state_status) || is_review_blocked(input.review_decision) || input.failed_checks.length > 0) {
|
|
2416
|
+
return "failure";
|
|
2417
|
+
}
|
|
2418
|
+
return void 0;
|
|
2419
|
+
}
|
|
2420
|
+
function is_merge_state_clean(merge_state_status) {
|
|
2421
|
+
return merge_state_status === MERGE_STATE_CLEAN;
|
|
2422
|
+
}
|
|
2423
|
+
function is_every_required_passing(statuses) {
|
|
2424
|
+
return statuses.every((status) => status === CHECK_STATUS_PASS);
|
|
2425
|
+
}
|
|
2426
|
+
function is_coderabbit_check(check_name) {
|
|
2427
|
+
return is_required_match(check_name, CODERABBIT_CHECK_NAME);
|
|
2428
|
+
}
|
|
2429
|
+
function is_unstable_only_from_coderabbit(snapshot) {
|
|
2430
|
+
if (snapshot.merge_state_status !== MERGE_STATE_UNSTABLE) return false;
|
|
2431
|
+
const non_passing = snapshot.rollup.filter((check) => check.status !== CHECK_STATUS_PASS);
|
|
2432
|
+
if (non_passing.length === 0) return false;
|
|
2433
|
+
return non_passing.every((check) => is_coderabbit_check(check.name));
|
|
2434
|
+
}
|
|
2435
|
+
function is_required_check(check_name) {
|
|
2436
|
+
return REQUIRED_CHECKS.some((required) => is_required_match(check_name, required));
|
|
2437
|
+
}
|
|
2438
|
+
function is_blocking_failure(check) {
|
|
2439
|
+
if (check.status !== CHECK_STATUS_FAIL) return false;
|
|
2440
|
+
return !is_coderabbit_check(check.name) || is_required_check(check.name);
|
|
2441
|
+
}
|
|
2442
|
+
function collect_blocking_failures(snapshot) {
|
|
2443
|
+
return snapshot.rollup.filter((check) => is_blocking_failure(check)).map((check) => check.name);
|
|
2444
|
+
}
|
|
2445
|
+
function is_mergeable_state(snapshot) {
|
|
2446
|
+
if (is_merge_state_clean(snapshot.merge_state_status)) return true;
|
|
2447
|
+
return is_unstable_only_from_coderabbit(snapshot);
|
|
2448
|
+
}
|
|
2449
|
+
function collect_failure_reasons(snapshot) {
|
|
2450
|
+
const reasons = [];
|
|
2451
|
+
if (is_merge_conflict(snapshot.merge_state_status)) reasons.push(FAILURE_REASON_CONFLICT);
|
|
2452
|
+
if (is_review_blocked(snapshot.review_decision)) reasons.push(FAILURE_REASON_REVIEW);
|
|
2453
|
+
const failed = collect_blocking_failures(snapshot);
|
|
2454
|
+
if (failed.length > 0) reasons.push(`${FAILURE_REASON_CHECKS}: ${failed.join(", ")}`);
|
|
2455
|
+
return reasons;
|
|
2456
|
+
}
|
|
2457
|
+
function describe_pr_failure(snapshot) {
|
|
2458
|
+
const reasons = collect_failure_reasons(snapshot);
|
|
2459
|
+
if (reasons.length === 0) return `${FAILURE_MESSAGE_PREFIX}.`;
|
|
2460
|
+
return `${FAILURE_MESSAGE_PREFIX} (${reasons.join("; ")}).`;
|
|
2461
|
+
}
|
|
2462
|
+
function evaluate_pr_state(snapshot) {
|
|
2463
|
+
const statuses = read_required_statuses(snapshot.rollup);
|
|
2464
|
+
const failure = evaluate_failure_state({
|
|
2465
|
+
review_decision: snapshot.review_decision,
|
|
2466
|
+
failed_checks: collect_blocking_failures(snapshot),
|
|
2467
|
+
merge_state_status: snapshot.merge_state_status
|
|
2468
|
+
});
|
|
2469
|
+
if (failure !== void 0) return failure;
|
|
2470
|
+
if (is_mergeable_state(snapshot) && is_every_required_passing(statuses)) return "success";
|
|
2471
|
+
return "pending";
|
|
2472
|
+
}
|
|
2473
|
+
function is_review_decision_decisive(snapshot) {
|
|
2474
|
+
return evaluate_pr_state(snapshot) !== "pending";
|
|
2475
|
+
}
|
|
2476
|
+
var PrConflictError = class extends Error {
|
|
2477
|
+
name = "PrConflictError";
|
|
2478
|
+
};
|
|
2479
|
+
|
|
2480
|
+
// scripts/time-runtime/time-format.ts
|
|
2481
|
+
var MS_PER_MINUTE = 6e4;
|
|
2482
|
+
var MS_PER_SECOND = 1e3;
|
|
2483
|
+
var MINUTE_DECIMALS = 1;
|
|
2484
|
+
var SECOND_DECIMALS = 1;
|
|
2485
|
+
var PERCENT_SCALE = 100;
|
|
2486
|
+
var PERCENT_DECIMALS = 1;
|
|
2487
|
+
var LABEL_WIDTH = 24;
|
|
2488
|
+
var MINUTES_WIDTH = 9;
|
|
2489
|
+
var NOT_MEASURED = "not measured";
|
|
2490
|
+
var NO_CALLS = "no tool call to divide";
|
|
2491
|
+
var MAX_ROWS = 15;
|
|
2492
|
+
function overflow_line(row_count) {
|
|
2493
|
+
if (row_count <= MAX_ROWS) return [];
|
|
2494
|
+
return [
|
|
2495
|
+
` \u2026 and ${String(row_count - MAX_ROWS)} more (--json carries every row this report holds)`
|
|
2496
|
+
];
|
|
2497
|
+
}
|
|
2498
|
+
function format_minutes(duration_ms) {
|
|
2499
|
+
return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`;
|
|
2500
|
+
}
|
|
2501
|
+
function format_seconds(duration_ms) {
|
|
2502
|
+
return `${(duration_ms / MS_PER_SECOND).toFixed(SECOND_DECIMALS)} s`;
|
|
2503
|
+
}
|
|
2504
|
+
function format_share(part, whole) {
|
|
2505
|
+
if (whole === 0) return "n/a";
|
|
2506
|
+
return `${(part / whole * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`;
|
|
2507
|
+
}
|
|
2508
|
+
function usd(amount, decimals) {
|
|
2509
|
+
return `$${amount.toFixed(decimals)}`;
|
|
2510
|
+
}
|
|
2511
|
+
function format_columns(label, minutes, suffix) {
|
|
2512
|
+
return ` ${label.padEnd(LABEL_WIDTH)}${minutes.padStart(MINUTES_WIDTH)} ${suffix}`;
|
|
2513
|
+
}
|
|
2514
|
+
function format_row(label, duration_ms, suffix) {
|
|
2515
|
+
return format_columns(label, format_minutes(duration_ms), suffix);
|
|
2516
|
+
}
|
|
2517
|
+
function unmeasured_row(label) {
|
|
2518
|
+
return format_columns(label, "", NOT_MEASURED);
|
|
2519
|
+
}
|
|
2520
|
+
var time_format = {
|
|
2521
|
+
MAX_ROWS,
|
|
2522
|
+
NO_CALLS,
|
|
2523
|
+
overflow_line,
|
|
2524
|
+
format_seconds,
|
|
2525
|
+
format_share,
|
|
2526
|
+
usd,
|
|
2527
|
+
format_columns,
|
|
2528
|
+
format_row,
|
|
2529
|
+
// `format_clock` stays private: `format_window` is its only caller, and a namespace that offers
|
|
2530
|
+
// both invites a second renderer to join the two with its own arrow.
|
|
2531
|
+
unmeasured_row
|
|
2532
|
+
};
|
|
2533
|
+
|
|
2534
|
+
// scripts/followup/git-followup-stages.ts
|
|
2535
|
+
var STAGE_LINE_PREFIX = "followup stage: ";
|
|
2536
|
+
var STAGE_TOTAL_PREFIX = "followup stages total: ";
|
|
2537
|
+
var STAGE_NAME_WIDTH = 26;
|
|
2538
|
+
var VALUE_COLUMN = STAGE_LINE_PREFIX.length + STAGE_NAME_WIDTH;
|
|
2539
|
+
var NO_DURATION = 0;
|
|
2540
|
+
var STAGE = {
|
|
2541
|
+
closes_and_context: "closes-and-context",
|
|
2542
|
+
checks_wait: "checks-wait",
|
|
2543
|
+
coderabbit_comments: "coderabbit-comments",
|
|
2544
|
+
ai_review_comments: "ai-review-comments",
|
|
2545
|
+
telegram: "telegram",
|
|
2546
|
+
merge: "merge",
|
|
2547
|
+
completion_and_epic_close: "completion-and-epic-close",
|
|
2548
|
+
// The lap that was still running when a stage threw. `followup` exits non-zero on an AI-review
|
|
2549
|
+
// blocker and on a red check, and those are the runs whose wait is longest — reporting nothing for
|
|
2550
|
+
// them would leave the measurement blind to exactly the invocations worth measuring.
|
|
2551
|
+
interrupted: "interrupted",
|
|
2552
|
+
// The interrupted lap when the wait failed on a merge conflict (joshuafolkken/kit#3221), so the
|
|
2553
|
+
// stage block names the cause a resumed session used to look up with `gh pr view`.
|
|
2554
|
+
conflict: "conflict"
|
|
2555
|
+
};
|
|
2556
|
+
function stopped_lap(error) {
|
|
2557
|
+
return error instanceof PrConflictError ? STAGE.conflict : STAGE.interrupted;
|
|
2558
|
+
}
|
|
2559
|
+
function new_log() {
|
|
2560
|
+
return { stages: [], last_ms: performance.now() };
|
|
2561
|
+
}
|
|
2562
|
+
function lap(log, name) {
|
|
2563
|
+
const now_ms = performance.now();
|
|
2564
|
+
log.stages.push({ name, duration_ms: now_ms - log.last_ms });
|
|
2565
|
+
log.last_ms = now_ms;
|
|
2566
|
+
}
|
|
2567
|
+
function total_ms(stages) {
|
|
2568
|
+
return stages.reduce((sum, stage) => sum + stage.duration_ms, NO_DURATION);
|
|
2569
|
+
}
|
|
2570
|
+
function format_stage(stage) {
|
|
2571
|
+
const name = stage.name.padEnd(STAGE_NAME_WIDTH);
|
|
2572
|
+
return `${STAGE_LINE_PREFIX}${name}${time_format.format_seconds(stage.duration_ms)}`;
|
|
2573
|
+
}
|
|
2574
|
+
function format_stages(log) {
|
|
2575
|
+
if (log.stages.length === 0) return [];
|
|
2576
|
+
const rows = log.stages.map((stage) => format_stage(stage));
|
|
2577
|
+
const total = time_format.format_seconds(total_ms(log.stages));
|
|
2578
|
+
return ["", ...rows, `${STAGE_TOTAL_PREFIX.padEnd(VALUE_COLUMN)}${total}`];
|
|
2579
|
+
}
|
|
2580
|
+
function print_stages(log) {
|
|
2581
|
+
for (const line of format_stages(log)) console.info(line);
|
|
2582
|
+
}
|
|
2583
|
+
var git_followup_stages = {
|
|
2584
|
+
STAGE,
|
|
2585
|
+
STAGE_LINE_PREFIX,
|
|
2586
|
+
STAGE_TOTAL_PREFIX,
|
|
2587
|
+
new_log,
|
|
2588
|
+
lap,
|
|
2589
|
+
total_ms,
|
|
2590
|
+
format_stages,
|
|
2591
|
+
print_stages,
|
|
2592
|
+
stopped_lap
|
|
2593
|
+
};
|
|
2594
|
+
|
|
2595
|
+
// scripts/time-runtime/time-followup-stage.ts
|
|
2596
|
+
var LINE_SEPARATOR = "\n";
|
|
2597
|
+
var SECONDS_SUFFIX = " s";
|
|
2598
|
+
var DIGIT_OR_POINT = /[\d.]/u;
|
|
2599
|
+
var MS_PER_SECOND2 = 1e3;
|
|
2600
|
+
var NO_STAGES = [];
|
|
2601
|
+
function stage_body(line) {
|
|
2602
|
+
const trimmed = line.trimStart();
|
|
2603
|
+
if (!trimmed.startsWith(git_followup_stages.STAGE_LINE_PREFIX)) return void 0;
|
|
2604
|
+
return trimmed.slice(git_followup_stages.STAGE_LINE_PREFIX.length);
|
|
2605
|
+
}
|
|
2606
|
+
function digits_start(head) {
|
|
2607
|
+
let index = head.length;
|
|
2608
|
+
while (index > 0 && DIGIT_OR_POINT.test(head.charAt(index - 1))) index -= 1;
|
|
2609
|
+
return index;
|
|
2610
|
+
}
|
|
2611
|
+
function is_duration(digits) {
|
|
2612
|
+
return digits !== "" && Number.isFinite(Number(digits));
|
|
2613
|
+
}
|
|
2614
|
+
function to_stage(body) {
|
|
2615
|
+
const text = body.trimEnd();
|
|
2616
|
+
if (!text.endsWith(SECONDS_SUFFIX)) return void 0;
|
|
2617
|
+
const head = text.slice(0, -SECONDS_SUFFIX.length);
|
|
2618
|
+
const start = digits_start(head);
|
|
2619
|
+
const name = head.slice(0, start).trim();
|
|
2620
|
+
const digits = head.slice(start);
|
|
2621
|
+
if (name === "" || !is_duration(digits)) return void 0;
|
|
2622
|
+
return { name, duration_ms: Number(digits) * MS_PER_SECOND2 };
|
|
2623
|
+
}
|
|
2624
|
+
function read_stages(text) {
|
|
2625
|
+
if (!text.includes(git_followup_stages.STAGE_LINE_PREFIX)) return NO_STAGES;
|
|
2626
|
+
return text.split(LINE_SEPARATOR).map((line) => stage_body(line)).filter((body) => body !== void 0).map((body) => to_stage(body)).filter((stage) => stage !== void 0);
|
|
2627
|
+
}
|
|
2628
|
+
var time_followup_stage = { NO_STAGES, read_stages };
|
|
2629
|
+
|
|
2630
|
+
// scripts/time-runtime/time-reported-failure.ts
|
|
2631
|
+
import { z as z5 } from "zod";
|
|
2632
|
+
var TEXT_BLOCK_SCHEMA = z5.object({ text: z5.string().nullish() });
|
|
2633
|
+
var CONTENT_SCHEMA = z5.union([z5.string(), z5.array(z5.unknown())]);
|
|
2634
|
+
var LINE_SEPARATOR2 = "\n";
|
|
2635
|
+
function block_text(block) {
|
|
2636
|
+
const parsed = TEXT_BLOCK_SCHEMA.safeParse(block);
|
|
2637
|
+
return parsed.success ? parsed.data.text ?? "" : "";
|
|
2638
|
+
}
|
|
2639
|
+
function result_text2(content) {
|
|
2640
|
+
const parsed = CONTENT_SCHEMA.safeParse(content);
|
|
2641
|
+
if (!parsed.success) return "";
|
|
2642
|
+
if (typeof parsed.data === "string") return parsed.data;
|
|
2643
|
+
return parsed.data.map((block) => block_text(block)).join(LINE_SEPARATOR2);
|
|
2644
|
+
}
|
|
2645
|
+
function is_failure_line(line) {
|
|
2646
|
+
return line.trimStart().startsWith(status_icons.FAIL_ICON);
|
|
2647
|
+
}
|
|
2648
|
+
function is_failed_verdict(line) {
|
|
2649
|
+
return josh_verdict.read_verdict(line) === josh_verdict.FAILED_VERDICT;
|
|
2650
|
+
}
|
|
2651
|
+
function is_passed_verdict(line) {
|
|
2652
|
+
return josh_verdict.read_verdict(line) === josh_verdict.PASSED_VERDICT;
|
|
2653
|
+
}
|
|
2654
|
+
function new_scan() {
|
|
2655
|
+
return {
|
|
2656
|
+
did_find: false,
|
|
2657
|
+
has_failure_before_region: false,
|
|
2658
|
+
has_failure_in_region: false,
|
|
2659
|
+
is_region_open: false
|
|
2660
|
+
};
|
|
2661
|
+
}
|
|
2662
|
+
function close_region(scan) {
|
|
2663
|
+
scan.did_find ||= scan.is_region_open && scan.has_failure_before_region;
|
|
2664
|
+
scan.has_failure_before_region = false;
|
|
2665
|
+
scan.has_failure_in_region = false;
|
|
2666
|
+
scan.is_region_open = false;
|
|
2667
|
+
}
|
|
2668
|
+
function note_failure(scan) {
|
|
2669
|
+
if (scan.is_region_open) {
|
|
2670
|
+
scan.has_failure_in_region = true;
|
|
2671
|
+
return;
|
|
2672
|
+
}
|
|
2673
|
+
scan.has_failure_before_region = true;
|
|
2674
|
+
}
|
|
2675
|
+
function scan_line(scan, line) {
|
|
2676
|
+
if (is_passed_verdict(line)) {
|
|
2677
|
+
close_region(scan);
|
|
2678
|
+
return;
|
|
2679
|
+
}
|
|
2680
|
+
if (is_failure_line(line)) {
|
|
2681
|
+
note_failure(scan);
|
|
2682
|
+
return;
|
|
2683
|
+
}
|
|
2684
|
+
if (josh_verdict.is_gate_opening(line)) scan.is_region_open = true;
|
|
2685
|
+
}
|
|
2686
|
+
function scan_body(lines) {
|
|
2687
|
+
const scan = new_scan();
|
|
2688
|
+
for (const line of lines) scan_line(scan, line);
|
|
2689
|
+
return scan;
|
|
2690
|
+
}
|
|
2691
|
+
function did_scan_find(scan) {
|
|
2692
|
+
return scan.did_find || scan.has_failure_before_region || scan.has_failure_in_region;
|
|
2693
|
+
}
|
|
2694
|
+
function has_failure_line(content) {
|
|
2695
|
+
const lines = result_text2(content).split(LINE_SEPARATOR2);
|
|
2696
|
+
if (lines.some((line) => is_failed_verdict(line))) return true;
|
|
2697
|
+
return did_scan_find(scan_body(lines));
|
|
2698
|
+
}
|
|
2699
|
+
function is_reported_failure(josh_command, did_print_failure) {
|
|
2700
|
+
return josh_command !== "" && did_print_failure;
|
|
2701
|
+
}
|
|
2702
|
+
var time_reported_failure = { result_text: result_text2, has_failure_line, is_reported_failure };
|
|
2703
|
+
|
|
2704
|
+
// scripts/time-runtime/time-bundle-call.ts
|
|
2705
|
+
var { BASH_TOOL: BASH_TOOL2 } = cost_blocks;
|
|
2706
|
+
var BUNDLEABLE_TOOLS = /* @__PURE__ */ new Set(["Edit", "Glob", "Grep", "Read", "WebFetch", "WebSearch", "Write"]);
|
|
2707
|
+
var LAUNCH_TOOLS = /* @__PURE__ */ new Set(["Agent", "Task"]);
|
|
2708
|
+
var PRIOR_REFERENCE_MARKERS = [
|
|
2709
|
+
"previous finding",
|
|
2710
|
+
"prior finding",
|
|
2711
|
+
"earlier finding",
|
|
2712
|
+
"previous result",
|
|
2713
|
+
"prior result",
|
|
2714
|
+
"earlier result",
|
|
2715
|
+
"based on the previous",
|
|
2716
|
+
"based on the earlier",
|
|
2717
|
+
"from the previous agent",
|
|
2718
|
+
"from the prior agent",
|
|
2719
|
+
"the finding above",
|
|
2720
|
+
"as found earlier",
|
|
2721
|
+
"as found above",
|
|
2722
|
+
"building on the previous"
|
|
2723
|
+
];
|
|
2724
|
+
var READ_COMMANDS = /* @__PURE__ */ new Set([
|
|
2725
|
+
"awk",
|
|
2726
|
+
"basename",
|
|
2727
|
+
"cat",
|
|
2728
|
+
"comm",
|
|
2729
|
+
"cut",
|
|
2730
|
+
"diff",
|
|
2731
|
+
"dirname",
|
|
2732
|
+
"du",
|
|
2733
|
+
"echo",
|
|
2734
|
+
"file",
|
|
2735
|
+
"find",
|
|
2736
|
+
"gh",
|
|
2737
|
+
"grep",
|
|
2738
|
+
"head",
|
|
2739
|
+
"jq",
|
|
2740
|
+
"ls",
|
|
2741
|
+
"nl",
|
|
2742
|
+
"printf",
|
|
2743
|
+
"pwd",
|
|
2744
|
+
"realpath",
|
|
2745
|
+
"rg",
|
|
2746
|
+
// **`sed -i` is deliberately not excluded.** An in-place edit is what `Edit` does, and `Edit` is on
|
|
2747
|
+
// the allow-list above — a turn may issue several of them, so rejecting the shell spelling of the
|
|
2748
|
+
// same thing would exclude a call the tool form counts. Two in-place edits of the *same* file are
|
|
2749
|
+
// caught by the target test instead, which is where that ordering actually lives.
|
|
2750
|
+
"sed",
|
|
2751
|
+
"sort",
|
|
2752
|
+
"stat",
|
|
2753
|
+
"tail",
|
|
2754
|
+
"tree",
|
|
2755
|
+
"uniq",
|
|
2756
|
+
"wc",
|
|
2757
|
+
"which"
|
|
2758
|
+
]);
|
|
2759
|
+
var MUTATION_WORDS = /* @__PURE__ */ new Set([
|
|
2760
|
+
"--field",
|
|
2761
|
+
"--method",
|
|
2762
|
+
"--raw-field",
|
|
2763
|
+
"-F",
|
|
2764
|
+
"-X",
|
|
2765
|
+
"-delete",
|
|
2766
|
+
"-exec",
|
|
2767
|
+
"-f",
|
|
2768
|
+
"add",
|
|
2769
|
+
"chmod",
|
|
2770
|
+
"chown",
|
|
2771
|
+
"close",
|
|
1652
2772
|
"comment",
|
|
1653
2773
|
"cp",
|
|
1654
2774
|
"create",
|
|
@@ -1810,202 +2930,59 @@ function bash_facts(command) {
|
|
|
1810
2930
|
const writes = {
|
|
1811
2931
|
is_writing: is_in_place_sed(write_segment(command)),
|
|
1812
2932
|
may_write: may_write_command(command)
|
|
1813
|
-
};
|
|
1814
|
-
if (is_read_josh(command)) {
|
|
1815
|
-
return {
|
|
1816
|
-
is_bundleable: true,
|
|
1817
|
-
targets: targets_in(time_shell.unquoted(command)),
|
|
1818
|
-
...writes,
|
|
1819
|
-
has_prior_reference: false
|
|
1820
|
-
};
|
|
1821
|
-
}
|
|
1822
|
-
if (!READ_COMMANDS.has(time_shell.leading_word(command)) || has_mutation(command)) {
|
|
1823
|
-
return { ...not_bundleable(), ...writes };
|
|
1824
|
-
}
|
|
1825
|
-
return {
|
|
1826
|
-
is_bundleable: true,
|
|
1827
|
-
targets: targets_in(time_shell.unquoted(command)),
|
|
1828
|
-
...writes,
|
|
1829
|
-
has_prior_reference: false
|
|
1830
|
-
};
|
|
1831
|
-
}
|
|
1832
|
-
function call_facts(name, input) {
|
|
1833
|
-
if (name !== BASH_TOOL2) return tool_facts(name, input);
|
|
1834
|
-
return bash_facts(time_shell.bash_command(input));
|
|
1835
|
-
}
|
|
1836
|
-
var time_bundle_call = {
|
|
1837
|
-
MAX_TARGETS,
|
|
1838
|
-
not_bundleable,
|
|
1839
|
-
bash_facts,
|
|
1840
|
-
call_facts,
|
|
1841
|
-
tool_facts,
|
|
1842
|
-
// Exported for `time-agent-bundles.ts` (joshuafolkken/kit#1854), which asks the launch question of a
|
|
1843
|
-
// span's `label` — the tool name for a non-Bash call — so the set lives in one place.
|
|
1844
|
-
is_launch_tool,
|
|
1845
|
-
// Exported for `time-writes.ts` (joshuafolkken/kit#1472), which asks what a call *wrote* rather
|
|
1846
|
-
// than what it named. The extraction is the same one either way — a second copy of it would let a
|
|
1847
|
-
// path be recognized as a target when read and missed when written.
|
|
1848
|
-
targets_in,
|
|
1849
|
-
tool_targets,
|
|
1850
|
-
// Exported for the batching guard's own word scan (joshuafolkken/kit#1390), so the two scanners
|
|
1851
|
-
// cannot come to disagree about where one word of a shell line ends and the next begins.
|
|
1852
|
-
// Exported for the read-fold notice (joshuafolkken/kit#2311), which offers `read:files <path>` only
|
|
1853
|
-
// over file-shaped targets — a bare directory like `scripts/` is a target here but not something
|
|
1854
|
-
// `read:files` can read, so the notice reuses this test rather than keep a second copy that could
|
|
1855
|
-
// drift from what counts as a file path.
|
|
1856
|
-
has_extension,
|
|
1857
|
-
// Exported for `time-writes.ts` (joshuafolkken/kit#1509), which needs the same two answers to say
|
|
1858
|
-
// *which* files an in-place `sed` wrote. Two copies of this test disagreed in both directions at
|
|
1859
|
-
// once — one called a piped `grep -i` a write, the other missed a bundled `sed -ni`.
|
|
1860
|
-
write_segment,
|
|
1861
|
-
is_in_place_sed,
|
|
1862
|
-
// Exported for the drift test in `time-bundle-call.test.ts` (joshuafolkken/kit#1875), which pins that
|
|
1863
|
-
// every name here is a real `josh` command and none of them writes.
|
|
1864
|
-
READ_JOSH_SUBCOMMANDS
|
|
1865
|
-
};
|
|
1866
|
-
|
|
1867
|
-
// scripts/time-runtime/time-format.ts
|
|
1868
|
-
var MS_PER_MINUTE = 6e4;
|
|
1869
|
-
var MS_PER_SECOND = 1e3;
|
|
1870
|
-
var MINUTE_DECIMALS = 1;
|
|
1871
|
-
var SECOND_DECIMALS = 1;
|
|
1872
|
-
var PERCENT_SCALE = 100;
|
|
1873
|
-
var PERCENT_DECIMALS = 1;
|
|
1874
|
-
var LABEL_WIDTH = 24;
|
|
1875
|
-
var MINUTES_WIDTH = 9;
|
|
1876
|
-
var NOT_MEASURED = "not measured";
|
|
1877
|
-
var NO_CALLS = "no tool call to divide";
|
|
1878
|
-
var MAX_ROWS = 15;
|
|
1879
|
-
function overflow_line(row_count) {
|
|
1880
|
-
if (row_count <= MAX_ROWS) return [];
|
|
1881
|
-
return [
|
|
1882
|
-
` \u2026 and ${String(row_count - MAX_ROWS)} more (--json carries every row this report holds)`
|
|
1883
|
-
];
|
|
1884
|
-
}
|
|
1885
|
-
function format_minutes(duration_ms) {
|
|
1886
|
-
return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`;
|
|
1887
|
-
}
|
|
1888
|
-
function format_seconds(duration_ms) {
|
|
1889
|
-
return `${(duration_ms / MS_PER_SECOND).toFixed(SECOND_DECIMALS)} s`;
|
|
1890
|
-
}
|
|
1891
|
-
function format_share(part, whole) {
|
|
1892
|
-
if (whole === 0) return "n/a";
|
|
1893
|
-
return `${(part / whole * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`;
|
|
1894
|
-
}
|
|
1895
|
-
function usd(amount, decimals) {
|
|
1896
|
-
return `$${amount.toFixed(decimals)}`;
|
|
1897
|
-
}
|
|
1898
|
-
function format_columns(label, minutes, suffix) {
|
|
1899
|
-
return ` ${label.padEnd(LABEL_WIDTH)}${minutes.padStart(MINUTES_WIDTH)} ${suffix}`;
|
|
1900
|
-
}
|
|
1901
|
-
function format_row(label, duration_ms, suffix) {
|
|
1902
|
-
return format_columns(label, format_minutes(duration_ms), suffix);
|
|
1903
|
-
}
|
|
1904
|
-
function unmeasured_row(label) {
|
|
1905
|
-
return format_columns(label, "", NOT_MEASURED);
|
|
1906
|
-
}
|
|
1907
|
-
var time_format = {
|
|
1908
|
-
MAX_ROWS,
|
|
1909
|
-
NO_CALLS,
|
|
1910
|
-
overflow_line,
|
|
1911
|
-
format_seconds,
|
|
1912
|
-
format_share,
|
|
1913
|
-
usd,
|
|
1914
|
-
format_columns,
|
|
1915
|
-
format_row,
|
|
1916
|
-
// `format_clock` stays private: `format_window` is its only caller, and a namespace that offers
|
|
1917
|
-
// both invites a second renderer to join the two with its own arrow.
|
|
1918
|
-
unmeasured_row
|
|
1919
|
-
};
|
|
1920
|
-
|
|
1921
|
-
// scripts/followup/git-followup-stages.ts
|
|
1922
|
-
var STAGE_LINE_PREFIX = "followup stage: ";
|
|
1923
|
-
var STAGE_TOTAL_PREFIX = "followup stages total: ";
|
|
1924
|
-
var STAGE_NAME_WIDTH = 26;
|
|
1925
|
-
var VALUE_COLUMN = STAGE_LINE_PREFIX.length + STAGE_NAME_WIDTH;
|
|
1926
|
-
var NO_DURATION = 0;
|
|
1927
|
-
var STAGE = {
|
|
1928
|
-
closes_and_context: "closes-and-context",
|
|
1929
|
-
checks_wait: "checks-wait",
|
|
1930
|
-
coderabbit_comments: "coderabbit-comments",
|
|
1931
|
-
ai_review_comments: "ai-review-comments",
|
|
1932
|
-
telegram: "telegram",
|
|
1933
|
-
merge: "merge",
|
|
1934
|
-
completion_and_epic_close: "completion-and-epic-close",
|
|
1935
|
-
// The lap that was still running when a stage threw. `followup` exits non-zero on an AI-review
|
|
1936
|
-
// blocker and on a red check, and those are the runs whose wait is longest — reporting nothing for
|
|
1937
|
-
// them would leave the measurement blind to exactly the invocations worth measuring.
|
|
1938
|
-
interrupted: "interrupted"
|
|
1939
|
-
};
|
|
1940
|
-
function new_log() {
|
|
1941
|
-
return { stages: [], last_ms: performance.now() };
|
|
1942
|
-
}
|
|
1943
|
-
function lap(log, name) {
|
|
1944
|
-
const now_ms = performance.now();
|
|
1945
|
-
log.stages.push({ name, duration_ms: now_ms - log.last_ms });
|
|
1946
|
-
log.last_ms = now_ms;
|
|
1947
|
-
}
|
|
1948
|
-
function total_ms(stages) {
|
|
1949
|
-
return stages.reduce((sum, stage) => sum + stage.duration_ms, NO_DURATION);
|
|
1950
|
-
}
|
|
1951
|
-
function format_stage(stage) {
|
|
1952
|
-
const name = stage.name.padEnd(STAGE_NAME_WIDTH);
|
|
1953
|
-
return `${STAGE_LINE_PREFIX}${name}${time_format.format_seconds(stage.duration_ms)}`;
|
|
1954
|
-
}
|
|
1955
|
-
function format_stages(log) {
|
|
1956
|
-
if (log.stages.length === 0) return [];
|
|
1957
|
-
const rows = log.stages.map((stage) => format_stage(stage));
|
|
1958
|
-
const total = time_format.format_seconds(total_ms(log.stages));
|
|
1959
|
-
return ["", ...rows, `${STAGE_TOTAL_PREFIX.padEnd(VALUE_COLUMN)}${total}`];
|
|
1960
|
-
}
|
|
1961
|
-
function print_stages(log) {
|
|
1962
|
-
for (const line of format_stages(log)) console.info(line);
|
|
1963
|
-
}
|
|
1964
|
-
var git_followup_stages = {
|
|
1965
|
-
STAGE,
|
|
1966
|
-
STAGE_LINE_PREFIX,
|
|
1967
|
-
STAGE_TOTAL_PREFIX,
|
|
1968
|
-
new_log,
|
|
1969
|
-
lap,
|
|
1970
|
-
total_ms,
|
|
1971
|
-
format_stages,
|
|
1972
|
-
print_stages
|
|
1973
|
-
};
|
|
1974
|
-
|
|
1975
|
-
// scripts/time-runtime/time-followup-stage.ts
|
|
1976
|
-
var LINE_SEPARATOR = "\n";
|
|
1977
|
-
var SECONDS_SUFFIX = " s";
|
|
1978
|
-
var DIGIT_OR_POINT = /[\d.]/u;
|
|
1979
|
-
var MS_PER_SECOND2 = 1e3;
|
|
1980
|
-
var NO_STAGES = [];
|
|
1981
|
-
function stage_body(line) {
|
|
1982
|
-
const trimmed = line.trimStart();
|
|
1983
|
-
if (!trimmed.startsWith(git_followup_stages.STAGE_LINE_PREFIX)) return void 0;
|
|
1984
|
-
return trimmed.slice(git_followup_stages.STAGE_LINE_PREFIX.length);
|
|
1985
|
-
}
|
|
1986
|
-
function digits_start(head) {
|
|
1987
|
-
let index = head.length;
|
|
1988
|
-
while (index > 0 && DIGIT_OR_POINT.test(head.charAt(index - 1))) index -= 1;
|
|
1989
|
-
return index;
|
|
1990
|
-
}
|
|
1991
|
-
function is_duration(digits) {
|
|
1992
|
-
return digits !== "" && Number.isFinite(Number(digits));
|
|
1993
|
-
}
|
|
1994
|
-
function to_stage(body) {
|
|
1995
|
-
const text = body.trimEnd();
|
|
1996
|
-
if (!text.endsWith(SECONDS_SUFFIX)) return void 0;
|
|
1997
|
-
const head = text.slice(0, -SECONDS_SUFFIX.length);
|
|
1998
|
-
const start = digits_start(head);
|
|
1999
|
-
const name = head.slice(0, start).trim();
|
|
2000
|
-
const digits = head.slice(start);
|
|
2001
|
-
if (name === "" || !is_duration(digits)) return void 0;
|
|
2002
|
-
return { name, duration_ms: Number(digits) * MS_PER_SECOND2 };
|
|
2933
|
+
};
|
|
2934
|
+
if (is_read_josh(command)) {
|
|
2935
|
+
return {
|
|
2936
|
+
is_bundleable: true,
|
|
2937
|
+
targets: targets_in(time_shell.unquoted(command)),
|
|
2938
|
+
...writes,
|
|
2939
|
+
has_prior_reference: false
|
|
2940
|
+
};
|
|
2941
|
+
}
|
|
2942
|
+
if (!READ_COMMANDS.has(time_shell.leading_word(command)) || has_mutation(command)) {
|
|
2943
|
+
return { ...not_bundleable(), ...writes };
|
|
2944
|
+
}
|
|
2945
|
+
return {
|
|
2946
|
+
is_bundleable: true,
|
|
2947
|
+
targets: targets_in(time_shell.unquoted(command)),
|
|
2948
|
+
...writes,
|
|
2949
|
+
has_prior_reference: false
|
|
2950
|
+
};
|
|
2003
2951
|
}
|
|
2004
|
-
function
|
|
2005
|
-
if (
|
|
2006
|
-
return
|
|
2952
|
+
function call_facts(name, input) {
|
|
2953
|
+
if (name !== BASH_TOOL2) return tool_facts(name, input);
|
|
2954
|
+
return bash_facts(time_shell.bash_command(input));
|
|
2007
2955
|
}
|
|
2008
|
-
var
|
|
2956
|
+
var time_bundle_call = {
|
|
2957
|
+
MAX_TARGETS,
|
|
2958
|
+
not_bundleable,
|
|
2959
|
+
bash_facts,
|
|
2960
|
+
call_facts,
|
|
2961
|
+
tool_facts,
|
|
2962
|
+
// Exported for `time-agent-bundles.ts` (joshuafolkken/kit#1854), which asks the launch question of a
|
|
2963
|
+
// span's `label` — the tool name for a non-Bash call — so the set lives in one place.
|
|
2964
|
+
is_launch_tool,
|
|
2965
|
+
// Exported for `time-writes.ts` (joshuafolkken/kit#1472), which asks what a call *wrote* rather
|
|
2966
|
+
// than what it named. The extraction is the same one either way — a second copy of it would let a
|
|
2967
|
+
// path be recognized as a target when read and missed when written.
|
|
2968
|
+
targets_in,
|
|
2969
|
+
tool_targets,
|
|
2970
|
+
// Exported for the batching guard's own word scan (joshuafolkken/kit#1390), so the two scanners
|
|
2971
|
+
// cannot come to disagree about where one word of a shell line ends and the next begins.
|
|
2972
|
+
// Exported for the read-fold notice (joshuafolkken/kit#2311), which offers `read:files <path>` only
|
|
2973
|
+
// over file-shaped targets — a bare directory like `scripts/` is a target here but not something
|
|
2974
|
+
// `read:files` can read, so the notice reuses this test rather than keep a second copy that could
|
|
2975
|
+
// drift from what counts as a file path.
|
|
2976
|
+
has_extension,
|
|
2977
|
+
// Exported for `time-writes.ts` (joshuafolkken/kit#1509), which needs the same two answers to say
|
|
2978
|
+
// *which* files an in-place `sed` wrote. Two copies of this test disagreed in both directions at
|
|
2979
|
+
// once — one called a piped `grep -i` a write, the other missed a bundled `sed -ni`.
|
|
2980
|
+
write_segment,
|
|
2981
|
+
is_in_place_sed,
|
|
2982
|
+
// Exported for the drift test in `time-bundle-call.test.ts` (joshuafolkken/kit#1875), which pins that
|
|
2983
|
+
// every name here is a real `josh` command and none of them writes.
|
|
2984
|
+
READ_JOSH_SUBCOMMANDS
|
|
2985
|
+
};
|
|
2009
2986
|
|
|
2010
2987
|
// scripts/cost-runtime/cost-attribute.ts
|
|
2011
2988
|
var ISSUE_BRANCH_PATTERN = /^(\d+)-/u;
|
|
@@ -2162,121 +3139,6 @@ var time_markers = {
|
|
|
2162
3139
|
bash_issue
|
|
2163
3140
|
};
|
|
2164
3141
|
|
|
2165
|
-
// scripts/lib/status-icons.ts
|
|
2166
|
-
var FAIL_ICON = "\u2717";
|
|
2167
|
-
var PASS_ICON = "\u2714";
|
|
2168
|
-
var status_icons = { FAIL_ICON, PASS_ICON };
|
|
2169
|
-
|
|
2170
|
-
// scripts/josh/josh-verdict.ts
|
|
2171
|
-
var { FAIL_ICON: FAIL_ICON2, PASS_ICON: PASS_ICON2 } = status_icons;
|
|
2172
|
-
var GATE_SUBJECT = "verification gate";
|
|
2173
|
-
var GATE_PASSED_PREFIX = `${PASS_ICON2} ${GATE_SUBJECT} passed`;
|
|
2174
|
-
var GATE_FAILED_PREFIX = `${FAIL_ICON2} ${GATE_SUBJECT} failed`;
|
|
2175
|
-
var PASSED_VERDICT = "passed";
|
|
2176
|
-
var FAILED_VERDICT = "failed";
|
|
2177
|
-
function format_gate_passed(step_count, total) {
|
|
2178
|
-
return `${GATE_PASSED_PREFIX} (${step_count} checks) in ${total}.`;
|
|
2179
|
-
}
|
|
2180
|
-
function format_gate_failed(failed_labels, total) {
|
|
2181
|
-
return `${GATE_FAILED_PREFIX}: ${failed_labels} (${total})`;
|
|
2182
|
-
}
|
|
2183
|
-
var GATE_OPENING_PREFIX = "plan: ";
|
|
2184
|
-
var GATE_OPENING_MARK = " checks at once";
|
|
2185
|
-
function is_gate_opening(line) {
|
|
2186
|
-
const trimmed = line.trimStart();
|
|
2187
|
-
return trimmed.startsWith(GATE_OPENING_PREFIX) && trimmed.includes(GATE_OPENING_MARK);
|
|
2188
|
-
}
|
|
2189
|
-
function read_verdict(line) {
|
|
2190
|
-
const trimmed = line.trimStart();
|
|
2191
|
-
if (trimmed.startsWith(GATE_FAILED_PREFIX)) return FAILED_VERDICT;
|
|
2192
|
-
if (trimmed.startsWith(GATE_PASSED_PREFIX)) return PASSED_VERDICT;
|
|
2193
|
-
return void 0;
|
|
2194
|
-
}
|
|
2195
|
-
var josh_verdict = {
|
|
2196
|
-
PASSED_VERDICT,
|
|
2197
|
-
FAILED_VERDICT,
|
|
2198
|
-
format_gate_passed,
|
|
2199
|
-
format_gate_failed,
|
|
2200
|
-
GATE_OPENING_MARK,
|
|
2201
|
-
GATE_OPENING_PREFIX,
|
|
2202
|
-
is_gate_opening,
|
|
2203
|
-
read_verdict
|
|
2204
|
-
};
|
|
2205
|
-
|
|
2206
|
-
// scripts/time-runtime/time-reported-failure.ts
|
|
2207
|
-
import { z as z2 } from "zod";
|
|
2208
|
-
var TEXT_BLOCK_SCHEMA = z2.object({ text: z2.string().nullish() });
|
|
2209
|
-
var CONTENT_SCHEMA = z2.union([z2.string(), z2.array(z2.unknown())]);
|
|
2210
|
-
var LINE_SEPARATOR2 = "\n";
|
|
2211
|
-
function block_text(block) {
|
|
2212
|
-
const parsed = TEXT_BLOCK_SCHEMA.safeParse(block);
|
|
2213
|
-
return parsed.success ? parsed.data.text ?? "" : "";
|
|
2214
|
-
}
|
|
2215
|
-
function result_text2(content) {
|
|
2216
|
-
const parsed = CONTENT_SCHEMA.safeParse(content);
|
|
2217
|
-
if (!parsed.success) return "";
|
|
2218
|
-
if (typeof parsed.data === "string") return parsed.data;
|
|
2219
|
-
return parsed.data.map((block) => block_text(block)).join(LINE_SEPARATOR2);
|
|
2220
|
-
}
|
|
2221
|
-
function is_failure_line(line) {
|
|
2222
|
-
return line.trimStart().startsWith(status_icons.FAIL_ICON);
|
|
2223
|
-
}
|
|
2224
|
-
function is_failed_verdict(line) {
|
|
2225
|
-
return josh_verdict.read_verdict(line) === josh_verdict.FAILED_VERDICT;
|
|
2226
|
-
}
|
|
2227
|
-
function is_passed_verdict(line) {
|
|
2228
|
-
return josh_verdict.read_verdict(line) === josh_verdict.PASSED_VERDICT;
|
|
2229
|
-
}
|
|
2230
|
-
function new_scan() {
|
|
2231
|
-
return {
|
|
2232
|
-
did_find: false,
|
|
2233
|
-
has_failure_before_region: false,
|
|
2234
|
-
has_failure_in_region: false,
|
|
2235
|
-
is_region_open: false
|
|
2236
|
-
};
|
|
2237
|
-
}
|
|
2238
|
-
function close_region(scan) {
|
|
2239
|
-
scan.did_find ||= scan.is_region_open && scan.has_failure_before_region;
|
|
2240
|
-
scan.has_failure_before_region = false;
|
|
2241
|
-
scan.has_failure_in_region = false;
|
|
2242
|
-
scan.is_region_open = false;
|
|
2243
|
-
}
|
|
2244
|
-
function note_failure(scan) {
|
|
2245
|
-
if (scan.is_region_open) {
|
|
2246
|
-
scan.has_failure_in_region = true;
|
|
2247
|
-
return;
|
|
2248
|
-
}
|
|
2249
|
-
scan.has_failure_before_region = true;
|
|
2250
|
-
}
|
|
2251
|
-
function scan_line(scan, line) {
|
|
2252
|
-
if (is_passed_verdict(line)) {
|
|
2253
|
-
close_region(scan);
|
|
2254
|
-
return;
|
|
2255
|
-
}
|
|
2256
|
-
if (is_failure_line(line)) {
|
|
2257
|
-
note_failure(scan);
|
|
2258
|
-
return;
|
|
2259
|
-
}
|
|
2260
|
-
if (josh_verdict.is_gate_opening(line)) scan.is_region_open = true;
|
|
2261
|
-
}
|
|
2262
|
-
function scan_body(lines) {
|
|
2263
|
-
const scan = new_scan();
|
|
2264
|
-
for (const line of lines) scan_line(scan, line);
|
|
2265
|
-
return scan;
|
|
2266
|
-
}
|
|
2267
|
-
function did_scan_find(scan) {
|
|
2268
|
-
return scan.did_find || scan.has_failure_before_region || scan.has_failure_in_region;
|
|
2269
|
-
}
|
|
2270
|
-
function has_failure_line(content) {
|
|
2271
|
-
const lines = result_text2(content).split(LINE_SEPARATOR2);
|
|
2272
|
-
if (lines.some((line) => is_failed_verdict(line))) return true;
|
|
2273
|
-
return did_scan_find(scan_body(lines));
|
|
2274
|
-
}
|
|
2275
|
-
function is_reported_failure(josh_command, did_print_failure) {
|
|
2276
|
-
return josh_command !== "" && did_print_failure;
|
|
2277
|
-
}
|
|
2278
|
-
var time_reported_failure = { result_text: result_text2, has_failure_line, is_reported_failure };
|
|
2279
|
-
|
|
2280
3142
|
// scripts/time-runtime/time-single-check.ts
|
|
2281
3143
|
var CHECK_COMMANDS = /* @__PURE__ */ new Set([
|
|
2282
3144
|
"josh check",
|
|
@@ -2301,47 +3163,48 @@ function check_key(josh_command, command) {
|
|
|
2301
3163
|
var time_single_check = { NO_CHECK, check_key };
|
|
2302
3164
|
|
|
2303
3165
|
// scripts/time-runtime/time-transcript-line.ts
|
|
2304
|
-
import { z as
|
|
3166
|
+
import { z as z6 } from "zod";
|
|
2305
3167
|
|
|
2306
3168
|
// scripts/time-runtime/time-instant.ts
|
|
2307
3169
|
function parse_instant(raw) {
|
|
2308
|
-
|
|
3170
|
+
if (raw === null || raw === void 0) return void 0;
|
|
3171
|
+
const parsed = Date.parse(raw);
|
|
2309
3172
|
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
2310
3173
|
}
|
|
2311
3174
|
var time_instant = { parse_instant };
|
|
2312
3175
|
|
|
2313
3176
|
// scripts/time-runtime/time-transcript-line.ts
|
|
2314
|
-
var BLOCK_SCHEMA2 =
|
|
2315
|
-
type:
|
|
2316
|
-
name:
|
|
2317
|
-
id:
|
|
2318
|
-
tool_use_id:
|
|
2319
|
-
input:
|
|
3177
|
+
var BLOCK_SCHEMA2 = z6.object({
|
|
3178
|
+
type: z6.string().nullish(),
|
|
3179
|
+
name: z6.string().nullish(),
|
|
3180
|
+
id: z6.string().nullish(),
|
|
3181
|
+
tool_use_id: z6.string().nullish(),
|
|
3182
|
+
input: z6.unknown().nullish(),
|
|
2320
3183
|
// Whether the harness wrote this result back as a failure (joshuafolkken/kit#1309). Present on a
|
|
2321
3184
|
// `tool_result` block and on nothing else, and absent even there for the tools that never report
|
|
2322
3185
|
// one — which is why it is read as three answers rather than as a boolean with a default.
|
|
2323
|
-
is_error:
|
|
3186
|
+
is_error: z6.boolean().nullish(),
|
|
2324
3187
|
// What the call printed. Read only to recover the outcome a pipeline threw away
|
|
2325
3188
|
// (joshuafolkken/kit#1361): it is kept as flattened text rather than as blocks, because that is
|
|
2326
3189
|
// the whole of what `time-reported-failure.ts` asks of it.
|
|
2327
|
-
content:
|
|
3190
|
+
content: z6.unknown().nullish()
|
|
2328
3191
|
});
|
|
2329
|
-
var CONTENT_SCHEMA2 =
|
|
2330
|
-
var MESSAGE_SCHEMA2 =
|
|
2331
|
-
var LINE_SCHEMA =
|
|
2332
|
-
type:
|
|
2333
|
-
timestamp:
|
|
3192
|
+
var CONTENT_SCHEMA2 = z6.union([z6.string(), z6.array(BLOCK_SCHEMA2)]);
|
|
3193
|
+
var MESSAGE_SCHEMA2 = z6.object({ id: z6.string().nullish(), content: CONTENT_SCHEMA2.nullish() });
|
|
3194
|
+
var LINE_SCHEMA = z6.object({
|
|
3195
|
+
type: z6.string().nullish(),
|
|
3196
|
+
timestamp: z6.string().nullish(),
|
|
2334
3197
|
// The branch the line was written on, which is where the issue number lives — `josh git` names a
|
|
2335
3198
|
// branch `<N>-<slug>`. Read here rather than re-parsed by a second reader so `josh time --issue`
|
|
2336
3199
|
// and `josh cost --issue` answer from the same field (joshuafolkken/kit#1268).
|
|
2337
|
-
gitBranch:
|
|
3200
|
+
gitBranch: z6.string().nullish(),
|
|
2338
3201
|
// The two fields outside `message` that the harness writes an end-of-task notice on
|
|
2339
3202
|
// (joshuafolkken/kit#1696). **Both are read as `unknown` rather than as strings**: a schema
|
|
2340
3203
|
// insisting on a string here would reject every line whose `content` is a list of blocks — which is
|
|
2341
3204
|
// most of them — and a rejected line is dropped from the timeline entirely, so the shares would stop
|
|
2342
3205
|
// reconstructing the elapsed time. The shape is checked at the read below instead.
|
|
2343
|
-
content:
|
|
2344
|
-
attachment:
|
|
3206
|
+
content: z6.unknown().nullish(),
|
|
3207
|
+
attachment: z6.unknown().nullish(),
|
|
2345
3208
|
message: MESSAGE_SCHEMA2.nullish()
|
|
2346
3209
|
});
|
|
2347
3210
|
var UNKNOWN_BRANCH = "";
|
|
@@ -2349,6 +3212,9 @@ var PROMPT_KEY2 = "prompt";
|
|
|
2349
3212
|
var NO_MESSAGE_ID = "";
|
|
2350
3213
|
var ERROR_TEXT_LIMIT = 256;
|
|
2351
3214
|
var REFUSAL_MARKER = "\u26D4";
|
|
3215
|
+
var HOOK_ERROR_LABEL = /^PreToolUse:\S+ hook error: /u;
|
|
3216
|
+
var TOKEN_LINE = /^[a-z][a-z-]*$/u;
|
|
3217
|
+
var TOKEN_LINE_LIMIT = 8;
|
|
2352
3218
|
function block_names(raw) {
|
|
2353
3219
|
return {
|
|
2354
3220
|
type: raw.type ?? "",
|
|
@@ -2358,12 +3224,15 @@ function block_names(raw) {
|
|
|
2358
3224
|
};
|
|
2359
3225
|
}
|
|
2360
3226
|
function guard_from_refusal(text) {
|
|
2361
|
-
const trimmed = text.trimStart();
|
|
3227
|
+
const trimmed = text.trimStart().replace(HOOK_ERROR_LABEL, "");
|
|
2362
3228
|
if (!trimmed.startsWith(REFUSAL_MARKER)) return "";
|
|
2363
3229
|
const headline = trimmed.slice(REFUSAL_MARKER.length).split("\n", 1)[0]?.trimStart() ?? "";
|
|
2364
3230
|
const colon = headline.indexOf(":");
|
|
2365
3231
|
return (colon === -1 ? headline : headline.slice(0, colon)).trim();
|
|
2366
3232
|
}
|
|
3233
|
+
function token_lines_of(text) {
|
|
3234
|
+
return text.split("\n").map((line) => line.trim()).filter((line) => TOKEN_LINE.test(line)).slice(0, TOKEN_LINE_LIMIT);
|
|
3235
|
+
}
|
|
2367
3236
|
function to_block2(raw) {
|
|
2368
3237
|
const text = time_reported_failure.result_text(raw.content);
|
|
2369
3238
|
const is_error = raw.is_error ?? void 0;
|
|
@@ -2375,6 +3244,7 @@ function to_block2(raw) {
|
|
|
2375
3244
|
followup_stages: time_followup_stage.read_stages(text),
|
|
2376
3245
|
error_text: is_error === true ? text.slice(0, ERROR_TEXT_LIMIT) : "",
|
|
2377
3246
|
refusal_guard: is_error === true ? guard_from_refusal(text) : "",
|
|
3247
|
+
token_lines: is_error === true ? [] : token_lines_of(text),
|
|
2378
3248
|
background_id: time_background.launch_id(text),
|
|
2379
3249
|
agent_id: time_background.agent_launch_id(text)
|
|
2380
3250
|
};
|
|
@@ -2408,6 +3278,7 @@ function parse_line2(line) {
|
|
|
2408
3278
|
var time_transcript_line = {
|
|
2409
3279
|
ERROR_TEXT_LIMIT,
|
|
2410
3280
|
NO_MESSAGE_ID,
|
|
3281
|
+
TOKEN_LINE_LIMIT,
|
|
2411
3282
|
guard_from_refusal,
|
|
2412
3283
|
parse_line: parse_line2
|
|
2413
3284
|
};
|
|
@@ -2426,24 +3297,9 @@ var time_writes = {
|
|
|
2426
3297
|
tool_writes
|
|
2427
3298
|
};
|
|
2428
3299
|
|
|
2429
|
-
// scripts/time-runtime/time-
|
|
2430
|
-
var { NO_MESSAGE_ID: NO_MESSAGE_ID2
|
|
2431
|
-
var ASSISTANT_TYPE = "assistant";
|
|
2432
|
-
var USER_TYPE = "user";
|
|
3300
|
+
// scripts/time-runtime/time-tool-call.ts
|
|
3301
|
+
var { NO_MESSAGE_ID: NO_MESSAGE_ID2 } = time_transcript_line;
|
|
2433
3302
|
var UNKNOWN_TOOL = "unknown";
|
|
2434
|
-
var MODEL_CATEGORY = "model";
|
|
2435
|
-
var TOOL_CATEGORY = "tool";
|
|
2436
|
-
var HUMAN_CATEGORY = "human";
|
|
2437
|
-
var OK_OUTCOME = "ok";
|
|
2438
|
-
var FAILED_OUTCOME = "failed";
|
|
2439
|
-
var UNKNOWN_OUTCOME = "unknown";
|
|
2440
|
-
var NO_RESULT = {
|
|
2441
|
-
call_id: "",
|
|
2442
|
-
outcome: UNKNOWN_OUTCOME,
|
|
2443
|
-
refusal_guard: "",
|
|
2444
|
-
background_id: time_background.NO_BACKGROUND,
|
|
2445
|
-
followup_stages: time_followup_stage.NO_STAGES
|
|
2446
|
-
};
|
|
2447
3303
|
var NO_CALL = {
|
|
2448
3304
|
label: "",
|
|
2449
3305
|
josh_command: "",
|
|
@@ -2505,6 +3361,31 @@ function to_tool_call(name, input, message_id) {
|
|
|
2505
3361
|
if (name !== cost_blocks.BASH_TOOL) return non_bash_call(name, input, message_id);
|
|
2506
3362
|
return bash_call(input, message_id);
|
|
2507
3363
|
}
|
|
3364
|
+
var time_tool_call = {
|
|
3365
|
+
UNKNOWN_TOOL,
|
|
3366
|
+
NO_CALL,
|
|
3367
|
+
UNKNOWN_CALL,
|
|
3368
|
+
to_tool_call
|
|
3369
|
+
};
|
|
3370
|
+
|
|
3371
|
+
// scripts/time-runtime/time-spans.ts
|
|
3372
|
+
var { NO_MESSAGE_ID: NO_MESSAGE_ID3, parse_line: parse_line3 } = time_transcript_line;
|
|
3373
|
+
var { NO_CALL: NO_CALL2, UNKNOWN_CALL: UNKNOWN_CALL2, UNKNOWN_TOOL: UNKNOWN_TOOL2, to_tool_call: to_tool_call2 } = time_tool_call;
|
|
3374
|
+
var ASSISTANT_TYPE = "assistant";
|
|
3375
|
+
var USER_TYPE = "user";
|
|
3376
|
+
var MODEL_CATEGORY = "model";
|
|
3377
|
+
var TOOL_CATEGORY = "tool";
|
|
3378
|
+
var HUMAN_CATEGORY = "human";
|
|
3379
|
+
var OK_OUTCOME = "ok";
|
|
3380
|
+
var FAILED_OUTCOME = "failed";
|
|
3381
|
+
var UNKNOWN_OUTCOME = "unknown";
|
|
3382
|
+
var NO_RESULT = {
|
|
3383
|
+
call_id: "",
|
|
3384
|
+
outcome: UNKNOWN_OUTCOME,
|
|
3385
|
+
refusal_guard: "",
|
|
3386
|
+
background_id: time_background.NO_BACKGROUND,
|
|
3387
|
+
followup_stages: time_followup_stage.NO_STAGES
|
|
3388
|
+
};
|
|
2508
3389
|
function tool_use_blocks(lines) {
|
|
2509
3390
|
return lines.flatMap(
|
|
2510
3391
|
(line) => line.blocks.filter((block) => block.type === cost_blocks.TOOL_USE_TYPE && block.id !== "").map((block) => ({ block, message_id: line.message_id }))
|
|
@@ -2514,7 +3395,7 @@ function collect_calls(lines) {
|
|
|
2514
3395
|
return new Map(
|
|
2515
3396
|
tool_use_blocks(lines).map(({ block, message_id }) => [
|
|
2516
3397
|
block.id,
|
|
2517
|
-
|
|
3398
|
+
to_tool_call2(block.name, block.input, message_id)
|
|
2518
3399
|
])
|
|
2519
3400
|
);
|
|
2520
3401
|
}
|
|
@@ -2542,13 +3423,13 @@ function facts_of(result, call) {
|
|
|
2542
3423
|
}
|
|
2543
3424
|
function user_event(line, calls) {
|
|
2544
3425
|
const result = result_block(line);
|
|
2545
|
-
if (result === void 0) return event_of(line, HUMAN_CATEGORY,
|
|
2546
|
-
const call = calls.get(result.result_id) ??
|
|
3426
|
+
if (result === void 0) return event_of(line, HUMAN_CATEGORY, NO_CALL2);
|
|
3427
|
+
const call = calls.get(result.result_id) ?? UNKNOWN_CALL2;
|
|
2547
3428
|
return event_of(line, TOOL_CATEGORY, call, facts_of(result, call));
|
|
2548
3429
|
}
|
|
2549
3430
|
function to_event(line, calls) {
|
|
2550
3431
|
if (line.type === ASSISTANT_TYPE) {
|
|
2551
|
-
return event_of(line, MODEL_CATEGORY, { ...
|
|
3432
|
+
return event_of(line, MODEL_CATEGORY, { ...NO_CALL2, message_id: line.message_id });
|
|
2552
3433
|
}
|
|
2553
3434
|
return line.type === USER_TYPE ? user_event(line, calls) : void 0;
|
|
2554
3435
|
}
|
|
@@ -2630,8 +3511,8 @@ var time_spans = {
|
|
|
2630
3511
|
OK_OUTCOME,
|
|
2631
3512
|
FAILED_OUTCOME,
|
|
2632
3513
|
UNKNOWN_OUTCOME,
|
|
2633
|
-
NO_MESSAGE_ID:
|
|
2634
|
-
UNKNOWN_TOOL,
|
|
3514
|
+
NO_MESSAGE_ID: NO_MESSAGE_ID3,
|
|
3515
|
+
UNKNOWN_TOOL: UNKNOWN_TOOL2,
|
|
2635
3516
|
has_transcript_data,
|
|
2636
3517
|
equal_durations,
|
|
2637
3518
|
no_background,
|
|
@@ -2640,7 +3521,7 @@ var time_spans = {
|
|
|
2640
3521
|
bash_label: time_shell.bash_label,
|
|
2641
3522
|
josh_command_of: time_shell.josh_command_of,
|
|
2642
3523
|
josh_commands_of: time_shell.josh_commands_of,
|
|
2643
|
-
to_tool_call,
|
|
3524
|
+
to_tool_call: to_tool_call2,
|
|
2644
3525
|
parse_line: parse_line3,
|
|
2645
3526
|
parse_timeline
|
|
2646
3527
|
};
|
|
@@ -3109,7 +3990,7 @@ function describe_span(span) {
|
|
|
3109
3990
|
}
|
|
3110
3991
|
var FOLD_MINIMUM = 2;
|
|
3111
3992
|
function read_targets(sequence) {
|
|
3112
|
-
const paths = sequence.filter((span) => span.is_bundleable && !span.is_writing).map((span) => span.targets[0] ?? "").filter((
|
|
3993
|
+
const paths = sequence.filter((span) => span.is_bundleable && !span.is_writing).map((span) => span.targets[0] ?? "").filter((path7) => path7 !== "" && time_bundle_call.has_extension(path7));
|
|
3113
3994
|
return [...new Set(paths)];
|
|
3114
3995
|
}
|
|
3115
3996
|
function read_fold_directive(sequence) {
|
|
@@ -3118,7 +3999,7 @@ function read_fold_directive(sequence) {
|
|
|
3118
3999
|
return ` Fold them into one call: \`pnpm josh read:files ${paths.join(" ")}\`.`;
|
|
3119
4000
|
}
|
|
3120
4001
|
function write_targets(sequence) {
|
|
3121
|
-
const paths = sequence.filter((span) => span.label === EDIT_TOOL).map((span) => span.targets[0] ?? "").filter((
|
|
4002
|
+
const paths = sequence.filter((span) => span.label === EDIT_TOOL).map((span) => span.targets[0] ?? "").filter((path7) => path7 !== "" && time_bundle_call.has_extension(path7));
|
|
3122
4003
|
return [...new Set(paths)];
|
|
3123
4004
|
}
|
|
3124
4005
|
function write_fold_directive(sequence) {
|
|
@@ -3170,41 +4051,41 @@ var time_batch_guard = {
|
|
|
3170
4051
|
};
|
|
3171
4052
|
|
|
3172
4053
|
// scripts/time-runtime/time-hook-transcript.ts
|
|
3173
|
-
import
|
|
4054
|
+
import path6 from "node:path";
|
|
3174
4055
|
|
|
3175
4056
|
// scripts/cost-runtime/cost-transcript.ts
|
|
3176
|
-
import { readdirSync, readFileSync as
|
|
4057
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
3177
4058
|
import { homedir } from "node:os";
|
|
3178
|
-
import
|
|
4059
|
+
import path5 from "node:path";
|
|
3179
4060
|
|
|
3180
4061
|
// scripts/lane/lane-paths.ts
|
|
3181
|
-
import
|
|
4062
|
+
import path4 from "node:path";
|
|
3182
4063
|
var LANE_ROOT_KEY = "JOSH_LANE_ROOT";
|
|
3183
4064
|
var LANE_DIRECTORY_SUFFIX = "-lanes";
|
|
3184
4065
|
var LANE_BRANCH_SUFFIX = "-lane";
|
|
3185
4066
|
function default_lane_root(repository_root) {
|
|
3186
|
-
const name =
|
|
3187
|
-
return
|
|
4067
|
+
const name = path4.basename(repository_root);
|
|
4068
|
+
return path4.join(path4.dirname(repository_root), `.${name}${LANE_DIRECTORY_SUFFIX}`);
|
|
3188
4069
|
}
|
|
3189
4070
|
function lane_root(repository_root, environment = process.env) {
|
|
3190
4071
|
const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
|
|
3191
|
-
return configured.length === 0 ? default_lane_root(repository_root) :
|
|
4072
|
+
return configured.length === 0 ? default_lane_root(repository_root) : path4.resolve(configured);
|
|
3192
4073
|
}
|
|
3193
4074
|
function lane_directory(root, issue) {
|
|
3194
|
-
return
|
|
4075
|
+
return path4.join(root, issue);
|
|
3195
4076
|
}
|
|
3196
4077
|
var LANE_ISSUE_PATTERN = /^\d+$/u;
|
|
3197
4078
|
var DEFAULT_LANE_ROOT_PATTERN = new RegExp(String.raw`^\..+${LANE_DIRECTORY_SUFFIX}$`, "u");
|
|
3198
4079
|
function is_lane_root(directory, environment) {
|
|
3199
4080
|
const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
|
|
3200
|
-
if (configured.length > 0) return
|
|
3201
|
-
return DEFAULT_LANE_ROOT_PATTERN.test(
|
|
4081
|
+
if (configured.length > 0) return path4.resolve(configured) === directory;
|
|
4082
|
+
return DEFAULT_LANE_ROOT_PATTERN.test(path4.basename(directory));
|
|
3202
4083
|
}
|
|
3203
4084
|
function lane_issue_of(directory, environment = process.env) {
|
|
3204
|
-
const resolved =
|
|
3205
|
-
const issue =
|
|
4085
|
+
const resolved = path4.resolve(directory);
|
|
4086
|
+
const issue = path4.basename(resolved);
|
|
3206
4087
|
if (!LANE_ISSUE_PATTERN.test(issue)) return void 0;
|
|
3207
|
-
return is_lane_root(
|
|
4088
|
+
return is_lane_root(path4.dirname(resolved), environment) ? issue : void 0;
|
|
3208
4089
|
}
|
|
3209
4090
|
function lane_branch(issue) {
|
|
3210
4091
|
return `${issue}${LANE_BRANCH_SUFFIX}`;
|
|
@@ -3220,25 +4101,25 @@ var lane_paths = {
|
|
|
3220
4101
|
};
|
|
3221
4102
|
|
|
3222
4103
|
// scripts/lib/read-file.ts
|
|
3223
|
-
import { readFileSync } from "node:fs";
|
|
4104
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
3224
4105
|
var ABSENT_CODE = "ENOENT";
|
|
3225
4106
|
function is_absent(error) {
|
|
3226
4107
|
return error instanceof Error && "code" in error && error.code === ABSENT_CODE;
|
|
3227
4108
|
}
|
|
3228
|
-
function read_optional(
|
|
4109
|
+
function read_optional(path7) {
|
|
3229
4110
|
try {
|
|
3230
|
-
return
|
|
4111
|
+
return readFileSync2(path7, "utf8");
|
|
3231
4112
|
} catch (error) {
|
|
3232
4113
|
if (is_absent(error)) return void 0;
|
|
3233
4114
|
throw error;
|
|
3234
4115
|
}
|
|
3235
4116
|
}
|
|
3236
|
-
function read_file_or_empty(
|
|
3237
|
-
return read_optional(
|
|
4117
|
+
function read_file_or_empty(path7) {
|
|
4118
|
+
return read_optional(path7) ?? "";
|
|
3238
4119
|
}
|
|
3239
|
-
function read_if_readable(
|
|
4120
|
+
function read_if_readable(path7) {
|
|
3240
4121
|
try {
|
|
3241
|
-
return
|
|
4122
|
+
return readFileSync2(path7, "utf8");
|
|
3242
4123
|
} catch {
|
|
3243
4124
|
return void 0;
|
|
3244
4125
|
}
|
|
@@ -3246,30 +4127,30 @@ function read_if_readable(path6) {
|
|
|
3246
4127
|
var file_reader = { read_optional, read_file_or_empty, read_if_readable };
|
|
3247
4128
|
|
|
3248
4129
|
// scripts/cost-runtime/cost-usage.ts
|
|
3249
|
-
import { z as
|
|
3250
|
-
var CACHE_CREATION_SCHEMA =
|
|
3251
|
-
ephemeral_1h_input_tokens:
|
|
3252
|
-
ephemeral_5m_input_tokens:
|
|
4130
|
+
import { z as z7 } from "zod";
|
|
4131
|
+
var CACHE_CREATION_SCHEMA = z7.object({
|
|
4132
|
+
ephemeral_1h_input_tokens: z7.number().nullish(),
|
|
4133
|
+
ephemeral_5m_input_tokens: z7.number().nullish()
|
|
3253
4134
|
});
|
|
3254
|
-
var USAGE_SCHEMA =
|
|
3255
|
-
input_tokens:
|
|
3256
|
-
cache_creation_input_tokens:
|
|
3257
|
-
cache_read_input_tokens:
|
|
3258
|
-
output_tokens:
|
|
3259
|
-
output_tokens_details:
|
|
4135
|
+
var USAGE_SCHEMA = z7.object({
|
|
4136
|
+
input_tokens: z7.number(),
|
|
4137
|
+
cache_creation_input_tokens: z7.number().nullish(),
|
|
4138
|
+
cache_read_input_tokens: z7.number().nullish(),
|
|
4139
|
+
output_tokens: z7.number(),
|
|
4140
|
+
output_tokens_details: z7.object({ thinking_tokens: z7.number().nullish() }).nullish(),
|
|
3260
4141
|
cache_creation: CACHE_CREATION_SCHEMA.nullish()
|
|
3261
4142
|
});
|
|
3262
|
-
var MESSAGE_SCHEMA3 =
|
|
3263
|
-
id:
|
|
3264
|
-
model:
|
|
4143
|
+
var MESSAGE_SCHEMA3 = z7.object({
|
|
4144
|
+
id: z7.string().nullish(),
|
|
4145
|
+
model: z7.string().nullish(),
|
|
3265
4146
|
usage: USAGE_SCHEMA.nullish()
|
|
3266
4147
|
});
|
|
3267
|
-
var LINE_SCHEMA2 =
|
|
3268
|
-
type:
|
|
3269
|
-
requestId:
|
|
3270
|
-
uuid:
|
|
3271
|
-
gitBranch:
|
|
3272
|
-
timestamp:
|
|
4148
|
+
var LINE_SCHEMA2 = z7.object({
|
|
4149
|
+
type: z7.string(),
|
|
4150
|
+
requestId: z7.string().nullish(),
|
|
4151
|
+
uuid: z7.string().nullish(),
|
|
4152
|
+
gitBranch: z7.string().nullish(),
|
|
4153
|
+
timestamp: z7.string().nullish(),
|
|
3273
4154
|
message: MESSAGE_SCHEMA3.nullish()
|
|
3274
4155
|
});
|
|
3275
4156
|
var SYNTHETIC_MODEL = "<synthetic>";
|
|
@@ -3383,7 +4264,7 @@ var cost_usage = {
|
|
|
3383
4264
|
};
|
|
3384
4265
|
|
|
3385
4266
|
// scripts/cost-runtime/cost-transcript.ts
|
|
3386
|
-
var TRANSCRIPT_ROOT =
|
|
4267
|
+
var TRANSCRIPT_ROOT = path5.join(".claude", "projects");
|
|
3387
4268
|
var TRANSCRIPT_EXTENSION = ".jsonl";
|
|
3388
4269
|
var SLUG_PATTERN = /[^a-zA-Z0-9-]/gu;
|
|
3389
4270
|
var UNIT_DIRECTORY = "subagents";
|
|
@@ -3392,7 +4273,7 @@ function project_slug(cwd) {
|
|
|
3392
4273
|
return cwd.replaceAll(SLUG_PATTERN, "-");
|
|
3393
4274
|
}
|
|
3394
4275
|
function transcript_directory(cwd, home = homedir()) {
|
|
3395
|
-
return
|
|
4276
|
+
return path5.join(home, TRANSCRIPT_ROOT, project_slug(cwd));
|
|
3396
4277
|
}
|
|
3397
4278
|
var GIT_ENTRY = ".git";
|
|
3398
4279
|
var GITDIR_PREFIX = "gitdir:";
|
|
@@ -3400,7 +4281,7 @@ var WORKTREE_SEGMENT = `/${GIT_ENTRY}/worktrees/`;
|
|
|
3400
4281
|
var NOT_FOUND = -1;
|
|
3401
4282
|
function linked_worktree_gitdir(cwd) {
|
|
3402
4283
|
try {
|
|
3403
|
-
const contents =
|
|
4284
|
+
const contents = readFileSync3(path5.join(cwd, GIT_ENTRY), "utf8").trim();
|
|
3404
4285
|
return contents.startsWith(GITDIR_PREFIX) ? contents.slice(GITDIR_PREFIX.length).trim() : "";
|
|
3405
4286
|
} catch {
|
|
3406
4287
|
return "";
|
|
@@ -3408,22 +4289,22 @@ function linked_worktree_gitdir(cwd) {
|
|
|
3408
4289
|
}
|
|
3409
4290
|
function session_cwd(cwd) {
|
|
3410
4291
|
const gitdir = linked_worktree_gitdir(cwd);
|
|
3411
|
-
const absolute = gitdir === "" ? "" :
|
|
4292
|
+
const absolute = gitdir === "" ? "" : path5.resolve(cwd, gitdir);
|
|
3412
4293
|
const segment = absolute.indexOf(WORKTREE_SEGMENT);
|
|
3413
4294
|
return segment === NOT_FOUND ? cwd : absolute.slice(0, segment);
|
|
3414
4295
|
}
|
|
3415
4296
|
function read_directory(directory) {
|
|
3416
4297
|
try {
|
|
3417
|
-
return
|
|
4298
|
+
return readdirSync3(directory);
|
|
3418
4299
|
} catch {
|
|
3419
4300
|
return [];
|
|
3420
4301
|
}
|
|
3421
4302
|
}
|
|
3422
4303
|
var LANE_ISSUE_SLUG = /^\d+$/u;
|
|
3423
4304
|
function lane_transcript_directories(main_cwd, home) {
|
|
3424
|
-
const projects =
|
|
4305
|
+
const projects = path5.join(home, TRANSCRIPT_ROOT);
|
|
3425
4306
|
const prefix = `${project_slug(lane_paths.lane_root(main_cwd))}-`;
|
|
3426
|
-
return read_directory(projects).filter((name) => name.startsWith(prefix) && LANE_ISSUE_SLUG.test(name.slice(prefix.length))).map((name) =>
|
|
4307
|
+
return read_directory(projects).filter((name) => name.startsWith(prefix) && LANE_ISSUE_SLUG.test(name.slice(prefix.length))).map((name) => path5.join(projects, name));
|
|
3427
4308
|
}
|
|
3428
4309
|
function transcript_directories(cwd, home = homedir()) {
|
|
3429
4310
|
const own = transcript_directory(cwd, home);
|
|
@@ -3454,16 +4335,16 @@ function without_extension(name) {
|
|
|
3454
4335
|
return name.slice(0, -TRANSCRIPT_EXTENSION.length);
|
|
3455
4336
|
}
|
|
3456
4337
|
function own_files(directory, names) {
|
|
3457
|
-
return names.filter((name) => is_transcript(name)).map((name) => to_session_file(
|
|
4338
|
+
return names.filter((name) => is_transcript(name)).map((name) => to_session_file(path5.join(directory, name), without_extension(name), OWN_DEPTH)).filter((file) => file !== void 0);
|
|
3458
4339
|
}
|
|
3459
4340
|
function unit_directory(directory, session_id) {
|
|
3460
|
-
return
|
|
4341
|
+
return path5.join(directory, session_id, UNIT_DIRECTORY);
|
|
3461
4342
|
}
|
|
3462
4343
|
var UNIT_DEPTH = 1;
|
|
3463
4344
|
function level_units(subagents_directory, prefix, depth) {
|
|
3464
4345
|
return read_directory(subagents_directory).filter((name) => is_transcript(name)).map(
|
|
3465
4346
|
(name) => to_session_file(
|
|
3466
|
-
|
|
4347
|
+
path5.join(subagents_directory, name),
|
|
3467
4348
|
`${prefix}${UNIT_ID_SEPARATOR}${without_extension(name)}`,
|
|
3468
4349
|
depth
|
|
3469
4350
|
)
|
|
@@ -3605,10 +4486,10 @@ function is_agent_id(value) {
|
|
|
3605
4486
|
return typeof value === "string" && AGENT_ID_PATTERN.test(value);
|
|
3606
4487
|
}
|
|
3607
4488
|
function fork_path(transcript_path, agent_id) {
|
|
3608
|
-
const directory =
|
|
3609
|
-
const session_id =
|
|
4489
|
+
const directory = path6.dirname(transcript_path);
|
|
4490
|
+
const session_id = path6.basename(transcript_path, TRANSCRIPT_EXTENSION2);
|
|
3610
4491
|
const file_name = `${AGENT_PREFIX}${agent_id}${TRANSCRIPT_EXTENSION2}`;
|
|
3611
|
-
return
|
|
4492
|
+
return path6.join(cost_transcript.unit_directory(directory, session_id), file_name);
|
|
3612
4493
|
}
|
|
3613
4494
|
function transcript_of(transcript_path, agent_id) {
|
|
3614
4495
|
if (!is_agent_id(agent_id)) return transcript_path;
|
|
@@ -3622,127 +4503,7 @@ var time_hook_transcript = {
|
|
|
3622
4503
|
|
|
3623
4504
|
// scripts/time-runtime/time-density-hook.ts
|
|
3624
4505
|
import { closeSync, fstatSync, openSync, readSync } from "node:fs";
|
|
3625
|
-
|
|
3626
|
-
// scripts/josh/stamp-file.ts
|
|
3627
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
3628
|
-
import { lstatSync, readFileSync as readFileSync3, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
3629
|
-
import path5 from "node:path";
|
|
3630
|
-
|
|
3631
|
-
// scripts/init/init-paths.ts
|
|
3632
|
-
import path4 from "node:path";
|
|
3633
|
-
import { fileURLToPath } from "node:url";
|
|
3634
|
-
var PACKAGE_DIR = path4.join(path4.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
3635
|
-
var PROJECT_ROOT = process.cwd();
|
|
3636
|
-
|
|
3637
|
-
// scripts/josh/platform-temporary.ts
|
|
3638
|
-
import { accessSync, constants } from "node:fs";
|
|
3639
|
-
import { tmpdir } from "node:os";
|
|
3640
|
-
var POSIX_TEMP_ROOT = "/tmp";
|
|
3641
|
-
var WINDOWS_PLATFORM = "win32";
|
|
3642
|
-
function is_writable_directory(directory) {
|
|
3643
|
-
try {
|
|
3644
|
-
accessSync(directory, constants.W_OK);
|
|
3645
|
-
return true;
|
|
3646
|
-
} catch {
|
|
3647
|
-
return false;
|
|
3648
|
-
}
|
|
3649
|
-
}
|
|
3650
|
-
function resolve_temporary_root(platform, can_write = is_writable_directory) {
|
|
3651
|
-
if (platform === WINDOWS_PLATFORM) return tmpdir();
|
|
3652
|
-
return can_write(POSIX_TEMP_ROOT) ? POSIX_TEMP_ROOT : tmpdir();
|
|
3653
|
-
}
|
|
3654
|
-
var TEMP_ROOT_KEY = "JOSH_TEMP_ROOT";
|
|
3655
|
-
function temporary_root(override, platform) {
|
|
3656
|
-
return override === void 0 || override === "" ? resolve_temporary_root(platform) : override;
|
|
3657
|
-
}
|
|
3658
|
-
var PLATFORM_TEMP_ROOT = temporary_root(process.env[TEMP_ROOT_KEY], process.platform);
|
|
3659
|
-
|
|
3660
|
-
// scripts/josh/stamp-file.ts
|
|
3661
|
-
var HASH_ALGORITHM = "sha256";
|
|
3662
|
-
var STAMP_SUFFIX = ".json";
|
|
3663
|
-
var STAMP_KEY_LENGTH = 16;
|
|
3664
|
-
var STAMP_FILE_MODE = 384;
|
|
3665
|
-
var STAMP_WRITE_FLAG = "wx";
|
|
3666
|
-
var STAMP_CREATE_FLAG = STAMP_WRITE_FLAG;
|
|
3667
|
-
var EXISTS_ERROR_CODE = "EEXIST";
|
|
3668
|
-
var ACCOUNT_KEY_SEPARATOR = ":";
|
|
3669
|
-
function digest(content) {
|
|
3670
|
-
return createHash(HASH_ALGORITHM).update(content).digest("hex");
|
|
3671
|
-
}
|
|
3672
|
-
function account_key() {
|
|
3673
|
-
return String(process.getuid?.() ?? "");
|
|
3674
|
-
}
|
|
3675
|
-
function stamp_path(prefix, root = PACKAGE_DIR, suffix = STAMP_SUFFIX) {
|
|
3676
|
-
const key = digest(`${account_key()}${ACCOUNT_KEY_SEPARATOR}${root}`).slice(0, STAMP_KEY_LENGTH);
|
|
3677
|
-
return path5.join(PLATFORM_TEMP_ROOT, `${prefix}${key}${suffix}`);
|
|
3678
|
-
}
|
|
3679
|
-
function write_exclusively(target, content) {
|
|
3680
|
-
rmSync(target, { force: true });
|
|
3681
|
-
writeFileSync(target, content, { flag: STAMP_WRITE_FLAG, mode: STAMP_FILE_MODE });
|
|
3682
|
-
return target;
|
|
3683
|
-
}
|
|
3684
|
-
function write_stamp(target, payload) {
|
|
3685
|
-
return write_exclusively(target, JSON.stringify(payload));
|
|
3686
|
-
}
|
|
3687
|
-
function replace_stamp(target, payload) {
|
|
3688
|
-
const temporary = `${target}.${String(process.pid)}.${randomUUID()}`;
|
|
3689
|
-
try {
|
|
3690
|
-
writeFileSync(temporary, JSON.stringify(payload), {
|
|
3691
|
-
flag: STAMP_CREATE_FLAG,
|
|
3692
|
-
mode: STAMP_FILE_MODE
|
|
3693
|
-
});
|
|
3694
|
-
renameSync(temporary, target);
|
|
3695
|
-
return target;
|
|
3696
|
-
} finally {
|
|
3697
|
-
rmSync(temporary, { force: true });
|
|
3698
|
-
}
|
|
3699
|
-
}
|
|
3700
|
-
function write_text_stamp(target, text) {
|
|
3701
|
-
return write_exclusively(target, text);
|
|
3702
|
-
}
|
|
3703
|
-
function create_stamp(target, payload) {
|
|
3704
|
-
try {
|
|
3705
|
-
writeFileSync(target, JSON.stringify(payload), {
|
|
3706
|
-
flag: STAMP_CREATE_FLAG,
|
|
3707
|
-
mode: STAMP_FILE_MODE
|
|
3708
|
-
});
|
|
3709
|
-
return true;
|
|
3710
|
-
} catch (error) {
|
|
3711
|
-
if (error.code === EXISTS_ERROR_CODE) return false;
|
|
3712
|
-
throw error;
|
|
3713
|
-
}
|
|
3714
|
-
}
|
|
3715
|
-
function remove_stamp(target) {
|
|
3716
|
-
rmSync(target, { force: true });
|
|
3717
|
-
}
|
|
3718
|
-
function is_own_regular_file(source) {
|
|
3719
|
-
const stats = lstatSync(source);
|
|
3720
|
-
if (!stats.isFile()) return false;
|
|
3721
|
-
const uid = process.getuid?.();
|
|
3722
|
-
return uid === void 0 || stats.uid === uid;
|
|
3723
|
-
}
|
|
3724
|
-
function read_stamp_text(source) {
|
|
3725
|
-
try {
|
|
3726
|
-
if (!is_own_regular_file(source)) return void 0;
|
|
3727
|
-
return readFileSync3(source, "utf8");
|
|
3728
|
-
} catch {
|
|
3729
|
-
return void 0;
|
|
3730
|
-
}
|
|
3731
|
-
}
|
|
3732
|
-
var stamp_file = {
|
|
3733
|
-
create_stamp,
|
|
3734
|
-
digest,
|
|
3735
|
-
is_own_regular_file,
|
|
3736
|
-
read_stamp_text,
|
|
3737
|
-
replace_stamp,
|
|
3738
|
-
remove_stamp,
|
|
3739
|
-
stamp_path,
|
|
3740
|
-
write_stamp,
|
|
3741
|
-
write_text_stamp
|
|
3742
|
-
};
|
|
3743
|
-
|
|
3744
|
-
// scripts/time-runtime/time-density-hook.ts
|
|
3745
|
-
import { z as z5 } from "zod";
|
|
4506
|
+
import { z as z8 } from "zod";
|
|
3746
4507
|
|
|
3747
4508
|
// scripts/time-runtime/time-density.ts
|
|
3748
4509
|
var MIN_ROUND_TRIPS = 10;
|
|
@@ -3798,15 +4559,15 @@ var TAIL_BYTES = 262144;
|
|
|
3798
4559
|
var FILE_START = 0;
|
|
3799
4560
|
var NOTICE_PREFIX = "josh-density-notice-";
|
|
3800
4561
|
var NEVER_MS = 0;
|
|
3801
|
-
var payload_schema =
|
|
3802
|
-
transcript_path:
|
|
4562
|
+
var payload_schema = z8.object({
|
|
4563
|
+
transcript_path: z8.string().min(1).optional(),
|
|
3803
4564
|
// **`nullish`, not `optional`.** A payload spelling the absent agent as `null` has to read as "no
|
|
3804
4565
|
// fork"; rejected, it would fail `safeParse` for the whole payload and silence the line for every
|
|
3805
4566
|
// edit of the main line — the opposite of this module's stated failure direction.
|
|
3806
|
-
agent_id:
|
|
4567
|
+
agent_id: z8.string().nullish()
|
|
3807
4568
|
});
|
|
3808
|
-
var notice_schema =
|
|
3809
|
-
var call_schema =
|
|
4569
|
+
var notice_schema = z8.object({ notified_at_ms: z8.number() });
|
|
4570
|
+
var call_schema = z8.object({ tool_name: z8.string().min(1), tool_input: z8.unknown() });
|
|
3810
4571
|
function parse_transcript_path(raw_payload) {
|
|
3811
4572
|
const parsed = payload_schema.safeParse(JSON.parse(raw_payload));
|
|
3812
4573
|
if (!parsed.success || parsed.data.transcript_path === void 0) return void 0;
|
|
@@ -3873,16 +4634,29 @@ var time_density_hook = {
|
|
|
3873
4634
|
};
|
|
3874
4635
|
|
|
3875
4636
|
export {
|
|
3876
|
-
PROJECT_ROOT,
|
|
3877
|
-
PLATFORM_TEMP_ROOT,
|
|
3878
|
-
stamp_file,
|
|
3879
4637
|
json_value,
|
|
3880
4638
|
cost_blocks,
|
|
3881
4639
|
ESLINT_EDIT_CACHE_FLAGS,
|
|
4640
|
+
process_identity,
|
|
4641
|
+
process_owner_schema,
|
|
3882
4642
|
time_shell,
|
|
3883
4643
|
time_bundle_call,
|
|
3884
|
-
|
|
4644
|
+
blocking_issue_schema,
|
|
4645
|
+
rest_comment_schema,
|
|
4646
|
+
open_issue_schema,
|
|
4647
|
+
CHECK_STATUS_PENDING,
|
|
4648
|
+
CHECK_STATUS_FAIL,
|
|
4649
|
+
read_string,
|
|
4650
|
+
parse_pr_state_snapshot,
|
|
4651
|
+
is_merge_conflict,
|
|
4652
|
+
is_coderabbit_check,
|
|
4653
|
+
is_required_check,
|
|
4654
|
+
describe_pr_failure,
|
|
4655
|
+
evaluate_pr_state,
|
|
4656
|
+
is_review_decision_decisive,
|
|
4657
|
+
PrConflictError,
|
|
3885
4658
|
time_reported_failure,
|
|
4659
|
+
cost_attribute,
|
|
3886
4660
|
time_transcript_line,
|
|
3887
4661
|
time_spans,
|
|
3888
4662
|
time_batch_guard,
|