@joshuafolkken/kit 1.1178.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 +6 -2
- package/.claude/skills/workflow-commands/backlogrun-park.md +23 -2
- 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 +21 -13
- 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 +6 -1
- 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 +32 -31
- 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-S6X6WYKR.js → chunk-55HHG5PX.js} +1210 -711
- package/dist/hooks/{chunk-ZAL3NRGL.js → chunk-5VMKCCC4.js} +25 -10
- package/dist/hooks/chunk-5VNDSNG3.js +12 -0
- package/dist/hooks/{chunk-32GQTL4F.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-VESKRQOF.js → chunk-F56MFS4B.js} +3 -3
- package/dist/hooks/{chunk-UAGLLIGZ.js → chunk-FIVDHQGT.js} +7 -6
- package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
- package/dist/hooks/{chunk-G6KRCKEC.js → chunk-JUDKDCDP.js} +496 -378
- package/dist/hooks/{chunk-GDS5N2KB.js → chunk-NV2JRZZO.js} +718 -681
- package/dist/hooks/{chunk-VQLLNFNT.js → chunk-RNWHN5BP.js} +3 -3
- package/dist/hooks/{chunk-DO6NWWHU.js → chunk-TQNPDZNH.js} +4 -4
- package/dist/hooks/{chunk-I4XSL4TT.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 +217 -195
- 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 +66 -58
- package/dist/josh.js +868 -74
- 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 +16 -5
- package/scripts/backlog/backlog-offer-cli.ts +6 -6
- package/scripts/backlog/backlog-offer.ts +1 -1
- package/scripts/backlog/backlog-plan-cli.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +57 -11
- package/scripts/backlog/backlog-ready.ts +1 -1
- 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/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/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-pr-followup-checks.ts +142 -0
- package/scripts/followup/git-pr-followup.ts +4 -129
- 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-pr-read.ts +64 -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 +1 -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 +7 -5
- 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 +2 -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/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/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 +10 -0
- 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 +15 -1
- 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-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 +1 -1
- 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} +1 -1
- 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} +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} +2 -2
- 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-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} +4 -3
- 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-steps.ts → ship/run-ship-steps.ts} +11 -12
- package/scripts/run/ship/run-ship-stop-text.ts +13 -0
- package/scripts/run/{run-ship-sync.ts → ship/run-ship-sync.ts} +25 -11
- 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} +23 -8
- 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} +59 -8
- 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/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/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/git/{schemas.ts → git-schemas.ts} +0 -0
- /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-cut-report.ts → cut/run-cut-report.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-next.ts → ship/run-ship-next.ts} +0 -0
- /package/scripts/run/{run-ship-pre-detach.ts → ship/run-ship-pre-detach.ts} +0 -0
- /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
- /package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +0 -0
- /package/scripts/run/{run-ship.ts → ship/run-ship.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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { git_stash } from '#scripts/git/stash/git-stash'
|
|
2
|
+
import { lane_launch_cli, type LaunchOutcome } from '#scripts/lane/lane-launch-cli'
|
|
3
|
+
import { backlog_drive_owner } from './backlog-drive-owner'
|
|
4
|
+
|
|
5
|
+
// The driver's lane launch (joshuafolkken/kit#3272). The parent that ran `josh latest` in the primary
|
|
6
|
+
// checkout leaves its rewritten lock file in a stash under this message — `backlogrun-lanes.md` →
|
|
7
|
+
// "Once per repository, before the first lane opens" — and the lane that pops it carries the update
|
|
8
|
+
// into its pull request. **The stash itself is the "first lane" marker**: each launch asks whether it
|
|
9
|
+
// is still on the stack, and the pop that `lane:launch --stash` runs consumes it, so the first launch
|
|
10
|
+
// after the push takes it and every later one finds nothing. A restarted driver needs no memory of
|
|
11
|
+
// which lane was first. Two entries under the message are a state a person resolves, so neither is
|
|
12
|
+
// guessed at — the launch goes ahead without one, as `stash:pop` would refuse it anyway. That skip is
|
|
13
|
+
// said on stderr, because `stash:pop` refusing would have been heard and a silent skip would let the
|
|
14
|
+
// update never reach a pull request.
|
|
15
|
+
const LATEST_STASH_MESSAGE = 'backlogrun: josh latest before lanes'
|
|
16
|
+
|
|
17
|
+
async function latest_stash(): Promise<string | undefined> {
|
|
18
|
+
const selection = git_stash.select(await git_stash.list(), LATEST_STASH_MESSAGE)
|
|
19
|
+
|
|
20
|
+
if (selection.kind === 'ambiguous') {
|
|
21
|
+
console.error(
|
|
22
|
+
`Launching without the "${LATEST_STASH_MESSAGE}" stash: ${selection.selectors.join(', ')} all match — keep one.`,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return selection.kind === 'match' ? LATEST_STASH_MESSAGE : undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function launch(issue: string, owner: string): Promise<LaunchOutcome['kind']> {
|
|
30
|
+
await backlog_drive_owner.assert_current(owner)
|
|
31
|
+
|
|
32
|
+
const outcome = await lane_launch_cli.launch_lane({ issue, stash: await latest_stash() })
|
|
33
|
+
|
|
34
|
+
return outcome.kind
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const backlog_drive_launch = { LATEST_STASH_MESSAGE, launch }
|
|
38
|
+
|
|
39
|
+
export { backlog_drive_launch }
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { EPIC_LABEL, has_label_name, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
2
2
|
import type { IssueState } from '#scripts/issue/issue-state'
|
|
3
3
|
import { issue_state_cli } from '#scripts/issue/issue-state-cli'
|
|
4
|
-
import type { RunCarry } from '#scripts/run/run-carry'
|
|
5
|
-
import type { MergeResult } from '#scripts/run/run-merge-cli'
|
|
4
|
+
import type { RunCarry } from '#scripts/run/carry/run-carry'
|
|
5
|
+
import type { MergeResult } from '#scripts/run/merge/run-merge-cli'
|
|
6
6
|
import { backlog_budget } from './backlog-budget'
|
|
7
7
|
import type { DriveState, OfferRead } from './backlog-drive'
|
|
8
8
|
import { backlog_drive_named } from './backlog-drive-named'
|
|
@@ -58,9 +58,7 @@ function settled_outcome(state: IssueState): MergeResult['outcome'] | undefined
|
|
|
58
58
|
async function classify(issue: string, named: OfferRead, owner: string): Promise<OfferRead> {
|
|
59
59
|
const result = await issue_state_cli.read_issue(issue)
|
|
60
60
|
|
|
61
|
-
if (result.kind !== 'state') {
|
|
62
|
-
return { verdict: 'issue-state', issues: [], retries: NO_RETRIES }
|
|
63
|
-
}
|
|
61
|
+
if (result.kind !== 'state') return { verdict: 'issue-state', issues: [], retries: NO_RETRIES }
|
|
64
62
|
|
|
65
63
|
const outcome = settled_outcome(result.state)
|
|
66
64
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { has_label_name, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
2
2
|
import { issue_state_cli } from '#scripts/issue/issue-state-cli'
|
|
3
|
-
import { run_carry, type RunCarry } from '#scripts/run/run-carry'
|
|
4
|
-
import type { RunEvent } from '#scripts/run/run-event-stream'
|
|
5
|
-
import type { MergeResult } from '#scripts/run/run-merge-cli'
|
|
3
|
+
import { run_carry, type RunCarry } from '#scripts/run/carry/run-carry'
|
|
4
|
+
import type { RunEvent } from '#scripts/run/event/run-event-stream'
|
|
5
|
+
import type { MergeResult } from '#scripts/run/merge/run-merge-cli'
|
|
6
6
|
import type { DriveState, OfferRead } from './backlog-drive'
|
|
7
7
|
import { backlog_drive_restore } from './backlog-drive-restore'
|
|
8
8
|
import { backlog_named } from './backlog-named'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { doctor_consumer } from '#scripts/doctor/doctor-consumer'
|
|
2
2
|
import { find_package_directory } from '#scripts/josh/josh-logic'
|
|
3
|
-
import type { RunCarry } from '#scripts/run/run-carry'
|
|
3
|
+
import type { RunCarry } from '#scripts/run/carry/run-carry'
|
|
4
4
|
import { run_retrospective } from '#scripts/run/run-retrospective'
|
|
5
5
|
|
|
6
6
|
// Whether a drain owes the retrospective, read through the owed rule `run:step` reads, so a drain it
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// without a process, a network or a clock.
|
|
18
18
|
|
|
19
19
|
import type { LaunchOutcome } from '#scripts/lane/lane-launch-cli'
|
|
20
|
-
import type { MergeResult } from '#scripts/run/run-merge-cli'
|
|
20
|
+
import type { MergeResult } from '#scripts/run/merge/run-merge-cli'
|
|
21
21
|
|
|
22
22
|
const RUN_VERDICT = 'run'
|
|
23
23
|
const STOP_VERDICT = 'stop'
|
|
@@ -146,6 +146,19 @@ function report(result: EpicNextResult, context: PoolContext): number {
|
|
|
146
146
|
return SUCCESS_EXIT_CODE
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
// The settled set the views were classified against, so a standalone row and an epic child weigh the
|
|
150
|
+
// same blocker the same way.
|
|
151
|
+
function running_of(
|
|
152
|
+
views: ReadonlyArray<EpicView>,
|
|
153
|
+
graphs: ReadonlyArray<ReadonlyArray<EpicChild>>,
|
|
154
|
+
context: PoolContext,
|
|
155
|
+
): ReadonlySet<string> {
|
|
156
|
+
return (
|
|
157
|
+
views[0]?.running ??
|
|
158
|
+
backlog_pool.running_set(graphs, context.opted_in.issues, context.repo, context.tracking.index)
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
149
162
|
// The two halves as one result. The epic half is already classified by `epic:next`; the standalone
|
|
150
163
|
// half is classified here; the verdict is decided from the merge, so a backlog with a runnable epic
|
|
151
164
|
// child and nothing else says `run` exactly as one with a runnable standalone issue does.
|
|
@@ -161,10 +174,7 @@ function combine(views: ReadonlyArray<EpicView>, context: PoolContext): EpicNext
|
|
|
161
174
|
tracked: epic_index.withheld_children(context.tracking.index, context.opted_in.issues),
|
|
162
175
|
exclude: context.exclude,
|
|
163
176
|
repo: context.repo,
|
|
164
|
-
|
|
165
|
-
// the same blocker the same way.
|
|
166
|
-
running:
|
|
167
|
-
views[0]?.running ?? backlog_pool.running_set(graphs, context.opted_in.issues, context.repo),
|
|
177
|
+
running: running_of(views, graphs, context),
|
|
168
178
|
})
|
|
169
179
|
|
|
170
180
|
// The same checkout map `epic:next` hands `build_result`. Without it every bundle heading reads
|
|
@@ -194,6 +204,7 @@ function settled_views(
|
|
|
194
204
|
views[0]?.running ?? running,
|
|
195
205
|
context.opted_in.issues,
|
|
196
206
|
context.repo,
|
|
207
|
+
context.tracking.index,
|
|
197
208
|
)
|
|
198
209
|
|
|
199
210
|
return settled.size === running.size ? views : settled_views(reads, settled, context)
|
|
@@ -212,7 +223,7 @@ function views_from(reads: ReadonlyArray<EpicRead>, context: PoolContext): Reado
|
|
|
212
223
|
|
|
213
224
|
return settled_views(
|
|
214
225
|
reads,
|
|
215
|
-
backlog_pool.running_set(graphs, context.opted_in.issues, context.repo),
|
|
226
|
+
backlog_pool.running_set(graphs, context.opted_in.issues, context.repo, context.tracking.index),
|
|
216
227
|
context,
|
|
217
228
|
)
|
|
218
229
|
}
|
|
@@ -3,8 +3,8 @@ import { fileURLToPath } from 'node:url'
|
|
|
3
3
|
import { josh_command } from '#scripts/josh/josh-run'
|
|
4
4
|
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
5
5
|
import { rule_value_cache } from '#scripts/rules/rule-value-cache'
|
|
6
|
-
import { run_event_stream } from '#scripts/run/run-event-stream'
|
|
7
|
-
import { run_event_stream_emit } from '#scripts/run/run-event-stream-emit'
|
|
6
|
+
import { run_event_stream } from '#scripts/run/event/run-event-stream'
|
|
7
|
+
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
8
8
|
import { z } from 'zod'
|
|
9
9
|
import { backlog_offer, type OfferAnswer } from './backlog-offer'
|
|
10
10
|
|
|
@@ -74,8 +74,8 @@ function to_count(raw: string | undefined): number | undefined {
|
|
|
74
74
|
|
|
75
75
|
// A count flag that was given but unreadable makes the invocation unreadable rather than defaulted —
|
|
76
76
|
// the contract `backlog:budget` follows for its own counts.
|
|
77
|
-
function count_of(raw: string | undefined
|
|
78
|
-
return raw === undefined ?
|
|
77
|
+
function count_of(raw: string | undefined): number | undefined {
|
|
78
|
+
return raw === undefined ? DEFAULT_COUNT : to_count(raw)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
interface OfferCounts {
|
|
@@ -86,8 +86,8 @@ interface OfferCounts {
|
|
|
86
86
|
// The two counts the mapping needs: `--running` decides `wait`, `--retries` decides `retry`. Either
|
|
87
87
|
// given but unreadable refuses the whole invocation.
|
|
88
88
|
function counts_of(values: ParsedValues): OfferCounts | undefined {
|
|
89
|
-
const running = count_of(cli_flags.string_of(values.running)
|
|
90
|
-
const retries = count_of(cli_flags.string_of(values.retries)
|
|
89
|
+
const running = count_of(cli_flags.string_of(values.running))
|
|
90
|
+
const retries = count_of(cli_flags.string_of(values.retries))
|
|
91
91
|
|
|
92
92
|
if (running === undefined || retries === undefined) return undefined
|
|
93
93
|
|
|
@@ -5,7 +5,7 @@ import { backlog_next } from './backlog-next'
|
|
|
5
5
|
// answered — its stdout tokens and its exit code — into the one word `backlog:budget` is then asked
|
|
6
6
|
// with, plus the issue numbers to start and the consecutive-retry count carried to the next ask.
|
|
7
7
|
//
|
|
8
|
-
// **The mapping is `docs/josh-commands-
|
|
8
|
+
// **The mapping is `docs/josh-commands-backlog.md` → "`josh backlog:offer`", held here so it cannot
|
|
9
9
|
// drift.** It fixes which `backlog:next` answer becomes which `backlog:budget` word, and it carries two
|
|
10
10
|
// context branches an agent once applied by hand every iteration: `wait` is `blocked` while this run
|
|
11
11
|
// has children in flight and `exhausted` when it has none, and `retry` is `blocked` until the third
|
|
@@ -4,8 +4,8 @@ import { auto_ok_cli } from '#scripts/auto-ok/auto-ok-cli'
|
|
|
4
4
|
import { epic_index } from '#scripts/epic/epic-index'
|
|
5
5
|
import type { EpicNextResult } from '#scripts/epic/epic-report'
|
|
6
6
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
7
|
+
import { open_issue_schema, type OpenIssueData } from '#scripts/git/git-schemas'
|
|
7
8
|
import { read_json_listing } from '#scripts/git/parse-json-array'
|
|
8
|
-
import { open_issue_schema, type OpenIssueData } from '#scripts/git/schemas'
|
|
9
9
|
import { run_invocation } from '#scripts/run/run-invocation'
|
|
10
10
|
import { backlog_named } from './backlog-named'
|
|
11
11
|
import { backlog_next, type OptedIn } from './backlog-next'
|
|
@@ -5,7 +5,7 @@ import { epic_index } from '#scripts/epic/epic-index'
|
|
|
5
5
|
import { epic_issue } from '#scripts/epic/epic-issue'
|
|
6
6
|
import type { EpicView } from '#scripts/epic/epic-next-views'
|
|
7
7
|
import { epic_outside_blocker } from '#scripts/epic/epic-outside-blocker'
|
|
8
|
-
import type { OpenIssueData } from '#scripts/git/schemas'
|
|
8
|
+
import type { OpenIssueData } from '#scripts/git/git-schemas'
|
|
9
9
|
import { git_next_issues } from '#scripts/issue/git-next-issues'
|
|
10
10
|
import {
|
|
11
11
|
ALREADY_DONE_LABEL,
|
|
@@ -37,6 +37,9 @@ const DECISION_LABELS: ReadonlySet<string> = new Set([NEEDS_DECISION_LABEL, ALRE
|
|
|
37
37
|
// `tracked` is the narrowed set `epic_index.withheld_children` builds, not every child an epic
|
|
38
38
|
// tracks (joshuafolkken/kit#1668) — the narrowing itself is defined there, once, for this half and
|
|
39
39
|
// `auto-ok:next` alike.
|
|
40
|
+
// Child number to every open epic whose task list names it — `epic_index.build_tracking_index`.
|
|
41
|
+
type TrackingIndex = ReadonlyMap<number, ReadonlyArray<number>>
|
|
42
|
+
|
|
40
43
|
// The part of the context that decides which rows the standalone half considers at all.
|
|
41
44
|
type ConsideredContext = Pick<StandaloneContext, 'tracked' | 'exclude' | 'repo'>
|
|
42
45
|
|
|
@@ -69,24 +72,64 @@ function needs_person(issue: OpenIssueData, context: StandaloneContext): boolean
|
|
|
69
72
|
)
|
|
70
73
|
}
|
|
71
74
|
|
|
75
|
+
// Each open epic's key, read off the tracking index — child number to the epics listing it.
|
|
76
|
+
function epic_keys_of(tracking: TrackingIndex, repo: string): ReadonlySet<string> {
|
|
77
|
+
return new Set([...tracking.values()].flat().map((number) => epic_graph.key_of({ repo, number })))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// The set with every epic that tracks a member added, nested epics included (joshuafolkken/kit#3289).
|
|
81
|
+
// An epic is a container rather than work, so it is never run itself — but it closes once its children
|
|
82
|
+
// do, so a row blocked by it waits on time exactly when one of those children is in this run.
|
|
83
|
+
function with_tracking_epics(
|
|
84
|
+
running: ReadonlySet<string>,
|
|
85
|
+
tracking: TrackingIndex,
|
|
86
|
+
repo: string,
|
|
87
|
+
): ReadonlySet<string> {
|
|
88
|
+
const tracking_epics = [...tracking]
|
|
89
|
+
.filter(([child]) => running.has(epic_graph.key_of({ repo, number: child })))
|
|
90
|
+
.flatMap(([, epics]) => epics.map((number) => epic_graph.key_of({ repo, number })))
|
|
91
|
+
const grown = new Set([...running, ...tracking_epics])
|
|
92
|
+
|
|
93
|
+
return grown.size === running.size ? running : with_tracking_epics(grown, tracking, repo)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// The epics re-derived from the members alone, so an epic whose last running child was just taken out
|
|
97
|
+
// leaves with it rather than lingering from an earlier pass.
|
|
98
|
+
function rooted(
|
|
99
|
+
running: ReadonlySet<string>,
|
|
100
|
+
tracking: TrackingIndex,
|
|
101
|
+
repo: string,
|
|
102
|
+
): ReadonlySet<string> {
|
|
103
|
+
const epics = epic_keys_of(tracking, repo)
|
|
104
|
+
const members = new Set([...running].filter((key) => !epics.has(key)))
|
|
105
|
+
|
|
106
|
+
return with_tracking_epics(members, tracking, repo)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function is_stuck(issue: OpenIssueData, running: ReadonlySet<string>, repo: string): boolean {
|
|
110
|
+
return has_any_label(issue.labels, DECISION_LABELS) || waits_outside(issue, running, repo)
|
|
111
|
+
}
|
|
112
|
+
|
|
72
113
|
// The running set with every standalone row a person has to resolve taken out, repeated until a pass
|
|
73
114
|
// removes nothing — a row waiting on such a row waits on that person too, however long the chain.
|
|
74
115
|
function settle_standalone(
|
|
75
116
|
running: ReadonlySet<string>,
|
|
76
117
|
issues: ReadonlyArray<OpenIssueData>,
|
|
77
118
|
repo: string,
|
|
119
|
+
tracking: TrackingIndex,
|
|
78
120
|
): ReadonlySet<string> {
|
|
79
121
|
const settled = new Set(running)
|
|
80
122
|
|
|
81
|
-
// An epic row is never
|
|
123
|
+
// An epic row is never a standalone row, so deleting its key here never happens; `rooted` decides it.
|
|
82
124
|
for (const issue of issues) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (is_stuck) settled.delete(epic_graph.key_of({ repo, number: issue.number }))
|
|
125
|
+
if (is_stuck(issue, running, repo)) {
|
|
126
|
+
settled.delete(epic_graph.key_of({ repo, number: issue.number }))
|
|
127
|
+
}
|
|
87
128
|
}
|
|
88
129
|
|
|
89
|
-
|
|
130
|
+
const next = rooted(settled, tracking, repo)
|
|
131
|
+
|
|
132
|
+
return next.size === running.size ? next : settle_standalone(next, issues, repo, tracking)
|
|
90
133
|
}
|
|
91
134
|
|
|
92
135
|
// An opted-in row as the graph's node type. Both halves of the pool are then the same shape, so one
|
|
@@ -182,18 +225,21 @@ function classify_standalone(
|
|
|
182
225
|
// (joshuafolkken/kit#1943). A child is opted in through its epic's `auto-ok` even where it carries none
|
|
183
226
|
// of its own, which is why the set is built from the graphs that were read rather than from labels. A
|
|
184
227
|
// standalone row a person has to resolve is left out, so a row waiting on it waits for that person too;
|
|
185
|
-
// an epic child in the same state is taken out by `epic_next_views.settle_views`.
|
|
228
|
+
// an epic child in the same state is taken out by `epic_next_views.settle_views`. An open epic with a
|
|
229
|
+
// child in the set is in it too, so a row blocked by that epic waits rather than needs a person. A
|
|
230
|
+
// closed child is left out: it runs nothing, and kept in the set it would hold its epic there.
|
|
186
231
|
function running_set(
|
|
187
232
|
graphs: ReadonlyArray<ReadonlyArray<EpicChild>>,
|
|
188
233
|
issues: ReadonlyArray<OpenIssueData>,
|
|
189
234
|
repo: string,
|
|
235
|
+
tracking: TrackingIndex,
|
|
190
236
|
): ReadonlySet<string> {
|
|
191
237
|
const running = epic_outside_blocker.running_keys([
|
|
192
|
-
...graphs.flat(),
|
|
238
|
+
...graphs.flat().filter((child) => child.state === 'OPEN'),
|
|
193
239
|
...to_children(standalone_rows(issues), repo),
|
|
194
240
|
])
|
|
195
241
|
|
|
196
|
-
return settle_standalone(running, issues, repo)
|
|
242
|
+
return settle_standalone(rooted(running, tracking, repo), issues, repo, tracking)
|
|
197
243
|
}
|
|
198
244
|
|
|
199
245
|
// A cycle no single epic can see, because its links cross from one graph into another. Each epic's own
|
|
@@ -336,4 +382,4 @@ const backlog_pool = {
|
|
|
336
382
|
}
|
|
337
383
|
|
|
338
384
|
export { backlog_pool }
|
|
339
|
-
export type { ConsideredContext, StandaloneContext }
|
|
385
|
+
export type { ConsideredContext, StandaloneContext, TrackingIndex }
|
|
@@ -3,7 +3,7 @@ import { issue_cite } from '#scripts/issue/issue-cite'
|
|
|
3
3
|
import { josh_command, type JoshResult } from '#scripts/josh/josh-run'
|
|
4
4
|
import { lane_capacity } from '#scripts/lane/lane-capacity'
|
|
5
5
|
import { lane_registry } from '#scripts/lane/lane-registry'
|
|
6
|
-
import type { RunCarry } from '#scripts/run/run-carry'
|
|
6
|
+
import type { RunCarry } from '#scripts/run/carry/run-carry'
|
|
7
7
|
import { run_headless } from '#scripts/run/run-headless'
|
|
8
8
|
import { run_invocation } from '#scripts/run/run-invocation'
|
|
9
9
|
import { backlog_stalled } from './backlog-stalled'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EpicNextResult } from '#scripts/epic/epic-report'
|
|
2
|
-
import type { OpenIssueData } from '#scripts/git/schemas'
|
|
2
|
+
import type { OpenIssueData } from '#scripts/git/git-schemas'
|
|
3
3
|
import { AUTO_OK_LABEL, EPIC_LABEL, has_any_label } from '#scripts/issue/issue-labels'
|
|
4
4
|
|
|
5
5
|
// Which open issues the backlog will not run, and why (joshuafolkken/kit#1652).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { telegram_notify } from '#scripts/notify/telegram-notify'
|
|
2
|
-
import { run_event_stream, type RunEvent } from '#scripts/run/run-event-stream'
|
|
3
|
-
import { run_event_stream_emit } from '#scripts/run/run-event-stream-emit'
|
|
2
|
+
import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
|
|
3
|
+
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
4
4
|
import { backlog_ready, type ReadyPorts } from './backlog-ready'
|
|
5
5
|
import { backlog_stalled, type StallReading, type StallVerdict } from './backlog-stalled'
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { epic_triage } from '#scripts/epic/epic-triage'
|
|
2
|
-
import { run_event_stream, type RunEvent } from '#scripts/run/run-event-stream'
|
|
2
|
+
import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
|
|
3
3
|
|
|
4
4
|
// When ready backlog work sits undispatched while lanes are free, nobody notices until a person asks
|
|
5
5
|
// (joshuafolkken/kit#2359). This is the mechanical judge of that state: three facts read, never
|
|
@@ -10,7 +10,9 @@ const CODEX_HOOKS = path.join(REPO_ROOT, '.codex', 'hooks.json')
|
|
|
10
10
|
|
|
11
11
|
// Regenerate `.codex/hooks.json` from `.claude/settings.json` (joshuafolkken/kit#2997). The output is
|
|
12
12
|
// committed rather than gitignored: Codex reads it straight from a fresh clone of kit, before any
|
|
13
|
-
// build has run, and `josh init` / `josh sync` copy it to consumers from the package.
|
|
13
|
+
// build has run, and `josh init` / `josh sync` copy it to consumers from the package. It is run by
|
|
14
|
+
// hand, never from `pnpm build`, so a build never rewrites a committed file (joshuafolkken/kit#3324):
|
|
15
|
+
// `codex-project-config.test.ts` fails the gate when the committed copy has drifted.
|
|
14
16
|
function build_codex_hooks(): string {
|
|
15
17
|
writeFileSync(CODEX_HOOKS, codex_hooks.codex_hooks_text(readFileSync(CLAUDE_SETTINGS, 'utf8')))
|
|
16
18
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { rmSync } from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { COMMAND_MAP } from '#scripts/josh/josh-command-map'
|
|
6
|
+
import { BUNDLED_COMMAND_DIRECTORY, josh_in_process } from '#scripts/josh/josh-in-process'
|
|
7
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
8
|
+
import { build } from 'esbuild'
|
|
9
|
+
|
|
10
|
+
const PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
|
|
11
|
+
const OUT_DIR = path.join(PACKAGE_DIR, BUNDLED_COMMAND_DIRECTORY)
|
|
12
|
+
|
|
13
|
+
// Each `is_bundled` command is pre-built to its own `dist/commands/<script basename>.js`, so a
|
|
14
|
+
// consumer's `dist/josh.js` imports it under plain node instead of spawning tsx for its `.ts`
|
|
15
|
+
// (joshuafolkken/kit#3328, `docs/maintainers/runtime-bundling.md`).
|
|
16
|
+
//
|
|
17
|
+
// **No code splitting, and that is why the import closure is checked.** Every entry is one
|
|
18
|
+
// self-contained file, so every module it imports shares the entry's `import.meta.url`; a second
|
|
19
|
+
// `process.argv[1] === fileURLToPath(import.meta.url)` guard inside the closure would fire with the
|
|
20
|
+
// entry's own. `build-commands.test.ts` refuses a bundled command whose closure carries one.
|
|
21
|
+
//
|
|
22
|
+
// The bundle sits two levels under the package root, exactly as its source does under `scripts/`,
|
|
23
|
+
// so a module that finds the package from its own `import.meta.url` resolves the same directory.
|
|
24
|
+
function bundled_scripts(): Array<string> {
|
|
25
|
+
return Object.values(COMMAND_MAP)
|
|
26
|
+
.filter((entry) => entry.is_bundled === true)
|
|
27
|
+
.map((entry) => entry.script ?? '')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function entry_point(script: string): { in: string; out: string } {
|
|
31
|
+
const out = path.basename(josh_in_process.bundled_script_path(PACKAGE_DIR, script), '.js')
|
|
32
|
+
|
|
33
|
+
return { in: path.join(PACKAGE_DIR, script), out }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Nothing in this checkout launches `dist/commands/` (kit's own `pnpm josh` runs the source), so the
|
|
37
|
+
// directory is emptied first rather than pruned after, which drops the output of a command no longer
|
|
38
|
+
// bundled.
|
|
39
|
+
async function build_commands(out_directory: string = OUT_DIR): Promise<string> {
|
|
40
|
+
rmSync(out_directory, { recursive: true, force: true })
|
|
41
|
+
await build({
|
|
42
|
+
absWorkingDir: PACKAGE_DIR,
|
|
43
|
+
entryPoints: bundled_scripts().map((script) => entry_point(script)),
|
|
44
|
+
outdir: out_directory,
|
|
45
|
+
bundle: true,
|
|
46
|
+
platform: 'node',
|
|
47
|
+
format: 'esm',
|
|
48
|
+
target: 'node22',
|
|
49
|
+
packages: 'external',
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return out_directory
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function main(): Promise<void> {
|
|
56
|
+
try {
|
|
57
|
+
console.info(` ✔ ${await build_commands()} built`)
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error(error_text.message_of(error))
|
|
60
|
+
process.exit(1)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
|
|
65
|
+
|
|
66
|
+
export { build_commands, bundled_scripts, OUT_DIR }
|
|
@@ -49,7 +49,7 @@ interface HookBundle {
|
|
|
49
49
|
out: string
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
// The
|
|
52
|
+
// The settings.json hooks (the session-start audit provisioner among them), the Codex input adapter, and the three guards `pretool-guard`
|
|
53
53
|
// composes: `batch-guard`, `investigation-guard` and `duplicate-read-guard` each self-invoke, so they
|
|
54
54
|
// must be their own entries to keep their `import.meta.url` out of `pretool-guard`'s file.
|
|
55
55
|
// `delivered-rules` (the fourth guard) has no self-invoke, so it stays inlined.
|
|
@@ -59,6 +59,7 @@ const HOOK_BUNDLES: ReadonlyArray<HookBundle> = [
|
|
|
59
59
|
{ source: 'scripts/hooks/stop-guard.ts', out: 'stop-guard' },
|
|
60
60
|
{ source: 'scripts/hooks/format-edited-cli.ts', out: 'format-edited' },
|
|
61
61
|
{ source: 'scripts/josh/session-language-cli.ts', out: 'session-lang' },
|
|
62
|
+
{ source: 'scripts/security/security-audit-provision.ts', out: 'audit-provision' },
|
|
62
63
|
{ source: 'scripts/hooks/batch-guard.ts', out: 'batch-guard' },
|
|
63
64
|
{ source: 'scripts/delegation/investigation-guard.ts', out: 'investigation-guard' },
|
|
64
65
|
{ source: 'scripts/delegation/duplicate-read-guard.ts', out: 'duplicate-read-guard' },
|
|
@@ -7,6 +7,13 @@ import { dts } from 'rollup-plugin-dts'
|
|
|
7
7
|
|
|
8
8
|
const PACKAGE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..')
|
|
9
9
|
const SCRIPTS_IMPORT_PREFIX = '#scripts/'
|
|
10
|
+
// Every public library `pnpm build` bundles — each one a `./<name>` export in package.json.
|
|
11
|
+
const PUBLIC_LIBRARIES: ReadonlyArray<string> = [
|
|
12
|
+
'version',
|
|
13
|
+
'config-merge',
|
|
14
|
+
'managed-marker',
|
|
15
|
+
'self-sync-guard',
|
|
16
|
+
]
|
|
10
17
|
|
|
11
18
|
interface LibraryPaths {
|
|
12
19
|
entry_point: string
|
|
@@ -73,11 +80,13 @@ async function build_library_dts(entry_point: string, dts_file: string): Promise
|
|
|
73
80
|
async function build_library(name: string): Promise<LibraryPaths> {
|
|
74
81
|
const paths = library_paths(name)
|
|
75
82
|
|
|
76
|
-
await
|
|
77
|
-
|
|
83
|
+
await Promise.all([
|
|
84
|
+
build_library_js(paths.entry_point, paths.outfile),
|
|
85
|
+
build_library_dts(paths.entry_point, paths.dts_file),
|
|
86
|
+
])
|
|
78
87
|
|
|
79
88
|
return paths
|
|
80
89
|
}
|
|
81
90
|
|
|
82
91
|
export type { LibraryPaths }
|
|
83
|
-
export { build_library, library_paths }
|
|
92
|
+
export { build_library, library_paths, PUBLIC_LIBRARIES }
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
4
|
+
import { OUTFILE as BIN_OUTFILE, build_bin } from './build-bin'
|
|
5
|
+
import { build_claude_md } from './build-claude-md'
|
|
6
|
+
import { build_commands } from './build-commands'
|
|
7
|
+
import { build_hooks, OUT_DIR as HOOKS_OUT_DIR } from './build-hooks'
|
|
8
|
+
import { build_library, PUBLIC_LIBRARIES } from './build-library'
|
|
9
|
+
|
|
10
|
+
interface BuildStep {
|
|
11
|
+
name: string
|
|
12
|
+
run: () => Promise<string>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function bin_step(): Promise<string> {
|
|
16
|
+
await build_bin()
|
|
17
|
+
|
|
18
|
+
return BIN_OUTFILE
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function hooks_step(): Promise<string> {
|
|
22
|
+
await build_hooks()
|
|
23
|
+
|
|
24
|
+
return HOOKS_OUT_DIR
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function library_step(name: string): Promise<string> {
|
|
28
|
+
const { outfile } = await build_library(name)
|
|
29
|
+
|
|
30
|
+
return outfile
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function claude_md_step(): Promise<string> {
|
|
34
|
+
return build_claude_md()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Every step `pnpm build` runs (joshuafolkken/kit#3324). The steps write disjoint paths under
|
|
38
|
+
// `dist/`, so they run concurrently from this one entry instead of eight serial `tsx` launches.
|
|
39
|
+
// Nothing here writes a git-tracked file: `.codex/hooks.json` is regenerated by hand with
|
|
40
|
+
// `tsx scripts/build/build-codex-hooks.ts`, and `codex-project-config.test.ts` fails the gate when
|
|
41
|
+
// the committed copy drifts from `.claude/settings.json`.
|
|
42
|
+
function build_steps(): ReadonlyArray<BuildStep> {
|
|
43
|
+
return [
|
|
44
|
+
{ name: 'bin', run: bin_step },
|
|
45
|
+
{ name: 'hooks', run: hooks_step },
|
|
46
|
+
{ name: 'commands', run: async () => await build_commands() },
|
|
47
|
+
...PUBLIC_LIBRARIES.map((name) => ({ name, run: async () => await library_step(name) })),
|
|
48
|
+
{ name: 'claude-md', run: claude_md_step },
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function build_all(): Promise<ReadonlyArray<string>> {
|
|
53
|
+
return await Promise.all(build_steps().map(async (step) => await step.run()))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function main(): Promise<void> {
|
|
57
|
+
try {
|
|
58
|
+
const outputs = await build_all()
|
|
59
|
+
|
|
60
|
+
for (const output of outputs) console.info(` ✔ ${output} built`)
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(error_text.message_of(error))
|
|
63
|
+
process.exit(1)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
|
|
68
|
+
|
|
69
|
+
export type { BuildStep }
|
|
70
|
+
export { build_all, build_steps }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs'
|
|
2
2
|
import { createRequire } from 'node:module'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
+
import { ancestor_directories } from '#scripts/lib/ancestor-directories'
|
|
4
5
|
import { package_bin_schema } from '#scripts/lib/schemas'
|
|
5
6
|
|
|
6
7
|
const NODE_MODULES = 'node_modules'
|
|
@@ -27,20 +28,9 @@ function resolve_local_bin(project_root: string, bin_name: string): string {
|
|
|
27
28
|
// in `src/lib` would miss the toolkit its sibling checks resolve fine (joshuafolkken/kit#934).
|
|
28
29
|
// Ascending for the shim itself, rather than for a `package.json` first, is what keeps the two in
|
|
29
30
|
// step: a nested manifest that owns no `node_modules` is not where pnpm would stop either.
|
|
30
|
-
function ancestor_directories(start_directory: string): ReadonlyArray<string> {
|
|
31
|
-
const directories: Array<string> = []
|
|
32
|
-
let current = start_directory
|
|
33
|
-
|
|
34
|
-
while (!directories.includes(current)) {
|
|
35
|
-
directories.push(current)
|
|
36
|
-
current = path.dirname(current)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return directories
|
|
40
|
-
}
|
|
41
|
-
|
|
42
31
|
function find_local_bin_upwards(start_directory: string, bin_name: string): string | undefined {
|
|
43
|
-
return ancestor_directories
|
|
32
|
+
return ancestor_directories
|
|
33
|
+
.list(start_directory)
|
|
44
34
|
.map((directory) => resolve_local_bin(directory, bin_name))
|
|
45
35
|
.find((candidate) => existsSync(candidate))
|
|
46
36
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { cost_blocks } from '#scripts/cost-runtime/cost-blocks'
|
|
3
3
|
import { cost_transcript } from '#scripts/cost-runtime/cost-transcript'
|
|
4
|
+
import { capped_print_part } from '#scripts/document/capped-print-part'
|
|
4
5
|
import { hook_decision, type GuardRun } from '#scripts/josh/hook-decision'
|
|
5
6
|
import { time_batch_guard, type GuardedCall } from '#scripts/time-runtime/time-batch-guard'
|
|
6
7
|
import { time_bundle_call } from '#scripts/time-runtime/time-bundle-call'
|
|
@@ -212,7 +213,8 @@ function is_session_artifact(target: string): boolean {
|
|
|
212
213
|
|
|
213
214
|
return (
|
|
214
215
|
segments.some((_segment, index) => has_state_root(segments, index)) ||
|
|
215
|
-
is_harness_output(segments)
|
|
216
|
+
is_harness_output(segments) ||
|
|
217
|
+
capped_print_part.is_part_file(absolute)
|
|
216
218
|
)
|
|
217
219
|
}
|
|
218
220
|
|