@pareto4/pp-core 1.11.0 → 1.12.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-plugin/plugin.json +1 -1
- package/README.md +31 -0
- package/agents/pp-code-fixer.md +1 -1
- package/agents/pp-debug-session-manager.md +1 -1
- package/agents/pp-debugger.md +1 -1
- package/agents/pp-executor.md +20 -10
- package/agents/pp-intel-updater.md +1 -1
- package/agents/pp-phase-researcher.md +1 -1
- package/agents/pp-plan-checker.md +5 -5
- package/agents/pp-planner.md +10 -24
- package/agents/pp-project-researcher.md +1 -1
- package/agents/pp-research-synthesizer.md +1 -1
- package/agents/pp-ui-researcher.md +1 -1
- package/agents/pp-verifier.md +8 -4
- package/bin/install.js +429 -82
- package/commands/pp-autonomous.md +8 -6
- package/commands/pp-discovery-to-build.md +1 -1
- package/commands/pp-discovery.md +3 -2
- package/commands/pp-discuss-phase.md +2 -2
- package/commands/pp-execute-phase.md +3 -1
- package/commands/pp-graphify.md +5 -5
- package/commands/pp-import.md +1 -1
- package/commands/pp-map-codebase.md +1 -1
- package/commands/pp-ns-project.md +2 -3
- package/commands/pp-ns-workflow.md +1 -1
- package/commands/pp-plan-phase.md +2 -1
- package/commands/pp-verify-work.md +2 -1
- package/gemini-extension.json +1 -1
- package/hooks/dist/pp-cursor-session-start.js +2 -2
- package/hooks/dist/pp-session-state.sh +1 -1
- package/hooks/dist/pp-statusline.js +21 -2
- package/hooks/pp-cursor-session-start.js +2 -2
- package/hooks/pp-session-state.sh +1 -1
- package/hooks/pp-statusline.js +21 -2
- package/package.json +18 -5
- package/pareto-skills/pp-project-setup/SKILL.md +5 -63
- package/pp-core/bin/detect-build-commands.sh +182 -0
- package/pp-core/bin/lib/capability-registry.cjs +65 -7
- package/pp-core/bin/lib/check-command-router.cjs +79 -38
- package/pp-core/bin/lib/clusters.cjs +2 -3
- package/pp-core/bin/lib/command-aliases.cjs +36 -0
- package/pp-core/bin/lib/command-arg-projection.cjs +99 -1
- package/pp-core/bin/lib/commands.cjs +21 -6
- package/pp-core/bin/lib/compose-bindings.cjs +128 -15
- package/pp-core/bin/lib/config-schema.cjs +16 -0
- package/pp-core/bin/lib/config.cjs +142 -27
- package/pp-core/bin/lib/core-utils.cjs +43 -7
- package/pp-core/bin/lib/discovery-input-check.cjs +218 -0
- package/pp-core/bin/lib/discovery-rebaseline.cjs +1372 -0
- package/pp-core/bin/lib/discovery-research-track.cjs +979 -0
- package/pp-core/bin/lib/discovery-rollup.cjs +476 -0
- package/pp-core/bin/lib/discovery-screens.cjs +1995 -0
- package/pp-core/bin/lib/discovery-sweep.cjs +390 -0
- package/pp-core/bin/lib/discovery-table.cjs +98 -0
- package/pp-core/bin/lib/dispatch-plan.cjs +472 -0
- package/pp-core/bin/lib/frontmatter.cjs +17 -2
- package/pp-core/bin/lib/init-command-router.cjs +8 -5
- package/pp-core/bin/lib/init-contract.cjs +213 -33
- package/pp-core/bin/lib/init-interactive.cjs +20 -1
- package/pp-core/bin/lib/init.cjs +124 -134
- package/pp-core/bin/lib/install-profiles.cjs +5 -0
- package/pp-core/bin/lib/install-run.cjs +536 -0
- package/pp-core/bin/lib/io.cjs +15 -0
- package/pp-core/bin/lib/loop-resolver.cjs +24 -0
- package/pp-core/bin/lib/milestone.cjs +345 -48
- package/pp-core/bin/lib/phase-command-router.cjs +23 -1
- package/pp-core/bin/lib/phase-locator.cjs +15 -6
- package/pp-core/bin/lib/phase-scope.cjs +91 -0
- package/pp-core/bin/lib/phase-tier.cjs +467 -0
- package/pp-core/bin/lib/phase.cjs +247 -21
- package/pp-core/bin/lib/phases-command-router.cjs +2 -0
- package/pp-core/bin/lib/plan-graph.cjs +368 -0
- package/pp-core/bin/lib/planning-workspace.cjs +53 -0
- package/pp-core/bin/lib/platform-bindings.cjs +32 -2
- package/pp-core/bin/lib/profile-output.cjs +11 -3
- package/pp-core/bin/lib/prohibition-enforcement.cjs +112 -0
- package/pp-core/bin/lib/roadmap-parser.cjs +366 -99
- package/pp-core/bin/lib/roadmap.cjs +141 -39
- package/pp-core/bin/lib/runtime-hooks-surface.cjs +1 -1
- package/pp-core/bin/lib/shell-command-projection.cjs +24 -0
- package/pp-core/bin/lib/state-command-router.cjs +82 -13
- package/pp-core/bin/lib/state-document.cjs +124 -7
- package/pp-core/bin/lib/state.cjs +784 -257
- package/pp-core/bin/lib/template.cjs +22 -6
- package/pp-core/bin/lib/vault-command-router.cjs +57 -6
- package/pp-core/bin/lib/vault-practices.cjs +6 -36
- package/pp-core/bin/lib/vault-write-back.cjs +20 -4
- package/pp-core/bin/lib/vault.cjs +555 -23
- package/pp-core/bin/lib/verify.cjs +53 -31
- package/pp-core/bin/lib/workstream.cjs +1 -1
- package/pp-core/bin/lib/worktree-safety.cjs +26 -15
- package/pp-core/bin/portable-timeout.sh +89 -0
- package/pp-core/bin/pp-tools.cjs +158 -8
- package/pp-core/bin/shared/config-defaults.manifest.json +7 -0
- package/pp-core/bin/shared/config-schema.manifest.json +3 -0
- package/pp-core/references/autonomous-best-effort.md +461 -0
- package/pp-core/references/autonomous-lifecycle.md +146 -0
- package/pp-core/references/autonomous-smart-discuss.md +16 -12
- package/pp-core/references/checkpoints.md +1 -1
- package/pp-core/references/discovery-id-conventions.md +202 -0
- package/pp-core/references/discovery-rebaseline.md +254 -0
- package/pp-core/references/discovery-research-track.md +283 -0
- package/pp-core/references/discovery-traceability.md +400 -0
- package/pp-core/references/loop-hook-dispatch.md +7 -0
- package/pp-core/references/mandatory-initial-read.md +1 -1
- package/pp-core/references/planner-gap-closure.md +1 -0
- package/pp-core/references/planner-human-verify-mode.md +1 -1
- package/pp-core/references/planner-load-graph-context.md +1 -1
- package/pp-core/references/planner-plan-graph.md +66 -0
- package/pp-core/references/planner-tdd.md +1 -0
- package/pp-core/references/planning-config.md +8 -0
- package/pp-core/references/sketch-tooling.md +4 -0
- package/pp-core/references/tdd.md +1 -0
- package/pp-core/templates/claude-md.md +1 -1
- package/pp-core/templates/phase-prompt.md +6 -2
- package/pp-core/templates/prototype-review/review.js +303 -0
- package/pp-core/templates/state.md +6 -0
- package/pp-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/pp-core/workflows/add-backlog.md +1 -1
- package/pp-core/workflows/add-phase.md +1 -1
- package/pp-core/workflows/add-tests.md +1 -1
- package/pp-core/workflows/add-todo.md +1 -1
- package/pp-core/workflows/ai-integration-phase.md +2 -2
- package/pp-core/workflows/audit-fix.md +12 -16
- package/pp-core/workflows/audit-milestone.md +1 -1
- package/pp-core/workflows/audit-uat.md +1 -1
- package/pp-core/workflows/autonomous.md +68 -306
- package/pp-core/workflows/check-todos.md +1 -1
- package/pp-core/workflows/cleanup.md +1 -1
- package/pp-core/workflows/code-review-fix.md +1 -1
- package/pp-core/workflows/code-review.md +19 -7
- package/pp-core/workflows/complete-milestone.md +41 -60
- package/pp-core/workflows/debug.md +1 -1
- package/pp-core/workflows/diagnose-issues.md +1 -1
- package/pp-core/workflows/discovery-sprint/gap-analysis.md +140 -0
- package/pp-core/workflows/discovery-sprint/input-package.md +140 -0
- package/pp-core/workflows/discovery-sprint/prefill.md +92 -0
- package/pp-core/workflows/discovery-sprint/prototype.md +257 -0
- package/pp-core/workflows/discovery-sprint/rebaseline.md +276 -0
- package/pp-core/workflows/discovery-sprint/session-13-gates.md +24 -0
- package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +92 -0
- package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +98 -0
- package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +215 -0
- package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +146 -0
- package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +98 -0
- package/pp-core/workflows/discovery-sprint/sessions/06-security.md +107 -0
- package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +98 -0
- package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +85 -0
- package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +109 -0
- package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +119 -0
- package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +92 -0
- package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +98 -0
- package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +205 -0
- package/pp-core/workflows/discovery-sprint/templates/context-template.md +266 -0
- package/pp-core/workflows/discovery-sprint.md +79 -1714
- package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +5 -5
- package/pp-core/workflows/discovery-to-build/steps/screen-inventory-gate.md +70 -0
- package/pp-core/workflows/discovery-to-build/templates/discovery-references.md +54 -0
- package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +184 -0
- package/pp-core/workflows/discovery-to-build.md +21 -238
- package/pp-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/pp-core/workflows/discuss-phase/modes/auto.md +1 -1
- package/pp-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/pp-core/workflows/discuss-phase-assumptions.md +1 -1
- package/pp-core/workflows/discuss-phase.md +9 -2
- package/pp-core/workflows/do.md +4 -4
- package/pp-core/workflows/docs-update.md +1 -1
- package/pp-core/workflows/edit-phase.md +1 -1
- package/pp-core/workflows/eval-review.md +1 -1
- package/pp-core/workflows/execute-phase/steps/checkpoint-handling.md +45 -0
- package/pp-core/workflows/execute-phase/steps/client-context-gate.md +1 -1
- package/pp-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +90 -0
- package/pp-core/workflows/execute-phase/steps/install-run.md +29 -0
- package/pp-core/workflows/execute-phase/steps/phase-close-rebaseline.md +23 -0
- package/pp-core/workflows/execute-phase/steps/post-merge-gate.md +76 -77
- package/pp-core/workflows/execute-phase/steps/serial-group-dispatch.md +72 -0
- package/pp-core/workflows/execute-phase/steps/vault-fetch.md +5 -5
- package/pp-core/workflows/execute-phase/steps/vault-load-gate.md +19 -112
- package/pp-core/workflows/execute-phase.md +102 -216
- package/pp-core/workflows/execute-plan.md +6 -2
- package/pp-core/workflows/explore.md +1 -1
- package/pp-core/workflows/extract-learnings.md +1 -1
- package/pp-core/workflows/forensics.md +4 -4
- package/pp-core/workflows/graduation.md +1 -1
- package/pp-core/workflows/health.md +1 -1
- package/pp-core/workflows/help/modes/brief.md +1 -0
- package/pp-core/workflows/help/modes/default.md +2 -1
- package/pp-core/workflows/help/modes/full.md +12 -5
- package/pp-core/workflows/import.md +1 -1
- package/pp-core/workflows/ingest-docs.md +1 -1
- package/pp-core/workflows/init.md +18 -2
- package/pp-core/workflows/insert-phase.md +1 -1
- package/pp-core/workflows/list-workspaces.md +1 -1
- package/pp-core/workflows/manager.md +3 -3
- package/pp-core/workflows/map-codebase.md +2 -2
- package/pp-core/workflows/milestone-summary.md +4 -4
- package/pp-core/workflows/mvp-phase.md +1 -1
- package/pp-core/workflows/new-milestone.md +7 -8
- package/pp-core/workflows/new-project.md +6 -1
- package/pp-core/workflows/new-workspace.md +1 -1
- package/pp-core/workflows/next.md +2 -2
- package/pp-core/workflows/note.md +2 -2
- package/pp-core/workflows/pause-work.md +1 -1
- package/pp-core/workflows/plan-milestone-gaps.md +1 -1
- package/pp-core/workflows/plan-phase/steps/chunked-planning.md +111 -0
- package/pp-core/workflows/plan-phase/steps/phase-tier.md +34 -0
- package/pp-core/workflows/plan-phase.md +43 -167
- package/pp-core/workflows/plan-review-convergence.md +2 -2
- package/pp-core/workflows/plant-seed.md +1 -1
- package/pp-core/workflows/pr-branch.md +1 -1
- package/pp-core/workflows/profile-user.md +1 -1
- package/pp-core/workflows/progress.md +3 -3
- package/pp-core/workflows/quick.md +3 -1
- package/pp-core/workflows/remove-phase.md +1 -1
- package/pp-core/workflows/remove-workspace.md +1 -1
- package/pp-core/workflows/resume-project.md +6 -12
- package/pp-core/workflows/review.md +1 -1
- package/pp-core/workflows/scan.md +1 -1
- package/pp-core/workflows/secure-phase.md +1 -1
- package/pp-core/workflows/settings-advanced.md +1 -1
- package/pp-core/workflows/settings-integrations.md +1 -1
- package/pp-core/workflows/settings.md +1 -1
- package/pp-core/workflows/ship.md +25 -8
- package/pp-core/workflows/sketch-wrap-up.md +1 -1
- package/pp-core/workflows/sketch.md +2 -1
- package/pp-core/workflows/spec-phase.md +1 -1
- package/pp-core/workflows/spike-wrap-up.md +1 -1
- package/pp-core/workflows/spike.md +1 -1
- package/pp-core/workflows/stats.md +2 -2
- package/pp-core/workflows/thread.md +1 -1
- package/pp-core/workflows/transition.md +5 -9
- package/pp-core/workflows/ui-phase.md +23 -2
- package/pp-core/workflows/ui-review.md +1 -1
- package/pp-core/workflows/ultraplan-phase.md +2 -2
- package/pp-core/workflows/validate-phase.md +1 -1
- package/pp-core/workflows/vault-write-back.md +1 -1
- package/pp-core/workflows/verify-phase.md +29 -26
- package/pp-core/workflows/verify-work.md +14 -10
- package/scripts/base64-scan.sh +7 -41
- package/scripts/changeset/cli.cjs +25 -5
- package/scripts/dev-env.cjs +462 -0
- package/scripts/lib/allowlist-ratchet.cjs +103 -1
- package/scripts/lib/size-budget.cjs +311 -0
- package/scripts/lint-neutrality-names.cjs +694 -0
- package/scripts/lint-org-coordinates.allowlist.json +35 -0
- package/scripts/lint-org-coordinates.cjs +426 -0
- package/scripts/lint-skill-deps.cjs +48 -9
- package/scripts/lint-test-file-count.cjs +17 -2
- package/scripts/prompt-injection-scan.sh +41 -20
- package/scripts/sync-manifest-versions.cjs +41 -7
- package/scripts/sync-runtime-launcher.cjs +106 -1
- package/scripts/update-size-baseline.cjs +274 -30
- package/scripts/workflow-size.cjs +61 -9
- package/commands/pp-build-handoff.md +0 -46
- package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +0 -94
|
@@ -11,7 +11,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11
11
|
};
|
|
12
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
-
const clock_cjs_1 = require("./clock.cjs");
|
|
15
14
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
16
15
|
const ioMod = require("./io.cjs");
|
|
17
16
|
const { output, error } = ioMod;
|
|
@@ -19,11 +18,11 @@ const { output, error } = ioMod;
|
|
|
19
18
|
const phaseIdMod = require("./phase-id.cjs");
|
|
20
19
|
const { escapeRegex, normalizePhaseName, phaseMarkdownRegexSource, phaseMarkdownRegexSourceExact, phaseTokenMatches } = phaseIdMod;
|
|
21
20
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
22
|
-
const
|
|
23
|
-
const {
|
|
21
|
+
const phaseScopeMod = require("./phase-scope.cjs");
|
|
22
|
+
const { resolvePhaseForRead } = phaseScopeMod;
|
|
24
23
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
25
24
|
const roadmapParserModule = require("./roadmap-parser.cjs");
|
|
26
|
-
const { stripShippedMilestones, extractCurrentMilestone, replaceInCurrentMilestone } = roadmapParserModule;
|
|
25
|
+
const { stripShippedMilestones, extractCurrentMilestone, replaceInCurrentMilestone, buildPlansSummaryLinePattern, PHASE_SECTION_SCAN } = roadmapParserModule;
|
|
27
26
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
28
27
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
29
28
|
const planningWorkspace = require("./planning-workspace.cjs");
|
|
@@ -375,12 +374,69 @@ function cmdRoadmapAnalyze(cwd, raw) {
|
|
|
375
374
|
output(result, raw, undefined);
|
|
376
375
|
}
|
|
377
376
|
// ─── cmdRoadmapUpdatePlanProgress ─────────────────────────────────────────────
|
|
377
|
+
/**
|
|
378
|
+
* The status a phase carries between its last executed wave and the
|
|
379
|
+
* `execute:post` governance gate (D-08-15).
|
|
380
|
+
*
|
|
381
|
+
* Every plan has a SUMMARY, and nothing has yet recorded the phase as governed.
|
|
382
|
+
* It is deliberately a third literal, distinct from both neighbours:
|
|
383
|
+
* - `In Progress` — plans remain unexecuted;
|
|
384
|
+
* - `Built` — all plans executed, governance not yet granted;
|
|
385
|
+
* - `Complete` — written ONLY by `phase.complete`, after the execute:post
|
|
386
|
+
* gate returned without halting (D-08-13).
|
|
387
|
+
*
|
|
388
|
+
* A reader (or an auditor) can therefore tell "the code exists" from "the code
|
|
389
|
+
* was allowed to ship" by looking at one cell.
|
|
390
|
+
*/
|
|
391
|
+
const ROADMAP_BUILT_STATUS = 'Built';
|
|
392
|
+
/**
|
|
393
|
+
* Refresh a phase's ROADMAP.md plan rows, executed count and status from disk.
|
|
394
|
+
*
|
|
395
|
+
* D-08-12: this handler can NOT write phase-level completion. It never ticks the
|
|
396
|
+
* phase checkbox, never writes a `(completed <date>)` stamp, never writes the
|
|
397
|
+
* `Complete` status cell and never writes `plans complete`. Those four surfaces
|
|
398
|
+
* belong to `phase.complete` (`src/phase.cts` `cmdPhaseComplete`), which the
|
|
399
|
+
* execute-phase workflow reaches only AFTER the `execute:post` gate dispatch
|
|
400
|
+
* returned without halting (D-08-13).
|
|
401
|
+
*
|
|
402
|
+
* Why it was narrowed — VA-R2-F2, measured: completion used to be INFERRED here
|
|
403
|
+
* from a file count (`summaryCount >= planCount`), and both call sites run per
|
|
404
|
+
* wave, several waves before governance runs. The round-2 fixture caught the
|
|
405
|
+
* consequence: ROADMAP.md read `Complete 2/2` for a phase whose blocking
|
|
406
|
+
* `vault.trace` gate had halted, while STATE.md still read `status: executing`.
|
|
407
|
+
* A file count is evidence that plans were built; it is not evidence that the
|
|
408
|
+
* phase was governed, and this verb is no longer allowed to confuse the two.
|
|
409
|
+
*
|
|
410
|
+
* D-08-32 — AND IT MAY NOT UNWRITE ONE EITHER. D-08-12 closed the forward
|
|
411
|
+
* direction and left the reverse open: on the live UAT fixture, phase 1 read
|
|
412
|
+
* `| 2/2 | Complete | 2026-09-16 |` after a governed completion, and a single
|
|
413
|
+
* `roadmap update-plan-progress 1` demoted it to `Built` and erased the date.
|
|
414
|
+
* A completion date is the one stored fact that distinguishes "the code exists"
|
|
415
|
+
* from "the code was allowed to ship", and a counter that can silently delete it
|
|
416
|
+
* makes the record unusable as a record.
|
|
417
|
+
*
|
|
418
|
+
* So: a phase is GOVERNED when its progress row's Status cell reads `Complete`
|
|
419
|
+
* (case-insensitive, trimmed) OR its Plans summary line already says
|
|
420
|
+
* `plans complete`. Both are read from the UNMODIFIED content before any write.
|
|
421
|
+
* On a governed phase this verb refreshes the executed-count cell and nothing
|
|
422
|
+
* else — Status, Completed and the summary line are left exactly as
|
|
423
|
+
* `phase.complete` wrote them. Un-governing a phase (a plan added after
|
|
424
|
+
* completion) is a `phase`-family action, not this counter's.
|
|
425
|
+
*
|
|
426
|
+
* And on EVERY path, governed or not, the Completed cell is never assigned. It
|
|
427
|
+
* is `phase.complete`'s cell (D-08-12); a `-` placeholder is the template's own
|
|
428
|
+
* not-complete marker, and blanking it is still a write to a cell this verb does
|
|
429
|
+
* not own.
|
|
430
|
+
*
|
|
431
|
+
* `status` and `built` in the JSON output stay count-derived, so this verb still
|
|
432
|
+
* never REPORTS `Complete`; `governed` says whether it preserved a row.
|
|
433
|
+
*/
|
|
378
434
|
function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) {
|
|
379
435
|
if (!phaseNum) {
|
|
380
436
|
error('phase number required for roadmap update-plan-progress');
|
|
381
437
|
}
|
|
382
438
|
const roadmapPath = planningPaths(cwd).roadmap;
|
|
383
|
-
const phaseInfo =
|
|
439
|
+
const phaseInfo = resolvePhaseForRead(cwd, phaseNum);
|
|
384
440
|
if (!phaseInfo) {
|
|
385
441
|
error(`Phase ${phaseNum} not found`);
|
|
386
442
|
}
|
|
@@ -390,59 +446,91 @@ function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) {
|
|
|
390
446
|
output({ updated: false, reason: 'No plans found', plan_count: 0, summary_count: 0 }, raw, 'no plans');
|
|
391
447
|
return;
|
|
392
448
|
}
|
|
393
|
-
const
|
|
394
|
-
const status =
|
|
395
|
-
const today = clock_cjs_1.realClock.today();
|
|
449
|
+
const built = summaryCount >= planCount;
|
|
450
|
+
const status = built ? ROADMAP_BUILT_STATUS : summaryCount > 0 ? 'In Progress' : 'Planned';
|
|
396
451
|
if (!node_fs_1.default.existsSync(roadmapPath)) {
|
|
397
452
|
output({ updated: false, reason: 'ROADMAP.md not found', plan_count: planCount, summary_count: summaryCount }, raw, 'no roadmap');
|
|
398
453
|
return;
|
|
399
454
|
}
|
|
455
|
+
// Hoisted out of the locked section so the JSON output can report it
|
|
456
|
+
// (D-08-32); assigned exactly once, inside the lock, from the content read
|
|
457
|
+
// there.
|
|
458
|
+
let governedPhase = false;
|
|
400
459
|
// Wrap entire read-modify-write in lock to prevent concurrent corruption
|
|
401
460
|
withPlanningLock(cwd, () => {
|
|
402
461
|
let roadmapContent = node_fs_1.default.readFileSync(roadmapPath, 'utf-8');
|
|
403
462
|
const phasePattern = phaseMarkdownRegexSource(phaseNum);
|
|
404
463
|
// Progress table row: update Plans/Status/Date columns (handles 4 or 5 column tables)
|
|
405
464
|
const tableRowPattern = new RegExp(`^(\\|\\s*${phasePattern}\\.?\\s[^|]*(?:\\|[^\\n]*))$`, 'im');
|
|
465
|
+
// Update plan count in phase detail section. The three recognised spellings,
|
|
466
|
+
// the phase-number boundary, the phase-section bound and the same-line tail
|
|
467
|
+
// all live in `buildPlansSummaryLinePattern` (src/roadmap-parser.cjs, D-08-33)
|
|
468
|
+
// — the same builder `cmdPhaseComplete` uses. Two writers, one reading of
|
|
469
|
+
// what "this phase's Plans line" means.
|
|
470
|
+
const planCountPattern = buildPlansSummaryLinePattern(phaseNum);
|
|
471
|
+
// ── D-08-32: is this phase already GOVERNED? ─────────────────────────────
|
|
472
|
+
// BOTH reads run against the UNMODIFIED content, before any write, so the
|
|
473
|
+
// answer cannot be contaminated by this call's own edits.
|
|
474
|
+
const governedByRow = (() => {
|
|
475
|
+
const rowMatch = roadmapContent.match(tableRowPattern);
|
|
476
|
+
if (!rowMatch)
|
|
477
|
+
return false;
|
|
478
|
+
const cells = rowMatch[0].split('|').slice(1, -1);
|
|
479
|
+
// Same column arithmetic as the write below: Status is index 3 on a
|
|
480
|
+
// 5-column table and index 2 on a 4-column one.
|
|
481
|
+
const statusCell = cells.length === 5 ? cells[3] : cells.length === 4 ? cells[2] : undefined;
|
|
482
|
+
return statusCell !== undefined && statusCell.trim().toLowerCase() === 'complete';
|
|
483
|
+
})();
|
|
484
|
+
const governedByLine = (() => {
|
|
485
|
+
// Scoped exactly as the WRITE is (`replaceInCurrentMilestone`): a
|
|
486
|
+
// `plans complete` line inside an archived <details> milestone says
|
|
487
|
+
// nothing about the phase in the active one.
|
|
488
|
+
const lastClose = roadmapContent.lastIndexOf('</details>');
|
|
489
|
+
const scoped = lastClose === -1 ? roadmapContent : roadmapContent.slice(lastClose + '</details>'.length);
|
|
490
|
+
const lineMatch = scoped.match(planCountPattern);
|
|
491
|
+
if (!lineMatch)
|
|
492
|
+
return false;
|
|
493
|
+
const value = lineMatch[0].slice(lineMatch[1].length);
|
|
494
|
+
return /plans\s+complete/i.test(value);
|
|
495
|
+
})();
|
|
496
|
+
const governed = governedByRow || governedByLine;
|
|
497
|
+
governedPhase = governed;
|
|
406
498
|
roadmapContent = roadmapContent.replace(tableRowPattern, (fullRow) => {
|
|
407
499
|
const cells = fullRow.split('|').slice(1, -1); // drop leading/trailing empty from split
|
|
408
|
-
|
|
500
|
+
// The Completed cell is `phase.complete`'s to fill (D-08-12) and is NEVER
|
|
501
|
+
// assigned here, on any branch (D-08-32) — not even to blank it. A `-`
|
|
502
|
+
// placeholder is the template's own not-complete marker and survives.
|
|
503
|
+
// The Status cell is written only when the phase is NOT governed; on a
|
|
504
|
+
// governed row only the executed count is refreshed.
|
|
505
|
+
// Both padded cells carry a TRAILING space as well as a leading one: the
|
|
506
|
+
// cells are re-joined on a bare `|`, so ` ${status.padEnd(11)}` rendered
|
|
507
|
+
// an 11-character status as `| In Progress|` — a malformed table cell
|
|
508
|
+
// observed in three consecutive live runs of this verb.
|
|
409
509
|
if (cells.length === 5) {
|
|
410
510
|
// 5-col: Phase | Milestone | Plans | Status | Completed
|
|
411
511
|
cells[2] = ` ${summaryCount}/${planCount} `;
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const existingDate5 = cells[4].trim();
|
|
415
|
-
cells[4] = isComplete
|
|
416
|
-
? (dateShape.test(existingDate5) ? cells[4] : ` ${today} `)
|
|
417
|
-
: ' ';
|
|
512
|
+
if (!governed)
|
|
513
|
+
cells[3] = ` ${status.padEnd(11)} `;
|
|
418
514
|
}
|
|
419
515
|
else if (cells.length === 4) {
|
|
420
516
|
// 4-col: Phase | Plans | Status | Completed
|
|
421
517
|
cells[1] = ` ${summaryCount}/${planCount} `;
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
const existingDate4 = cells[3].trim();
|
|
425
|
-
cells[3] = isComplete
|
|
426
|
-
? (dateShape.test(existingDate4) ? cells[3] : ` ${today} `)
|
|
427
|
-
: ' ';
|
|
518
|
+
if (!governed)
|
|
519
|
+
cells[2] = ` ${status.padEnd(11)} `;
|
|
428
520
|
}
|
|
429
521
|
return '|' + cells.join('|') + '|';
|
|
430
522
|
});
|
|
431
|
-
//
|
|
432
|
-
//
|
|
433
|
-
//
|
|
434
|
-
//
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
: `${summaryCount}/${planCount} plans executed`;
|
|
440
|
-
roadmapContent = replaceInCurrentMilestone(roadmapContent, planCountPattern, `$1${planCountText}`);
|
|
441
|
-
// If complete: check checkbox
|
|
442
|
-
if (isComplete) {
|
|
443
|
-
const checkboxPattern = new RegExp(`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${phasePattern}[:\\s][^\\n]*)`, 'i');
|
|
444
|
-
roadmapContent = replaceInCurrentMilestone(roadmapContent, checkboxPattern, `$1x$2 (completed ${today})`);
|
|
523
|
+
// Always "executed", never "complete" (D-08-12): this is a count of the
|
|
524
|
+
// SUMMARY files on disk, not a statement that the phase was governed.
|
|
525
|
+
// And on a GOVERNED phase the line is not rewritten at all (D-08-32) —
|
|
526
|
+
// demoting `2/2 plans complete` to `2/2 plans executed` would delete the
|
|
527
|
+
// very distinction D-08-12 introduced the two wordings to preserve.
|
|
528
|
+
if (!governed) {
|
|
529
|
+
const planCountText = `${summaryCount}/${planCount} plans executed`;
|
|
530
|
+
roadmapContent = replaceInCurrentMilestone(roadmapContent, planCountPattern, `$1${planCountText}`);
|
|
445
531
|
}
|
|
532
|
+
// The phase checkbox is NOT ticked here under any count (D-08-12).
|
|
533
|
+
// `phase.complete` ticks it, after the execute:post gate (D-08-13).
|
|
446
534
|
// Mark completed plan checkboxes (e.g. "- [ ] 50-01-PLAN.md", "- [ ] 50-01:", or "- [ ] **50-01**")
|
|
447
535
|
for (const summaryFile of phaseInfo.summaries) {
|
|
448
536
|
const planId = summaryFile.replace('-SUMMARY.md', '').replace('SUMMARY.md', '');
|
|
@@ -490,8 +578,17 @@ function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) {
|
|
|
490
578
|
//
|
|
491
579
|
// Pattern A: anchor to bare `Plans:` header (preferred).
|
|
492
580
|
// Pattern B: fallback to bold summary when no bare header exists.
|
|
493
|
-
|
|
494
|
-
|
|
581
|
+
//
|
|
582
|
+
// BOTH anchors carry the same phase-section bound as the summary-line
|
|
583
|
+
// builder (`PHASE_SECTION_SCAN`, D-08-33). They did not, and the omission
|
|
584
|
+
// was the F2 defect wearing a second hat: given a phase whose section has
|
|
585
|
+
// NO Plans anchor of either shape, the unbounded lazy scan found the next
|
|
586
|
+
// phase's anchor and inserted THIS phase's plan rows into THAT phase's
|
|
587
|
+
// checklist — a plan row asserting membership of a phase it has nothing to
|
|
588
|
+
// do with. Bounded, a phase with no anchor simply gets no rows, which is
|
|
589
|
+
// the honest outcome.
|
|
590
|
+
const insertRowsPatternA = new RegExp(`(#{2,4}\\s*Phase\\s+${phasePattern}(?=[:\\s])${PHASE_SECTION_SCAN}(?:^|\\n)(?:Plans:)[^\\n]*)`, 'i');
|
|
591
|
+
const insertRowsPatternB = new RegExp(`(#{2,4}\\s*Phase\\s+${phasePattern}(?=[:\\s])${PHASE_SECTION_SCAN}(?:\\*\\*Plans\\*\\*:|\\*\\*Plans:\\*\\*)[^\\n]*)`, 'i');
|
|
495
592
|
const sortedMissing = [...missingPlans].sort();
|
|
496
593
|
const newRows = sortedMissing.map(p => `- [ ] ${p}`).join('\n');
|
|
497
594
|
const inserter = (match) => `${match}\n${newRows}`;
|
|
@@ -534,7 +631,11 @@ function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) {
|
|
|
534
631
|
plan_count: planCount,
|
|
535
632
|
summary_count: summaryCount,
|
|
536
633
|
status,
|
|
537
|
-
|
|
634
|
+
built,
|
|
635
|
+
// D-08-32: true when the phase was already governed and this call therefore
|
|
636
|
+
// refreshed the executed count only. `status`/`built` stay count-derived, so
|
|
637
|
+
// this verb still never REPORTS completion — it only says it preserved one.
|
|
638
|
+
governed: governedPhase,
|
|
538
639
|
}, raw, `${summaryCount}/${planCount} ${status}`);
|
|
539
640
|
}
|
|
540
641
|
// ─── cmdRoadmapAnnotateDependencies ───────────────────────────────────────────
|
|
@@ -560,7 +661,7 @@ function cmdRoadmapAnnotateDependencies(cwd, phaseNum, raw) {
|
|
|
560
661
|
output({ updated: false, reason: 'ROADMAP.md not found' }, raw, 'no roadmap');
|
|
561
662
|
return;
|
|
562
663
|
}
|
|
563
|
-
const phaseInfo =
|
|
664
|
+
const phaseInfo = resolvePhaseForRead(cwd, phaseNum);
|
|
564
665
|
if (!phaseInfo || phaseInfo.plans.length === 0) {
|
|
565
666
|
output({ updated: false, reason: 'no plans found for phase', phase: phaseNum }, raw, 'no plans');
|
|
566
667
|
return;
|
|
@@ -730,6 +831,7 @@ function cmdRoadmapAnnotateDependencies(cwd, phaseNum, raw) {
|
|
|
730
831
|
}, raw, updated ? `annotated ${waves.length} wave(s), ${crossCuttingTruths.length} constraint(s)` : 'skipped (already annotated or no plan list)');
|
|
731
832
|
}
|
|
732
833
|
module.exports = {
|
|
834
|
+
ROADMAP_BUILT_STATUS,
|
|
733
835
|
cmdRoadmapGetPhase,
|
|
734
836
|
getRoadmapPhaseWithFallback,
|
|
735
837
|
cmdRoadmapAnalyze,
|
|
@@ -45,7 +45,7 @@ const reset = '\x1b[0m';
|
|
|
45
45
|
// ---------------------------------------------------------------------------
|
|
46
46
|
const GSD_COPILOT_HOOK_FILE = 'pp-session.json';
|
|
47
47
|
const GSD_COPILOT_SESSION_MSG_PRESENT = 'pp-core: .planning/STATE.md present - review the current phase and any blockers before acting.';
|
|
48
|
-
const GSD_COPILOT_SESSION_MSG_ABSENT = 'pp-core: no .planning/ workflow found - run /pp-
|
|
48
|
+
const GSD_COPILOT_SESSION_MSG_ABSENT = 'pp-core: no .planning/ workflow found - run /pp-init to start a tracked workflow.';
|
|
49
49
|
const GSD_COPILOT_SESSION_HOOK_BASH = 'if [ -f .planning/STATE.md ]; then ' +
|
|
50
50
|
`printf '%s' '{"additionalContext":"${GSD_COPILOT_SESSION_MSG_PRESENT}"}'; else ` +
|
|
51
51
|
`printf '%s' '{"additionalContext":"${GSD_COPILOT_SESSION_MSG_ABSENT}"}'; fi`;
|
|
@@ -166,6 +166,21 @@ const MANAGED_HOOK_BASENAMES_BY_SURFACE = {
|
|
|
166
166
|
'pp-check-update.js',
|
|
167
167
|
]),
|
|
168
168
|
};
|
|
169
|
+
// This set must be a SUPERSET of every `MANAGED_HOOKS` name
|
|
170
|
+
// (hooks/managed-hooks-registry.cjs, the authoritative list) that the
|
|
171
|
+
// settings-json surface can register. `isManagedHookCommand` reads it, and the
|
|
172
|
+
// uninstall filter plus the #338 migration read both go through that — so a
|
|
173
|
+
// registry hook missing here is classified as a *user* hook and survives an
|
|
174
|
+
// uninstall. Measured in a phase-9 fixture: two names were missing, leaving one
|
|
175
|
+
// pp-core hook still wired to a script that persists (a live PreToolUse hook in
|
|
176
|
+
// a project the operator believes is uninstalled, D-09-08) and one wired to a
|
|
177
|
+
// script the same uninstall had just deleted.
|
|
178
|
+
//
|
|
179
|
+
// It cannot require() the registry: this module is a leaf compiled into
|
|
180
|
+
// pp-core/bin/lib/, and Codex/Copilot/Cline installs ship no hooks/ dir beside
|
|
181
|
+
// it. The pin that keeps the two in step therefore lives in
|
|
182
|
+
// tests/shell-command-projection-dispatch.test.cjs, which drives the check from
|
|
183
|
+
// MANAGED_HOOKS minus a named, reasoned exclusion table.
|
|
169
184
|
const MANAGED_HOOK_COMMAND_BASENAMES_BY_SURFACE = {
|
|
170
185
|
'settings-json': new Set([
|
|
171
186
|
'pp-check-update.js',
|
|
@@ -180,6 +195,15 @@ const MANAGED_HOOK_COMMAND_BASENAMES_BY_SURFACE = {
|
|
|
180
195
|
'pp-session-state.sh',
|
|
181
196
|
'pp-validate-commit.sh',
|
|
182
197
|
'pp-phase-boundary.sh',
|
|
198
|
+
// Registered by the Claude installer into the settings file (PreToolUse /
|
|
199
|
+
// PostToolUse / SessionStart) but absent from this set until phase 9.
|
|
200
|
+
'pp-worktree-path-guard.js',
|
|
201
|
+
'pp-graphify-update.sh',
|
|
202
|
+
// Registered on a settings-json-shaped surface by the marketplace plugin
|
|
203
|
+
// manifest (hooks/hooks.json, SessionStart); a classic install never wires
|
|
204
|
+
// it, so recognising it removes an entry that is there and changes nothing
|
|
205
|
+
// when it is not.
|
|
206
|
+
'pp-ensure-canonical-path.js',
|
|
183
207
|
]),
|
|
184
208
|
'codex-toml': new Set([
|
|
185
209
|
'pp-check-update.js',
|
|
@@ -13,12 +13,19 @@
|
|
|
13
13
|
* ADR-457 build-at-publish: the hand-written bin/lib/state-command-router.cjs
|
|
14
14
|
* collapsed to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
|
|
15
15
|
* from the prior hand-written .cjs; only types are added.
|
|
16
|
+
*
|
|
17
|
+
* 261008-mwk: every subcommand declares the arguments it reads in STATE_ARG_SPECS,
|
|
18
|
+
* and routeStateCommand refuses anything else (reason `usage`) BEFORE dispatch, so
|
|
19
|
+
* a refused call writes nothing. The same entry feeds each handler's parseNamedArgs
|
|
20
|
+
* call, so the validator and the parser read one owner (D-1, D-6).
|
|
16
21
|
*/
|
|
17
22
|
const command_aliases_cjs_1 = require("./command-aliases.cjs");
|
|
18
23
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
19
24
|
const cjsCommandRouterAdapter = require("./cjs-command-router-adapter.cjs");
|
|
20
25
|
const { routeHubCommandFamily } = cjsCommandRouterAdapter;
|
|
21
26
|
const command_arg_projection_cjs_1 = require("./command-arg-projection.cjs");
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
|
+
const io = require("./io.cjs");
|
|
22
29
|
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
23
30
|
// Helper: extract string-only named arg value (value flags never return boolean).
|
|
24
31
|
function strArg(opts, key) {
|
|
@@ -27,8 +34,69 @@ function strArg(opts, key) {
|
|
|
27
34
|
return undefined;
|
|
28
35
|
return v;
|
|
29
36
|
}
|
|
37
|
+
// ─── Argument specs (261008-mwk D-6) ──────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* The arguments each state subcommand reads — one entry per registered subcommand
|
|
40
|
+
* (STATE_SUBCOMMANDS plus complete-phase). routeStateCommand validates argv against
|
|
41
|
+
* the entry before dispatch, and every handler's named-arg parse takes its flag
|
|
42
|
+
* lists from the same entry. A subcommand added without an entry reds the coverage
|
|
43
|
+
* pin in tests/state.test.cjs.
|
|
44
|
+
*
|
|
45
|
+
* planned-phase reads --phase and --plans only: cmdStatePlannedPhase has no name
|
|
46
|
+
* parameter, so a name flag would be parsed and dropped (D-4).
|
|
47
|
+
*/
|
|
48
|
+
const STATE_ARG_SPECS = Object.freeze({
|
|
49
|
+
load: {},
|
|
50
|
+
json: {},
|
|
51
|
+
'advance-plan': {},
|
|
52
|
+
'update-progress': {},
|
|
53
|
+
'signal-resume': {},
|
|
54
|
+
validate: {},
|
|
55
|
+
get: { maxPositionals: 1, verbatimPositionals: true, positionalLabel: 'at most one positional <section>' },
|
|
56
|
+
update: { maxPositionals: 2, verbatimPositionals: true, positionalLabel: 'at most two positionals <field> <value>' },
|
|
57
|
+
patch: { free: true },
|
|
58
|
+
'complete-phase': {
|
|
59
|
+
valueFlags: ['phase'],
|
|
60
|
+
maxPositionals: 1,
|
|
61
|
+
positionalExcludedBy: 'phase',
|
|
62
|
+
positionalLabel: '--phase <value> or one positional <phase>',
|
|
63
|
+
},
|
|
64
|
+
'begin-phase': { valueFlags: ['phase', 'name', 'plans'] },
|
|
65
|
+
'record-metric': { valueFlags: ['phase', 'plan', 'duration', 'tasks', 'files'] },
|
|
66
|
+
'add-decision': { valueFlags: ['phase', 'summary', 'summary-file', 'rationale', 'rationale-file'] },
|
|
67
|
+
'add-blocker': { valueFlags: ['text', 'text-file'] },
|
|
68
|
+
'resolve-blocker': { valueFlags: ['text'] },
|
|
69
|
+
'record-session': { valueFlags: ['stopped-at', 'resume-file'] },
|
|
70
|
+
'signal-waiting': { valueFlags: ['type', 'question', 'options', 'phase'] },
|
|
71
|
+
'planned-phase': { valueFlags: ['phase', 'plans'] },
|
|
72
|
+
sync: { booleanFlags: ['verify'] },
|
|
73
|
+
prune: { valueFlags: ['keep-recent'], booleanFlags: ['dry-run'] },
|
|
74
|
+
'milestone-switch': { valueFlags: ['milestone', 'name'] },
|
|
75
|
+
'add-roadmap-evolution': { valueFlags: ['phase', 'action', 'after', 'note', 'note-file'], booleanFlags: ['urgent'] },
|
|
76
|
+
});
|
|
77
|
+
// Own-property lookup only: a subcommand named `constructor` or `__proto__` must
|
|
78
|
+
// reach the hub's unknown-subcommand path, not an Object.prototype member.
|
|
79
|
+
function specFor(sub) {
|
|
80
|
+
return Object.prototype.hasOwnProperty.call(STATE_ARG_SPECS, sub) ? STATE_ARG_SPECS[sub] : undefined;
|
|
81
|
+
}
|
|
30
82
|
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
31
83
|
function routeStateCommand({ state, args, cwd, raw, error }) {
|
|
84
|
+
// 261008-mwk D-1: refuse before dispatch, so a refused call runs no handler and
|
|
85
|
+
// writes nothing. Unknown subcommands fall through to the hub's own message.
|
|
86
|
+
const sub = args[1] || 'load';
|
|
87
|
+
const spec = specFor(sub);
|
|
88
|
+
if (spec) {
|
|
89
|
+
const verdict = (0, command_arg_projection_cjs_1.validateVerbArgs)(args.slice(2), spec, `state ${sub}`);
|
|
90
|
+
if (!verdict.ok) {
|
|
91
|
+
error(verdict.reason, io.ERROR_REASON.USAGE);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Every handler's named-arg parse reads its flag lists from the verb's spec (D-6).
|
|
96
|
+
const named = (verb) => {
|
|
97
|
+
const s = specFor(verb) ?? {};
|
|
98
|
+
return (0, command_arg_projection_cjs_1.parseNamedArgs)(args, s.valueFlags ?? [], s.booleanFlags ?? []);
|
|
99
|
+
};
|
|
32
100
|
const parsePlans = (plans) => {
|
|
33
101
|
const parsedPlans = plans == null ? null : Number.parseInt(plans, 10);
|
|
34
102
|
if (plans != null && Number.isNaN(parsedPlans)) {
|
|
@@ -90,7 +158,7 @@ function routeStateCommand({ state, args, cwd, raw, error }) {
|
|
|
90
158
|
},
|
|
91
159
|
'advance-plan': () => state.cmdStateAdvancePlan(cwd, raw),
|
|
92
160
|
'record-metric': () => {
|
|
93
|
-
const a = (
|
|
161
|
+
const a = named('record-metric');
|
|
94
162
|
state.cmdStateRecordMetric(cwd, {
|
|
95
163
|
phase: strArg(a, 'phase'),
|
|
96
164
|
plan: strArg(a, 'plan'),
|
|
@@ -101,7 +169,7 @@ function routeStateCommand({ state, args, cwd, raw, error }) {
|
|
|
101
169
|
},
|
|
102
170
|
'update-progress': () => state.cmdStateUpdateProgress(cwd, raw),
|
|
103
171
|
'add-decision': () => {
|
|
104
|
-
const a = (
|
|
172
|
+
const a = named('add-decision');
|
|
105
173
|
state.cmdStateAddDecision(cwd, {
|
|
106
174
|
phase: strArg(a, 'phase'),
|
|
107
175
|
summary: strArg(a, 'summary'),
|
|
@@ -111,11 +179,11 @@ function routeStateCommand({ state, args, cwd, raw, error }) {
|
|
|
111
179
|
}, raw);
|
|
112
180
|
},
|
|
113
181
|
'add-blocker': () => {
|
|
114
|
-
const a = (
|
|
182
|
+
const a = named('add-blocker');
|
|
115
183
|
state.cmdStateAddBlocker(cwd, { text: strArg(a, 'text'), text_file: strArg(a, 'text-file') }, raw);
|
|
116
184
|
},
|
|
117
185
|
'add-roadmap-evolution': () => {
|
|
118
|
-
const a = (
|
|
186
|
+
const a = named('add-roadmap-evolution');
|
|
119
187
|
state.cmdStateAddRoadmapEvolution(cwd, {
|
|
120
188
|
phase: strArg(a, 'phase'),
|
|
121
189
|
action: strArg(a, 'action'),
|
|
@@ -125,43 +193,43 @@ function routeStateCommand({ state, args, cwd, raw, error }) {
|
|
|
125
193
|
urgent: a['urgent'] === true,
|
|
126
194
|
}, raw);
|
|
127
195
|
},
|
|
128
|
-
'resolve-blocker': () => state.cmdStateResolveBlocker(cwd, strArg((
|
|
196
|
+
'resolve-blocker': () => state.cmdStateResolveBlocker(cwd, strArg(named('resolve-blocker'), 'text'), raw),
|
|
129
197
|
'record-session': () => {
|
|
130
|
-
const a = (
|
|
198
|
+
const a = named('record-session');
|
|
131
199
|
// Pass resume_file as-is (undefined when --resume-file was not provided) so
|
|
132
200
|
// cmdStateRecordSession can distinguish "caller explicitly passed a value" from
|
|
133
201
|
// "option was not supplied" and apply the template-default-only replacement guard.
|
|
134
202
|
state.cmdStateRecordSession(cwd, { stopped_at: strArg(a, 'stopped-at'), resume_file: strArg(a, 'resume-file') }, raw);
|
|
135
203
|
},
|
|
136
204
|
'begin-phase': () => {
|
|
137
|
-
const a = (
|
|
205
|
+
const a = named('begin-phase');
|
|
138
206
|
state.cmdStateBeginPhase(cwd, strArg(a, 'phase'), strArg(a, 'name'), parsePlans(strArg(a, 'plans')), raw);
|
|
139
207
|
},
|
|
140
208
|
'signal-waiting': () => {
|
|
141
|
-
const a = (
|
|
209
|
+
const a = named('signal-waiting');
|
|
142
210
|
state.cmdSignalWaiting(cwd, strArg(a, 'type'), strArg(a, 'question'), strArg(a, 'options'), strArg(a, 'phase'), raw);
|
|
143
211
|
},
|
|
144
212
|
'signal-resume': () => state.cmdSignalResume(cwd, raw),
|
|
145
213
|
'planned-phase': () => {
|
|
146
|
-
const a = (
|
|
214
|
+
const a = named('planned-phase');
|
|
147
215
|
state.cmdStatePlannedPhase(cwd, strArg(a, 'phase'), parsePlans(strArg(a, 'plans')), raw);
|
|
148
216
|
},
|
|
149
217
|
validate: () => state.cmdStateValidate(cwd, raw),
|
|
150
218
|
sync: () => {
|
|
151
|
-
const a = (
|
|
219
|
+
const a = named('sync');
|
|
152
220
|
state.cmdStateSync(cwd, { verify: a['verify'] }, raw);
|
|
153
221
|
},
|
|
154
222
|
prune: () => {
|
|
155
|
-
const a = (
|
|
223
|
+
const a = named('prune');
|
|
156
224
|
state.cmdStatePrune(cwd, { keepRecent: strArg(a, 'keep-recent') || '3', dryRun: a['dry-run'] === true }, raw);
|
|
157
225
|
},
|
|
158
226
|
// complete-phase: CJS-only — no SDK counterpart.
|
|
159
227
|
'complete-phase': () => {
|
|
160
|
-
const a = (
|
|
228
|
+
const a = named('complete-phase');
|
|
161
229
|
state.cmdStateCompletePhase(cwd, raw, strArg(a, 'phase') || args[2]);
|
|
162
230
|
},
|
|
163
231
|
'milestone-switch': () => {
|
|
164
|
-
const a = (
|
|
232
|
+
const a = named('milestone-switch');
|
|
165
233
|
state.cmdStateMilestoneSwitch(cwd, strArg(a, 'milestone'), strArg(a, 'name'), raw);
|
|
166
234
|
},
|
|
167
235
|
},
|
|
@@ -169,4 +237,5 @@ function routeStateCommand({ state, args, cwd, raw, error }) {
|
|
|
169
237
|
}
|
|
170
238
|
module.exports = {
|
|
171
239
|
routeStateCommand,
|
|
240
|
+
STATE_ARG_SPECS,
|
|
172
241
|
};
|