@pareto4/pp-core 1.12.1 → 1.17.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 +3 -3
- package/README.md +26 -9
- package/agents/pp-code-reviewer.md +3 -2
- package/agents/pp-debug-session-manager.md +9 -6
- package/agents/pp-executor.md +7 -21
- package/agents/pp-plan-checker.md +4 -4
- package/agents/pp-planner.md +23 -9
- package/agents/pp-vault-reviewer.md +274 -0
- package/agents/pp-verifier.md +7 -3
- package/bin/install.js +10 -3
- package/commands/pp-execute-phase.md +1 -3
- package/commands/pp-ns-review.md +2 -1
- package/commands/pp-plan-phase.md +1 -2
- package/commands/pp-vault-review.md +35 -0
- package/commands/pp-verify-work.md +1 -2
- package/gemini-extension.json +1 -1
- package/hooks/dist/pp-check-update.js +0 -0
- package/hooks/dist/pp-cursor-session-start.js +1 -1
- package/hooks/dist/pp-statusline.js +1 -1
- package/hooks/dist/pp-update-banner.js +0 -0
- package/hooks/pp-check-update.js +0 -0
- package/hooks/pp-cursor-session-start.js +1 -1
- package/hooks/pp-statusline.js +1 -1
- package/hooks/pp-update-banner.js +0 -0
- package/package.json +14 -19
- package/pareto-skills/_shared/create-project-board.sh +0 -0
- package/pareto-skills/pp-project-setup/SKILL.md +1 -1
- package/pp-core/bin/check-latest-version.cjs +0 -0
- package/pp-core/bin/detect-build-commands.sh +2 -2
- package/pp-core/bin/lib/capability-activation.cjs +83 -9
- package/pp-core/bin/lib/capability-registry.cjs +526 -22
- package/pp-core/bin/lib/capability-state.cjs +160 -4
- package/pp-core/bin/lib/capability-writer.cjs +19 -5
- package/pp-core/bin/lib/check-command-router.cjs +3867 -274
- package/pp-core/bin/lib/clusters.cjs +4 -0
- package/pp-core/bin/lib/command-aliases.cjs +0 -28
- package/pp-core/bin/lib/commands.cjs +9 -4
- package/pp-core/bin/lib/compose-bindings.cjs +253 -76
- package/pp-core/bin/lib/config-loader.cjs +7 -103
- package/pp-core/bin/lib/config-schema.cjs +1 -1
- package/pp-core/bin/lib/config.cjs +154 -62
- package/pp-core/bin/lib/decisions.cjs +104 -27
- package/pp-core/bin/lib/discovery-vault-check.cjs +246 -0
- package/pp-core/bin/lib/frontmatter.cjs +1 -1
- package/pp-core/bin/lib/git-base-branch.cjs +138 -10
- package/pp-core/bin/lib/git-provider.cjs +4 -4
- package/pp-core/bin/lib/init-command-router.cjs +5 -8
- package/pp-core/bin/lib/init-contract.cjs +653 -629
- package/pp-core/bin/lib/init-interactive.cjs +77 -21
- package/pp-core/bin/lib/init.cjs +24 -51
- package/pp-core/bin/lib/install-profiles.cjs +1 -1
- package/pp-core/bin/lib/io.cjs +8 -0
- package/pp-core/bin/lib/loop-resolver.cjs +169 -47
- package/pp-core/bin/lib/org-profile.cjs +544 -53
- package/pp-core/bin/lib/package-identity.cjs +3 -3
- package/pp-core/bin/lib/phase-command-router.cjs +1 -23
- package/pp-core/bin/lib/phase-scope.cjs +1 -1
- package/pp-core/bin/lib/phase.cjs +11 -203
- package/pp-core/bin/lib/platform-bindings.cjs +40 -19
- package/pp-core/bin/lib/practices-review-check.cjs +15 -9
- package/pp-core/bin/lib/profile-output.cjs +1 -1
- package/pp-core/bin/lib/shell-command-projection.cjs +104 -1
- package/pp-core/bin/lib/state.cjs +11 -85
- package/pp-core/bin/lib/template.cjs +1 -1
- package/pp-core/bin/lib/vault-audit.cjs +2594 -0
- package/pp-core/bin/lib/vault-command-router.cjs +2756 -60
- package/pp-core/bin/lib/vault-coordinates.cjs +13 -4
- package/pp-core/bin/lib/vault-index.cjs +699 -0
- package/pp-core/bin/lib/vault-mode.cjs +235 -0
- package/pp-core/bin/lib/vault-practices.cjs +1194 -89
- package/pp-core/bin/lib/vault-review.cjs +2102 -0
- package/pp-core/bin/lib/vault-seal.cjs +1936 -0
- package/pp-core/bin/lib/vault-standards.cjs +1505 -0
- package/pp-core/bin/lib/vault-trace.cjs +3184 -0
- package/pp-core/bin/lib/vault-update.cjs +242 -0
- package/pp-core/bin/lib/vault-write-back.cjs +78 -31
- package/pp-core/bin/lib/vault.cjs +2713 -634
- package/pp-core/bin/lib/verify.cjs +0 -11
- package/pp-core/bin/portable-timeout.sh +1 -1
- package/pp-core/bin/pp-tools.cjs +184 -37
- package/pp-core/bin/shared/config-defaults.manifest.json +0 -7
- package/pp-core/bin/shared/config-schema.manifest.json +0 -3
- package/pp-core/bin/shared/model-catalog.json +1 -0
- package/pp-core/bin/verify-reapply-patches.cjs +0 -0
- package/pp-core/org-profile.json +26 -0
- package/pp-core/references/autonomous-best-effort.md +8 -7
- package/pp-core/references/loop-hook-dispatch.md +0 -14
- package/pp-core/references/planner-gap-closure.md +0 -1
- package/pp-core/references/planner-tdd.md +0 -1
- package/pp-core/references/planner-vault-practices.md +31 -3
- package/pp-core/references/planner-vault-standards.md +320 -0
- package/pp-core/references/planning-config.md +0 -8
- package/pp-core/references/practice-arithmetic-contract.md +121 -0
- package/pp-core/references/tdd.md +0 -1
- package/pp-core/references/verifier-practice-verdicts.md +263 -0
- package/pp-core/templates/README.md +1 -0
- package/pp-core/templates/VAULT-REVIEW.md +202 -0
- package/pp-core/templates/phase-prompt.md +2 -6
- package/pp-core/templates/practices/README.md +137 -11
- package/pp-core/templates/project-charter.md +226 -0
- package/pp-core/workflows/_runtime-launcher.snippet.sh +0 -0
- package/pp-core/workflows/add-tests.md +55 -0
- package/pp-core/workflows/audit-fix.md +63 -0
- package/pp-core/workflows/audit-milestone.md +1 -1
- package/pp-core/workflows/autonomous.md +85 -11
- package/pp-core/workflows/check-todos.md +13 -2
- package/pp-core/workflows/code-review-fix.md +59 -1
- package/pp-core/workflows/code-review.md +10 -1
- package/pp-core/workflows/complete-milestone.md +1 -1
- package/pp-core/workflows/debug.md +56 -2
- package/pp-core/workflows/discovery-sprint/prefill.md +21 -0
- package/pp-core/workflows/discovery-sprint/prototype.md +46 -48
- package/pp-core/workflows/discovery-sprint/session-13-gates.md +2 -0
- package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +20 -24
- package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/06-security.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +1 -6
- package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +1 -3
- package/pp-core/workflows/discovery-sprint/templates/context-template.md +1 -1
- package/pp-core/workflows/discovery-sprint/vault-context.md +213 -0
- package/pp-core/workflows/discovery-sprint.md +7 -3
- package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +4 -4
- package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +43 -1
- package/pp-core/workflows/discovery-to-build.md +9 -1
- package/pp-core/workflows/discuss-phase.md +3 -10
- package/pp-core/workflows/execute-phase/steps/check-query-gate.md +329 -0
- package/pp-core/workflows/execute-phase/steps/client-context-gate.md +3 -2
- package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -1
- package/pp-core/workflows/execute-phase/steps/execute-pre-dispatch.md +98 -0
- package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
- package/pp-core/workflows/execute-phase/steps/post-merge-gate.md +6 -8
- package/pp-core/workflows/execute-phase/steps/vault-fetch.md +115 -14
- package/pp-core/workflows/execute-phase/steps/vault-load-gate.md +322 -18
- package/pp-core/workflows/execute-phase/steps/verifier-practice-payload.md +165 -0
- package/pp-core/workflows/execute-phase/steps/verify-post-gate.md +163 -0
- package/pp-core/workflows/execute-phase.md +154 -110
- package/pp-core/workflows/execute-plan.md +58 -4
- package/pp-core/workflows/fast.md +53 -0
- package/pp-core/workflows/help/modes/full.md +1 -0
- package/pp-core/workflows/init/steps/client-context-capture.md +101 -0
- package/pp-core/workflows/init/steps/gitlab-provisioning.md +130 -0
- package/pp-core/workflows/init/steps/project-md-deferral-narration.md +66 -0
- package/pp-core/workflows/init/steps/reachability-outcome.md +70 -0
- package/pp-core/workflows/init.md +232 -272
- package/pp-core/workflows/new-project.md +31 -23
- package/pp-core/workflows/plan-phase.md +99 -43
- package/pp-core/workflows/quick.md +120 -2
- package/pp-core/workflows/secure-phase.md +1 -1
- package/pp-core/workflows/ship.md +57 -24
- package/pp-core/workflows/update.md +3 -3
- package/pp-core/workflows/validate-phase.md +60 -1
- package/pp-core/workflows/vault-review.md +325 -0
- package/pp-core/workflows/verify-work.md +13 -12
- package/scripts/changeset/cli.cjs +6 -5
- package/scripts/changeset/lint.cjs +0 -0
- package/scripts/changeset/new.cjs +33 -50
- package/scripts/dev-env.cjs +25 -85
- package/scripts/gen-capability-registry.cjs +199 -0
- package/scripts/gen-practice-arithmetic-contract.cjs +412 -0
- package/scripts/lib/allowlist-ratchet.cjs +1 -103
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -2
- package/scripts/lint-docs-required.cjs +0 -0
- package/scripts/lint-pr-check-project-dir.cjs +1 -3
- package/scripts/lint-test-file-count.allowlist.json +13 -2
- package/scripts/practice-arithmetic-contract.allow.json +35 -0
- package/scripts/prompt-injection-scan.sh +22 -15
- package/scripts/record-vault-mode-golden.cjs +89 -0
- package/scripts/release-channel.cjs +0 -0
- package/scripts/sync-manifest-versions.cjs +5 -4
- package/scripts/sync-rulesets.sh +1 -1
- package/scripts/update-size-baseline.cjs +30 -274
- package/scripts/vault-calibrate.cjs +996 -0
- package/scripts/verify-opengsd-sweep.cjs +3 -5
- package/scripts/workflow-size.cjs +9 -61
- package/pp-core/bin/lib/dispatch-plan.cjs +0 -472
- package/pp-core/bin/lib/install-run.cjs +0 -536
- package/pp-core/bin/lib/phase-tier.cjs +0 -467
- package/pp-core/bin/lib/plan-graph.cjs +0 -368
- package/pp-core/references/planner-plan-graph.md +0 -66
- package/pp-core/workflows/execute-phase/steps/checkpoint-handling.md +0 -45
- package/pp-core/workflows/execute-phase/steps/install-run.md +0 -29
- package/pp-core/workflows/execute-phase/steps/phase-close-rebaseline.md +0 -23
- package/pp-core/workflows/execute-phase/steps/serial-group-dispatch.md +0 -72
- package/pp-core/workflows/plan-phase/steps/phase-tier.md +0 -34
- package/scripts/lib/size-budget.cjs +0 -311
- package/scripts/lint-neutrality-names.cjs +0 -694
- package/scripts/lint-org-coordinates.allowlist.json +0 -35
- package/scripts/lint-org-coordinates.cjs +0 -426
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
const packageName = "@pareto4/pp-core";
|
|
7
7
|
const binName = "pp-core";
|
|
8
|
-
const repoSlug = "
|
|
9
|
-
const repoUrl = "https://
|
|
10
|
-
const changelogRawUrl = "https://
|
|
8
|
+
const repoSlug = "pareto000/pp-core";
|
|
9
|
+
const repoUrl = "https://github.com/pareto000/pp-core";
|
|
10
|
+
const changelogRawUrl = "https://raw.githubusercontent.com/pareto000/pp-core/main/CHANGELOG.md";
|
|
11
11
|
const cacheSlug = "pareto4-pp-core";
|
|
12
12
|
const updateCacheFileName = "pp-update-check-pareto4-pp-core.json";
|
|
13
13
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Unsupported in this router:
|
|
7
7
|
* - scaffold: routed through top-level scaffold command.
|
|
8
8
|
*
|
|
9
|
-
* CJS-only subcommands: mvp-mode
|
|
9
|
+
* CJS-only subcommands: mvp-mode (dispatched directly, before hub).
|
|
10
10
|
*
|
|
11
11
|
* #3788: dispatch is mediated by CommandRoutingHub. The public entry point
|
|
12
12
|
* and observable CLI behaviour are unchanged.
|
|
@@ -51,28 +51,6 @@ function routePhaseCommand({ phase, args, cwd, raw, error }) {
|
|
|
51
51
|
phase.cmdPhaseMvpMode(cwd, args.slice(2), raw);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
// `dispatch-plan` (pack 9): read-only; the executor spawns, suite runs and
|
|
55
|
-
// tracking commits execute-phase obeys (src/dispatch-plan.cts).
|
|
56
|
-
if (subcommand === 'dispatch-plan') {
|
|
57
|
-
phase.cmdPhaseDispatchPlan(cwd, args.slice(2), raw);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
// `install-run` (pack 9): heavy-tier verification of the installed product —
|
|
61
|
-
// pack, install, init, run the phase's install checks (src/install-run.cts).
|
|
62
|
-
if (subcommand === 'install-run') {
|
|
63
|
-
phase.cmdPhaseInstallRun(cwd, args.slice(2), raw);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
// `tier` / `tier-propose` (pack 9): the phase's ceremony tier and its
|
|
67
|
-
// proposal (src/phase-tier.cts); `tier-propose --record` writes ROADMAP.
|
|
68
|
-
if (subcommand === 'tier') {
|
|
69
|
-
phase.cmdPhaseTier(cwd, args.slice(2), raw);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
if (subcommand === 'tier-propose') {
|
|
73
|
-
phase.cmdPhaseTierPropose(cwd, args.slice(2), raw);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
54
|
// ── Build the CJS registry ──────────────────────────────────────────────────
|
|
77
55
|
// Each handler receives a ctx object from the hub and must return a HubResult.
|
|
78
56
|
const cjsRegistry = {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* this caller use it?
|
|
5
5
|
*
|
|
6
6
|
* THE owner of that decision for every consumer of the raw phase locator
|
|
7
|
-
|
|
7
|
+
* (PBI 75323, quick 261009-gvf). The raw locator in phase-locator.cts answers a
|
|
8
8
|
* phase token from the live `phases/` tree first and then falls through to the
|
|
9
9
|
* closed milestones' `milestones/<v>-phases/` archives, marking such a match
|
|
10
10
|
* with the archive's version. It applies no milestone compare, and it must not:
|
|
@@ -56,10 +56,6 @@ const clock_cjs_1 = require("./clock.cjs");
|
|
|
56
56
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- uat-predicate.cjs is an export= CommonJS module
|
|
57
57
|
const uatPredicate = require("./uat-predicate.cjs");
|
|
58
58
|
const { evaluateUatPassed } = uatPredicate;
|
|
59
|
-
const plan_graph_cjs_1 = require("./plan-graph.cjs");
|
|
60
|
-
const dispatch_plan_cjs_1 = require("./dispatch-plan.cjs");
|
|
61
|
-
const phase_tier_cjs_1 = require("./phase-tier.cjs");
|
|
62
|
-
const install_run_cjs_1 = require("./install-run.cjs");
|
|
63
59
|
const { planningDir, withPlanningLock, milestonePathsFor } = planningWorkspace;
|
|
64
60
|
const { extractFrontmatter } = frontmatterMod;
|
|
65
61
|
const { readModifyWriteStateMd, stateExtractField, stateReplaceField, stateReplaceFieldWithFallback, syncStateFrontmatter, withStateLock, updatePerformanceMetricsSection, } = stateMod;
|
|
@@ -408,140 +404,6 @@ function cmdPhasePlanIndex(cwd, phase, raw) {
|
|
|
408
404
|
if (!phase) {
|
|
409
405
|
error('phase required for phase-plan-index');
|
|
410
406
|
}
|
|
411
|
-
const built = buildPhasePlanIndex(cwd, phase);
|
|
412
|
-
if (built.fatal !== undefined) {
|
|
413
|
-
error(built.fatal);
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
output(built.result, raw);
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* `phase.dispatch-plan <phase> [--wave N] [--gaps-only] [--use-worktrees true|false]`:
|
|
420
|
-
* the executor spawns, builds, suite runs and tracking commits for the phase's
|
|
421
|
-
* incomplete plans (computed by src/dispatch-plan.cts from the plan inventory).
|
|
422
|
-
*/
|
|
423
|
-
function cmdPhaseDispatchPlan(cwd, args, raw) {
|
|
424
|
-
const parsed = (0, dispatch_plan_cjs_1.parseDispatchPlanArgs)(args);
|
|
425
|
-
if ('error' in parsed) {
|
|
426
|
-
error(parsed.error);
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
const built = buildPhasePlanIndex(cwd, parsed.phase);
|
|
430
|
-
if (built.fatal !== undefined) {
|
|
431
|
-
error(built.fatal);
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
if (built.phaseDir === null) {
|
|
435
|
-
output({ phase: built.result['phase'], error: 'Phase not found' }, raw);
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
const policy = (0, dispatch_plan_cjs_1.resolveDispatchPolicy)(cwd, parsed);
|
|
439
|
-
const plans = built.result['plans'].map((p) => {
|
|
440
|
-
const extra = built.extras.get(p['id']);
|
|
441
|
-
return {
|
|
442
|
-
id: p['id'],
|
|
443
|
-
title: p['title'] ?? null,
|
|
444
|
-
wave: p['wave'],
|
|
445
|
-
serial_group: p['serial_group'] ?? null,
|
|
446
|
-
files_modified: p['files_modified'],
|
|
447
|
-
autonomous: p['autonomous'],
|
|
448
|
-
has_summary: p['has_summary'],
|
|
449
|
-
requirements: extra?.requirements ?? [],
|
|
450
|
-
gap_closure: extra?.gapClosure ?? false,
|
|
451
|
-
};
|
|
452
|
-
});
|
|
453
|
-
const phaseDirRel = node_path_1.default.relative(cwd, built.phaseDir).split(node_path_1.default.sep).join('/');
|
|
454
|
-
const tier = (0, phase_tier_cjs_1.resolvePhaseTierForProject)(cwd, parsed.phase, parsed.tier);
|
|
455
|
-
output((0, dispatch_plan_cjs_1.computeDispatchPlan)(built.result['phase'], phaseDirRel, plans, policy, tier, { planBounceScript: tier.plan_bounce_script }), raw);
|
|
456
|
-
}
|
|
457
|
-
/**
|
|
458
|
-
* `phase.install-run <phase> [--tarball <tgz>] [--package-dir <dir>] [--no-build]`:
|
|
459
|
-
* pack, install into a temp project, init and run the phase's install checks
|
|
460
|
-
* against the installed copy; writes `<NN>-INSTALL-RUN.json` (src/install-run.cts).
|
|
461
|
-
*/
|
|
462
|
-
function cmdPhaseInstallRun(cwd, args, raw) {
|
|
463
|
-
const parsed = (0, install_run_cjs_1.parseInstallRunArgs)(args);
|
|
464
|
-
if ('error' in parsed) {
|
|
465
|
-
error(parsed.error, ERROR_REASON.USAGE);
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
let out;
|
|
469
|
-
try {
|
|
470
|
-
out = (0, install_run_cjs_1.runInstallRun)({ cwd, phase: parsed.phase, tarball: parsed.tarball, packageDir: parsed.packageDir, build: parsed.build });
|
|
471
|
-
}
|
|
472
|
-
catch (e) {
|
|
473
|
-
error(e.message);
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
output(out, raw);
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* `phase.tier <phase> [--tier light|standard|heavy]`: the phase's resolved
|
|
480
|
-
* ceremony tier — tier, source, gate set, suppressed gates (src/phase-tier.cts).
|
|
481
|
-
*/
|
|
482
|
-
function cmdPhaseTier(cwd, args, raw) {
|
|
483
|
-
const usage = 'Usage: phase tier <phase> [--tier light|standard|heavy]';
|
|
484
|
-
const parsed = (0, phase_tier_cjs_1.parseTierFlag)(args.filter((a) => a !== '--raw'));
|
|
485
|
-
if ('error' in parsed) {
|
|
486
|
-
error(`${parsed.error}. ${usage}`, ERROR_REASON.USAGE);
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
if (parsed.rest.length !== 1 || parsed.rest[0].startsWith('--')) {
|
|
490
|
-
error(parsed.rest.length === 0 ? `phase required for phase tier. ${usage}` : `phase tier takes one phase and --tier. ${usage}`, ERROR_REASON.USAGE);
|
|
491
|
-
return;
|
|
492
|
-
}
|
|
493
|
-
const phaseArg = parsed.rest[0];
|
|
494
|
-
output({ phase: phaseArg, ...(0, phase_tier_cjs_1.resolvePhaseTierForProject)(cwd, phaseArg, parsed.tier) }, raw);
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* `phase.tier-propose <phase> [--record] [--tier X]`: propose a tier from the
|
|
498
|
-
* phase's plans (`files_modified`) or, before planning, its requirement tags
|
|
499
|
-
* and ROADMAP text. `--record` writes it to the phase's ROADMAP `**Tier:**`
|
|
500
|
-
* field, marked `(proposed: …)`, unless the operator already chose one;
|
|
501
|
-
* `--record --tier X` records X as the operator's choice.
|
|
502
|
-
*/
|
|
503
|
-
function cmdPhaseTierPropose(cwd, args, raw) {
|
|
504
|
-
const usage = 'Usage: phase tier-propose <phase> [--record] [--tier light|standard|heavy]';
|
|
505
|
-
const parsed = (0, phase_tier_cjs_1.parseTierFlag)(args.filter((a) => a !== '--raw'));
|
|
506
|
-
if ('error' in parsed) {
|
|
507
|
-
error(`${parsed.error}. ${usage}`, ERROR_REASON.USAGE);
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
const doRecord = parsed.rest.includes('--record');
|
|
511
|
-
const positional = parsed.rest.filter((a) => a !== '--record');
|
|
512
|
-
if (positional.length !== 1 || positional[0].startsWith('--')) {
|
|
513
|
-
error(positional.length === 0 ? `phase required for phase tier-propose. ${usage}` : `phase tier-propose does not support ${positional.find((a) => a.startsWith('--')) ?? positional.join(' ')}. ${usage}`, ERROR_REASON.USAGE);
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
const phaseArg = positional[0];
|
|
517
|
-
const record = (0, phase_tier_cjs_1.readPhaseRecord)(cwd, phaseArg);
|
|
518
|
-
if (record.section === null) {
|
|
519
|
-
output({ phase: phaseArg, error: 'Phase not found in ROADMAP.md' }, raw);
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
const built = buildPhasePlanIndex(cwd, phaseArg);
|
|
523
|
-
const planRows = built.fatal === undefined && built.phaseDir !== null
|
|
524
|
-
? built.result['plans'].map((p) => ({ id: p['id'], files_modified: p['files_modified'] ?? [] }))
|
|
525
|
-
: [];
|
|
526
|
-
const reqMatch = record.section.match(/^\*\*Requirements:?\*\*[^\S\n]*:?[^\S\n]*([^\n]*)$/m);
|
|
527
|
-
const requirements = reqMatch ? reqMatch[1].replace(/[[\]]/g, '').split(',').map((s) => s.trim()).filter((s) => s !== '' && s !== 'TBD') : [];
|
|
528
|
-
const proposal = (0, phase_tier_cjs_1.proposePhaseTier)({ plans: planRows, requirements, roadmapText: record.section });
|
|
529
|
-
let recorded = null;
|
|
530
|
-
if (doRecord) {
|
|
531
|
-
recorded = parsed.tier !== null
|
|
532
|
-
? (0, phase_tier_cjs_1.recordPhaseTier)(cwd, phaseArg, parsed.tier, { proposed: false })
|
|
533
|
-
: (0, phase_tier_cjs_1.recordPhaseTier)(cwd, phaseArg, proposal.tier, { proposed: true, reason: proposal.reason });
|
|
534
|
-
}
|
|
535
|
-
const after = (0, phase_tier_cjs_1.resolvePhaseTierForProject)(cwd, phaseArg, parsed.tier);
|
|
536
|
-
output({
|
|
537
|
-
phase: phaseArg,
|
|
538
|
-
proposal,
|
|
539
|
-
phase_record: record.tier !== null ? { tier: record.tier, proposed: record.proposed } : null,
|
|
540
|
-
recorded,
|
|
541
|
-
effective: { tier: after.tier, source: after.source, suppressed: after.suppressed },
|
|
542
|
-
}, raw);
|
|
543
|
-
}
|
|
544
|
-
function buildPhasePlanIndex(cwd, phase) {
|
|
545
407
|
const phasesDir = node_path_1.default.join(planningDir(cwd), 'phases');
|
|
546
408
|
const normalized = normalizePhaseName(phase);
|
|
547
409
|
let phaseDir = null;
|
|
@@ -562,11 +424,8 @@ function buildPhasePlanIndex(cwd, phase) {
|
|
|
562
424
|
// phases dir doesn't exist
|
|
563
425
|
}
|
|
564
426
|
if (!phaseDir) {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
phaseDir: null,
|
|
568
|
-
extras: new Map(),
|
|
569
|
-
};
|
|
427
|
+
output({ phase: normalized, error: 'Phase not found', plans: [], waves: {}, incomplete: [], has_checkpoints: false }, raw);
|
|
428
|
+
return;
|
|
570
429
|
}
|
|
571
430
|
void phaseDirName; // used only to set phaseDir above
|
|
572
431
|
const phaseFiles = node_fs_1.default.readdirSync(phaseDir);
|
|
@@ -588,13 +447,6 @@ function buildPhasePlanIndex(cwd, phase) {
|
|
|
588
447
|
const xmlTasks = content.match(/<task[\s>]/gi) || [];
|
|
589
448
|
const mdTasks = content.match(/##\s*Task\s*\d+/gi) || [];
|
|
590
449
|
const taskCount = xmlTasks.length || mdTasks.length;
|
|
591
|
-
const taskTypes = xmlTasks.length > 0
|
|
592
|
-
? [...content.matchAll(/<task(\s[^>]*)?>/gi)].map((m) => /type=["']?([\w:-]+)/i.exec(m[1] ?? '')?.[1] ?? 'auto')
|
|
593
|
-
: mdTasks.map(() => 'auto');
|
|
594
|
-
const fmString = (key) => {
|
|
595
|
-
const value = fm[key];
|
|
596
|
-
return typeof value === 'string' && value.trim() !== '' ? value.trim() : null;
|
|
597
|
-
};
|
|
598
450
|
const parsedWave = parseInt(fm['wave'], 10);
|
|
599
451
|
const declaredWave = Number.isNaN(parsedWave) ? null : parsedWave;
|
|
600
452
|
let dependsOn = [];
|
|
@@ -617,10 +469,6 @@ function buildPhasePlanIndex(cwd, phase) {
|
|
|
617
469
|
filesModified = Array.isArray(fmFiles) ? fmFiles.map(String) : [String(fmFiles)];
|
|
618
470
|
}
|
|
619
471
|
const hasSummary = completedPlanIds.has(planId) || completedPlanIds.has(extractCanonicalPlanId(planFile));
|
|
620
|
-
const fmReqs = fm['requirements'];
|
|
621
|
-
const requirements = (Array.isArray(fmReqs) ? fmReqs.map(String) : typeof fmReqs === 'string' && fmReqs.trim() !== '' ? fmReqs.split(/[\s,]+/) : [])
|
|
622
|
-
.map((r) => r.trim())
|
|
623
|
-
.filter((r) => r !== '' && r !== '[]');
|
|
624
472
|
rawPlans.push({
|
|
625
473
|
id: planId,
|
|
626
474
|
declaredWave,
|
|
@@ -630,13 +478,6 @@ function buildPhasePlanIndex(cwd, phase) {
|
|
|
630
478
|
filesModified,
|
|
631
479
|
taskCount,
|
|
632
480
|
hasSummary,
|
|
633
|
-
title: (0, plan_graph_cjs_1.readPlanTitle)(fm['title']),
|
|
634
|
-
serialGroup: fmString('serial_group'),
|
|
635
|
-
chainReason: fmString('chain_reason'),
|
|
636
|
-
taskTypes,
|
|
637
|
-
requirements,
|
|
638
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string -- FrontmatterValue scalar-to-string
|
|
639
|
-
gapClosure: String(fm['gap_closure'] ?? '').trim() === 'true',
|
|
640
481
|
});
|
|
641
482
|
}
|
|
642
483
|
// ── Pass 2: topological level assignment via depends_on DAG ──────────────
|
|
@@ -645,31 +486,18 @@ function buildPhasePlanIndex(cwd, phase) {
|
|
|
645
486
|
const lower = p.id.toLowerCase();
|
|
646
487
|
const existing = seenLower.get(lower);
|
|
647
488
|
if (existing !== undefined) {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
};
|
|
489
|
+
error(`depends_on index collision in phase ${normalized}: plan IDs '${existing}' and '${p.id}' are identical when case-folded. Rename one file to avoid ambiguous dependency resolution.`);
|
|
490
|
+
return;
|
|
651
491
|
}
|
|
652
492
|
seenLower.set(lower, p.id);
|
|
653
493
|
}
|
|
654
494
|
const planMap = new Map(rawPlans.map((p) => [p.id.toLowerCase(), p]));
|
|
655
495
|
const canonicalToId = new Map(rawPlans.map((p) => [extractCanonicalPlanId(p.id).toLowerCase(), p.id]));
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
const graph = (0, plan_graph_cjs_1.computePlanGraph)(rawPlans.map((p) => ({
|
|
662
|
-
id: p.id,
|
|
663
|
-
title: p.title,
|
|
664
|
-
dependsOn: p.dependsOn.map(resolveDep).filter((d) => d !== undefined),
|
|
665
|
-
filesModified: p.filesModified,
|
|
666
|
-
serialGroup: p.serialGroup,
|
|
667
|
-
chainReason: p.chainReason,
|
|
668
|
-
taskTypes: p.taskTypes,
|
|
669
|
-
})));
|
|
670
|
-
if (graph.cycle) {
|
|
671
|
-
const cycleNodes = graph.cycle;
|
|
672
|
-
return { fatal: `depends_on cycle detected in phase ${normalized} — cycle involves: ${cycleNodes.join(', ')}` };
|
|
496
|
+
const { level, visited } = computeDependencyLevels(rawPlans, planMap, canonicalToId);
|
|
497
|
+
if (visited < rawPlans.length) {
|
|
498
|
+
const cycleNodes = rawPlans.filter((p) => !level.has(p.id)).map((p) => p.id);
|
|
499
|
+
error(`depends_on cycle detected in phase ${normalized} — cycle involves: ${cycleNodes.join(', ')}`);
|
|
500
|
+
return;
|
|
673
501
|
}
|
|
674
502
|
// ── Pass 3: determine lowest bucket key and build output ─────────────────
|
|
675
503
|
const anyWaveZero = rawPlans.some((p) => p.declaredWave === 0);
|
|
@@ -686,16 +514,14 @@ function buildPhasePlanIndex(cwd, phase) {
|
|
|
686
514
|
if (!rawPlan.hasSummary) {
|
|
687
515
|
incomplete.push(rawPlan.id);
|
|
688
516
|
}
|
|
689
|
-
const computedWave = (
|
|
517
|
+
const computedWave = (level.get(rawPlan.id) ?? 0) + levelOffset;
|
|
690
518
|
const effectiveWave = computedWave;
|
|
691
519
|
if (rawPlan.declaredWave !== null && rawPlan.declaredWave !== computedWave) {
|
|
692
520
|
warnings.push(`Plan ${rawPlan.id}: declared wave: ${rawPlan.declaredWave} but depends_on DAG places it in wave ${computedWave}`);
|
|
693
521
|
}
|
|
694
522
|
const plan = {
|
|
695
523
|
id: rawPlan.id,
|
|
696
|
-
title: rawPlan.title,
|
|
697
524
|
wave: effectiveWave,
|
|
698
|
-
serial_group: graph.serialGroupOf[rawPlan.id] ?? null,
|
|
699
525
|
depends_on: rawPlan.dependsOn.map((dep) => {
|
|
700
526
|
const lower = String(dep).toLowerCase();
|
|
701
527
|
return planMap.has(lower) ? planMap.get(lower).id : dep;
|
|
@@ -717,28 +543,14 @@ function buildPhasePlanIndex(cwd, phase) {
|
|
|
717
543
|
phase: normalized,
|
|
718
544
|
plans,
|
|
719
545
|
waves,
|
|
720
|
-
serial_groups: Object.fromEntries(graph.serialGroups.map((g) => [g.name, { wave: g.level + levelOffset, plans: g.plans, shared_files: g.shared_files }])),
|
|
721
|
-
graph: {
|
|
722
|
-
plan_count: graph.plan_count,
|
|
723
|
-
wave_count: graph.wave_count,
|
|
724
|
-
longest_chain: graph.longest_chain,
|
|
725
|
-
chain_check: graph.chain_check,
|
|
726
|
-
implicit_edges: graph.implicitEdges,
|
|
727
|
-
merge_candidates: graph.merge_candidates,
|
|
728
|
-
},
|
|
729
546
|
incomplete,
|
|
730
547
|
has_checkpoints: hasCheckpoints,
|
|
731
548
|
};
|
|
732
|
-
warnings.push(...graph.warnings);
|
|
733
549
|
if (planNamingWarning)
|
|
734
550
|
result['warning'] = planNamingWarning;
|
|
735
551
|
if (warnings.length > 0)
|
|
736
552
|
result['warnings'] = warnings;
|
|
737
|
-
|
|
738
|
-
result,
|
|
739
|
-
phaseDir,
|
|
740
|
-
extras: new Map(rawPlans.map((p) => [p.id, { requirements: p.requirements, gapClosure: p.gapClosure }])),
|
|
741
|
-
};
|
|
553
|
+
output(result, raw);
|
|
742
554
|
}
|
|
743
555
|
function cmdPhaseAdd(cwd, description, raw, customId) {
|
|
744
556
|
if (!description) {
|
|
@@ -1657,10 +1469,6 @@ module.exports = {
|
|
|
1657
1469
|
cmdPhaseNextDecimal,
|
|
1658
1470
|
cmdFindPhase,
|
|
1659
1471
|
cmdPhasePlanIndex,
|
|
1660
|
-
cmdPhaseDispatchPlan,
|
|
1661
|
-
cmdPhaseInstallRun,
|
|
1662
|
-
cmdPhaseTier,
|
|
1663
|
-
cmdPhaseTierPropose,
|
|
1664
1472
|
cmdPhaseAdd,
|
|
1665
1473
|
cmdPhaseAddBatch,
|
|
1666
1474
|
cmdPhaseMvpMode,
|
|
@@ -34,8 +34,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
34
34
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
35
35
|
};
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.BINDINGS_COORDINATE_FIELDS = exports.MACHINE_SPECIFIC_CLONE_TARGET_PATTERNS = exports.VAULT_REPO_PATTERN_SOURCE = exports.PLATFORM_REPO_PATTERN_SOURCE = exports.CONTRACT_SCHEMA_VERSION = void 0;
|
|
37
|
+
exports.BINDINGS_COORDINATE_FIELDS = exports.MACHINE_SPECIFIC_CLONE_TARGET_PATTERNS = exports.VAULT_REPO_PATTERN_SOURCE = exports.PLATFORM_REPO_PATTERN_SOURCE = exports.SLUG_RE = exports.CONTRACT_SCHEMA_VERSION = void 0;
|
|
38
38
|
exports.validateBindings = validateBindings;
|
|
39
|
+
exports.redactCoordinateForEmission = redactCoordinateForEmission;
|
|
40
|
+
exports.redactBindingsField = redactBindingsField;
|
|
39
41
|
exports.redactBindingsForEmission = redactBindingsForEmission;
|
|
40
42
|
exports.cmdPlatformBindings = cmdPlatformBindings;
|
|
41
43
|
exports.cmdValidateBindings = cmdValidateBindings;
|
|
@@ -65,7 +67,7 @@ const SCHEMA_VERSION_RE = /^\d+\.\d+\.\d+$/;
|
|
|
65
67
|
exports.CONTRACT_SCHEMA_VERSION = '1.1.0';
|
|
66
68
|
const PLATFORM_TAG_RE = /^v\d+\.\d+\.\d+/;
|
|
67
69
|
// Provisional namespace pattern (lenient): only enforced if client.slug is present.
|
|
68
|
-
|
|
70
|
+
exports.SLUG_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
69
71
|
// A host-relative path of two or more slash-separated segments built from
|
|
70
72
|
// word/dot/hyphen characters — e.g. `pareto4/pareto-platform-gcp` or Azure's
|
|
71
73
|
// four-segment `org/project/_git/repo`. This is the pre-v1.1.0 vault-repo
|
|
@@ -77,8 +79,8 @@ const HOST_RELATIVE_SLUG_SOURCE = '^[\\w.-]+(?:\\/[\\w.-]+)+$';
|
|
|
77
79
|
* A host-relative path of two or more segments. Compiled into
|
|
78
80
|
* `platform.repo.pattern` by `scripts/gen-platform-bindings-schema.cjs` so
|
|
79
81
|
* the runtime regex and the schema pattern cannot drift (D-06). Deliberately
|
|
80
|
-
* accepts no URL and no SSH form: `
|
|
81
|
-
* host from `platform.host` itself (Phase 31 D-09), so a full URL here would
|
|
82
|
+
* accepts no URL and no SSH form: `resolveLatestPlatformTag` (compose-bindings)
|
|
83
|
+
* composes the host from `platform.host` itself (Phase 31 D-09), so a full URL here would
|
|
82
84
|
* give the host two competing encodings — `platform.host` is authoritative.
|
|
83
85
|
*/
|
|
84
86
|
exports.PLATFORM_REPO_PATTERN_SOURCE = HOST_RELATIVE_SLUG_SOURCE;
|
|
@@ -183,7 +185,7 @@ function validateBindings(o) {
|
|
|
183
185
|
// Provisional namespaces — lenient. A missing/unknown namespace is fine; only
|
|
184
186
|
// a PRESENT slug field that is malformed is flagged (it never gates on absence).
|
|
185
187
|
if (isObject(o.client) && o.client.slug !== undefined) {
|
|
186
|
-
if (typeof o.client.slug !== 'string' || !SLUG_RE.test(o.client.slug)) {
|
|
188
|
+
if (typeof o.client.slug !== 'string' || !exports.SLUG_RE.test(o.client.slug)) {
|
|
187
189
|
errors.push('client.slug: present but not a url-safe lowercase slug');
|
|
188
190
|
}
|
|
189
191
|
}
|
|
@@ -203,35 +205,53 @@ function validateBindings(o) {
|
|
|
203
205
|
// IN-03: project.slug — symmetric lenient check matching client.slug behaviour.
|
|
204
206
|
// The schema defines the same ^[a-z0-9][a-z0-9-]*$ pattern for both fields.
|
|
205
207
|
if (isObject(o.project) && o.project.slug !== undefined) {
|
|
206
|
-
if (typeof o.project.slug !== 'string' || !SLUG_RE.test(o.project.slug)) {
|
|
208
|
+
if (typeof o.project.slug !== 'string' || !exports.SLUG_RE.test(o.project.slug)) {
|
|
207
209
|
errors.push('project.slug: present but not a url-safe lowercase slug');
|
|
208
210
|
}
|
|
209
211
|
}
|
|
210
212
|
return { valid: errors.length === 0, errors, warnings };
|
|
211
213
|
}
|
|
212
214
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
215
|
+
* VAULT-EGRESS-1 (quick 261005-8py gap closure): the `.platform-bindings.json`
|
|
216
|
+
* fields that carry a remote repo coordinate, and therefore the fields a
|
|
217
|
+
* credential (`https://user:TOKEN@host/…`, `user:TOKEN@host:path`) can ride in.
|
|
218
|
+
* Hosts are deliberately NOT listed: `platform.host` is read for real use by
|
|
219
|
+
* /pp-init's provisioning step (`--pick platform.host`), and a host is a bare
|
|
220
|
+
* host by contract.
|
|
216
221
|
*/
|
|
217
222
|
exports.BINDINGS_COORDINATE_FIELDS = Object.freeze(['platform.repo', 'client.vaultRepo']);
|
|
218
223
|
/**
|
|
219
|
-
* Emission-only:
|
|
220
|
-
*
|
|
221
|
-
* required
|
|
222
|
-
*
|
|
224
|
+
* Emission-only: the display-safe form of one coordinate, through the ONE
|
|
225
|
+
* owner (`redactCloneTarget` in `src/vault.cts`) — never a second redactor.
|
|
226
|
+
* Lazily required, the idiom `src/vault-command-router.cts` uses, so this
|
|
227
|
+
* module's load graph is unchanged. Never call this on a value that is written
|
|
228
|
+
* to disk or handed to git: those keep the RAW coordinate.
|
|
229
|
+
*/
|
|
230
|
+
function redactCoordinateForEmission(value) {
|
|
231
|
+
if (typeof value !== 'string' || value === '')
|
|
232
|
+
return value;
|
|
233
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
234
|
+
const { redactCloneTarget } = require('./vault.cjs');
|
|
235
|
+
return redactCloneTarget(value) ?? value;
|
|
236
|
+
}
|
|
237
|
+
/** Emission-only: `value` redacted when `field` (dotted) is a coordinate field. */
|
|
238
|
+
function redactBindingsField(field, value) {
|
|
239
|
+
return exports.BINDINGS_COORDINATE_FIELDS.includes(field) ? redactCoordinateForEmission(value) : value;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Emission-only: a copy of a bindings-shaped object with every coordinate
|
|
243
|
+
* field routed through the owner. The input is never mutated — callers that
|
|
244
|
+
* compare (drift, `action`) or write keep the raw object.
|
|
223
245
|
*/
|
|
224
246
|
function redactBindingsForEmission(obj) {
|
|
225
247
|
if (!isObject(obj))
|
|
226
248
|
return obj;
|
|
227
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
228
|
-
const { redactCloneTarget } = require('./vault.cjs');
|
|
229
249
|
const copy = JSON.parse(JSON.stringify(obj));
|
|
230
250
|
for (const field of exports.BINDINGS_COORDINATE_FIELDS) {
|
|
231
251
|
const [ns, key] = field.split('.');
|
|
232
252
|
const parent = copy[ns];
|
|
233
253
|
if (isObject(parent) && typeof parent[key] === 'string') {
|
|
234
|
-
parent[key] =
|
|
254
|
+
parent[key] = redactCoordinateForEmission(parent[key]);
|
|
235
255
|
}
|
|
236
256
|
}
|
|
237
257
|
return copy;
|
|
@@ -281,9 +301,10 @@ function cmdPlatformBindings(cwd, args, raw) {
|
|
|
281
301
|
output(validateBindings(parsed), raw);
|
|
282
302
|
return;
|
|
283
303
|
}
|
|
284
|
-
// present + valid → echo the bindings under a present flag.
|
|
285
|
-
//
|
|
286
|
-
//
|
|
304
|
+
// present + valid → echo the bindings under a present flag. The coordinate
|
|
305
|
+
// fields are display-safe (VAULT-EGRESS-1); every other field is verbatim,
|
|
306
|
+
// and the one consumer of the whole dump (vault-load-gate.md) reads only
|
|
307
|
+
// `client.vaultRepo`'s presence and the raw `client.vaultRef`.
|
|
287
308
|
output(Object.assign({ present: true }, redactBindingsForEmission(parsed)), raw);
|
|
288
309
|
}
|
|
289
310
|
// Anchored regex for `?ref=` values in module source lines (T-07-04: untrusted text,
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
*
|
|
47
47
|
* Every function here treats its input as UNTRUSTED TEXT. The review file
|
|
48
48
|
* this module parses is authored partly by an untrusted client vault
|
|
49
|
-
* (`REFERENCE_DATA_PREAMBLE`, `FENCE_START_MARKER`/`FENCE_END_MARKER`
|
|
50
|
-
*
|
|
51
|
-
* content) and partly by an LLM reviewer whose output is not guaranteed
|
|
49
|
+
* (`REFERENCE_DATA_PREAMBLE`, `FENCE_START_MARKER`/`FENCE_END_MARKER` — read
|
|
50
|
+
* from the vault-index leaf, their one owner — and heading-shaped lines can
|
|
51
|
+
* all legitimately appear inside client body content) and partly by an LLM reviewer whose output is not guaranteed
|
|
52
52
|
* well-formed. The module performs zero I/O: no environment-variable read, no
|
|
53
53
|
* stdout write, no early process termination, no filesystem access, no
|
|
54
54
|
* dynamic `require`, no `eval`. It is pure text in, structure out — the CLI arm
|
|
@@ -163,15 +163,19 @@
|
|
|
163
163
|
*
|
|
164
164
|
* ## Reuses (no new runtime dependency)
|
|
165
165
|
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
166
|
+
* One import, and no runtime dependency: the dependency-free vault-index leaf
|
|
167
|
+
* (`src/vault-index.cts`), the single owner of the external-content marker
|
|
168
|
+
* literals (D-17/D-26, 14-04). Everything else is pure string processing over
|
|
169
|
+
* already-materialized text, recognising the markers and the zero-width-space
|
|
170
|
+
* defanged form `defangFenceMarkers` produces, but reimplementing no logic
|
|
171
|
+
* from `src/vault-practices.cts`.
|
|
170
172
|
*
|
|
171
173
|
* ADR-457 build-at-publish: this TypeScript file is the SOURCE OF TRUTH. It
|
|
172
174
|
* compiles to the git-ignored `pp-core/bin/lib/practices-review-check.cjs`;
|
|
173
175
|
* do NOT hand-edit the compiled output.
|
|
174
176
|
*/
|
|
177
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
178
|
+
const vaultIndexLeaf = require("./vault-index.cjs");
|
|
175
179
|
// ─── Literals ────────────────────────────────────────────────────────────────
|
|
176
180
|
//
|
|
177
181
|
// Copied character-for-character from pp-core/workflows/code-review.md's
|
|
@@ -182,8 +186,10 @@ const SECTION_HEADING = '## Practices Findings (client vault)';
|
|
|
182
186
|
const FINDING_HEADING = '### PR-';
|
|
183
187
|
const ASKS_LABEL = '**Asks:**';
|
|
184
188
|
const FILE_LABEL = '**File:**';
|
|
185
|
-
|
|
186
|
-
|
|
189
|
+
// D-17/D-26 (14-04): the marker values come from the vault-index leaf, their
|
|
190
|
+
// one owner; the local names stay so every call site below reads unchanged.
|
|
191
|
+
const FENCE_START_MARKER = vaultIndexLeaf.EXTERNAL_CONTENT_FENCE_START;
|
|
192
|
+
const FENCE_END_MARKER = vaultIndexLeaf.EXTERNAL_CONTENT_FENCE_END;
|
|
187
193
|
// The fixed reference-data disclaimer sentences `boundedFencedExcerpt`
|
|
188
194
|
// (src/vault-practices.cts) prepends to EVERY excerpt. `clientBodyOf` strips
|
|
189
195
|
// these before an excerpt enters the unfenced-quote comparison corpus, so a
|
|
@@ -28,7 +28,7 @@ const { loadConfig } = configLoader;
|
|
|
28
28
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
29
29
|
const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
|
|
30
30
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
31
|
-
//
|
|
31
|
+
// PBI 75232: the start-command fallback uses the pp-named alias (same function).
|
|
32
32
|
const runtime_slash_cjs_2 = require("./runtime-slash.cjs");
|
|
33
33
|
const runtime_name_policy_cjs_1 = require("./runtime-name-policy.cjs");
|
|
34
34
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- planning-workspace.cjs is an export= CommonJS module
|