@pareto4/pp-core 1.5.4 → 1.6.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/agents/pp-code-fixer.md +3 -3
- package/bin/install.js +0 -6
- package/commands/pp-init.md +36 -0
- package/commands/pp-ns-project.md +2 -1
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/pp-core/bin/lib/agent-install-check.cjs +1 -1
- package/pp-core/bin/lib/audit-command-router.cjs +3 -3
- package/pp-core/bin/lib/audit.cjs +1 -1
- package/pp-core/bin/lib/capability-activation.cjs +1 -1
- package/pp-core/bin/lib/capability-registry.cjs +138 -5
- package/pp-core/bin/lib/capability-state.cjs +1 -1
- package/pp-core/bin/lib/capability-writer.cjs +1 -1
- package/pp-core/bin/lib/check-command-router.cjs +190 -8
- package/pp-core/bin/lib/cjs-command-router-adapter.cjs +1 -1
- package/pp-core/bin/lib/clusters.cjs +1 -0
- package/pp-core/bin/lib/code-review-flags.cjs +1 -1
- package/pp-core/bin/lib/command-aliases.cjs +7 -0
- package/pp-core/bin/lib/config-loader.cjs +1 -1
- package/pp-core/bin/lib/config.cjs +1 -1
- package/pp-core/bin/lib/context-utilization.cjs +1 -1
- package/pp-core/bin/lib/docs.cjs +1 -1
- package/pp-core/bin/lib/frontmatter.cjs +1 -1
- package/pp-core/bin/lib/git-base-branch.cjs +2 -2
- package/pp-core/bin/lib/graphify-command-router.cjs +4 -4
- package/pp-core/bin/lib/graphify.cjs +1 -1
- package/pp-core/bin/lib/gsd2-import.cjs +1 -1
- package/pp-core/bin/lib/init-command-router.cjs +1 -1
- package/pp-core/bin/lib/init.cjs +1 -1
- package/pp-core/bin/lib/intel-command-router.cjs +5 -5
- package/pp-core/bin/lib/intel.cjs +1 -1
- package/pp-core/bin/lib/io.cjs +4 -2
- package/pp-core/bin/lib/loop-resolver.cjs +1 -1
- package/pp-core/bin/lib/phase-command-router.cjs +1 -1
- package/pp-core/bin/lib/phases-command-router.cjs +1 -1
- package/pp-core/bin/lib/plan-drift-guard.cjs +1 -1
- package/pp-core/bin/lib/platform-bindings.cjs +336 -0
- package/pp-core/bin/lib/profile-output.cjs +216 -1
- package/pp-core/bin/lib/prohibition-enforcement.cjs +2 -2
- package/pp-core/bin/lib/roadmap-command-router.cjs +2 -2
- package/pp-core/bin/lib/roadmap-parser.cjs +1 -1
- package/pp-core/bin/lib/state-command-router.cjs +1 -1
- package/pp-core/bin/lib/state.cjs +2 -2
- package/pp-core/bin/lib/validate-command-router.cjs +1 -1
- package/pp-core/bin/lib/verify-command-router.cjs +1 -1
- package/pp-core/bin/lib/verify.cjs +1 -1
- package/pp-core/bin/lib/worktree-base-ref.cjs +2 -2
- package/pp-core/bin/lib/worktree-safety.cjs +1 -1
- package/pp-core/bin/pp-tools.cjs +61 -24
- package/pp-core/workflows/discovery-sprint.md +27 -10
- package/pp-core/workflows/execute-phase/steps/client-context-gate.md +37 -0
- package/pp-core/workflows/execute-phase.md +4 -0
- package/pp-core/workflows/init.md +530 -0
- package/pp-core/workflows/new-project.md +54 -1
- package/pp-core/workflows/ship.md +24 -1
- package/pp-core/workflows/verify-work.md +1 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -0
- package/assets/gsd-logo-2000-transparent.png +0 -0
- package/assets/gsd-logo-2000-transparent.svg +0 -17
- package/assets/gsd-logo-2000.png +0 -0
- package/assets/gsd-logo-2000.svg +0 -21
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* Manifest-backed verify subcommand router.
|
|
4
|
-
* Keeps
|
|
4
|
+
* Keeps pp-tools.cjs thin while preserving existing command semantics.
|
|
5
5
|
*
|
|
6
6
|
* ADR-457 build-at-publish: the hand-written bin/lib/verify-command-router.cjs
|
|
7
7
|
* collapsed to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
|
|
@@ -1432,7 +1432,7 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
1432
1432
|
getMilestoneFromPhaseId: getMilestoneFromPhaseId,
|
|
1433
1433
|
});
|
|
1434
1434
|
for (const mm of mismatches) {
|
|
1435
|
-
addIssue('warning', 'W021', `Phase ${mm.phaseId}: integer prefix implies ${mm.expectedMilestone} but listed under ${mm.foundInMilestone}`, 'Run `
|
|
1435
|
+
addIssue('warning', 'W021', `Phase ${mm.phaseId}: integer prefix implies ${mm.expectedMilestone} but listed under ${mm.foundInMilestone}`, 'Run `pp-tools roadmap upgrade --convention milestone-prefixed` to migrate (dry-run by default)');
|
|
1436
1436
|
}
|
|
1437
1437
|
}
|
|
1438
1438
|
}
|
|
@@ -94,9 +94,9 @@ function parseJsonc(text) {
|
|
|
94
94
|
}
|
|
95
95
|
// ─── Message constants (verbatim — downstream docs/tests depend on these) ─────
|
|
96
96
|
function buildMsgDiverged(headSha, forkRef, forkSha) {
|
|
97
|
-
return `⚠ Worktree base mismatch: HEAD (${shortSha(headSha)}) differs from ${forkRef} (${shortSha(forkSha)}). Running this phase sequentially on the main working tree. To keep parallel worktrees, set worktree.baseRef:"head" in .claude/settings.local.json (or run:
|
|
97
|
+
return `⚠ Worktree base mismatch: HEAD (${shortSha(headSha)}) differs from ${forkRef} (${shortSha(forkSha)}). Running this phase sequentially on the main working tree. To keep parallel worktrees, set worktree.baseRef:"head" in .claude/settings.local.json (or run: pp-tools worktree set-baseref). See #683.`;
|
|
98
98
|
}
|
|
99
|
-
const MSG_UNKNOWN = `⚠ Cannot determine the worktree fork base (origin/HEAD unresolved). Running this phase sequentially on the main working tree to avoid a base mismatch. To keep parallel worktrees, set worktree.baseRef:"head" in .claude/settings.local.json (or run:
|
|
99
|
+
const MSG_UNKNOWN = `⚠ Cannot determine the worktree fork base (origin/HEAD unresolved). Running this phase sequentially on the main working tree to avoid a base mismatch. To keep parallel worktrees, set worktree.baseRef:"head" in .claude/settings.local.json (or run: pp-tools worktree set-baseref). See #683.`;
|
|
100
100
|
// ─── Exports ──────────────────────────────────────────────────────────────────
|
|
101
101
|
/**
|
|
102
102
|
* Returns the first 8 characters of a SHA, or '' if null/empty.
|
|
@@ -958,7 +958,7 @@ function pruneOrphanedWorktrees(repoRoot) {
|
|
|
958
958
|
const plan = planWorktreePrune(repoRoot, { allowDestructive: false }, { parseWorktreePorcelain });
|
|
959
959
|
const pruneResult = executeWorktreePrunePlan(plan);
|
|
960
960
|
if (pruneResult && pruneResult.timedOut) {
|
|
961
|
-
process.stderr.write('[
|
|
961
|
+
process.stderr.write('[pp-tools] WARNING: worktree health check degraded' +
|
|
962
962
|
' — git worktree prune timed out after 10s.' +
|
|
963
963
|
' Orphaned worktree metadata may remain until the next successful run.\n');
|
|
964
964
|
}
|
package/pp-core/bin/pp-tools.cjs
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Replaces repetitive inline bash patterns across ~50 GSD command/workflow/agent files.
|
|
7
7
|
* Centralizes: config parsing, model resolution, phase lookup, git commits, summary verification.
|
|
8
8
|
*
|
|
9
|
-
* Usage: node
|
|
9
|
+
* Usage: node pp-tools.cjs <command> [args] [--raw] [--pick <field>]
|
|
10
10
|
*
|
|
11
11
|
* Atomic Commands:
|
|
12
12
|
* state load Load project config + state
|
|
@@ -209,6 +209,7 @@ const phase = require('./lib/phase.cjs');
|
|
|
209
209
|
const roadmap = require('./lib/roadmap.cjs');
|
|
210
210
|
const verify = require('./lib/verify.cjs');
|
|
211
211
|
const config = require('./lib/config.cjs');
|
|
212
|
+
const platformBindings = require('./lib/platform-bindings.cjs');
|
|
212
213
|
const template = require('./lib/template.cjs');
|
|
213
214
|
const milestone = require('./lib/milestone.cjs');
|
|
214
215
|
const commands = require('./lib/commands.cjs');
|
|
@@ -236,6 +237,7 @@ const { routeTaskCommand } = require('./lib/task-command-router.cjs');
|
|
|
236
237
|
const { parseNamedArgs, parseMultiwordArg } = require('./lib/command-arg-projection.cjs');
|
|
237
238
|
const { cmdGitBaseBranch } = require('./lib/git-base-branch.cjs');
|
|
238
239
|
const { getEffectiveAuthority, classifyDriftSeverity } = require('./lib/plan-drift-guard.cjs');
|
|
240
|
+
const profileOutput = require('./lib/profile-output.cjs');
|
|
239
241
|
|
|
240
242
|
// ─── Bridge collapsed (Phase 4) ────────────────────────────────────────────────
|
|
241
243
|
// Non-family commands now run through their CJS handlers directly. Keep the
|
|
@@ -251,7 +253,7 @@ const { getEffectiveAuthority, classifyDriftSeverity } = require('./lib/plan-dri
|
|
|
251
253
|
* @param {object} opts
|
|
252
254
|
* @param {string} opts.registryCommand - legacy bridge placeholder
|
|
253
255
|
* @param {string[]} opts.registryArgs - legacy bridge placeholder
|
|
254
|
-
* @param {string} opts.legacyCommand - original
|
|
256
|
+
* @param {string} opts.legacyCommand - original pp-tools command name
|
|
255
257
|
* @param {string[]} opts.legacyArgs - original args
|
|
256
258
|
* @param {string} opts.cwd - project dir
|
|
257
259
|
* @param {boolean} opts.raw - raw output mode
|
|
@@ -291,7 +293,7 @@ function _dispatchNonFamily({ registryCommand, registryArgs, legacyCommand, lega
|
|
|
291
293
|
* before requiring — defense-in-depth against corrupted/hand-edited registry entries.
|
|
292
294
|
*
|
|
293
295
|
* @param {object} opts
|
|
294
|
-
* @param {string} opts.command The command name (top-level
|
|
296
|
+
* @param {string} opts.command The command name (top-level pp-tools command)
|
|
295
297
|
* @param {string[]} opts.args Remaining args passed to the router
|
|
296
298
|
* @param {string} opts.cwd Project working directory
|
|
297
299
|
* @param {boolean} opts.raw Raw output mode flag
|
|
@@ -485,7 +487,7 @@ async function main() {
|
|
|
485
487
|
let command = args[0];
|
|
486
488
|
|
|
487
489
|
// Accept `query` as a meta-prefix for canonical dotted/spaced commands.
|
|
488
|
-
// Workflows may call `node
|
|
490
|
+
// Workflows may call `node pp-tools.cjs query <command>` directly.
|
|
489
491
|
if (command === 'query') {
|
|
490
492
|
args.shift();
|
|
491
493
|
command = args[0];
|
|
@@ -510,21 +512,21 @@ async function main() {
|
|
|
510
512
|
}
|
|
511
513
|
}
|
|
512
514
|
|
|
513
|
-
// Top-level usage string — emitted by `
|
|
514
|
-
// `
|
|
515
|
+
// Top-level usage string — emitted by `pp-tools` (no args) and by
|
|
516
|
+
// `pp-tools --help` / any `--help` request below.
|
|
515
517
|
// CR feedback: the command list must enumerate every top-level command
|
|
516
518
|
// supported by the dispatcher so `--help` is actually useful for
|
|
517
519
|
// discovery; previously it was a partial subset that didn't include
|
|
518
520
|
// phase / roadmap / milestone / progress / etc.
|
|
519
|
-
const TOP_LEVEL_USAGE = 'Usage:
|
|
521
|
+
const TOP_LEVEL_USAGE = 'Usage: pp-tools <command> [args] [--raw] [--pick <field>] [--cwd <path>] [--ws <name>] [--json-errors]\n' +
|
|
520
522
|
'Commands: agent, agent-skills, audit-open, audit-uat, check, check-commit, commit, commit-to-subrepo, ' +
|
|
521
523
|
'config-ensure-section, config-get, config-new-project, config-path, config-set, migrate-config, ' +
|
|
522
524
|
'current-timestamp, detect-custom-files, docs-init, drift-guard, effort, extract-messages, find-phase, ' +
|
|
523
525
|
'from-gsd2, frontmatter, gap-analysis, generate-claude-md, generate-claude-profile, ' +
|
|
524
|
-
'generate-dev-preferences, generate-slug, graphify, history-digest, init, intel, ' +
|
|
525
|
-
'capability, classify-confidence, git, learnings, list-todos, loop, milestone, package-legitimacy, phase, phase-plan-index, phases, profile-questionnaire, ' +
|
|
526
|
+
'generate-client-context, generate-dev-preferences, generate-slug, graphify, history-digest, init, intel, ' +
|
|
527
|
+
'capability, classify-confidence, git, learnings, list-todos, loop, milestone, package-legitimacy, phase, phase-plan-index, phases, platform-bindings, profile-questionnaire, ' +
|
|
526
528
|
'profile-sample, progress, prompt-budget, requirements, research-plan, research-store, resolve-granularity, resolve-model, roadmap, scaffold, state, ' +
|
|
527
|
-
'task, template, user-story, validate, verify, verify-path-exists, verify-summary, workstream, worktree\n\n' +
|
|
529
|
+
'task, template, user-story, validate, validate-bindings, verify, verify-path-exists, verify-summary, workstream, worktree\n\n' +
|
|
528
530
|
'Global flags:\n' +
|
|
529
531
|
' --raw Emit raw output without post-processing\n' +
|
|
530
532
|
' --pick <field> Extract a single field from JSON output (dot/bracket notation)\n' +
|
|
@@ -532,7 +534,7 @@ async function main() {
|
|
|
532
534
|
' --ws <name> Override active workstream (or set GSD_WORKSTREAM)\n' +
|
|
533
535
|
' --json-errors Emit structured JSON error objects on stderr (or set GSD_JSON_ERRORS=1)\n\n' +
|
|
534
536
|
'For command-specific argument requirements, invoke the command without args ' +
|
|
535
|
-
'(e.g. `
|
|
537
|
+
'(e.g. `pp-tools phase add`) — the resulting error lists what is required.';
|
|
536
538
|
|
|
537
539
|
if (!command) {
|
|
538
540
|
error(TOP_LEVEL_USAGE);
|
|
@@ -556,7 +558,7 @@ async function main() {
|
|
|
556
558
|
const NEVER_VALID_FLAGS = new Set(['--version', '-v']);
|
|
557
559
|
for (const arg of args) {
|
|
558
560
|
if (NEVER_VALID_FLAGS.has(arg)) {
|
|
559
|
-
error(`Unknown flag: ${arg}\
|
|
561
|
+
error(`Unknown flag: ${arg}\npp-tools does not accept version flags. Run "pp-tools" with no arguments for usage.`, ERROR_REASON.USAGE);
|
|
560
562
|
}
|
|
561
563
|
}
|
|
562
564
|
|
|
@@ -697,6 +699,41 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
697
699
|
break;
|
|
698
700
|
}
|
|
699
701
|
|
|
702
|
+
case 'platform-bindings': {
|
|
703
|
+
platformBindings.cmdPlatformBindings(cwd, args.slice(1), raw);
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
case 'validate-bindings': {
|
|
708
|
+
platformBindings.cmdValidateBindings(cwd, args.slice(1), raw);
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
case 'generate-client-context': {
|
|
713
|
+
// generate-client-context --from-json <path> [--output <path>] [--force]
|
|
714
|
+
// generate-client-context --read [--output <path>]
|
|
715
|
+
const gcArgs = args.slice(1);
|
|
716
|
+
const gcOptions = {};
|
|
717
|
+
for (let i = 0; i < gcArgs.length; i++) {
|
|
718
|
+
const a = gcArgs[i];
|
|
719
|
+
if (a === '--from-json') {
|
|
720
|
+
const v = gcArgs[i + 1];
|
|
721
|
+
if (v !== undefined && !v.startsWith('--')) { gcOptions.fromJson = v; i++; }
|
|
722
|
+
else error('--from-json requires a <path> argument');
|
|
723
|
+
} else if (a === '--output') {
|
|
724
|
+
const v = gcArgs[i + 1];
|
|
725
|
+
if (v !== undefined && !v.startsWith('--')) { gcOptions.output = v; i++; }
|
|
726
|
+
else error('--output requires a <path> argument');
|
|
727
|
+
} else if (a === '--read') {
|
|
728
|
+
gcOptions.read = true;
|
|
729
|
+
} else if (a === '--force') {
|
|
730
|
+
gcOptions.force = true;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
profileOutput.cmdGenerateClientContext(cwd, gcOptions, raw);
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
|
|
700
737
|
case 'resolve-granularity': {
|
|
701
738
|
// Parse optional --granularity <val> flag (space form only); positional is phase-type.
|
|
702
739
|
// The =form (--granularity=<val>) is intentionally not supported: parseNamedArgs and
|
|
@@ -1500,18 +1537,18 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1500
1537
|
} else if (subcommand === 'query') {
|
|
1501
1538
|
const tagIdx = args.indexOf('--tag');
|
|
1502
1539
|
const tag = tagIdx !== -1 ? args[tagIdx + 1] : null;
|
|
1503
|
-
if (!tag) error('Usage:
|
|
1540
|
+
if (!tag) error('Usage: pp-tools learnings query --tag <tag>', ERROR_REASON.USAGE);
|
|
1504
1541
|
learnings.cmdLearningsQuery(tag, raw);
|
|
1505
1542
|
} else if (subcommand === 'copy') {
|
|
1506
1543
|
learnings.cmdLearningsCopy(cwd, raw);
|
|
1507
1544
|
} else if (subcommand === 'prune') {
|
|
1508
1545
|
const olderIdx = args.indexOf('--older-than');
|
|
1509
1546
|
const olderThan = olderIdx !== -1 ? args[olderIdx + 1] : null;
|
|
1510
|
-
if (!olderThan) error('Usage:
|
|
1547
|
+
if (!olderThan) error('Usage: pp-tools learnings prune --older-than <duration>', ERROR_REASON.USAGE);
|
|
1511
1548
|
learnings.cmdLearningsPrune(olderThan, raw);
|
|
1512
1549
|
} else if (subcommand === 'delete') {
|
|
1513
1550
|
const id = args[2];
|
|
1514
|
-
if (!id) error('Usage:
|
|
1551
|
+
if (!id) error('Usage: pp-tools learnings delete <id>', ERROR_REASON.USAGE);
|
|
1515
1552
|
learnings.cmdLearningsDelete(id, raw);
|
|
1516
1553
|
} else {
|
|
1517
1554
|
error('Unknown learnings subcommand. Available: list, query, copy, prune, delete', ERROR_REASON.SDK_UNKNOWN_COMMAND);
|
|
@@ -1550,7 +1587,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1550
1587
|
const configDirIdx = args.indexOf('--config-dir');
|
|
1551
1588
|
const configDir = configDirIdx !== -1 ? args[configDirIdx + 1] : null;
|
|
1552
1589
|
if (!configDir) {
|
|
1553
|
-
error('Usage:
|
|
1590
|
+
error('Usage: pp-tools detect-custom-files --config-dir <path>', ERROR_REASON.USAGE);
|
|
1554
1591
|
}
|
|
1555
1592
|
const resolvedConfigDir = path.resolve(configDir);
|
|
1556
1593
|
if (!fs.existsSync(resolvedConfigDir)) {
|
|
@@ -1859,7 +1896,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1859
1896
|
if (subcommand === 'get') {
|
|
1860
1897
|
const key = args[2];
|
|
1861
1898
|
if (!key || key.startsWith('--')) {
|
|
1862
|
-
error('Usage:
|
|
1899
|
+
error('Usage: pp-tools research-store get <key> [--kind <k>]', ERROR_REASON.USAGE);
|
|
1863
1900
|
}
|
|
1864
1901
|
if (!researchStore.isValidResearchKey(key)) {
|
|
1865
1902
|
error('research-store: <key> must be a 64-char sha256 hex (use research-plan to obtain keys)', ERROR_REASON.USAGE);
|
|
@@ -1870,7 +1907,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1870
1907
|
} else if (subcommand === 'put') {
|
|
1871
1908
|
const key = args[2];
|
|
1872
1909
|
if (!key || key.startsWith('--')) {
|
|
1873
|
-
error('Usage:
|
|
1910
|
+
error('Usage: pp-tools research-store put <key> --content <str> --source <s> --provider <p> --confidence <c> --kind <k>', ERROR_REASON.USAGE);
|
|
1874
1911
|
}
|
|
1875
1912
|
if (!researchStore.isValidResearchKey(key)) {
|
|
1876
1913
|
error('research-store: <key> must be a 64-char sha256 hex (use research-plan to obtain keys)', ERROR_REASON.USAGE);
|
|
@@ -1895,7 +1932,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1895
1932
|
const confidence = getFlagValue(confidenceIdx, '--confidence');
|
|
1896
1933
|
const kind = getFlagValue(kindIdx, '--kind');
|
|
1897
1934
|
if (!content || !source || !provider || !confidence || !kind) {
|
|
1898
|
-
error('Usage:
|
|
1935
|
+
error('Usage: pp-tools research-store put <key> --content <str> --source <s> --provider <p> --confidence <c> --kind <k>', ERROR_REASON.USAGE);
|
|
1899
1936
|
}
|
|
1900
1937
|
const entry = researchStore.putResearch(cwd, key, { content, source, provider, confidence, kind }, { homeDir });
|
|
1901
1938
|
output(entry, raw);
|
|
@@ -1916,7 +1953,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1916
1953
|
const inputIdx = args.indexOf('--input');
|
|
1917
1954
|
const inputPath = inputIdx !== -1 ? args[inputIdx + 1] : null;
|
|
1918
1955
|
if (!inputPath || inputPath.startsWith('--')) {
|
|
1919
|
-
error('Usage:
|
|
1956
|
+
error('Usage: pp-tools research-plan --input <path>', ERROR_REASON.USAGE);
|
|
1920
1957
|
}
|
|
1921
1958
|
let planInput;
|
|
1922
1959
|
try {
|
|
@@ -1950,7 +1987,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1950
1987
|
const providerIdx = args.indexOf('--provider');
|
|
1951
1988
|
const provider = providerIdx !== -1 ? args[providerIdx + 1] : null;
|
|
1952
1989
|
if (!provider || provider.startsWith('--')) {
|
|
1953
|
-
error('Usage:
|
|
1990
|
+
error('Usage: pp-tools query classify-confidence --provider <id> [--package <name> --ecosystem <npm|pypi|crates>] [--verified]', ERROR_REASON.USAGE);
|
|
1954
1991
|
}
|
|
1955
1992
|
const verified = args.includes('--verified');
|
|
1956
1993
|
const pkgIdx = args.indexOf('--package');
|
|
@@ -1961,7 +1998,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1961
1998
|
if (pkg && (!pkg.startsWith('--'))) {
|
|
1962
1999
|
const VALID_ECOSYSTEMS = new Set(['npm', 'pypi', 'crates']);
|
|
1963
2000
|
if (!ecosystem || ecosystem.startsWith('--') || !VALID_ECOSYSTEMS.has(ecosystem)) {
|
|
1964
|
-
error('Usage:
|
|
2001
|
+
error('Usage: pp-tools query classify-confidence --provider <id> [--package <name> --ecosystem <npm|pypi|crates>] [--verified]', ERROR_REASON.USAGE);
|
|
1965
2002
|
}
|
|
1966
2003
|
const pkgLegitimacy = require('./lib/package-legitimacy.cjs');
|
|
1967
2004
|
const results = await pkgLegitimacy.checkPackages({ ecosystem, packages: [pkg] }, {});
|
|
@@ -1989,7 +2026,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1989
2026
|
const ecosystem = ecoIdx !== -1 ? args[ecoIdx + 1] : null;
|
|
1990
2027
|
const VALID_ECOSYSTEMS = new Set(['npm', 'pypi', 'crates']);
|
|
1991
2028
|
if (!ecosystem || !VALID_ECOSYSTEMS.has(ecosystem)) {
|
|
1992
|
-
error('Usage:
|
|
2029
|
+
error('Usage: pp-tools package-legitimacy check --ecosystem <npm|pypi|crates> <pkg1> ...', ERROR_REASON.USAGE);
|
|
1993
2030
|
}
|
|
1994
2031
|
// Collect positional package names.
|
|
1995
2032
|
// Only --ecosystem takes a value. Every non-flag arg is a package name.
|
|
@@ -2004,7 +2041,7 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
2004
2041
|
packages.push(a);
|
|
2005
2042
|
}
|
|
2006
2043
|
if (packages.length === 0) {
|
|
2007
|
-
error('Usage:
|
|
2044
|
+
error('Usage: pp-tools package-legitimacy check --ecosystem <eco> <pkg1> <pkg2> ...', ERROR_REASON.USAGE);
|
|
2008
2045
|
}
|
|
2009
2046
|
let pkgResults;
|
|
2010
2047
|
try {
|
|
@@ -16,7 +16,19 @@ First parse `SESSION_ARG` (the optional session number 1–13) from `$ARGUMENTS`
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
_PP_SHIM_NAME="pp-tools.cjs"; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; pp_run() { "$PP_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
19
|
-
|
|
19
|
+
# WR-03: validate the FULL numeric token. The old pattern (1[0-3]|[1-9]) let grep
|
|
20
|
+
# truncate out-of-range input to a spuriously valid session (14→1, 25→2, 99→9).
|
|
21
|
+
# Extract the whole digit run, then range-check 1–13; flag anything else as invalid.
|
|
22
|
+
SESSION_RAW=$(printf '%s' "${ARGUMENTS:-}" | grep -oE '[0-9]+' | head -1)
|
|
23
|
+
SESSION_ARG=""
|
|
24
|
+
SESSION_INVALID=""
|
|
25
|
+
if [ -n "$SESSION_RAW" ]; then
|
|
26
|
+
if [ "$SESSION_RAW" -ge 1 ] 2>/dev/null && [ "$SESSION_RAW" -le 13 ] 2>/dev/null; then
|
|
27
|
+
SESSION_ARG="$SESSION_RAW"
|
|
28
|
+
else
|
|
29
|
+
SESSION_INVALID="$SESSION_RAW"
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
20
32
|
INIT=$(pp_run query init.phase-op "${SESSION_ARG:-}")
|
|
21
33
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
22
34
|
```
|
|
@@ -26,9 +38,10 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
|
26
38
|
**Text mode:** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
|
|
27
39
|
|
|
28
40
|
**Dispatch:**
|
|
29
|
-
- If `
|
|
30
|
-
|
|
31
|
-
-
|
|
41
|
+
- If `SESSION_INVALID` is non-empty → show a usage error: "Session `$SESSION_INVALID` is out
|
|
42
|
+
of range — valid sessions are 1–13." Do not run any session or the progress view.
|
|
43
|
+
- Else if `SESSION_ARG` is empty (no numeric argument) → execute **Flow 1: Show Progress**
|
|
44
|
+
- Else (`SESSION_ARG` is a number 1–13) → execute **Flow 2: Facilitate Session N**
|
|
32
45
|
|
|
33
46
|
---
|
|
34
47
|
|
|
@@ -694,8 +707,8 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
|
|
|
694
707
|
2. **Technology stack selection**
|
|
695
708
|
- What is the preferred frontend technology (React, Angular, Vue, Mendix, etc.)?
|
|
696
709
|
- What is the preferred backend technology (Node.js, .NET, Java, Python)?
|
|
697
|
-
- What database technology is appropriate (relational, document, graph, time-series)?
|
|
698
|
-
- What messaging or eventing technology will be used (Kafka, RabbitMQ
|
|
710
|
+
- What database technology is appropriate (relational e.g. Cloud SQL via pareto-platform-gcp, document, graph, time-series)?
|
|
711
|
+
- What messaging or eventing technology will be used (Google Cloud Pub/Sub via pareto-platform-gcp, Kafka, RabbitMQ)?
|
|
699
712
|
- What caching strategy applies (Redis, in-memory, CDN)?
|
|
700
713
|
|
|
701
714
|
3. **Key architectural components**
|
|
@@ -717,6 +730,8 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
|
|
|
717
730
|
|
|
718
731
|
**Notes Template:**
|
|
719
732
|
|
|
733
|
+
> **Platform standard (D-08):** The Pareto platform standard is GCP / `pareto-platform-gcp`. Fill this table against that baseline unless the client has an overriding constraint.
|
|
734
|
+
|
|
720
735
|
**Technology Stack Decisions**
|
|
721
736
|
|
|
722
737
|
| Layer | Technology | Version | Rationale | Alternatives Considered | Risk |
|
|
@@ -1129,7 +1144,7 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
|
|
|
1129
1144
|
**What We Cover:**
|
|
1130
1145
|
|
|
1131
1146
|
1. **Cloud / hosting strategy**
|
|
1132
|
-
- What cloud provider will be used (AWS, Azure,
|
|
1147
|
+
- What cloud provider will be used (GCP / `pareto-platform-gcp` is the Pareto platform standard; or AWS, Azure, on-premises, hybrid)?
|
|
1133
1148
|
- What is the account and subscription structure?
|
|
1134
1149
|
- What regions and availability zones are required?
|
|
1135
1150
|
- Are there data sovereignty or residency requirements that constrain hosting?
|
|
@@ -1138,12 +1153,12 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
|
|
|
1138
1153
|
2. **Deployment strategy**
|
|
1139
1154
|
- What deployment model will be used (blue-green, canary, rolling, immutable)?
|
|
1140
1155
|
- How will the CI/CD pipeline be structured?
|
|
1141
|
-
- What tools will be used for CI/CD (GitHub Actions, Azure DevOps,
|
|
1156
|
+
- What tools will be used for CI/CD (GitLab CI is the Pareto platform pipeline; or GitHub Actions, Azure DevOps, Jenkins)?
|
|
1142
1157
|
- How will infrastructure be managed (IaC with Terraform, Pulumi, CloudFormation)?
|
|
1143
|
-
- What is the approach to containerization (Docker
|
|
1158
|
+
- What is the approach to containerization (GKE or Cloud Run via pareto-platform-gcp; Docker/Kubernetes on-prem; or other cloud options)?
|
|
1144
1159
|
|
|
1145
1160
|
3. **Monitoring, logging, and alerting**
|
|
1146
|
-
- What monitoring platform will be used (Datadog, New Relic,
|
|
1161
|
+
- What monitoring platform will be used (Google Cloud Monitoring / Cloud Logging via pareto-platform-gcp; or Datadog, New Relic, CloudWatch)?
|
|
1147
1162
|
- What metrics will be tracked (latency, error rate, throughput, saturation)?
|
|
1148
1163
|
- What is the alerting strategy (thresholds, escalation chains, on-call rotation)?
|
|
1149
1164
|
- How will application logs be aggregated and queried?
|
|
@@ -1162,6 +1177,8 @@ This session uses the **Session 3: Process-First Protocol** (Steps 5A–5G descr
|
|
|
1162
1177
|
|
|
1163
1178
|
**Notes Template:**
|
|
1164
1179
|
|
|
1180
|
+
> **Platform standard (D-08):** The Pareto deployment platform is GCP / `pareto-platform-gcp` with GitLab CI as the CI/CD pipeline and Google Cloud Monitoring / Cloud Logging for observability. Fill the tables below against this baseline unless the client has an overriding constraint.
|
|
1181
|
+
|
|
1165
1182
|
**Infrastructure Architecture**
|
|
1166
1183
|
|
|
1167
1184
|
| Component | Service / Product | Region | Tier / SKU | Redundancy | Est. Monthly Cost | Notes |
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Client-context gate (Build) — execute-phase sub-step
|
|
2
|
+
|
|
3
|
+
Confirms the Build agent has client context in hand before any executor is dispatched.
|
|
4
|
+
Gated entirely on `.platform-bindings.json` (D-13 / D-04, mirroring Phase 9): when no
|
|
5
|
+
bindings file is present this gate is a **no-op** — no prompt fires and Build proceeds
|
|
6
|
+
unchanged. All checks are **offline** — this gate never calls Obsidian, MCP, or any network
|
|
7
|
+
resource. The captured `## Client Context & Patterns` block in CLAUDE.md (the Phase 9
|
|
8
|
+
artifact, already on the Build/Validate read path) is the source of truth; the live vault is
|
|
9
|
+
out of scope here.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
_PP_SHIM_NAME="pp-tools.cjs"; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; pp_run() { "$PP_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; pp_run() { node "$PP_TOOLS" "$@"; }; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
13
|
+
CTX_GATE_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo false)
|
|
14
|
+
CTX_BLOCK=$(pp_run query generate-client-context --read 2>/dev/null || echo '{"present":false}')
|
|
15
|
+
CTX_BLOCK_PRESENT=$(printf '%s' "$CTX_BLOCK" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{process.stdout.write(String((JSON.parse(d).present)||false));}catch{process.stdout.write('false');}")
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**If `CTX_GATE_PRESENT` != `true`:** skip entirely (non-Pareto project — fully inert).
|
|
19
|
+
|
|
20
|
+
**If `CTX_GATE_PRESENT` == `true` and `CTX_BLOCK_PRESENT` == `true`:** the client-context
|
|
21
|
+
block exists and is on the executor's read path. Surface a one-line confirmation
|
|
22
|
+
("Client context loaded from CLAUDE.md — Build will apply captured client patterns.") and
|
|
23
|
+
require an explicit `confirmed` acknowledgment (`AskUserQuestion`, or a typed `confirmed` in
|
|
24
|
+
TEXT_MODE) before dispatching any executor. Advisory checkpoint, not a hard block.
|
|
25
|
+
|
|
26
|
+
**If `CTX_GATE_PRESENT` == `true` and `CTX_BLOCK_PRESENT` == `false`:** bindings indicate a
|
|
27
|
+
Pareto/client engagement but no client-context block was captured. Warn: "No
|
|
28
|
+
`## Client Context & Patterns` block found in CLAUDE.md — Build may proceed without client
|
|
29
|
+
patterns." Offer (`AskUserQuestion` / TEXT_MODE numbered list):
|
|
30
|
+
|
|
31
|
+
- **Capture now (recommended)** — pause and run `/pp-init` (its gated client-context step) to
|
|
32
|
+
write the block, then re-run `/pp-execute-phase`.
|
|
33
|
+
- **Proceed without** — continue knowingly; the executor builds without captured client
|
|
34
|
+
context. Requires an explicit `confirmed`.
|
|
35
|
+
|
|
36
|
+
`TEXT_MODE` follows the same rule as the host workflow (`--text` in `$ARGUMENTS`): replace
|
|
37
|
+
`AskUserQuestion` with a plain-text numbered prompt.
|
|
@@ -336,6 +336,10 @@ pp_run query state.begin-phase --phase "${PHASE_NUMBER}" --name "${PHASE_NAME}"
|
|
|
336
336
|
This updates Status, Last Activity, Current focus, Current Position, and plan counts in STATE.md so frontmatter and body text reflect the active phase immediately.
|
|
337
337
|
</step>
|
|
338
338
|
|
|
339
|
+
<step name="client_context_gate">
|
|
340
|
+
Read and execute `pp-core/workflows/execute-phase/steps/client-context-gate.md` — Pareto client-context gate (inert without `.platform-bindings.json`; confirms the Phase 9 CLAUDE.md block first).
|
|
341
|
+
</step>
|
|
342
|
+
|
|
339
343
|
<step name="discover_and_group_plans">
|
|
340
344
|
Load plan inventory with wave grouping in one call:
|
|
341
345
|
|