@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
|
@@ -9,6 +9,7 @@ import { git_gh_issue_list, MAX_SCANNED } from '#scripts/gh/git-gh-issue-list'
|
|
|
9
9
|
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
10
10
|
import { github_issue_url } from '#scripts/gh/github-issue-url'
|
|
11
11
|
import { error_text } from '#scripts/lib/error-message'
|
|
12
|
+
import type { PollOptions } from '#scripts/lib/poll'
|
|
12
13
|
import { repository_labels } from '#scripts/repo/repository-labels'
|
|
13
14
|
import { issue_auto_ok } from './issue-auto-ok'
|
|
14
15
|
import { issue_file, type FileArguments } from './issue-file'
|
|
@@ -19,9 +20,10 @@ import { issue_wip } from './issue-wip'
|
|
|
19
20
|
// `josh issue:file "<title>" --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>]…
|
|
20
21
|
// [--repo <owner/repo>] [--distinct <N,…>] [--over-cap] [--no-auto-ok]` — file an Issue with every
|
|
21
22
|
// filing step run in order (joshuafolkken/kit#2808): the third-party refusal, the body lint, the
|
|
22
|
-
// `## Origin` check for another repository, the
|
|
23
|
-
//
|
|
24
|
-
// (joshuafolkken/kit#
|
|
23
|
+
// `## Origin` check for another repository, the `auto-ok` decision (joshuafolkken/kit#3213) with the
|
|
24
|
+
// run label it owes (joshuafolkken/kit#3313), the WIP cap count (joshuafolkken/kit#3181), the duplicate
|
|
25
|
+
// scout, the missing workflow labels created (joshuafolkken/kit#3176), the create call carrying every
|
|
26
|
+
// label, and `epic:bundle` after it.
|
|
25
27
|
// A direct `gh api …/issues` filing is refused by the `direct-filing` delivered rule and pointed here.
|
|
26
28
|
|
|
27
29
|
const SUCCESS_EXIT_CODE = 0
|
|
@@ -36,6 +38,9 @@ const THIRD_PARTY_MESSAGE =
|
|
|
36
38
|
// `GH_REPO` is the variable `gh` reads `{owner}/{repo}` from, so setting it points every listing the
|
|
37
39
|
// scout and `epic:bundle` make at the target repository rather than at this checkout.
|
|
38
40
|
const GH_REPO_VARIABLE = 'GH_REPO'
|
|
41
|
+
// The open listing `epic:bundle` reads trails the create call, so the issue just filed is looked for
|
|
42
|
+
// again for up to ten seconds before the placement is given up (joshuafolkken/kit#3332).
|
|
43
|
+
const FRESH_ISSUE_POLL: PollOptions = { attempts: 6, interval_ms: 2000 }
|
|
39
44
|
|
|
40
45
|
interface Filing {
|
|
41
46
|
args: FileArguments
|
|
@@ -130,11 +135,9 @@ async function is_scout_clear(filing: Filing): Promise<boolean> {
|
|
|
130
135
|
return open.length === 0
|
|
131
136
|
}
|
|
132
137
|
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
async function create(filing: Filing): Promise<string | undefined> {
|
|
137
|
-
repository_labels.ensure_labels(filing.target)
|
|
138
|
+
// Every label the create call carries, or `undefined` when an `auto-ok` filing names neither run label
|
|
139
|
+
// (joshuafolkken/kit#3313). Decided before the WIP count and the scout, so a refusal costs no listing.
|
|
140
|
+
async function labels_of(filing: Filing): Promise<ReadonlyArray<string> | undefined> {
|
|
138
141
|
const auto_ok = await issue_auto_ok.resolve(
|
|
139
142
|
filing.args.is_auto_ok_opted_out,
|
|
140
143
|
filing.target,
|
|
@@ -142,10 +145,24 @@ async function create(filing: Filing): Promise<string | undefined> {
|
|
|
142
145
|
)
|
|
143
146
|
|
|
144
147
|
console.info(issue_auto_ok.line_of(auto_ok))
|
|
148
|
+
const labels = issue_file.labels_of(filing.args, filing.body, auto_ok.is_applied)
|
|
149
|
+
const problem = issue_file.triage_problem(labels)
|
|
150
|
+
|
|
151
|
+
if (problem === undefined) return labels
|
|
152
|
+
console.error(`✖ ${problem}`)
|
|
153
|
+
|
|
154
|
+
return undefined
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// `undefined` when the create call failed. `gh`'s standard error is captured into the thrown error
|
|
158
|
+
// rather than printed, so it is printed here — otherwise the filing fails with no reason given. A label
|
|
159
|
+
// the create applies is provisioned first, so it never arrives with a generated color.
|
|
160
|
+
async function create(filing: Filing, labels: ReadonlyArray<string>): Promise<string | undefined> {
|
|
161
|
+
repository_labels.ensure_labels(filing.target)
|
|
145
162
|
const request = git_gh_issue_write.issue_create_request({
|
|
146
163
|
title: filing.args.title,
|
|
147
164
|
body: filing.body,
|
|
148
|
-
labels
|
|
165
|
+
labels,
|
|
149
166
|
repo: filing.target,
|
|
150
167
|
})
|
|
151
168
|
|
|
@@ -165,7 +182,7 @@ async function create(filing: Filing): Promise<string | undefined> {
|
|
|
165
182
|
async function place(url: string, target: string): Promise<void> {
|
|
166
183
|
const issue_number = Number(github_issue_url.parse(url)?.issue_number)
|
|
167
184
|
const exit_code = Number.isSafeInteger(issue_number)
|
|
168
|
-
? await epic_bundle_cli.report_for(issue_number, target)
|
|
185
|
+
? await epic_bundle_cli.report_for(issue_number, target, FRESH_ISSUE_POLL)
|
|
169
186
|
: FAILURE_EXIT_CODE
|
|
170
187
|
|
|
171
188
|
if (exit_code !== SUCCESS_EXIT_CODE) {
|
|
@@ -173,17 +190,17 @@ async function place(url: string, target: string): Promise<void> {
|
|
|
173
190
|
}
|
|
174
191
|
}
|
|
175
192
|
|
|
176
|
-
|
|
193
|
+
function is_admitted(filing: Filing): boolean {
|
|
177
194
|
const refusals = refusals_of(filing)
|
|
178
195
|
|
|
179
|
-
if (refusals.length
|
|
180
|
-
|
|
196
|
+
if (refusals.length === 0) return true
|
|
197
|
+
console.error(refusals.join('\n'))
|
|
181
198
|
|
|
182
|
-
|
|
183
|
-
|
|
199
|
+
return false
|
|
200
|
+
}
|
|
184
201
|
|
|
185
|
-
|
|
186
|
-
const url = await create(filing)
|
|
202
|
+
async function send(filing: Filing, labels: ReadonlyArray<string>): Promise<number> {
|
|
203
|
+
const url = await create(filing, labels)
|
|
187
204
|
|
|
188
205
|
if (url === undefined) return FAILURE_EXIT_CODE
|
|
189
206
|
console.info(url)
|
|
@@ -192,6 +209,16 @@ async function file(filing: Filing): Promise<number> {
|
|
|
192
209
|
return SUCCESS_EXIT_CODE
|
|
193
210
|
}
|
|
194
211
|
|
|
212
|
+
async function file(filing: Filing): Promise<number> {
|
|
213
|
+
if (!is_admitted(filing)) return FAILURE_EXIT_CODE
|
|
214
|
+
const labels = await labels_of(filing)
|
|
215
|
+
|
|
216
|
+
if (labels === undefined) return FAILURE_EXIT_CODE
|
|
217
|
+
if (!(await is_wip_clear(filing)) || !(await is_scout_clear(filing))) return FAILURE_EXIT_CODE
|
|
218
|
+
|
|
219
|
+
return await send(filing, labels)
|
|
220
|
+
}
|
|
221
|
+
|
|
195
222
|
async function filing_of(args: FileArguments): Promise<Filing | string> {
|
|
196
223
|
const body = await read_body(args.body_file)
|
|
197
224
|
|
|
@@ -228,7 +255,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
228
255
|
process.exitCode = await run(argv)
|
|
229
256
|
}
|
|
230
257
|
|
|
231
|
-
const issue_file_cli = { THIRD_PARTY_MESSAGE, run }
|
|
258
|
+
const issue_file_cli = { FRESH_ISSUE_POLL, THIRD_PARTY_MESSAGE, run }
|
|
232
259
|
|
|
233
260
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
234
261
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { parseArgs } from 'node:util'
|
|
2
2
|
import { epic_issue } from '#scripts/epic/epic-issue'
|
|
3
|
+
import { epic_triage } from '#scripts/epic/epic-triage'
|
|
3
4
|
import { github_issue_url } from '#scripts/gh/github-issue-url'
|
|
4
5
|
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
5
6
|
import { issue_backlinks } from './issue-backlinks'
|
|
@@ -9,6 +10,8 @@ import {
|
|
|
9
10
|
DEPTH_LABEL_ORDER,
|
|
10
11
|
FILING_ROUTE_LABELS,
|
|
11
12
|
has_label_name,
|
|
13
|
+
RUN_LANE_LABEL,
|
|
14
|
+
RUN_SOLO_LABEL,
|
|
12
15
|
} from './issue-labels'
|
|
13
16
|
import { markdown_section } from './markdown-section'
|
|
14
17
|
|
|
@@ -152,6 +155,19 @@ function labels_of(args: FileArguments, body: string, is_auto_ok = false): Reado
|
|
|
152
155
|
return [...labels, AUTO_OK_LABEL]
|
|
153
156
|
}
|
|
154
157
|
|
|
158
|
+
// Why an `auto-ok` filing with neither `run:lane` nor `run:solo` is refused, or `undefined` when it is
|
|
159
|
+
// not (joshuafolkken/kit#3313). The offer paths withhold every candidate while one opted-in Issue is
|
|
160
|
+
// untriaged, so a run's own filing without the judgement stopped every lane. No default is applied:
|
|
161
|
+
// `run:solo` is the answer that keeps a verification defect from running beside others, and only a
|
|
162
|
+
// reading of the Issue gives it (`backlogrun-lanes.md`).
|
|
163
|
+
function triage_problem(labels: ReadonlyArray<string>): string | undefined {
|
|
164
|
+
const is_owed = has_label_name(labels, AUTO_OK_LABEL) && !epic_triage.has_triage_label(labels)
|
|
165
|
+
|
|
166
|
+
if (!is_owed) return undefined
|
|
167
|
+
|
|
168
|
+
return `an \`${AUTO_OK_LABEL}\` filing needs \`--label ${RUN_LANE_LABEL}\` or \`--label ${RUN_SOLO_LABEL}\` — \`${RUN_SOLO_LABEL}\` only for a defect in kit's own verification that makes unrelated PRs answer wrongly on main now (\`backlogrun-lanes.md\`), else \`${RUN_LANE_LABEL}\``
|
|
169
|
+
}
|
|
170
|
+
|
|
155
171
|
function is_same_repository(target: string, current: string): boolean {
|
|
156
172
|
return target.toLowerCase() === current.toLowerCase()
|
|
157
173
|
}
|
|
@@ -202,7 +218,14 @@ function unacknowledged(
|
|
|
202
218
|
return candidates.filter((candidate) => !distinct.includes(candidate))
|
|
203
219
|
}
|
|
204
220
|
|
|
205
|
-
const issue_file = {
|
|
221
|
+
const issue_file = {
|
|
222
|
+
parse,
|
|
223
|
+
labels_of,
|
|
224
|
+
origin_problem,
|
|
225
|
+
triage_problem,
|
|
226
|
+
unacknowledged,
|
|
227
|
+
is_same_repository,
|
|
228
|
+
}
|
|
206
229
|
|
|
207
230
|
export type { FileArguments }
|
|
208
231
|
export { issue_file }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
2
|
+
import { issue_label_schema } from '#scripts/git/git-schemas'
|
|
2
3
|
import { PAGE_CEILING_CAUSE } from '#scripts/git/listing-cutoff'
|
|
3
4
|
import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
|
|
4
|
-
import { issue_label_schema } from '#scripts/git/schemas'
|
|
5
5
|
import { z } from 'zod'
|
|
6
6
|
import { EPIC_LABEL, has_any_label } from './issue-labels'
|
|
7
7
|
import type { ScoutIssue } from './issue-scout'
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
3
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
4
4
|
import { bounded_pool } from '#scripts/lib/bounded-pool'
|
|
5
|
+
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
5
6
|
import { issue_report_failures, type ReadFailureKind } from './issue-report-failures'
|
|
6
7
|
import { issue_state, type IssueState } from './issue-state'
|
|
7
8
|
|
|
@@ -28,9 +29,6 @@ import { issue_state, type IssueState } from './issue-state'
|
|
|
28
29
|
|
|
29
30
|
const FAILURE_EXIT_CODE = 1
|
|
30
31
|
const ARGV_OFFSET = 2
|
|
31
|
-
const REPO_FLAG = '--repo'
|
|
32
|
-
const FLAG_PREFIX = '-'
|
|
33
|
-
const INLINE_REPO_FLAG = `${REPO_FLAG}=`
|
|
34
32
|
const ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u
|
|
35
33
|
const USAGE = 'Usage: josh issue:state <issue-number> [<issue-number> ...] [--repo <owner/repo>]'
|
|
36
34
|
// A blank line between the blocks of a multi-number report, so a person sees where one issue ends
|
|
@@ -60,85 +58,43 @@ interface IssueReport {
|
|
|
60
58
|
result: StateRead
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
function read_inline_repo(argv: ReadonlyArray<string>): RepoFlag | undefined {
|
|
79
|
-
const inline = argv.find((argument) => argument.startsWith(INLINE_REPO_FLAG))
|
|
80
|
-
|
|
81
|
-
if (inline === undefined) return undefined
|
|
82
|
-
|
|
83
|
-
const repo = inline.slice(INLINE_REPO_FLAG.length)
|
|
84
|
-
|
|
85
|
-
if (repo.length === 0) return { kind: 'incomplete' }
|
|
86
|
-
|
|
87
|
-
return { kind: 'named', repo, consumed: [argv.indexOf(inline)] }
|
|
61
|
+
// The read goes through `cli_flags`, both spellings gh itself accepts included (`--repo owner/repo`,
|
|
62
|
+
// `--repo=owner/repo`), and is strict (joshuafolkken/kit#3261). An unrecognized flag refuses the
|
|
63
|
+
// call: `--rep=owner/repo` used to be discarded for starting with a dash, so the call fell back to
|
|
64
|
+
// the session's repository and printed a confident state for a *different* repository's issue of
|
|
65
|
+
// that number (joshuafolkken/kit#1355).
|
|
66
|
+
const OPTIONS = { repo: { type: 'string', multiple: true } } as const
|
|
67
|
+
|
|
68
|
+
// `absent` and "given but with nothing usable" are different answers. Falling back to the session's
|
|
69
|
+
// repository on the second — an empty value, or `--repo` given twice — would print a confident state
|
|
70
|
+
// for a *different* issue of the same number, which is the exact misread `--repo` exists to prevent.
|
|
71
|
+
function read_repo(given: ReadonlyArray<string> | undefined): { repo?: string } | undefined {
|
|
72
|
+
if (given === undefined) return {}
|
|
73
|
+
const [repo, ...rest] = given
|
|
74
|
+
|
|
75
|
+
return repo !== undefined && rest.length === 0 && repo.length > 0 ? { repo } : undefined
|
|
88
76
|
}
|
|
89
77
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (repo === undefined || repo.startsWith(FLAG_PREFIX)) return { kind: 'incomplete' }
|
|
99
|
-
|
|
100
|
-
return { kind: 'named', repo, consumed: [index, value_index] }
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function read_repo_flag(argv: ReadonlyArray<string>): RepoFlag {
|
|
104
|
-
return read_inline_repo(argv) ?? read_separate_repo(argv)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// The argv positions the repository flag occupied, and nothing else. Everything outside this set was
|
|
108
|
-
// offered as an issue number, whatever it looks like — so a flag nobody recognizes reaches the check
|
|
109
|
-
// below and refuses the call instead of vanishing from it (joshuafolkken/kit#1355).
|
|
110
|
-
function consumed_indices(repo_flag: RepoFlag): ReadonlySet<number> {
|
|
111
|
-
return new Set(repo_flag.kind === 'named' ? repo_flag.consumed : [])
|
|
78
|
+
// A token that is not a number refuses the whole invocation rather than being dropped. Dropping it
|
|
79
|
+
// answers fewer numbers than were asked for and still exits zero — and with one number left, the
|
|
80
|
+
// surviving block prints in the single-number shape, so nothing in the output says a number went
|
|
81
|
+
// unanswered. `#1262` copied out of a `diag` table is exactly that token.
|
|
82
|
+
function is_issue_numbers(positionals: ReadonlyArray<string>): boolean {
|
|
83
|
+
return (
|
|
84
|
+
positionals.length > 0 && positionals.every((argument) => ISSUE_NUMBER_PATTERN.test(argument))
|
|
85
|
+
)
|
|
112
86
|
}
|
|
113
87
|
|
|
114
88
|
function parse_request(argv: ReadonlyArray<string>): StateRequest | undefined {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// issue number — and nothing else is removed here. Every remaining token is one the caller offered
|
|
121
|
-
// as an issue number, whatever it looks like.
|
|
122
|
-
const consumed = consumed_indices(repo_flag)
|
|
123
|
-
const rest = argv.filter((_argument, index) => !consumed.has(index))
|
|
124
|
-
const numbers = rest.filter((argument) => ISSUE_NUMBER_PATTERN.test(argument))
|
|
125
|
-
|
|
126
|
-
// A token that is not a number refuses the whole invocation rather than being dropped. Dropping
|
|
127
|
-
// it answers fewer numbers than were asked for and still exits zero — and with one number left,
|
|
128
|
-
// the surviving block prints in the single-number shape, so nothing in the output says a number
|
|
129
|
-
// went unanswered. `#1262` copied out of a `diag` table is exactly that token.
|
|
130
|
-
//
|
|
131
|
-
// An unrecognized flag reaches this same check rather than a lenient one of its own
|
|
132
|
-
// (joshuafolkken/kit#1355). `--rep=owner/repo` used to be discarded for starting with a dash, so
|
|
133
|
-
// the call fell back to the session's repository and printed a confident state for a *different*
|
|
134
|
-
// repository's issue of that number — the misread `incomplete` already exists to prevent.
|
|
135
|
-
if (numbers.length === 0 || numbers.length !== rest.length) return undefined
|
|
89
|
+
const parsed = cli_flags.arguments_of(argv, OPTIONS)
|
|
90
|
+
if (parsed === undefined) return undefined
|
|
91
|
+
const repo = read_repo(parsed.values.repo)
|
|
92
|
+
|
|
93
|
+
if (repo === undefined || !is_issue_numbers(parsed.positionals)) return undefined
|
|
136
94
|
|
|
137
95
|
// In the order they were typed, with a repeat dropped: repeating a number would spend a second
|
|
138
96
|
// read on an answer already in hand, and print a second block a caller counting rows counts twice.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return repo_flag.kind === 'named' ? { issue_numbers, repo: repo_flag.repo } : { issue_numbers }
|
|
97
|
+
return { issue_numbers: [...new Set(parsed.positionals)], ...repo }
|
|
142
98
|
}
|
|
143
99
|
|
|
144
100
|
// One number's read, reduced to what the report needs and nothing printed yet. Separating the two
|
|
@@ -60,6 +60,17 @@ interface CommandEntry {
|
|
|
60
60
|
// listing carries only what a consumer can run (joshuafolkken/kit#1988). The audience in
|
|
61
61
|
// `reference` separately decides whether the command appears in the default listing.
|
|
62
62
|
is_kit_only?: boolean
|
|
63
|
+
// Pre-built to `dist/commands/` so a consumer's `dist/josh.js` imports it in its own process
|
|
64
|
+
// instead of spawning tsx for it (joshuafolkken/kit#3328, `docs/maintainers/runtime-bundling.md`).
|
|
65
|
+
is_bundled?: boolean
|
|
66
|
+
// The cores the command reserves from the machine-wide budget before it starts its heavy tools
|
|
67
|
+
// (joshuafolkken/kit#3345). `josh-logic.ts` claims them at the one dispatch point every command
|
|
68
|
+
// passes through, so the command only declares the number. A function means the weight is read
|
|
69
|
+
// when the command starts: the unit suite's share depends on what else is running at that moment.
|
|
70
|
+
// **The edit hook declares none, on purpose.** It formats one file per edit and finishes in well
|
|
71
|
+
// under a second, so a wait for room on the machine would stall every edit for the length of
|
|
72
|
+
// another lane's check.
|
|
73
|
+
core_weight?: number | (() => number)
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
// The name `josh gate` registers under. It lives here rather than in `verification-gate.ts` so a
|
|
@@ -143,14 +143,14 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
|
|
|
143
143
|
reference: ['[<owner/repo>]', 'automation', ['none']],
|
|
144
144
|
},
|
|
145
145
|
'run:merge': {
|
|
146
|
-
script: 'scripts/run/run-merge-cli.ts',
|
|
146
|
+
script: 'scripts/run/merge/run-merge-cli.ts',
|
|
147
147
|
description:
|
|
148
148
|
'Collapse a backlogrun merge event into one call: confirm the child, do the post-merge steps, offer the next child',
|
|
149
149
|
category: 'AI tools',
|
|
150
150
|
reference: [ISSUE_WITH_OPTIONS, 'automation', ['git', 'network']],
|
|
151
151
|
},
|
|
152
152
|
'run:review': {
|
|
153
|
-
script: 'scripts/run/run-review-cli.ts',
|
|
153
|
+
script: 'scripts/run/review/run-review-cli.ts',
|
|
154
154
|
description:
|
|
155
155
|
'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)',
|
|
156
156
|
category: 'AI tools',
|
|
@@ -171,7 +171,7 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
|
|
|
171
171
|
// (`run:tail`) were four round trips re-billing the run's full context each. It stops at the first
|
|
172
172
|
// failed step and names it, so the run reads only the step to fix.
|
|
173
173
|
ship: {
|
|
174
|
-
script: 'scripts/run/run-ship-cli.ts',
|
|
174
|
+
script: 'scripts/run/ship/run-ship-cli.ts',
|
|
175
175
|
description:
|
|
176
176
|
'Ship a change in one call: gate, commit/push/PR, the CI-wait merge and the report bookkeeping, stopping at the first failed step',
|
|
177
177
|
category: 'AI tools',
|
|
@@ -182,7 +182,7 @@ const AI_COMMANDS: Record<string, CommandEntry> = {
|
|
|
182
182
|
],
|
|
183
183
|
},
|
|
184
184
|
'run:event': {
|
|
185
|
-
script: 'scripts/run/run-event-cli.ts',
|
|
185
|
+
script: 'scripts/run/event/run-event-cli.ts',
|
|
186
186
|
description:
|
|
187
187
|
'Append to, read or watch the run’s append-only event stream (--append <kind> <text> | --from|--follow <n> | --watch [<n>] | --last)',
|
|
188
188
|
category: 'AI tools',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { OPTIONAL_ENV_FILE_FLAGS, type CommandEntry } from './josh-command-types'
|
|
2
2
|
|
|
3
3
|
// The `backlog:*` command registry, split out of `josh-commands-ai.ts` so that file stays under its
|
|
4
4
|
// 300-code-line limit, exactly as `LANE_COMMANDS` and `SPLIT_COMMANDS` were for the same reason
|
|
@@ -41,6 +41,9 @@ const BACKLOG_COMMANDS: Record<string, CommandEntry> = {
|
|
|
41
41
|
},
|
|
42
42
|
'backlog:stalled': {
|
|
43
43
|
script: 'scripts/backlog/backlog-stalled-cli.ts',
|
|
44
|
+
// A stall sends one Telegram warning (joshuafolkken/kit#3357). The `Stop` hook calls the detector
|
|
45
|
+
// directly, so this flag costs only the manual command its in-process dispatch.
|
|
46
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
44
47
|
description:
|
|
45
48
|
'Report whether ready backlog work is sitting undispatched with a free lane and no recent dispatch',
|
|
46
49
|
category: 'AI tools',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { core_budget } from '#scripts/gate/core-budget'
|
|
2
|
+
import { gate_plan } from '#scripts/gate/gate-plan'
|
|
1
3
|
import { GATE_COMMAND, type CommandEntry } from './josh-command-types'
|
|
2
4
|
|
|
3
5
|
const FILE_ARGUMENTS = '[files...]'
|
|
@@ -25,18 +27,21 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
|
|
|
25
27
|
description: 'Check code with prettier and eslint (skips a tool a basic project lacks)',
|
|
26
28
|
category: 'Development',
|
|
27
29
|
reference: ['', 'developer', ['processes']],
|
|
30
|
+
core_weight: core_budget.CORE_WEIGHTS.lint,
|
|
28
31
|
},
|
|
29
32
|
'lint:related': {
|
|
30
33
|
script: 'scripts/lint/lint-related.ts',
|
|
31
34
|
description: 'Check only the changed files with prettier and eslint (whole tree on fallback)',
|
|
32
35
|
category: 'Development',
|
|
33
36
|
reference: [FILE_ARGUMENTS, 'developer', ['processes']],
|
|
37
|
+
core_weight: core_budget.CORE_WEIGHTS.lint,
|
|
34
38
|
},
|
|
35
39
|
lines: {
|
|
36
40
|
script: 'scripts/lines/lines-command.ts',
|
|
37
41
|
description: "Print a file's code lines against the max-lines limit and the headroom left",
|
|
38
42
|
category: 'Development',
|
|
39
43
|
reference: [REQUIRED_FILE_ARGUMENTS, 'developer', ['none']],
|
|
44
|
+
core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
|
|
40
45
|
},
|
|
41
46
|
'refactor:scan': {
|
|
42
47
|
script: 'scripts/refactor/refactor-scan-cli.ts',
|
|
@@ -44,6 +49,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
|
|
|
44
49
|
'List refactoring candidates in the changed scope by category and answer clear/candidates',
|
|
45
50
|
category: 'Development',
|
|
46
51
|
reference: ['', 'automation', ['processes']],
|
|
52
|
+
core_weight: core_budget.CORE_WEIGHTS.eslint_scan,
|
|
47
53
|
},
|
|
48
54
|
bytes: {
|
|
49
55
|
script: 'scripts/lines/bytes-command.ts',
|
|
@@ -130,6 +136,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
|
|
|
130
136
|
description: 'Run spell check including dotfiles',
|
|
131
137
|
category: 'Development',
|
|
132
138
|
reference: ['', 'developer', ['processes']],
|
|
139
|
+
core_weight: core_budget.CORE_WEIGHTS.spell_check,
|
|
133
140
|
},
|
|
134
141
|
behavior: {
|
|
135
142
|
script: 'scripts/behavior/behavior-cli.ts',
|
|
@@ -151,12 +158,14 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
|
|
|
151
158
|
'Run unit tests with Vitest (skips when Vitest is absent; fails when it has no tests)',
|
|
152
159
|
category: 'Development',
|
|
153
160
|
reference: [FILTER_ARGUMENTS, 'developer', ['processes']],
|
|
161
|
+
core_weight: gate_plan.direct_unit_weight,
|
|
154
162
|
},
|
|
155
163
|
'test:related': {
|
|
156
164
|
script: 'scripts/test/test-related.ts',
|
|
157
165
|
description: 'Run only the unit tests related to the changed files (full suite on fallback)',
|
|
158
166
|
category: 'Development',
|
|
159
167
|
reference: [FILE_ARGUMENTS, 'developer', ['processes']],
|
|
168
|
+
core_weight: gate_plan.direct_unit_weight,
|
|
160
169
|
},
|
|
161
170
|
'test:declared': {
|
|
162
171
|
script: 'scripts/test/test-declared.ts',
|
|
@@ -203,6 +212,7 @@ const DEV_COMMANDS: Record<string, CommandEntry> = {
|
|
|
203
212
|
description: 'Type-check with tsc (skips a basic project with no TypeScript to check)',
|
|
204
213
|
category: 'Development',
|
|
205
214
|
reference: ['[arguments...]', 'developer', ['processes']],
|
|
215
|
+
core_weight: core_budget.CORE_WEIGHTS.type_check,
|
|
206
216
|
},
|
|
207
217
|
port: {
|
|
208
218
|
script: 'scripts/ports/port-command.ts',
|
|
@@ -13,6 +13,7 @@ const DOCUMENT_COMMANDS: Record<string, CommandEntry> = {
|
|
|
13
13
|
description: 'Print one section of a markdown document, for a `file.md` → "Heading" reference',
|
|
14
14
|
category: 'AI tools',
|
|
15
15
|
reference: ['<file> <heading>', 'automation', ['none']],
|
|
16
|
+
is_bundled: true,
|
|
16
17
|
},
|
|
17
18
|
'read:set': {
|
|
18
19
|
script: 'scripts/document/read-set-cli.ts',
|
|
@@ -9,6 +9,10 @@ const LANE_SCRIPT = 'scripts/lane/lane-cli.ts'
|
|
|
9
9
|
// has to read `.env` to see them — without this the two are documented and unreachable.
|
|
10
10
|
const LANE_ARGUMENTS = { script: LANE_SCRIPT, tsx_arguments: OPTIONAL_ENV_FILE_FLAGS } as const
|
|
11
11
|
const ISSUE_WITH_OPTIONS = '<issue> [options]'
|
|
12
|
+
const MEASURE_ARGUMENTS = {
|
|
13
|
+
script: 'scripts/lane/lane-measure-cli.ts',
|
|
14
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
15
|
+
} as const
|
|
12
16
|
|
|
13
17
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
14
18
|
const LANE_COMMANDS: Record<string, CommandEntry> = {
|
|
@@ -69,6 +73,24 @@ const LANE_COMMANDS: Record<string, CommandEntry> = {
|
|
|
69
73
|
category: 'AI tools',
|
|
70
74
|
reference: ['<issue> [--stash <message>]', 'automation', ['files', 'git', 'processes']],
|
|
71
75
|
},
|
|
76
|
+
// The lane-limit measurement (joshuafolkken/kit#3355): `.env` is read so `lane:stats` labels the row
|
|
77
|
+
// with the `JOSH_LANE_LIMIT` a person set there.
|
|
78
|
+
'lane:sample': {
|
|
79
|
+
...MEASURE_ARGUMENTS,
|
|
80
|
+
description:
|
|
81
|
+
'Record the machine load (load average, swap, free memory, working lanes) to the lane ledger',
|
|
82
|
+
category: 'AI tools',
|
|
83
|
+
reference: ['[--every <seconds>]', 'maintainer', ['files']],
|
|
84
|
+
default_script_arguments: ['sample'],
|
|
85
|
+
},
|
|
86
|
+
'lane:stats': {
|
|
87
|
+
...MEASURE_ARGUMENTS,
|
|
88
|
+
description:
|
|
89
|
+
'Print one table row of lane throughput, gate duration and machine load over a period',
|
|
90
|
+
category: 'AI tools',
|
|
91
|
+
reference: ['--period <days> [--limit <lane-limit>]', 'maintainer', ['none']],
|
|
92
|
+
default_script_arguments: ['stats'],
|
|
93
|
+
},
|
|
72
94
|
}
|
|
73
95
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
74
96
|
|
|
@@ -21,7 +21,7 @@ const MAINTENANCE_COMMANDS: Record<string, CommandEntry> = {
|
|
|
21
21
|
script: 'scripts/overrides/overrides-check.ts',
|
|
22
22
|
description: 'Check pnpm overrides for drift',
|
|
23
23
|
category: 'Maintenance',
|
|
24
|
-
reference: ['[--save]', '
|
|
24
|
+
reference: ['[--save]', 'developer', ['files']],
|
|
25
25
|
},
|
|
26
26
|
audit: {
|
|
27
27
|
script: 'scripts/security/security-audit.ts',
|
|
@@ -49,7 +49,7 @@ const MAINTENANCE_COMMANDS: Record<string, CommandEntry> = {
|
|
|
49
49
|
],
|
|
50
50
|
description: 'Update pnpm, dependencies, and run security audit',
|
|
51
51
|
category: 'Maintenance',
|
|
52
|
-
reference: ['', '
|
|
52
|
+
reference: ['', 'developer', ['files', 'network', 'processes']],
|
|
53
53
|
argument_targets: ['latest:corepack', 'latest:update', 'audit'],
|
|
54
54
|
},
|
|
55
55
|
'latest:scope': {
|
|
@@ -73,13 +73,13 @@ const MAINTENANCE_COMMANDS: Record<string, CommandEntry> = {
|
|
|
73
73
|
script: 'scripts/version/latest-corepack.ts',
|
|
74
74
|
description: 'Update pnpm on the current major while preserving the integrity pin',
|
|
75
75
|
category: 'Maintenance',
|
|
76
|
-
reference: ['', '
|
|
76
|
+
reference: ['', 'developer', ['files', 'network']],
|
|
77
77
|
},
|
|
78
78
|
'latest:update': {
|
|
79
79
|
script: 'scripts/version/latest-update.ts',
|
|
80
80
|
description: 'Update all dependencies to latest',
|
|
81
81
|
category: 'Maintenance',
|
|
82
|
-
reference: ['', '
|
|
82
|
+
reference: ['', 'developer', ['files', 'network']],
|
|
83
83
|
},
|
|
84
84
|
}
|
|
85
85
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
@@ -6,7 +6,7 @@ import { OPTIONAL_ENV_FILE_FLAGS, type CommandEntry } from './josh-command-types
|
|
|
6
6
|
// the generated catalog keeps their order.
|
|
7
7
|
|
|
8
8
|
// One script answers both `run:hold` and `run:release`; the flag below is what tells them apart.
|
|
9
|
-
const RUN_HOLD_SCRIPT = 'scripts/run/run-hold-cli.ts'
|
|
9
|
+
const RUN_HOLD_SCRIPT = 'scripts/run/hold/run-hold-cli.ts'
|
|
10
10
|
|
|
11
11
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
12
12
|
const RUN_COMMANDS: Record<string, CommandEntry> = {
|
|
@@ -24,19 +24,22 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
|
|
|
24
24
|
default_script_arguments: ['--release'],
|
|
25
25
|
},
|
|
26
26
|
'run:tidy': {
|
|
27
|
-
script: 'scripts/run/run-tidy-cli.ts',
|
|
27
|
+
script: 'scripts/run/tidy/run-tidy-cli.ts',
|
|
28
28
|
description: 'Close merged lanes and drop stashes whose issues are all merged',
|
|
29
29
|
category: 'AI tools',
|
|
30
30
|
reference: ['', 'automation', ['git', 'network', 'files']],
|
|
31
31
|
},
|
|
32
32
|
'run:carry': {
|
|
33
|
-
script: 'scripts/run/run-carry-cli.ts',
|
|
33
|
+
script: 'scripts/run/carry/run-carry-cli.ts',
|
|
34
|
+
// `--stopped` sends the stop confirmation, so the Telegram credentials come from `.env` as for
|
|
35
|
+
// `run:wake` below (joshuafolkken/kit#3357).
|
|
36
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
34
37
|
description: 'Carry one invocation’s budget across its own session cuts',
|
|
35
38
|
category: 'AI tools',
|
|
36
39
|
reference: ['<operation> [arguments...]', 'automation', ['files']],
|
|
37
40
|
},
|
|
38
41
|
'run:wake': {
|
|
39
|
-
script: 'scripts/run/run-wake-cli.ts',
|
|
42
|
+
script: 'scripts/run/wake/run-wake-cli.ts',
|
|
40
43
|
// `.env` rather than the ambient environment:
|
|
41
44
|
// the failure warning needs the Telegram credentials, the same
|
|
42
45
|
// reasons `notify` and `followup` carry these flags.
|
|
@@ -46,7 +49,7 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
|
|
|
46
49
|
reference: ['[options]', 'automation', ['processes', 'notifications']],
|
|
47
50
|
},
|
|
48
51
|
'run:cut': {
|
|
49
|
-
script: 'scripts/run/run-cut-cli.ts',
|
|
52
|
+
script: 'scripts/run/cut/run-cut-cli.ts',
|
|
50
53
|
description: 'Cut a lane child before the gate and resume a fresh process',
|
|
51
54
|
category: 'AI tools',
|
|
52
55
|
reference: ['[--resume] <issue> [--impl] [--handoff <path>]', 'automation', ['files']],
|
|
@@ -64,7 +67,7 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
|
|
|
64
67
|
reference: ['<issue> --output <path> [--repo <owner/repo>]', 'automation', ['network']],
|
|
65
68
|
},
|
|
66
69
|
'run:progress': {
|
|
67
|
-
script: 'scripts/run/run-progress-cli.ts',
|
|
70
|
+
script: 'scripts/run/progress/run-progress-cli.ts',
|
|
68
71
|
description: 'Report an unattended run’s progress once it has gone quiet for an interval',
|
|
69
72
|
category: 'AI tools',
|
|
70
73
|
reference: [
|
|
@@ -83,7 +86,9 @@ const RUN_COMMANDS: Record<string, CommandEntry> = {
|
|
|
83
86
|
// read the budget, gather the issue reads and decide the pre-implementation step. `run:hold`,
|
|
84
87
|
// `cost --cut`, `run:prep` and `run:step` were four round trips re-billing a lane's full context each.
|
|
85
88
|
'run:entry': {
|
|
86
|
-
script: 'scripts/run/run-entry-cli.ts',
|
|
89
|
+
script: 'scripts/run/entry/run-entry-cli.ts',
|
|
90
|
+
// A `busy` hold or an `over` budget sends the stop confirmation (joshuafolkken/kit#3357).
|
|
91
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
87
92
|
description:
|
|
88
93
|
'Open a run in one call: claim the tree, read the budget, bundle the reads, decide the pre-implementation step',
|
|
89
94
|
category: 'AI tools',
|