@pareto4/pp-core 1.11.1 → 1.12.1
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-activation.cjs +19 -9
- 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 +70 -6
- package/pp-core/bin/lib/config-loader.cjs +151 -8
- 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 +93 -4
- 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 +40 -2
- 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 +592 -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 +149 -9
- 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 +14 -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 +2 -2
- 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 +2 -2
- package/pp-core/workflows/code-review.md +20 -8
- 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 +11 -4
- 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 +104 -218
- 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 +4 -2
- 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 +2 -2
- 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 +26 -9
- 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 +2 -2
- 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
|
@@ -19,8 +19,8 @@ const { output, error, ERROR_REASON } = io;
|
|
|
19
19
|
const planningWorkspaceMod = require("./planning-workspace.cjs");
|
|
20
20
|
const { planningDir } = planningWorkspaceMod;
|
|
21
21
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
22
|
-
const
|
|
23
|
-
const {
|
|
22
|
+
const phaseScopeMod = require("./phase-scope.cjs");
|
|
23
|
+
const { resolvePhaseForRead } = phaseScopeMod;
|
|
24
24
|
const decisions_cjs_1 = require("./decisions.cjs");
|
|
25
25
|
const ui_safety_gate_cjs_1 = require("./ui-safety-gate.cjs");
|
|
26
26
|
const semver_compare_cjs_1 = require("./semver-compare.cjs");
|
|
@@ -39,7 +39,7 @@ const { runGapAnalysis } = gapCheckerModule;
|
|
|
39
39
|
const prohibition_enforcement_cjs_1 = require("./prohibition-enforcement.cjs");
|
|
40
40
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
41
41
|
const vaultModule = require("./vault.cjs");
|
|
42
|
-
const { vaultStatus, readManifest } = vaultModule;
|
|
42
|
+
const { vaultStatus, readManifest, computeVaultVerdict, verdictFields, renderVaultCard, VAULT_GATE_POINTS } = vaultModule;
|
|
43
43
|
const git_base_branch_cjs_1 = require("./git-base-branch.cjs");
|
|
44
44
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
45
45
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -371,7 +371,7 @@ function cmdDecisionCoverageVerify(projectDir, args, raw) {
|
|
|
371
371
|
* Invocable as: pp_run check ui-plan-gate <phase>
|
|
372
372
|
*
|
|
373
373
|
* Uses checkUiPresence from ui-safety-gate.cjs — does NOT reimplement frontend detection.
|
|
374
|
-
* Uses getRoadmapPhaseWithFallback +
|
|
374
|
+
* Uses getRoadmapPhaseWithFallback + the phase-scope owner's reader answer for phase data.
|
|
375
375
|
*/
|
|
376
376
|
function findUiSpecInDir(phaseDir) {
|
|
377
377
|
if (!phaseDir || !node_fs_1.default.existsSync(phaseDir))
|
|
@@ -398,7 +398,7 @@ function findUiSpecInDir(phaseDir) {
|
|
|
398
398
|
* surface the miss — we do NOT silently degrade to frontend:false if the roadmap
|
|
399
399
|
* exists but the phase header is absent.
|
|
400
400
|
* (b) Runs checkUiPresence (frontend detection) — no reimplementation.
|
|
401
|
-
* (c) Resolves the phase directory via
|
|
401
|
+
* (c) Resolves the phase directory via resolvePhaseForRead (phase-scope.cjs); checks for *-UI-SPEC.md.
|
|
402
402
|
*
|
|
403
403
|
* Returns: { frontend, hasUiSpec, block, uiSpecPath, phaseLookupFailed }
|
|
404
404
|
* block = frontend && !hasUiSpec
|
|
@@ -432,12 +432,12 @@ function computeUiPlanGate(projectDir, phase) {
|
|
|
432
432
|
// (b) Run checkUiPresence (frontend detection) — reuse existing helper; no reimplementation
|
|
433
433
|
const presenceResult = (0, ui_safety_gate_cjs_1.checkUiPresence)(phaseSection);
|
|
434
434
|
const frontend = presenceResult.hasUI;
|
|
435
|
-
// (c) Resolve phase directory via
|
|
435
|
+
// (c) Resolve phase directory via the phase-scope owner and check for *-UI-SPEC.md
|
|
436
436
|
let phaseDir = '';
|
|
437
437
|
try {
|
|
438
|
-
const result =
|
|
438
|
+
const result = resolvePhaseForRead(projectDir, phase);
|
|
439
439
|
if (result && typeof result === 'object') {
|
|
440
|
-
//
|
|
440
|
+
// the owner returns the raw locator's { directory: '<relative-posix-path>', ... }
|
|
441
441
|
// directory is relative to cwd — resolve it to absolute.
|
|
442
442
|
const relDir = typeof result['directory'] === 'string' ? result['directory'] : '';
|
|
443
443
|
if (relDir) {
|
|
@@ -499,7 +499,7 @@ const UI_PATH_PATTERNS_RE = /\/(components|pages|views|screens|layouts|ui|fronte
|
|
|
499
499
|
* same lookup as computeUiPlanGate — to determine if this is a frontend phase.
|
|
500
500
|
* (b) Runs checkUiPresence (frontend detection) — no reimplementation.
|
|
501
501
|
* (c) Checks git diff HEAD~1..HEAD for UI file changes in the current worktree.
|
|
502
|
-
* (d) Resolves the phase directory via
|
|
502
|
+
* (d) Resolves the phase directory via resolvePhaseForRead (phase-scope.cjs); checks for *-UI-SPEC.md.
|
|
503
503
|
*
|
|
504
504
|
* Returns: { frontend, hasUiFiles, hasUiSpec, block, message?, phaseLookupFailed? }
|
|
505
505
|
* block = frontend && hasUiFiles && !hasUiSpec
|
|
@@ -543,7 +543,7 @@ function computeUiSafetyGate(projectDir, phase) {
|
|
|
543
543
|
// (d) Resolve phase directory and check for *-UI-SPEC.md (same as computeUiPlanGate)
|
|
544
544
|
let phaseDir = '';
|
|
545
545
|
try {
|
|
546
|
-
const result =
|
|
546
|
+
const result = resolvePhaseForRead(projectDir, phase);
|
|
547
547
|
if (result && typeof result === 'object') {
|
|
548
548
|
const relDir = typeof result['directory'] === 'string' ? result['directory'] : '';
|
|
549
549
|
if (relDir) {
|
|
@@ -587,7 +587,7 @@ function cmdTddReviewCheckpoint(projectDir, args, raw) {
|
|
|
587
587
|
// Resolve phase directory
|
|
588
588
|
let phaseDir = '';
|
|
589
589
|
try {
|
|
590
|
-
const result =
|
|
590
|
+
const result = resolvePhaseForRead(projectDir, phase);
|
|
591
591
|
if (result && typeof result === 'object') {
|
|
592
592
|
const relDir = typeof result['directory'] === 'string' ? result['directory'] : '';
|
|
593
593
|
if (relDir)
|
|
@@ -921,23 +921,28 @@ function cmdShipPlatformDrift(cwd, args, raw) {
|
|
|
921
921
|
output({ status, block: status === 'block', severity, pinned, latest, present: true }, raw, undefined);
|
|
922
922
|
}
|
|
923
923
|
/**
|
|
924
|
-
* cmdVaultStatus —
|
|
924
|
+
* cmdVaultStatus — gate-query handler for `check vault.status` / `check vault-status`.
|
|
925
925
|
*
|
|
926
|
-
* Contract
|
|
927
|
-
* - PURE
|
|
928
|
-
*
|
|
929
|
-
* -
|
|
930
|
-
*
|
|
926
|
+
* Contract:
|
|
927
|
+
* - PURE read: never fetches, never spawns, never throws, exits 0 on every
|
|
928
|
+
* verdict (a usage error — an unknown `--point` — is the only non-zero exit).
|
|
929
|
+
* - Pack 6 D-01: the verdict is decided by ONE owner, `computeVaultVerdict`
|
|
930
|
+
* (src/vault.cts). This handler spreads the owner's `VAULT_VERDICT_FIELDS`
|
|
931
|
+
* over the legacy envelope; it decides nothing itself.
|
|
932
|
+
* - Legacy envelope (§8 of v1.7.0-DESIGN), kept key for key:
|
|
933
|
+
* { status, block, present, tier, source, fallbackReason, repo, ref,
|
|
934
|
+
* resolvedSha, fileCount, stale, fetchedAt }
|
|
935
|
+
* `block` now comes from the owner: `enabled && required && verdict !==
|
|
936
|
+
* 'loaded'` (D-03) — false whenever `vault.required` is false, as before.
|
|
937
|
+
* `repo` is display-safe (D-07).
|
|
938
|
+
* - `--card --point plan|execute` (D-04) prints the human card the workflow
|
|
939
|
+
* relays verbatim; it prints nothing when the vault is inert (D-06).
|
|
931
940
|
*
|
|
932
|
-
*
|
|
933
|
-
* { status, block: false, present, tier, source, fallbackReason, repo, ref,
|
|
934
|
-
* resolvedSha, fileCount, stale }
|
|
935
|
-
*
|
|
936
|
-
* Invocable as: pp_run check vault.status [--raw]
|
|
941
|
+
* Invocable as: pp_run check vault.status [--raw] [--card --point plan|execute]
|
|
937
942
|
* The dot→hyphen normalization in routeCheckCommand maps "vault.status" to
|
|
938
943
|
* the "vault-status" branch.
|
|
939
944
|
*/
|
|
940
|
-
function cmdVaultStatus(cwd, raw) {
|
|
945
|
+
function cmdVaultStatus(cwd, args, raw) {
|
|
941
946
|
// Step 1: Resolve project root (same approach as cmdShipPlatformDrift).
|
|
942
947
|
let root;
|
|
943
948
|
try {
|
|
@@ -946,31 +951,42 @@ function cmdVaultStatus(cwd, raw) {
|
|
|
946
951
|
catch {
|
|
947
952
|
root = cwd;
|
|
948
953
|
}
|
|
949
|
-
|
|
950
|
-
|
|
954
|
+
const verdict = computeVaultVerdict(root);
|
|
955
|
+
if (args.includes('--card')) {
|
|
956
|
+
const pointIdx = args.indexOf('--point');
|
|
957
|
+
const point = pointIdx === -1 ? undefined : args[pointIdx + 1];
|
|
958
|
+
if (point === undefined || !VAULT_GATE_POINTS.includes(point)) {
|
|
959
|
+
error(`check vault.status --card needs --point ${VAULT_GATE_POINTS.join('|')} (got ${point === undefined ? 'none' : JSON.stringify(point)}).`, ERROR_REASON.SDK_MISSING_ARG);
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
const card = renderVaultCard(verdict, point);
|
|
963
|
+
output({ ...verdictFields(verdict), card }, true, card);
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
const fields = verdictFields(verdict);
|
|
967
|
+
// Step 2: Legacy inert envelope — absent .platform-bindings.json (unchanged keys and values).
|
|
951
968
|
const bindingsPath = node_path_1.default.join(root, '.platform-bindings.json');
|
|
952
969
|
if (!node_fs_1.default.existsSync(bindingsPath)) {
|
|
953
|
-
output({ status: 'inert', block:
|
|
970
|
+
output({ status: 'inert', block: verdict.block, present: false, ...fields }, raw, undefined);
|
|
954
971
|
return;
|
|
955
972
|
}
|
|
956
|
-
// Step 3: Call vaultStatus(
|
|
957
|
-
const vs = vaultStatus(
|
|
973
|
+
// Step 3: Call vaultStatus(root). present:false → miss.
|
|
974
|
+
const vs = vaultStatus(root);
|
|
958
975
|
if (!vs.present) {
|
|
959
|
-
output({ status: 'miss', block:
|
|
976
|
+
output({ status: 'miss', block: verdict.block, present: false, ...fields }, raw, undefined);
|
|
960
977
|
return;
|
|
961
978
|
}
|
|
962
|
-
// Step 4:
|
|
963
|
-
const
|
|
964
|
-
const manifest = readManifest(vaultDirPath);
|
|
979
|
+
// Step 4: fallbackReason + repo via readManifest (display-safe since Pack 6 D-07).
|
|
980
|
+
const manifest = readManifest(node_path_1.default.join(root, '.planning', 'vault'));
|
|
965
981
|
const fallbackReason = manifest?.fallbackReason ?? null;
|
|
966
982
|
const repo = manifest?.repo ?? null;
|
|
967
983
|
// Step 5: Derive status from manifest source.
|
|
968
984
|
const src = vs.source ?? 'miss';
|
|
969
985
|
const status = (src === 'fetched' || src === 'cache' || src === 'miss') ? src : 'miss';
|
|
970
|
-
// Step 6:
|
|
986
|
+
// Step 6: Legacy envelope + the owner's verdict fields (block among them).
|
|
971
987
|
output({
|
|
972
988
|
status,
|
|
973
|
-
block:
|
|
989
|
+
block: verdict.block,
|
|
974
990
|
present: true,
|
|
975
991
|
tier: vs.tier ?? null,
|
|
976
992
|
source: vs.source ?? null,
|
|
@@ -981,6 +997,7 @@ function cmdVaultStatus(cwd, raw) {
|
|
|
981
997
|
fileCount: vs.fileCount ?? 0,
|
|
982
998
|
stale: vs.stale ?? true,
|
|
983
999
|
fetchedAt: vs.fetchedAt ?? null,
|
|
1000
|
+
...fields,
|
|
984
1001
|
}, raw, undefined);
|
|
985
1002
|
}
|
|
986
1003
|
// ─── ship.practices query handler (INJ-03, Phase 28) ──────────────────────────
|
|
@@ -1084,7 +1101,7 @@ function chooseShipReviewFile(dir) {
|
|
|
1084
1101
|
/**
|
|
1085
1102
|
* Build the trailing "what did the code review record" pointer line
|
|
1086
1103
|
* (D-08/D-09). Reads `.planning/STATE.md`'s `current_phase`, resolves the
|
|
1087
|
-
* phase directory via `
|
|
1104
|
+
* phase directory via `resolvePhaseForRead` (never a hand-built
|
|
1088
1105
|
* `.planning/phases/` path, never a directory glob outside the chosen phase
|
|
1089
1106
|
* directory), chooses the right REVIEW.md file via `chooseShipReviewFile`,
|
|
1090
1107
|
* and reads its `practices.total` count. Every step degrades to the soft
|
|
@@ -1102,7 +1119,7 @@ function buildShipReviewPointerLine(root) {
|
|
|
1102
1119
|
if (currentPhase === undefined || currentPhase === null || currentPhase === '') {
|
|
1103
1120
|
return SHIP_REVIEW_SOFT_NOTE;
|
|
1104
1121
|
}
|
|
1105
|
-
const phaseResult =
|
|
1122
|
+
const phaseResult = resolvePhaseForRead(root, currentPhase);
|
|
1106
1123
|
if (!phaseResult)
|
|
1107
1124
|
return SHIP_REVIEW_SOFT_NOTE;
|
|
1108
1125
|
const phaseDir = node_path_1.default.join(root, phaseResult.directory);
|
|
@@ -1415,6 +1432,29 @@ function cmdCheckPracticesReview({ args }, _check, _core) {
|
|
|
1415
1432
|
const text = renderedLines.length > 0 ? renderedLines.join('\n') + '\n' : '';
|
|
1416
1433
|
c.output(text, true, text);
|
|
1417
1434
|
}
|
|
1435
|
+
/**
|
|
1436
|
+
* Pack 6 D-01: the check router's subcommand table — every subcommand
|
|
1437
|
+
* `routeCheckCommand` dispatches, in its hyphen form. `readsVerdict` marks the
|
|
1438
|
+
* ones that report the vault load verdict; each must spread the owner's
|
|
1439
|
+
* `VAULT_VERDICT_FIELDS` verbatim (tests/vault-status-check.test.cjs
|
|
1440
|
+
* enumerates this table and compares every reader against the owner).
|
|
1441
|
+
*/
|
|
1442
|
+
const CHECK_SUBCOMMANDS = Object.freeze([
|
|
1443
|
+
{ name: 'auto-mode', readsVerdict: false },
|
|
1444
|
+
{ name: 'decision-coverage-plan', readsVerdict: false },
|
|
1445
|
+
{ name: 'decision-coverage-verify', readsVerdict: false },
|
|
1446
|
+
{ name: 'gap-analysis-plan-post', readsVerdict: false },
|
|
1447
|
+
{ name: 'practices-review', readsVerdict: false },
|
|
1448
|
+
{ name: 'prohibition-enforcement', readsVerdict: false },
|
|
1449
|
+
{ name: 'ship-platform-drift', readsVerdict: false },
|
|
1450
|
+
{ name: 'ship-practices', readsVerdict: false },
|
|
1451
|
+
{ name: 'tdd-review-checkpoint', readsVerdict: false },
|
|
1452
|
+
{ name: 'ui-plan-gate', readsVerdict: false },
|
|
1453
|
+
{ name: 'ui-safety-gate', readsVerdict: false },
|
|
1454
|
+
{ name: 'vault-status', readsVerdict: true },
|
|
1455
|
+
{ name: 'verify-schema-drift', readsVerdict: false },
|
|
1456
|
+
{ name: 'verify-codebase-drift', readsVerdict: false },
|
|
1457
|
+
]);
|
|
1418
1458
|
function routeCheckCommand({ args, cwd, raw, _check, _core }) {
|
|
1419
1459
|
// Normalize dots to hyphens in the subcommand so both forms are accepted.
|
|
1420
1460
|
// This makes `check.query = "ui.plan-gate"` (dotted form in capability.json gates)
|
|
@@ -1469,7 +1509,7 @@ function routeCheckCommand({ args, cwd, raw, _check, _core }) {
|
|
|
1469
1509
|
// vault.status — advisory vault cache state query (Phase 13, D-01/D-02).
|
|
1470
1510
|
// Dot-to-hyphen normalization means query "vault.status" routes here.
|
|
1471
1511
|
// Pure manifest read; block is ALWAYS false; inert when bindings absent.
|
|
1472
|
-
cmdVaultStatus(cwd, raw);
|
|
1512
|
+
cmdVaultStatus(cwd, args, raw);
|
|
1473
1513
|
return;
|
|
1474
1514
|
}
|
|
1475
1515
|
if (subcommand === 'verify-schema-drift') {
|
|
@@ -1509,7 +1549,7 @@ function routeCheckCommand({ args, cwd, raw, _check, _core }) {
|
|
|
1509
1549
|
(0, prohibition_enforcement_cjs_1.routeProhibitionEnforcement)(args, raw);
|
|
1510
1550
|
return;
|
|
1511
1551
|
}
|
|
1512
|
-
error(
|
|
1552
|
+
error(`Unknown check subcommand. Available: ${CHECK_SUBCOMMANDS.map((c) => c.name).join(', ')}`, ERROR_REASON.SDK_UNKNOWN_COMMAND);
|
|
1513
1553
|
}
|
|
1514
1554
|
module.exports = {
|
|
1515
1555
|
routeCheckCommand,
|
|
@@ -1523,4 +1563,5 @@ module.exports = {
|
|
|
1523
1563
|
cmdShipPractices,
|
|
1524
1564
|
cmdVaultStatus,
|
|
1525
1565
|
cmdCheckPracticesReview,
|
|
1566
|
+
CHECK_SUBCOMMANDS,
|
|
1526
1567
|
};
|
|
@@ -23,10 +23,9 @@ exports.CLUSTERS = Object.freeze({
|
|
|
23
23
|
'init',
|
|
24
24
|
'new-project',
|
|
25
25
|
'discovery',
|
|
26
|
-
// Discovery→build handoff
|
|
27
|
-
//
|
|
26
|
+
// Discovery→build handoff, grouped with the other project-lifecycle
|
|
27
|
+
// entrypoints (routed via pp-ns-project).
|
|
28
28
|
'discovery-to-build',
|
|
29
|
-
'build-handoff',
|
|
30
29
|
'discuss-phase',
|
|
31
30
|
'plan-phase',
|
|
32
31
|
'execute-phase',
|
|
@@ -470,6 +470,14 @@ exports.PHASES_COMMAND_ALIASES = [
|
|
|
470
470
|
],
|
|
471
471
|
"subcommand": "archive",
|
|
472
472
|
"mutation": true
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"canonical": "phases.archive-closed",
|
|
476
|
+
"aliases": [
|
|
477
|
+
"phases archive-closed"
|
|
478
|
+
],
|
|
479
|
+
"subcommand": "archive-closed",
|
|
480
|
+
"mutation": true
|
|
473
481
|
}
|
|
474
482
|
];
|
|
475
483
|
exports.VALIDATE_COMMAND_ALIASES = [
|
|
@@ -690,6 +698,20 @@ exports.NON_FAMILY_COMMAND_ALIASES = [
|
|
|
690
698
|
],
|
|
691
699
|
"mutation": true
|
|
692
700
|
},
|
|
701
|
+
{
|
|
702
|
+
"canonical": "phase.dispatch-plan",
|
|
703
|
+
"aliases": [
|
|
704
|
+
"phase dispatch-plan"
|
|
705
|
+
],
|
|
706
|
+
"mutation": false
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
"canonical": "phase.install-run",
|
|
710
|
+
"aliases": [
|
|
711
|
+
"phase install-run"
|
|
712
|
+
],
|
|
713
|
+
"mutation": true
|
|
714
|
+
},
|
|
693
715
|
{
|
|
694
716
|
"canonical": "phase.mvp-mode",
|
|
695
717
|
"aliases": [
|
|
@@ -697,6 +719,20 @@ exports.NON_FAMILY_COMMAND_ALIASES = [
|
|
|
697
719
|
],
|
|
698
720
|
"mutation": false
|
|
699
721
|
},
|
|
722
|
+
{
|
|
723
|
+
"canonical": "phase.tier",
|
|
724
|
+
"aliases": [
|
|
725
|
+
"phase tier"
|
|
726
|
+
],
|
|
727
|
+
"mutation": false
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
"canonical": "phase.tier-propose",
|
|
731
|
+
"aliases": [
|
|
732
|
+
"phase tier-propose"
|
|
733
|
+
],
|
|
734
|
+
"mutation": true
|
|
735
|
+
},
|
|
700
736
|
{
|
|
701
737
|
"canonical": "progress.bar",
|
|
702
738
|
"aliases": [
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
* hand-written .cjs; only types are added.
|
|
7
7
|
*
|
|
8
8
|
* Shared helpers for command-family adapters to project argv tokens into
|
|
9
|
-
* typed named values and multi-word segments
|
|
9
|
+
* typed named values and multi-word segments, and (261008-mwk) to refuse the
|
|
10
|
+
* tokens a verb would not read — `validateVerbArgs`, the one owner of that rule.
|
|
10
11
|
*/
|
|
11
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
13
|
exports.parseNamedArgs = parseNamedArgs;
|
|
13
14
|
exports.parseMultiwordArg = parseMultiwordArg;
|
|
15
|
+
exports.validateVerbArgs = validateVerbArgs;
|
|
14
16
|
/**
|
|
15
17
|
* Extract named --flag <value> pairs from an args array.
|
|
16
18
|
* Returns an object mapping flag names to their values (null if absent).
|
|
@@ -53,3 +55,99 @@ function parseMultiwordArg(args, flag) {
|
|
|
53
55
|
}
|
|
54
56
|
return tokens.length > 0 ? tokens.join(' ') : null;
|
|
55
57
|
}
|
|
58
|
+
// T-mwk-02: refused tokens are echoed to stderr; cap each one.
|
|
59
|
+
const ECHO_LIMIT = 80;
|
|
60
|
+
function echoToken(token) {
|
|
61
|
+
const cut = token.length > ECHO_LIMIT ? token.slice(0, ECHO_LIMIT) : token;
|
|
62
|
+
return cut === '' || /\s/.test(cut) ? JSON.stringify(cut) : cut;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Refuse every argument a verb would not read (261008-mwk D-1, D-5, D-7).
|
|
66
|
+
*
|
|
67
|
+
* `parseNamedArgs` indexes argv for whole `--flag` tokens and looks at nothing
|
|
68
|
+
* else, so before this owner existed a stray positional, an unknown flag, a
|
|
69
|
+
* `--flag=value` token, a value flag with no value after it, and the second of
|
|
70
|
+
* a repeated flag were all dropped while the verb reported success. This walk
|
|
71
|
+
* reads the tokens exactly as the parser does and names each one it would drop:
|
|
72
|
+
*
|
|
73
|
+
* - `positional` — a non-flag token beyond the verb's positional allowance;
|
|
74
|
+
* - `unknown flag` — a `--name` the spec does not declare;
|
|
75
|
+
* - `use --name <value>` (or `use --name`) — a `--name=value` token;
|
|
76
|
+
* - `no value follows` — a value flag that is last or followed by a `--` token;
|
|
77
|
+
* - `given twice; only the first is read` — a repeated declared flag.
|
|
78
|
+
*
|
|
79
|
+
* Pure: no I/O, no environment. The caller turns a refusal into its own error
|
|
80
|
+
* (the state router uses `ERROR_REASON.USAGE`).
|
|
81
|
+
*
|
|
82
|
+
* @param tokens argv after the verb (global flags already stripped by pp-tools main()).
|
|
83
|
+
* @param spec the verb's declared shape.
|
|
84
|
+
* @param verb optional label for the message, e.g. `state record-session`.
|
|
85
|
+
* @returns `{ ok: true }`, or the refused tokens with kinds and a D-7 message.
|
|
86
|
+
*/
|
|
87
|
+
function validateVerbArgs(tokens, spec, verb) {
|
|
88
|
+
if (spec.free)
|
|
89
|
+
return { ok: true };
|
|
90
|
+
const valueFlags = spec.valueFlags ?? [];
|
|
91
|
+
const booleanFlags = spec.booleanFlags ?? [];
|
|
92
|
+
const refused = [];
|
|
93
|
+
const positionals = [];
|
|
94
|
+
const seen = new Set();
|
|
95
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
96
|
+
const token = tokens[i];
|
|
97
|
+
if (spec.verbatimPositionals || !token.startsWith('--')) {
|
|
98
|
+
positionals.push(token);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const name = token.slice(2);
|
|
102
|
+
const eq = name.indexOf('=');
|
|
103
|
+
if (eq !== -1) {
|
|
104
|
+
const bare = name.slice(0, eq);
|
|
105
|
+
if (valueFlags.includes(bare))
|
|
106
|
+
refused.push({ token, kind: `use --${bare} <value>` });
|
|
107
|
+
else if (booleanFlags.includes(bare))
|
|
108
|
+
refused.push({ token, kind: `use --${bare}` });
|
|
109
|
+
else
|
|
110
|
+
refused.push({ token, kind: 'unknown flag' });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const isValue = valueFlags.includes(name);
|
|
114
|
+
if (!isValue && !booleanFlags.includes(name)) {
|
|
115
|
+
refused.push({ token, kind: 'unknown flag' });
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const hasValue = isValue && i + 1 < tokens.length && !tokens[i + 1].startsWith('--');
|
|
119
|
+
if (seen.has(name)) {
|
|
120
|
+
refused.push({ token, kind: 'given twice; only the first is read' });
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
seen.add(name);
|
|
124
|
+
if (isValue && !hasValue)
|
|
125
|
+
refused.push({ token, kind: 'no value follows' });
|
|
126
|
+
}
|
|
127
|
+
if (hasValue)
|
|
128
|
+
i++;
|
|
129
|
+
}
|
|
130
|
+
const allowance = spec.positionalExcludedBy && seen.has(spec.positionalExcludedBy)
|
|
131
|
+
? 0
|
|
132
|
+
: (spec.maxPositionals ?? 0);
|
|
133
|
+
for (const token of positionals.slice(allowance))
|
|
134
|
+
refused.push({ token, kind: 'positional' });
|
|
135
|
+
if (refused.length === 0)
|
|
136
|
+
return { ok: true };
|
|
137
|
+
return { ok: false, refused, reason: refusalReason(refused, spec, verb) };
|
|
138
|
+
}
|
|
139
|
+
function refusalReason(refused, spec, verb) {
|
|
140
|
+
const prefix = verb ? `${verb} does not read:` : 'does not read:';
|
|
141
|
+
const list = refused.map((r) => `${echoToken(r.token)} (${r.kind})`).join(', ');
|
|
142
|
+
const accepts = spec.positionalLabel ?? acceptedShape(spec);
|
|
143
|
+
return `${prefix} ${list}. It accepts: ${accepts}. Nothing was written.`;
|
|
144
|
+
}
|
|
145
|
+
function acceptedShape(spec) {
|
|
146
|
+
const max = spec.maxPositionals ?? 0;
|
|
147
|
+
const parts = [
|
|
148
|
+
...(spec.valueFlags ?? []).map((f) => `--${f} <value>`),
|
|
149
|
+
...(spec.booleanFlags ?? []).map((f) => `--${f}`),
|
|
150
|
+
...(max > 0 ? [`at most ${max} positional${max === 1 ? '' : 's'}`] : []),
|
|
151
|
+
];
|
|
152
|
+
return parts.length ? parts.join(', ') : 'no arguments';
|
|
153
|
+
}
|
|
@@ -26,7 +26,10 @@ const phaseIdMod = require("./phase-id.cjs");
|
|
|
26
26
|
const { normalizePhaseName, comparePhaseNum, extractPhaseToken } = phaseIdMod;
|
|
27
27
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
28
|
const phaseLocatorMod = require("./phase-locator.cjs");
|
|
29
|
-
const { getArchivedPhaseDirs
|
|
29
|
+
const { getArchivedPhaseDirs } = phaseLocatorMod;
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
31
|
+
const phaseScopeMod = require("./phase-scope.cjs");
|
|
32
|
+
const { resolvePhaseForRead, resolvePhaseForWrite } = phaseScopeMod;
|
|
30
33
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
31
34
|
const roadmapParserMod = require("./roadmap-parser.cjs");
|
|
32
35
|
const { extractCurrentMilestone, stripShippedMilestones: _stripShippedMilestones, getMilestoneInfo, getMilestonePhaseFilter, getRoadmapPhaseInternal } = roadmapParserMod;
|
|
@@ -455,7 +458,9 @@ function cmdCommit(cwd, message, files, raw, amend, noVerify) {
|
|
|
455
458
|
const phaseMatch = (files || []).join(' ').match(/(\d+(?:\.\d+)*)-/);
|
|
456
459
|
if (phaseMatch) {
|
|
457
460
|
const phaseNum = phaseMatch[1];
|
|
458
|
-
|
|
461
|
+
// D-03: a prior milestone's archived phase whose number the current
|
|
462
|
+
// ROADMAP reuses names no branch (the phase-scope owner drops it).
|
|
463
|
+
const phaseInfo = resolvePhaseForRead(cwd, phaseNum);
|
|
459
464
|
if (phaseInfo) {
|
|
460
465
|
branchName = config['phase_branch_template']
|
|
461
466
|
.replace('{phase}', normalizePhaseName(phaseInfo['phase_number']))
|
|
@@ -902,8 +907,9 @@ function cmdTodoMatchPhase(cwd, phase, raw) {
|
|
|
902
907
|
const phaseKeywords = new Set(phaseText.split(/[\s\-_/.,;:()\[\]{}|]+/)
|
|
903
908
|
.map(w => w.replace(/[^a-z0-9]/g, ''))
|
|
904
909
|
.filter(w => w.length > 2 && !stopWords.has(w)));
|
|
905
|
-
// Find phase directory to get expected file paths
|
|
906
|
-
|
|
910
|
+
// Find phase directory to get expected file paths (D-03: through the
|
|
911
|
+
// phase-scope owner, so a prior milestone's archive never lends this phase its plans)
|
|
912
|
+
const phaseInfoDisk = resolvePhaseForRead(cwd, phase);
|
|
907
913
|
const phasePlans = [];
|
|
908
914
|
if (phaseInfoDisk && phaseInfoDisk['found']) {
|
|
909
915
|
try {
|
|
@@ -987,10 +993,19 @@ function cmdScaffold(cwd, type, options, raw) {
|
|
|
987
993
|
const { phase, name } = options;
|
|
988
994
|
const padded = phase ? normalizePhaseName(phase) : '00';
|
|
989
995
|
const today = new Date().toISOString().split('T')[0];
|
|
990
|
-
// Find phase directory
|
|
991
|
-
|
|
996
|
+
// Find phase directory. D-02 (todo "template-fill-writes-
|
|
997
|
+
// into-an-archived-phase-directory"): context / uat / verification never write into a
|
|
998
|
+
// closed milestone's archive. The phase-scope owner hands back a live match only; an
|
|
999
|
+
// archive this phase still names is refused naming it, and a prior milestone's archive
|
|
1000
|
+
// whose number the current ROADMAP reuses takes the not-found line. phase-dir never reads
|
|
1001
|
+
// the match (it always creates phases/<padded>-<slug of --name>), so it is unchanged.
|
|
1002
|
+
const writeVerdict = phase ? resolvePhaseForWrite(cwd, phase) : null;
|
|
1003
|
+
const phaseInfo = writeVerdict && writeVerdict.ok ? writeVerdict.match : null;
|
|
992
1004
|
const phaseDir = phaseInfo ? node_path_1.default.join(cwd, phaseInfo['directory']) : null;
|
|
993
1005
|
if (phase && !phaseDir && type !== 'phase-dir') {
|
|
1006
|
+
if (writeVerdict && !writeVerdict.ok && writeVerdict.reason === 'archived') {
|
|
1007
|
+
error(`Phase ${phase} is archived in ${writeVerdict.directory} (milestone ${writeVerdict.version}): refusing to write into a closed milestone's record`);
|
|
1008
|
+
}
|
|
994
1009
|
error(`Phase ${phase} directory not found`);
|
|
995
1010
|
}
|
|
996
1011
|
let filePath, content;
|
|
@@ -47,7 +47,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.COMPOSE_BINDINGS_FLAGS = exports.SEED_VALUE_MAX_LENGTH = void 0;
|
|
49
49
|
exports._resetPlatformTagMemoForTests = _resetPlatformTagMemoForTests;
|
|
50
|
+
exports.resolveCreatedWithFrom = resolveCreatedWithFrom;
|
|
50
51
|
exports.composeBindings = composeBindings;
|
|
52
|
+
exports.redactComposeResultForEmission = redactComposeResultForEmission;
|
|
51
53
|
exports.cmdComposeBindings = cmdComposeBindings;
|
|
52
54
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
53
55
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -436,12 +438,34 @@ function resolveLatestPlatformTag(cwd, repo, provider, opts) {
|
|
|
436
438
|
return result;
|
|
437
439
|
}
|
|
438
440
|
/**
|
|
439
|
-
* Read the first readable, semver-shaped `VERSION` file among the
|
|
440
|
-
*
|
|
441
|
-
*
|
|
441
|
+
* Read the first readable, semver-shaped `VERSION` file among the candidate
|
|
442
|
+
* locations resolved against `baseDir`, returning `<binName>@<version>`.
|
|
443
|
+
*
|
|
444
|
+
* The candidate list is `baseDir`-relative rather than `__dirname`-relative so
|
|
445
|
+
* the layout under test is CHOSEN by the caller instead of inherited from
|
|
446
|
+
* wherever the compiled module happens to sit — an installed tree and this
|
|
447
|
+
* repo's own tree put `VERSION` in different places, and a test that cannot
|
|
448
|
+
* pick a layout cannot tell those two cases apart.
|
|
449
|
+
*
|
|
450
|
+
* Three locations are probed, in order: the `VERSION` sitting beside the bin
|
|
451
|
+
* directory; then the installed `pp-core/VERSION` that the installer writes
|
|
452
|
+
* into a project's runtime home; then this repo's own root `VERSION`. The
|
|
453
|
+
* installed location is consulted BEFORE the repo root so an installed tree
|
|
454
|
+
* reports the version it was actually installed from. In this repo that middle
|
|
455
|
+
* candidate is absent, so resolution falls through to the root file.
|
|
456
|
+
*
|
|
457
|
+
* @param baseDir - directory the candidates are resolved against. Production
|
|
458
|
+
* passes this module's own `__dirname`; a test passes a fixture directory
|
|
459
|
+
* shaped like `pp-core/bin/lib`.
|
|
460
|
+
* @returns `<binName>@<version>` for the first readable, semver-shaped
|
|
461
|
+
* candidate; when no candidate is readable, `binName` alone.
|
|
442
462
|
*/
|
|
443
|
-
function
|
|
444
|
-
const candidates = [
|
|
463
|
+
function resolveCreatedWithFrom(baseDir) {
|
|
464
|
+
const candidates = [
|
|
465
|
+
node_path_1.default.join(baseDir, '..', 'VERSION'),
|
|
466
|
+
node_path_1.default.join(baseDir, '..', '..', 'VERSION'),
|
|
467
|
+
node_path_1.default.join(baseDir, '..', '..', '..', 'VERSION'),
|
|
468
|
+
];
|
|
445
469
|
for (const candidate of candidates) {
|
|
446
470
|
try {
|
|
447
471
|
const raw = node_fs_1.default.readFileSync(candidate, 'utf-8').trim();
|
|
@@ -455,6 +479,13 @@ function resolveCreatedWith() {
|
|
|
455
479
|
}
|
|
456
480
|
return package_identity_cjs_1.binName;
|
|
457
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* Resolve `project.createdWith` for the running installation by probing the
|
|
484
|
+
* candidate layout against this module's own directory.
|
|
485
|
+
*/
|
|
486
|
+
function resolveCreatedWith() {
|
|
487
|
+
return resolveCreatedWithFrom(__dirname);
|
|
488
|
+
}
|
|
458
489
|
/**
|
|
459
490
|
* Build the composed candidate object from the seed, the project answers
|
|
460
491
|
* `/pp-init` already captured, the resolved platform host, the D-04 tag pin,
|
|
@@ -772,6 +803,39 @@ function composeBindings(cwd, opts = {}) {
|
|
|
772
803
|
* does, then calls `composeBindings` and emits the result as data — a
|
|
773
804
|
* verdict is never a process error.
|
|
774
805
|
*/
|
|
806
|
+
/**
|
|
807
|
+
* Pack 6 D-07: the display-safe copy of a compose result, for EMISSION only.
|
|
808
|
+
* Every remote coordinate field (`platform.repo`, `client.vaultRepo`) in
|
|
809
|
+
* `composed`, `seed`, `provenance` and `drift` goes through the one owner
|
|
810
|
+
* (`redactCloneTarget`, src/vault.cts); warnings go through the prose
|
|
811
|
+
* redactor. `composeBindings` itself, its drift/action comparison and every
|
|
812
|
+
* write keep the RAW values — never write or compare the result of this.
|
|
813
|
+
*/
|
|
814
|
+
function redactComposeResultForEmission(result) {
|
|
815
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
816
|
+
const v = require('./vault.cjs');
|
|
817
|
+
const COORD = new Set(['platform.repo', 'client.vaultRepo']);
|
|
818
|
+
const safe = (x) => (typeof x === 'string' ? v.redactCloneTarget(x) : x);
|
|
819
|
+
const out = JSON.parse(JSON.stringify(result));
|
|
820
|
+
if (out.composed && typeof out.composed === 'object') {
|
|
821
|
+
for (const field of COORD) {
|
|
822
|
+
const [ns, key] = field.split('.');
|
|
823
|
+
const parent = out.composed[ns];
|
|
824
|
+
if (parent && typeof parent === 'object' && typeof parent[key] === 'string')
|
|
825
|
+
parent[key] = safe(parent[key]);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if (out.seed) {
|
|
829
|
+
if (typeof out.seed.platformRepo === 'string')
|
|
830
|
+
out.seed.platformRepo = safe(out.seed.platformRepo);
|
|
831
|
+
if (typeof out.seed.clientVaultRepo === 'string')
|
|
832
|
+
out.seed.clientVaultRepo = safe(out.seed.clientVaultRepo);
|
|
833
|
+
}
|
|
834
|
+
out.provenance = (out.provenance ?? []).map((p) => (COORD.has(p.field) ? { ...p, value: safe(p.value) } : p));
|
|
835
|
+
out.drift = (out.drift ?? []).map((d) => COORD.has(d.key) ? { ...d, profileValue: safe(d.profileValue), effectiveValue: safe(d.effectiveValue) } : d);
|
|
836
|
+
out.warnings = (out.warnings ?? []).map((w) => (typeof w === 'string' ? v.redactRemoteText(w) : w));
|
|
837
|
+
return out;
|
|
838
|
+
}
|
|
775
839
|
function cmdComposeBindings(cwd, options, raw) {
|
|
776
840
|
let root;
|
|
777
841
|
try {
|
|
@@ -781,5 +845,5 @@ function cmdComposeBindings(cwd, options, raw) {
|
|
|
781
845
|
root = cwd;
|
|
782
846
|
}
|
|
783
847
|
const result = composeBindings(root, { write: options.write === true, offline: options.offline === true });
|
|
784
|
-
output(result, raw);
|
|
848
|
+
output(redactComposeResultForEmission(result), raw);
|
|
785
849
|
}
|