@joshuafolkken/kit 1.1010.0 → 1.1050.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +1 -5
- package/.claude/skills/dependency-update/SKILL.md +6 -3
- package/.claude/skills/epic-commands/SKILL.md +46 -17
- package/.claude/skills/verify-ui/SKILL.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +10 -25
- package/.claude/skills/workflow-commands/background-commands.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-child.md +6 -4
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +6 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +30 -36
- package/.claude/skills/workflow-commands/backlogrun-steps.md +16 -16
- package/.claude/skills/workflow-commands/backlogrun.md +3 -12
- package/.claude/skills/workflow-commands/chain-rule.md +2 -2
- package/.claude/skills/workflow-commands/followup-reference.md +2 -2
- package/.claude/skills/workflow-commands/fullrun-steps.md +4 -3
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/halfrun.md +2 -1
- package/.claude/skills/workflow-commands/into-target.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +80 -126
- package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -36
- package/.claude/skills/workflow-commands/prerequisite.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +2 -2
- package/.codex/hooks.json +1 -5
- package/.github/workflows/auto-tag.yml +21 -0
- package/.github/workflows/publish.yml +9 -10
- package/.github/workflows/sonar-qube.yml +1 -1
- package/AGENTS.md +4 -25
- package/CLAUDE.md +24 -38
- package/GEMINI.md +4 -24
- package/README.md +22 -56
- package/dist/CLAUDE.md +24 -38
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-6PSTVOLH.js → chunk-5BK3K7V4.js} +114 -90
- package/dist/hooks/{chunk-PAXMLGSS.js → chunk-7VPDUBRN.js} +93 -175
- package/dist/hooks/{chunk-KPZN42RT.js → chunk-DMQN45FN.js} +3 -3
- package/dist/hooks/{chunk-WMIR5SNX.js → chunk-EJDX2TOB.js} +13 -3
- package/dist/hooks/{chunk-A2H5I2VD.js → chunk-GQ7KP45M.js} +2 -2
- package/dist/hooks/{chunk-4GDR2YTV.js → chunk-HJIISEAC.js} +4 -4
- package/dist/hooks/{chunk-AWTFKKFW.js → chunk-NAS4C7GP.js} +6 -33
- package/dist/hooks/{chunk-56LGMJJV.js → chunk-NJQOBE6L.js} +2 -2
- package/dist/hooks/{chunk-EZLHXKJ6.js → chunk-RLDX5SOC.js} +1222 -941
- package/dist/hooks/{chunk-GBJUERYK.js → chunk-WQ4OSBSS.js} +10 -3
- package/dist/hooks/codex-hook-adapter.js +10 -10
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +15 -34
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +23 -16
- package/dist/hooks/stop-guard.js +21 -200
- package/dist/josh.js +42 -125
- package/dist/version/index.js +466 -42
- package/eslint/base.js +2 -11
- package/package.json +36 -10
- package/prompts/coding-standards.md +15 -290
- package/prompts/collaboration-workflow/cross-repo-epic.md +2 -51
- package/prompts/collaboration-workflow/epic-audit.md +2 -53
- package/prompts/collaboration-workflow/epic-bundle.md +2 -106
- package/prompts/collaboration-workflow/file-edits.md +6 -53
- package/prompts/collaboration-workflow/issue-template.md +4 -4
- package/prompts/collaboration-workflow/operating-rules.md +18 -75
- package/prompts/collaboration-workflow/principles.md +74 -0
- package/prompts/collaboration-workflow/residency.md +55 -15
- package/prompts/collaboration-workflow/rule-delivery.md +5 -46
- package/prompts/collaboration-workflow/shell-body.md +7 -9
- package/prompts/collaboration-workflow/turn-batching.md +21 -37
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +15 -18
- package/prompts/collaboration-workflow.md +22 -28
- package/prompts/sonar-hotspot-handling.md +1 -1
- package/scripts/adopt/adopt-logic.ts +2 -2
- package/scripts/adopt/adopt-toolkits.ts +3 -1
- package/scripts/adopt/adopt.ts +2 -2
- package/scripts/agent/agent-event.ts +2 -9
- package/scripts/agent/agent-exit-record.ts +2 -9
- package/scripts/auto-ok/auto-ok-cli.ts +9 -9
- package/scripts/backlog/backlog-budget-cli.ts +2 -6
- package/scripts/backlog/backlog-drive-cli.ts +20 -10
- package/scripts/backlog/backlog-drive.ts +50 -16
- package/scripts/backlog/backlog-next.ts +24 -8
- package/scripts/backlog/backlog-offer-cli.ts +6 -5
- package/scripts/backlog/backlog-plan-cli.ts +5 -1
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +31 -11
- package/scripts/backlog/backlog-rank.ts +106 -0
- package/scripts/backlog/backlog-waves.ts +42 -29
- package/scripts/build/build-bin.ts +2 -1
- package/scripts/build/build-config-merge.ts +2 -1
- package/scripts/build/build-hooks.ts +31 -6
- package/scripts/build/build-managed-marker.ts +2 -1
- package/scripts/build/build-self-sync-guard.ts +2 -1
- package/scripts/build/build-version.ts +2 -1
- package/scripts/cases/cases-logic.ts +2 -6
- package/scripts/ci/pr-classification.ts +13 -11
- package/scripts/cost-runtime/cost-transcript.ts +4 -11
- package/scripts/delegation/delegation-policy.ts +11 -0
- package/scripts/doctor/doctor-consumer.ts +5 -12
- package/scripts/doctor/doctor-ports.ts +2 -2
- package/scripts/document/document-byte-budget.ts +13 -21
- package/scripts/document/document-section.ts +2 -6
- package/scripts/document/entry-read-budget.ts +6 -5
- package/scripts/{git/git-epic-add-body.ts → epic/epic-add-body.ts} +23 -23
- package/scripts/{git/git-epic-add-plan.ts → epic/epic-add-plan.ts} +23 -26
- package/scripts/{git/git-epic-add.ts → epic/epic-add.ts} +17 -17
- package/scripts/epic/epic-audit-cli.ts +4 -4
- package/scripts/epic/epic-audit-orphans.ts +2 -2
- package/scripts/epic/epic-audit-rationale.ts +1 -1
- package/scripts/epic/epic-audit.ts +1 -1
- package/scripts/{git/git-epic-body.ts → epic/epic-body.ts} +6 -6
- package/scripts/epic/epic-bundle-cli.ts +1 -1
- package/scripts/epic/epic-bundle.ts +2 -2
- package/scripts/epic/epic-candidate-confirm.ts +2 -1
- package/scripts/{git/git-epic-chains.ts → epic/epic-chains.ts} +4 -4
- package/{scripts-ai → scripts/epic}/epic-check.ts +5 -4
- package/{scripts-ai → scripts/epic}/epic-cli.ts +4 -4
- package/scripts/{git/git-epic-close-comment.ts → epic/epic-close-comment.ts} +9 -9
- package/scripts/{git/git-epic-close.ts → epic/epic-close.ts} +23 -19
- package/scripts/epic/epic-cross-repo.ts +21 -38
- package/scripts/{git/git-epic-decision.ts → epic/epic-decision.ts} +12 -14
- package/scripts/epic/epic-fetch.ts +3 -3
- package/scripts/epic/epic-graph.ts +3 -3
- package/scripts/epic/epic-index.ts +2 -2
- package/scripts/epic/epic-issue.ts +1 -1
- package/scripts/epic/epic-lane-offer.ts +11 -22
- package/scripts/epic/epic-next.ts +3 -3
- package/scripts/{git/git-epic-parse.ts → epic/epic-parse.ts} +3 -3
- package/scripts/{git/git-epic-promote.ts → epic/epic-promote.ts} +10 -10
- package/scripts/epic/epic-rank.ts +37 -0
- package/scripts/{git/git-epic-read.ts → epic/epic-read.ts} +9 -9
- package/scripts/{git/git-epic-reconcile.ts → epic/epic-reconcile.ts} +18 -20
- package/scripts/{git/git-epic-reference.ts → epic/epic-reference.ts} +4 -23
- package/scripts/epic/epic-relation-recheck.ts +4 -3
- package/scripts/{git/git-epic-relations.ts → epic/epic-relations.ts} +5 -5
- package/scripts/{git/git-epic-remove-plan.ts → epic/epic-remove-plan.ts} +17 -19
- package/scripts/{git/git-epic-remove.ts → epic/epic-remove.ts} +13 -13
- package/scripts/{git/git-epic-run.ts → epic/epic-run.ts} +27 -27
- package/scripts/{git/git-epic-sections.ts → epic/epic-sections.ts} +6 -6
- package/scripts/{git/git-epic-shape.ts → epic/epic-shape.ts} +7 -7
- package/scripts/epic/epic-solo.ts +29 -28
- package/scripts/{git/git-epic-validate.ts → epic/epic-validate.ts} +13 -13
- package/{scripts-ai → scripts/epic}/epic.ts +17 -16
- package/scripts/gh/fix-gh-packages.ts +2 -1
- package/scripts/gh/gh-spawn.ts +12 -10
- package/scripts/git/constants.ts +1 -1
- package/scripts/git/git-branch.ts +10 -1
- package/scripts/git/git-command.ts +2 -2
- package/scripts/git/git-error.ts +2 -5
- package/scripts/git/git-execa-error.ts +6 -1
- package/{scripts-ai → scripts/git}/git-followup-finish.ts +7 -7
- package/scripts/git/git-followup-flush.ts +74 -48
- package/scripts/git/git-followup-issue-close.ts +2 -2
- package/scripts/git/git-followup-label.ts +1 -1
- package/scripts/git/git-followup-pending.ts +1 -1
- package/{scripts-ai → scripts/git}/git-followup-workflow.ts +23 -11
- package/scripts/git/git-gh-exec.ts +85 -26
- package/scripts/git/git-gh-issue-read.ts +2 -2
- package/scripts/git/git-gh-issue-rest.ts +2 -2
- package/scripts/git/git-gh-issue-write.ts +6 -6
- package/scripts/git/git-gh-pr-read.ts +0 -21
- package/scripts/git/git-gh-pr.ts +2 -23
- package/scripts/git/git-next-issues.ts +34 -5
- package/scripts/git/git-pr-followup-wrapup.ts +2 -6
- package/scripts/git/git-preflight.ts +25 -10
- package/scripts/git/git-push-transport.ts +12 -69
- package/scripts/git/git-spawn.ts +79 -3
- package/scripts/git/git-ssh-keepalive.ts +74 -0
- package/scripts/git/git-staging.ts +21 -9
- package/{scripts-ai → scripts/git}/git-workflow.ts +11 -11
- package/scripts/git/github-issue-url.ts +1 -1
- package/scripts/git/gone-branch.ts +3 -2
- package/scripts/git/issue-labels.ts +13 -1
- package/scripts/git/issue-rank.ts +89 -0
- package/scripts/git/issue-reference.ts +19 -0
- package/scripts/git/main-merge.ts +2 -1
- package/scripts/git/main-sync.ts +3 -2
- package/scripts/git/schemas.ts +1 -1
- package/scripts/git/stash-pop-args.ts +7 -13
- package/scripts/git/stash-pop-cli.ts +2 -1
- package/{scripts-ai → scripts/git}/telegram-test-logic.ts +2 -2
- package/{scripts-ai → scripts/git}/telegram-test.ts +7 -7
- package/scripts/hooks/format-edited-cli.ts +15 -0
- package/scripts/hooks/format-edited-file.ts +2 -9
- package/scripts/hooks/format-rewrite-notice.ts +2 -8
- package/scripts/hooks/pretool-guard-cli.ts +21 -0
- package/scripts/hooks/pretool-guard.ts +14 -15
- package/scripts/init/init-ai-copy.ts +2 -5
- package/scripts/init/init.ts +8 -4
- package/scripts/init/start-exec.ts +7 -1
- package/scripts/init/start-plan.ts +18 -5
- package/scripts/init/start-setup-pr.ts +46 -19
- package/scripts/init/start-steps.ts +43 -10
- package/scripts/init/start.ts +42 -11
- package/scripts/issue/issue-cite.ts +19 -1
- package/scripts/issue/issue-comment-cli.ts +2 -1
- package/scripts/issue/issue-file-cli.ts +2 -1
- package/scripts/issue/issue-fold-cli.ts +9 -16
- package/scripts/issue/issue-scout-cli.ts +8 -13
- package/scripts/issue/measure-rerun-cli.ts +7 -6
- package/scripts/josh/josh-command-map.ts +0 -102
- package/scripts/josh/josh-commands-ai.ts +2 -2
- package/scripts/josh/josh-commands-backlog.ts +1 -1
- package/scripts/josh/josh-commands-development.ts +3 -3
- package/scripts/josh/josh-commands-project.ts +1 -1
- package/scripts/josh/josh-commands-workflow.ts +4 -4
- package/scripts/lane/lane-child-marker.ts +16 -2
- package/scripts/lane/lane-cli.ts +34 -15
- package/scripts/lane/lane-open.ts +3 -2
- package/scripts/lane/lane-registry.ts +3 -6
- package/scripts/lane/lane-report.ts +10 -4
- package/scripts/lib/cli-flags.ts +20 -2
- package/scripts/lib/error-message.ts +9 -0
- package/scripts/lib/read-file.ts +26 -2
- package/scripts/observations/observation-ledger-home.ts +98 -26
- package/scripts/observations/observation-ledger-migrate.ts +26 -21
- package/scripts/observations/observation-ledger-prepare.ts +10 -20
- package/scripts/observations/observation-ledger.ts +58 -25
- package/scripts/observations/observations-flush-cli.ts +6 -23
- package/scripts/observations/observations-flush-landing.ts +2 -1
- package/scripts/observations/observations-flush.ts +29 -20
- package/scripts/package/package-scout-cli.ts +8 -16
- package/scripts/ports/port-command.ts +2 -1
- package/scripts/propagate/propagate-plan.ts +185 -0
- package/scripts/propagate/propagate-publish.ts +6 -7
- package/scripts/propagate/propagate-run.ts +5 -1
- package/scripts/propagate/propagate-steps.ts +18 -2
- package/scripts/propagate/propagate-targets.ts +13 -2
- package/scripts/propagate/propagate.ts +63 -44
- package/scripts/refactor/import-graph.ts +2 -6
- package/scripts/registry-migration/migrate-logic.ts +1 -0
- package/scripts/registry-migration/migrate.ts +3 -2
- package/scripts/registry-migration/user-npmrc.ts +2 -2
- package/scripts/release/github-release.ts +1 -1
- package/scripts/release/release-cli.ts +2 -1
- package/scripts/repo/repo-setting.ts +10 -8
- package/scripts/review/review-attest.ts +44 -0
- package/scripts/review/review-brief-cli.ts +49 -2
- package/scripts/review/review-brief.ts +46 -1
- package/scripts/review/review-finding-ledger.ts +3 -3
- package/scripts/review/review-findings-cli.ts +4 -11
- package/scripts/review/review-record-cli.ts +14 -11
- package/scripts/review/review-record.ts +6 -16
- package/scripts/review/review-stamps.ts +7 -0
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/implementation-cut.ts +1 -1
- package/scripts/rules/issue-fold.ts +1 -2
- package/scripts/rules/lane-carry-conflict.ts +1 -2
- package/scripts/rules/lane-park.ts +1 -2
- package/scripts/rules/pre-gate-cut.ts +2 -2
- package/scripts/rules/rule-body-guard.ts +2 -2
- package/scripts/rules/rule-value-cache.ts +99 -0
- package/scripts/rules/rule-value-cli.ts +10 -9
- package/scripts/rules/rule-value.ts +1 -1
- package/scripts/run/run-carry-args.ts +2 -6
- package/scripts/run/run-carry-cli.ts +5 -7
- package/scripts/run/run-cut-args.ts +7 -13
- package/scripts/run/run-ending-cli.ts +4 -7
- package/scripts/run/run-event-stream.ts +2 -5
- package/scripts/run/run-headless.ts +22 -6
- package/scripts/run/run-liveness-cli.ts +4 -7
- package/scripts/run/run-parent-cut-hook.ts +144 -0
- package/scripts/run/run-progress-args.ts +2 -6
- package/scripts/run/run-progress-cli.ts +2 -1
- package/scripts/run/run-progress-read.ts +2 -1
- package/scripts/run/run-progress.ts +21 -8
- package/scripts/run/run-ship-cli.ts +6 -74
- package/scripts/run/run-ship-preflight.ts +87 -0
- package/scripts/run/run-ship-review-steps.ts +5 -26
- package/scripts/run/run-ship-review.ts +9 -0
- package/scripts/run/run-ship-scoped.ts +44 -0
- package/scripts/run/run-ship-stage.ts +5 -1
- package/scripts/run/run-ship-steps.ts +105 -0
- package/scripts/run/run-ship.ts +2 -0
- package/scripts/run/run-tail-cli.ts +3 -3
- package/scripts/run/run-tidy-stashes.ts +7 -14
- package/scripts/run/run-wake-cli.ts +4 -8
- package/scripts/run/run-wake-describe.ts +19 -1
- package/scripts/run/run-wake-driver.ts +15 -2
- package/scripts/run/run-wake-session.ts +14 -4
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/project-config.ts +3 -6
- package/scripts/security/security-audit-provision.ts +6 -7
- package/scripts/sonar/sonar-hotspots-cli.ts +2 -1
- package/scripts/sync/directory-copy-guard.ts +2 -1
- package/scripts/sync/sync-ai-files.ts +3 -3
- package/scripts/sync/template-source-logic.ts +3 -4
- package/scripts/test/e2e-retry-check.ts +3 -6
- package/scripts/time-runtime/time-bundle-call.ts +2 -2
- package/scripts/ui/ui-routes-cli.ts +3 -6
- package/scripts/version/bump-version.ts +2 -1
- package/scripts/version/npm-registry.ts +97 -0
- package/scripts/version/version-commands.ts +5 -4
- package/scripts/version/version-remote.ts +38 -33
- package/scripts/version/version-targets.ts +3 -3
- package/.claude/skills/workflow-commands/rule-residency.md +0 -267
- package/evals/scenarios/consult-not-execute.json +0 -20
- package/evals/scenarios/no-implicit-workflow.json +0 -26
- package/evals/scenarios/overrides-both-locations.json +0 -29
- package/evals/scenarios/upstream-interrupt.json +0 -23
- package/evals/scenarios/workflow-skill-loaded.json +0 -16
- package/prompts/agent-lint-protocol.json +0 -79
- package/prompts/agent-rules.md +0 -63
- package/prompts/collaboration-workflow/consultation-vs-execution.md +0 -8
- package/prompts/collaboration-workflow/distributed-docs.md +0 -7
- package/prompts/collaboration-workflow/durable-rules.md +0 -24
- package/prompts/collaboration-workflow/latest-first.md +0 -14
- package/prompts/collaboration-workflow/no-clones.md +0 -11
- package/prompts/collaboration-workflow/simplicity-first.md +0 -9
- package/prompts/collaboration-workflow/single-source-rules.md +0 -13
- package/scripts/build/shim-shell.ts +0 -25
- package/scripts/claude/skill-meta.ts +0 -37
- package/scripts/document/document-scan.ts +0 -108
- package/scripts/document/generate-catalog.ts +0 -69
- package/scripts/document/retired-phrases.ts +0 -143
- package/scripts/document/review-agent-type.ts +0 -46
- package/scripts/document/single-source.ts +0 -73
- package/scripts/git/git-fixture-workspace.ts +0 -88
- package/scripts/hooks/format-edited-file-fixtures.ts +0 -109
- package/scripts/hooks/prompt-hooks.ts +0 -38
- package/scripts/init/hook-command-bootstrap.ts +0 -83
- package/scripts/issue/issue-logic.ts +0 -50
- package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +0 -1227
- package/scripts/josh/josh-script-reader.ts +0 -11
- package/scripts/package/production-dependency-graph.ts +0 -68
- package/scripts/retrospective/retrospective-cli.ts +0 -97
- package/scripts/retrospective/retrospective.ts +0 -127
- package/scripts/rules/delivered-rules-harness.ts +0 -72
- package/scripts/rules/top-level-scripts-guard.ts +0 -47
- package/scripts/run/run-carry-flush.ts +0 -58
- package/scripts/run/run-transcript.golden.txt +0 -57
- package/scripts/run/run-wake-work.ts +0 -108
- package/scripts/sync/dependabot-pin-logic.ts +0 -135
- package/scripts/test/classify-isolation.ts +0 -149
- package/scripts/test/http-fault-injection.ts +0 -79
- package/scripts/test/josh-harness-environment.ts +0 -260
- package/scripts/test/josh-harness.ts +0 -96
- package/scripts/test/pilot-files.ts +0 -452
- package/scripts/test/pilot-measure.ts +0 -78
- package/scripts/test/test-network-guard.ts +0 -453
- package/scripts/test/test-repository-guard.ts +0 -317
- package/scripts/test/test-state-guard.ts +0 -85
- package/scripts/test/test-stdout-guard.ts +0 -54
- package/scripts/test/test-telegram-guard.ts +0 -90
- package/scripts/test/unit-guard-environment.ts +0 -12
- package/scripts/test/unit-projects.ts +0 -139
- package/scripts/test/vitest-include-globs.ts +0 -12
- package/scripts/time-runtime/time-batch-guard-fixtures.ts +0 -66
- package/scripts-ai/completion-gate.ts +0 -13
- package/scripts-ai/environment-loader.ts +0 -9
- /package/{scripts-ai → scripts/epic}/epic-cli-argv.ts +0 -0
- /package/{scripts-ai → scripts/epic}/epic-cli-remove.ts +0 -0
- /package/{scripts-ai → scripts/git}/followup-issue-number.ts +0 -0
|
@@ -19,6 +19,11 @@ const RUN_SOLO_LABEL = 'run:solo'
|
|
|
19
19
|
// (joshuafolkken/kit#2779). Without it an issue lacking `run:solo` could mean "judged parallel" or
|
|
20
20
|
// "never judged", and `backlog:next` withholds the second (`epic-triage.ts`).
|
|
21
21
|
const RUN_LANE_LABEL = 'run:lane'
|
|
22
|
+
// Puts an issue at the head of the backlog's ranking (joshuafolkken/kit#2928). A person or a run may
|
|
23
|
+
// apply it — a run only where it can cite a deadline or a stated urgency, or a policy a person wrote
|
|
24
|
+
// (`backlogrun-steps.md`) — and **only a person removes it**: a run that could clear it could undo
|
|
25
|
+
// the person's ordering. Read by `issue-rank.ts`, the one place the ranking keys are decided.
|
|
26
|
+
const PRIORITY_HIGH_LABEL = 'priority:high'
|
|
22
27
|
// Opts one issue outside any epic into unattended execution (joshuafolkken/kit#906). **Only a
|
|
23
28
|
// person applies it.** `epicrun #<E>` approves the merges inside `#<E>`; this label is the only way
|
|
24
29
|
// a person extends that approval past the epic's edge, so a label an AI could apply to itself would
|
|
@@ -212,6 +217,11 @@ const WORKFLOW_LABELS: ReadonlyArray<LabelDefinition> = [
|
|
|
212
217
|
color: '0e8a16',
|
|
213
218
|
description: 'Judged safe to run beside others in a backlogrun',
|
|
214
219
|
},
|
|
220
|
+
{
|
|
221
|
+
name: PRIORITY_HIGH_LABEL,
|
|
222
|
+
color: 'e99695',
|
|
223
|
+
description: 'Offered first in a backlogrun; only a person removes it',
|
|
224
|
+
},
|
|
215
225
|
...FILING_ROUTE_LABELS,
|
|
216
226
|
...DEPTH_LABELS,
|
|
217
227
|
]
|
|
@@ -282,7 +292,7 @@ function label_name_of(labels: ReadonlyArray<string>, wanted: string): string |
|
|
|
282
292
|
|
|
283
293
|
// The same comparison for a caller holding label *names* rather than listing rows. `EpicChild.labels`
|
|
284
294
|
// is an array of strings (`scripts/epic/epic-graph.ts`), which is the one shape `has_any_label` cannot
|
|
285
|
-
// take — so `epic-classify.ts` and `
|
|
295
|
+
// take — so `epic-classify.ts` and `epic-validate.ts` each grew a raw case-sensitive
|
|
286
296
|
// `Array.includes` instead, and an `Epic`-cased label walked past both. Kept here beside the rule it
|
|
287
297
|
// implements rather than at either call site, for the reason the comment above gives.
|
|
288
298
|
//
|
|
@@ -322,6 +332,7 @@ const ALL_LABELS: ReadonlySet<string> = new Set([
|
|
|
322
332
|
AUTO_OK_LABEL,
|
|
323
333
|
NEEDS_HUMAN_REVIEW_LABEL,
|
|
324
334
|
ALREADY_DONE_LABEL,
|
|
335
|
+
PRIORITY_HIGH_LABEL,
|
|
325
336
|
INTERRUPT_ROUTE_LABEL,
|
|
326
337
|
REVIEW_CAP_ROUTE_LABEL,
|
|
327
338
|
REVIEW_ROUND2_SKIPPED_LABEL,
|
|
@@ -364,6 +375,7 @@ export {
|
|
|
364
375
|
NEEDS_HUMAN_REVIEW_LABEL,
|
|
365
376
|
NOT_DIRECTLY_RUNNABLE_LABELS,
|
|
366
377
|
OTHER_CHANGE_LABEL,
|
|
378
|
+
PRIORITY_HIGH_LABEL,
|
|
367
379
|
RELEASE_CLASSIFICATION_LABELS,
|
|
368
380
|
RELEASE_CLASSIFICATION_NAMES,
|
|
369
381
|
REPOSITORY_LABELS,
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BUG_LABEL,
|
|
3
|
+
has_label_name,
|
|
4
|
+
INTERRUPT_ROUTE_LABEL,
|
|
5
|
+
PRIORITY_HIGH_LABEL,
|
|
6
|
+
RUN_SOLO_LABEL,
|
|
7
|
+
} from './issue-labels'
|
|
8
|
+
|
|
9
|
+
// The keys that decide which open issue is offered first (joshuafolkken/kit#2928), defined once for
|
|
10
|
+
// every ranking that asks: the `🗒 Next issues` display, the `auto-ok` pickup and `backlog:next`.
|
|
11
|
+
//
|
|
12
|
+
// In order: `priority:high`, then a defect on the verification path (`bug` with `run:solo`, or
|
|
13
|
+
// `route:interrupt`), then how many other open issues wait on it. Below those, the caller's own order
|
|
14
|
+
// stands — the sort is stable, so recency and the defect-rate adjustment survive as the last key.
|
|
15
|
+
//
|
|
16
|
+
// **`run:solo` alone is not a key.** It means "runs alone", not "runs first": tidying that only touches
|
|
17
|
+
// the verification path carries it too, and a low-priority one is not owed a place ahead of the queue.
|
|
18
|
+
// Only a defect on that path is, because `wip-cap.md` holds a batch until it has merged.
|
|
19
|
+
|
|
20
|
+
interface RankRow {
|
|
21
|
+
labels: ReadonlyArray<string>
|
|
22
|
+
dependents: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// One open issue as its key and the keys of the issues it is blocked by. The caller names the key
|
|
26
|
+
// format, so a ranking over listing rows and one over graph children each count in their own terms.
|
|
27
|
+
interface DependencyRow {
|
|
28
|
+
key: string
|
|
29
|
+
blockers: ReadonlyArray<string>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const NO_DEPENDENTS = 0
|
|
33
|
+
|
|
34
|
+
function flag(is_set: boolean): number {
|
|
35
|
+
return is_set ? 1 : 0
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function is_priority(labels: ReadonlyArray<string>): boolean {
|
|
39
|
+
return has_label_name(labels, PRIORITY_HIGH_LABEL)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function is_verification_defect(labels: ReadonlyArray<string>): boolean {
|
|
43
|
+
if (has_label_name(labels, INTERRUPT_ROUTE_LABEL)) return true
|
|
44
|
+
|
|
45
|
+
return has_label_name(labels, BUG_LABEL) && has_label_name(labels, RUN_SOLO_LABEL)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Negated so that the larger value sorts first under an ascending comparison.
|
|
49
|
+
function keys_of(row: RankRow): ReadonlyArray<number> {
|
|
50
|
+
return [
|
|
51
|
+
-flag(is_priority(row.labels)),
|
|
52
|
+
-flag(is_verification_defect(row.labels)),
|
|
53
|
+
-row.dependents,
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function compare(first: RankRow, second: RankRow): number {
|
|
58
|
+
const second_keys = keys_of(second)
|
|
59
|
+
const differences = keys_of(first).map((key, index) => key - (second_keys[index] ?? 0))
|
|
60
|
+
|
|
61
|
+
return differences.find((difference) => difference !== 0) ?? 0
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// How many of the rows wait on each key. A blocker outside the rows counts nothing, because only an
|
|
65
|
+
// open issue in the same pool can be held back by it.
|
|
66
|
+
function count_dependents(rows: ReadonlyArray<DependencyRow>): ReadonlyMap<string, number> {
|
|
67
|
+
const counts = new Map<string, number>()
|
|
68
|
+
|
|
69
|
+
for (const row of rows) {
|
|
70
|
+
const blockers = new Set(row.blockers)
|
|
71
|
+
|
|
72
|
+
for (const blocker of blockers) counts.set(blocker, (counts.get(blocker) ?? NO_DEPENDENTS) + 1)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return counts
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// The items in rank order, ties kept in the order they arrived.
|
|
79
|
+
function rank<T>(items: ReadonlyArray<T>, row_of: (item: T) => RankRow): Array<T> {
|
|
80
|
+
return items
|
|
81
|
+
.map((item) => ({ item, row: row_of(item) }))
|
|
82
|
+
.toSorted((first, second) => compare(first.row, second.row))
|
|
83
|
+
.map((entry) => entry.item)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const issue_rank = { compare, count_dependents, is_priority, is_verification_defect, rank }
|
|
87
|
+
|
|
88
|
+
export { issue_rank }
|
|
89
|
+
export type { DependencyRow, RankRow }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// An issue named from outside any one graph — a task-list row, a citation in prose, a blocker
|
|
2
|
+
// relation, a child that could not be read. Repository **and** number, because a number alone cannot
|
|
3
|
+
// identify one: issue numbers are unique per repository, so the same `#40` names two different issues
|
|
4
|
+
// depending on who wrote it (joshuafolkken/kit#1014).
|
|
5
|
+
//
|
|
6
|
+
// It lives in the git layer because the `blocked-by` relations are read here and carry a repository
|
|
7
|
+
// of their own (joshuafolkken/kit#1126); the epic domain builds on this layer, never the other way
|
|
8
|
+
// round (joshuafolkken/kit#2904). `epic-reference` re-exports it, so every epic importer is unchanged.
|
|
9
|
+
//
|
|
10
|
+
// `state` is present only on a reference read from a `blocked-by` relation whose response carried it
|
|
11
|
+
// (joshuafolkken/kit#1943). The classifier needs it for a blocker no named graph tracks, where there is
|
|
12
|
+
// no child record to read the state from; every other reference leaves it out.
|
|
13
|
+
interface IssueReference {
|
|
14
|
+
repo: string
|
|
15
|
+
number: number
|
|
16
|
+
state?: 'OPEN' | 'CLOSED'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type { IssueReference }
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
3
|
import { extract_issue_number } from '#scripts/hooks/check-commit-message'
|
|
4
4
|
import { composite_arguments, USAGE_ERROR_EXIT_CODE } from '#scripts/josh/josh-composite-arguments'
|
|
5
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
5
6
|
import { git_command } from './git-command'
|
|
6
7
|
import { main_merge_guard } from './main-merge-guard'
|
|
7
8
|
|
|
@@ -103,7 +104,7 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
103
104
|
try {
|
|
104
105
|
return await dispatch(argv)
|
|
105
106
|
} catch (error) {
|
|
106
|
-
console.error(
|
|
107
|
+
console.error(error_text.message_of(error))
|
|
107
108
|
|
|
108
109
|
return FAILURE_EXIT_CODE
|
|
109
110
|
}
|
package/scripts/git/main-sync.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
3
|
import { composite_arguments, USAGE_ERROR_EXIT_CODE } from '#scripts/josh/josh-composite-arguments'
|
|
4
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
4
5
|
import { git_command } from './git-command'
|
|
5
6
|
import { gone_branch, type PruneResult } from './gone-branch'
|
|
6
7
|
|
|
@@ -65,7 +66,7 @@ async function prune_quietly(default_branch: string): Promise<void> {
|
|
|
65
66
|
try {
|
|
66
67
|
report_prune(await gone_branch.prune(default_branch))
|
|
67
68
|
} catch (error) {
|
|
68
|
-
console.error(`branch prune skipped: ${
|
|
69
|
+
console.error(`branch prune skipped: ${error_text.message_of(error)}`)
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -104,7 +105,7 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
104
105
|
try {
|
|
105
106
|
return await dispatch(argv)
|
|
106
107
|
} catch (error) {
|
|
107
|
-
console.error(
|
|
108
|
+
console.error(error_text.message_of(error))
|
|
108
109
|
|
|
109
110
|
return FAILURE_EXIT_CODE
|
|
110
111
|
}
|
package/scripts/git/schemas.ts
CHANGED
|
@@ -111,7 +111,7 @@ const rest_comment_schema = z.looseObject({
|
|
|
111
111
|
// Labels come back as objects, so the name is picked out here rather than at every call site.
|
|
112
112
|
const issue_label_schema = z.object({ name: z.string() })
|
|
113
113
|
|
|
114
|
-
// `state` is optional because most readers ignore it — only `
|
|
114
|
+
// `state` is optional because most readers ignore it — only `epic-add.ts` consults it, to refuse
|
|
115
115
|
// adding a child to a closed epic (joshuafolkken/kit#2337). A reader that never asks the state field
|
|
116
116
|
// still parses cleanly.
|
|
117
117
|
const epic_subject_schema = z.object({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
2
2
|
|
|
3
3
|
// `josh stash:pop` turns its `argv` into a single request: the message of the stash to pop. Parsing
|
|
4
4
|
// lives here, acting on the stack lives in `stash-pop-cli.ts`, and a malformed command line is
|
|
@@ -21,18 +21,12 @@ interface Request {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function read_arguments(argv: ReadonlyArray<string>): ParsedValues | undefined {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
return { values: parsed.values, positionals: parsed.positionals }
|
|
33
|
-
} catch {
|
|
34
|
-
return undefined
|
|
35
|
-
}
|
|
24
|
+
return cli_flags.parse_or_undefined({
|
|
25
|
+
args: [...argv],
|
|
26
|
+
options: OPTIONS,
|
|
27
|
+
strict: true,
|
|
28
|
+
allowPositionals: true,
|
|
29
|
+
})
|
|
36
30
|
}
|
|
37
31
|
|
|
38
32
|
// The message is the sole positional and must be a non-empty string: an empty message matches every
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
2
3
|
import { git_stash } from './git-stash'
|
|
3
4
|
import { stash_pop_args, type Request } from './stash-pop-args'
|
|
4
5
|
|
|
@@ -66,7 +67,7 @@ async function answer(request: Request): Promise<number> {
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
function report_unknown(error: unknown): number {
|
|
69
|
-
console.error(
|
|
70
|
+
console.error(error_text.message_of(error))
|
|
70
71
|
|
|
71
72
|
return FAILURE_EXIT_CODE
|
|
72
73
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { cli_body } from '#scripts/josh/cli-body'
|
|
2
|
+
import type { TelegramSendInput, TelegramTaskType } from './telegram-notify'
|
|
3
3
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
5
5
|
interface CliValues {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
3
|
import { parseArgs } from 'node:util'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { josh_environment_file } from '#scripts/josh/josh-environment-file'
|
|
5
|
+
import { git_error } from './git-error'
|
|
6
|
+
import { git_gh_issue_read } from './git-gh-issue-read'
|
|
7
|
+
import { git_gh_repo } from './git-gh-repo'
|
|
8
|
+
import { github_issue_url, type IssueUrlTarget } from './github-issue-url'
|
|
9
|
+
import { telegram_notify } from './telegram-notify'
|
|
10
10
|
import { telegram_test_logic, type CliValues, type ResolvedContext } from './telegram-test-logic'
|
|
11
11
|
|
|
12
12
|
const REPO_NAME_SEPARATOR = '/'
|
|
@@ -97,7 +97,7 @@ async function resolve_context(values: CliValues): Promise<ResolvedContext> {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
async function main(): Promise<void> {
|
|
100
|
-
|
|
100
|
+
josh_environment_file.load_environment_file()
|
|
101
101
|
const values = parse_cli_arguments()
|
|
102
102
|
const context = await resolve_context(values)
|
|
103
103
|
const input = telegram_test_logic.build_input({ values, context })
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { text } from 'node:stream/consumers'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { report_no_payload, run_hook } from './format-edited-file'
|
|
5
|
+
|
|
6
|
+
// The `PostToolUse` hook's entry, kept apart from `format-edited-file.ts` for the reason
|
|
7
|
+
// `pretool-guard-cli.ts` gives (joshuafolkken/kit#2922): `codex-hook-adapter.ts` imports that module,
|
|
8
|
+
// so a self-invoke left in it lands in a shared chunk and the bundled hook never runs.
|
|
9
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
10
|
+
if (process.stdin.isTTY) {
|
|
11
|
+
report_no_payload()
|
|
12
|
+
} else {
|
|
13
|
+
await run_hook(await text(process.stdin))
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { existsSync } from 'node:fs'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import { text } from 'node:stream/consumers'
|
|
5
4
|
import { fileURLToPath } from 'node:url'
|
|
6
5
|
import { resolve_local_bin, resolve_package_bin } from '#scripts/build/local-bin'
|
|
7
6
|
import { ESLINT_EDIT_CACHE_FLAGS } from '#scripts/josh/josh-command-types'
|
|
@@ -482,14 +481,6 @@ async function run_hook(payload: string): Promise<void> {
|
|
|
482
481
|
if (context !== undefined) process.stdout.write(`${build_envelope(context)}\n`)
|
|
483
482
|
}
|
|
484
483
|
|
|
485
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
486
|
-
if (process.stdin.isTTY) {
|
|
487
|
-
report_no_payload()
|
|
488
|
-
} else {
|
|
489
|
-
await run_hook(await text(process.stdin))
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
484
|
export {
|
|
494
485
|
build_envelope,
|
|
495
486
|
compose_context,
|
|
@@ -501,7 +492,9 @@ export {
|
|
|
501
492
|
plan_commands,
|
|
502
493
|
plan_daemon_restart,
|
|
503
494
|
relative_to_root,
|
|
495
|
+
report_no_payload,
|
|
504
496
|
resolve_invocations,
|
|
497
|
+
run_hook,
|
|
505
498
|
select_invocation,
|
|
506
499
|
ESLINT_DAEMON,
|
|
507
500
|
MAX_DIAGNOSTIC_CHARS,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { file_reader } from '#scripts/lib/read-file'
|
|
2
2
|
|
|
3
3
|
// The rewrite half of the edit hook (joshuafolkken/kit#2314). The format hook runs prettier and
|
|
4
4
|
// `eslint --fix` in place after every edit, so a file the model just wrote can be rewritten out from
|
|
@@ -85,13 +85,7 @@ function build(before: string, after: string): string | undefined {
|
|
|
85
85
|
// handed nothing for, or one gone by the time it reads, compares as an empty string rather than
|
|
86
86
|
// throwing — the hook runs after the write already succeeded and must never turn it into a failure.
|
|
87
87
|
function read_text(file_path: string | undefined): string {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
return readFileSync(file_path, 'utf8')
|
|
92
|
-
} catch {
|
|
93
|
-
return ''
|
|
94
|
-
}
|
|
88
|
+
return file_path === undefined ? '' : (file_reader.read_if_readable(file_path) ?? '')
|
|
95
89
|
}
|
|
96
90
|
|
|
97
91
|
const rewrite_notice = { build, read_text }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { text } from 'node:stream/consumers'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
5
|
+
import { pretool_outcome_async } from './pretool-guard'
|
|
6
|
+
|
|
7
|
+
// The `PreToolUse` hook's entry, kept apart from the composition in `pretool-guard.ts`
|
|
8
|
+
// (joshuafolkken/kit#2922). The hook bundles are built with `splitting: true`, which moves a module
|
|
9
|
+
// imported by two entries into a shared chunk — and `codex-hook-adapter.ts` imports `pretool-guard.ts`.
|
|
10
|
+
// Its self-invoke went into that chunk, whose `import.meta.url` never equals the launched
|
|
11
|
+
// `dist/hooks/pretool-guard.js`, so the bundled hook ran no guard at all and every refusal failed open.
|
|
12
|
+
// An entry nothing imports keeps the self-invoke in the file that is actually launched.
|
|
13
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
14
|
+
if (process.stdin.isTTY) hook_decision.report_no_payload('pretool:guard')
|
|
15
|
+
else {
|
|
16
|
+
const raw_payload = await text(process.stdin)
|
|
17
|
+
|
|
18
|
+
hook_decision.load_environment_file()
|
|
19
|
+
hook_decision.emit_outcome(await pretool_outcome_async(raw_payload))
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
import { text } from 'node:stream/consumers'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
1
|
import { duplicate_read_outcome } from '#scripts/delegation/duplicate-read-guard'
|
|
5
2
|
import { investigation_refusal } from '#scripts/delegation/investigation-guard'
|
|
6
|
-
import {
|
|
3
|
+
import type { GuardOutcome } from '#scripts/josh/hook-decision'
|
|
7
4
|
import { delivered_rules } from '#scripts/rules/delivered-rules'
|
|
5
|
+
import { run_parent_cut_hook } from '#scripts/run/run-parent-cut-hook'
|
|
8
6
|
import { run_watcher_hook } from '#scripts/run/run-watcher-hook'
|
|
9
7
|
import { batch_outcome } from './batch-guard'
|
|
10
8
|
|
|
@@ -71,26 +69,27 @@ function pretool_outcome(raw_payload: string): GuardOutcome {
|
|
|
71
69
|
// as `combine_outcomes` orders them, and the watcher's refusal fills a clear verdict rather than
|
|
72
70
|
// overriding one. It fires once per run itself (`run-watcher-hook.ts`), so a stale watcher refuses the
|
|
73
71
|
// first call but not the `pnpm josh run:progress --wait` that fixes it.
|
|
72
|
+
//
|
|
73
|
+
// **The parent hand-off guard is the second asynchronous rule, asked after the watcher's**
|
|
74
|
+
// (joshuafolkken/kit#2947). It reads the carry record to tell the `backlogrun` parent apart, so it sits
|
|
75
|
+
// beside the watcher rather than among the synchronous rows; a stale watcher is the cheaper fix and is
|
|
76
|
+
// surfaced first.
|
|
77
|
+
async function async_reason(raw_payload: string): Promise<string | undefined> {
|
|
78
|
+
const watcher = await run_watcher_hook.watcher_hook_reason(raw_payload)
|
|
79
|
+
|
|
80
|
+
return watcher ?? (await run_parent_cut_hook.parent_cut_reason(raw_payload))
|
|
81
|
+
}
|
|
82
|
+
|
|
74
83
|
async function pretool_outcome_async(raw_payload: string): Promise<GuardOutcome> {
|
|
75
84
|
const base = pretool_outcome(raw_payload)
|
|
76
85
|
|
|
77
86
|
if (!is_clear(base)) return base
|
|
78
87
|
|
|
79
|
-
const reason = await
|
|
88
|
+
const reason = await async_reason(raw_payload)
|
|
80
89
|
|
|
81
90
|
return reason === undefined ? base : { reason, notice: undefined, fault: undefined }
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
const pretool_guard = { combine_outcomes, pretool_outcome, pretool_outcome_async }
|
|
85
94
|
|
|
86
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
87
|
-
if (process.stdin.isTTY) hook_decision.report_no_payload('pretool:guard')
|
|
88
|
-
else {
|
|
89
|
-
const raw_payload = await text(process.stdin)
|
|
90
|
-
|
|
91
|
-
hook_decision.load_environment_file()
|
|
92
|
-
hook_decision.emit_outcome(await pretool_outcome_async(raw_payload))
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
95
|
export { pretool_guard, pretool_outcome, pretool_outcome_async }
|
|
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { is_workflow_destination } from '#scripts/claude/workflow-destination'
|
|
4
4
|
import { gh_spawn } from '#scripts/gh/gh-spawn'
|
|
5
|
+
import { file_reader } from '#scripts/lib/read-file'
|
|
5
6
|
import { managed_marker_logic } from '#scripts/managed-marker/managed-marker-logic'
|
|
6
7
|
import {
|
|
7
8
|
classify_path,
|
|
@@ -238,11 +239,7 @@ function did_skip_ai_directory_copy(directory_name: string): boolean {
|
|
|
238
239
|
// moved onto the basic path — only that kit-written line, never the consumer's additions.
|
|
239
240
|
// An unreadable file is left as it is and reported as skipped, as it was before the migration.
|
|
240
241
|
function read_if_readable(destination_path: string): string | undefined {
|
|
241
|
-
|
|
242
|
-
return readFileSync(destination_path, 'utf8')
|
|
243
|
-
} catch {
|
|
244
|
-
return undefined
|
|
245
|
-
}
|
|
242
|
+
return file_reader.read_if_readable(destination_path)
|
|
246
243
|
}
|
|
247
244
|
|
|
248
245
|
function report_existing_claude_md(destination_path: string): void {
|
package/scripts/init/init.ts
CHANGED
|
@@ -4,6 +4,7 @@ import path from 'node:path'
|
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
5
|
import { resolve_local_bin } from '#scripts/build/local-bin'
|
|
6
6
|
import { doctor_io } from '#scripts/doctor/doctor-io'
|
|
7
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
7
8
|
import { package_version_schema, with_package_manager_schema } from '#scripts/lib/schemas'
|
|
8
9
|
import { auto_merge_setting } from '#scripts/repo/auto-merge-setting'
|
|
9
10
|
import { project_config } from '#scripts/safe-chain/project-config'
|
|
@@ -45,8 +46,11 @@ function show_sample(action: FileAction): void {
|
|
|
45
46
|
console.info(action.create().replaceAll(/^/gmu, () => SAMPLE_INDENT))
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
// A file that already holds the sample needs nothing added, so only one that differs gets it shown.
|
|
50
|
+
function report_unchanged(action: FileAction, existing: string): void {
|
|
51
|
+
const is_sample_missing = existing !== action.create()
|
|
52
|
+
|
|
53
|
+
if (is_sample_missing && action.should_show_sample_when_unchanged === true) show_sample(action)
|
|
50
54
|
else console.info(` ✔ unchanged ${action.dest}`)
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -59,7 +63,7 @@ function merge_existing_file(
|
|
|
59
63
|
const merged = merge_function(existing)
|
|
60
64
|
|
|
61
65
|
if (merged === existing) {
|
|
62
|
-
report_unchanged(action)
|
|
66
|
+
report_unchanged(action, existing)
|
|
63
67
|
|
|
64
68
|
return
|
|
65
69
|
}
|
|
@@ -375,7 +379,7 @@ function run_cli(args: ReadonlyArray<string>): void {
|
|
|
375
379
|
try {
|
|
376
380
|
if (main(args)) print_start_hint()
|
|
377
381
|
} catch (error) {
|
|
378
|
-
console.error(`\n✖ ${
|
|
382
|
+
console.error(`\n✖ ${error_text.message_of(error)}\n`)
|
|
379
383
|
process.exitCode = 1
|
|
380
384
|
}
|
|
381
385
|
}
|
|
@@ -23,6 +23,12 @@ function run(command: string, args: ReadonlyArray<string>, root: string): void {
|
|
|
23
23
|
execaSync(command, args, { ...git_gh_exec.direct_environment(), cwd: root, stdio: 'inherit' })
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
// A caller's own initialize command stands in for the in-process `josh init`, so it keeps the
|
|
27
|
+
// environment that setup would have had — its install goes through a scanner's proxy as usual.
|
|
28
|
+
function run_local(command: string, args: ReadonlyArray<string>, root: string): void {
|
|
29
|
+
execaSync(command, args, { cwd: root, stdio: 'inherit' })
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const start_exec = { succeeds, read_output, run, run_local }
|
|
27
33
|
|
|
28
34
|
export { start_exec }
|
|
@@ -8,6 +8,7 @@ interface StartOptions {
|
|
|
8
8
|
is_yes: boolean
|
|
9
9
|
is_github: boolean
|
|
10
10
|
visibility: Visibility
|
|
11
|
+
init_command: string | undefined
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
type StartStep = 'git_init' | 'initialize' | 'commit' | 'repository' | 'labels' | 'setup_pr'
|
|
@@ -137,20 +138,31 @@ function github_consent(
|
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
|
|
141
|
+
// A run whose initialize step was handed to a caller's command names that command wherever the step
|
|
142
|
+
// is printed, so the plan, the progress and a failure all say what actually runs (#2872).
|
|
143
|
+
function step_labels(init_command: string | undefined): Readonly<Record<StartStep, string>> {
|
|
144
|
+
if (init_command === undefined) return STEP_LABELS
|
|
145
|
+
|
|
146
|
+
return { ...STEP_LABELS, initialize: `Initialize with ${init_command}` }
|
|
147
|
+
}
|
|
148
|
+
|
|
140
149
|
// What a failed run prints, so the user can tell how far it got before deciding how to resume.
|
|
141
150
|
function progress_report(
|
|
142
151
|
failed: StartStep,
|
|
143
152
|
completed: ReadonlyArray<StartStep>,
|
|
144
153
|
cause: string,
|
|
154
|
+
labels: Readonly<Record<StartStep, string>> = STEP_LABELS,
|
|
145
155
|
): string {
|
|
146
|
-
const done =
|
|
147
|
-
completed.length === 0 ? 'nothing' : completed.map((step) => STEP_LABELS[step]).join('; ')
|
|
156
|
+
const done = completed.length === 0 ? 'nothing' : completed.map((step) => labels[step]).join('; ')
|
|
148
157
|
|
|
149
|
-
return `josh start stopped at: ${
|
|
158
|
+
return `josh start stopped at: ${labels[failed]}\nCompleted: ${done}\nCause: ${cause}`
|
|
150
159
|
}
|
|
151
160
|
|
|
152
|
-
function plan_summary(
|
|
153
|
-
|
|
161
|
+
function plan_summary(
|
|
162
|
+
steps: ReadonlyArray<StartStep>,
|
|
163
|
+
labels: Readonly<Record<StartStep, string>> = STEP_LABELS,
|
|
164
|
+
): string {
|
|
165
|
+
const lines = steps.map((step, index) => ` ${String(index + 1)}. ${labels[step]}`)
|
|
154
166
|
|
|
155
167
|
return ['josh start will:', ...lines].join('\n')
|
|
156
168
|
}
|
|
@@ -161,6 +173,7 @@ const start_plan = {
|
|
|
161
173
|
github_consent,
|
|
162
174
|
progress_report,
|
|
163
175
|
plan_summary,
|
|
176
|
+
step_labels,
|
|
164
177
|
STEP_LABELS,
|
|
165
178
|
}
|
|
166
179
|
export { start_plan }
|