@pareto4/pp-core 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/bin/install.js +116 -0
  3. package/commands/pp-build-handoff.md +46 -0
  4. package/commands/pp-discovery-to-build.md +40 -0
  5. package/gemini-extension.json +1 -1
  6. package/package.json +2 -1
  7. package/pareto-skills/_shared/create-project-board.sh +195 -0
  8. package/pareto-skills/_shared/pp-claude-md-protocol.md +306 -0
  9. package/pareto-skills/_shared/sync-phase-status.sh +139 -0
  10. package/pareto-skills/pp-brand/SKILL.md +644 -0
  11. package/pareto-skills/pp-brand/assets/crew/ParetoAgent.inline.html +120 -0
  12. package/pareto-skills/pp-brand/assets/crew/ParetoAgent.tsx +239 -0
  13. package/pareto-skills/pp-brand/assets/crew/build.svg +11 -0
  14. package/pareto-skills/pp-brand/assets/crew/deploy.svg +11 -0
  15. package/pareto-skills/pp-brand/assets/crew/discovery.svg +11 -0
  16. package/pareto-skills/pp-brand/assets/crew/plan.svg +11 -0
  17. package/pareto-skills/pp-brand/assets/crew/run.svg +11 -0
  18. package/pareto-skills/pp-brand/assets/crew/validate.svg +11 -0
  19. package/pareto-skills/pp-brand/assets/pareto-brand-preview.html +547 -0
  20. package/pareto-skills/pp-obsidian-notes/SKILL.md +127 -0
  21. package/pareto-skills/pp-obsidian-notes/templates/CLAUDE.md +29 -0
  22. package/pareto-skills/pp-obsidian-notes/templates/client-context.md +116 -0
  23. package/pareto-skills/pp-obsidian-notes/templates/meeting-note.md +66 -0
  24. package/pareto-skills/pp-obsidian-notes/templates/pareto-context.md +102 -0
  25. package/pareto-skills/pp-obsidian-notes/templates/proposal.md +117 -0
  26. package/pareto-skills/pp-project-setup/SKILL.md +1364 -0
  27. package/pp-core/bin/lib/intel.cjs +1 -1
  28. package/pp-core/bin/lib/io.cjs +120 -0
  29. package/pp-core/bin/lib/profile-pipeline-command-router.cjs +1 -1
  30. package/pp-core/bin/lib/roadmap-parser.cjs +1 -1
  31. package/pp-core/bin/lib/runtime-artifact-conversion.cjs +2 -2
  32. package/pp-core/bin/lib/surface.cjs +1 -1
  33. package/pp-core/bin/lib/worktree-safety.cjs +2 -2
  34. package/pp-core/bin/pp-tools.cjs +23 -0
  35. package/pp-core/references/ui-brand.md +73 -11
  36. package/pp-core/templates/codebase/structure.md +5 -5
  37. package/pp-core/templates/spec.md +7 -7
  38. package/pp-core/workflows/add-backlog.md +1 -1
  39. package/pp-core/workflows/autonomous.md +4 -4
  40. package/pp-core/workflows/debug.md +1 -1
  41. package/pp-core/workflows/discovery-to-build.md +598 -0
  42. package/pp-core/workflows/execute-phase.md +9 -1
  43. package/pp-core/workflows/plan-phase.md +14 -12
  44. package/pp-core/workflows/pr-branch.md +5 -4
  45. package/pp-core/workflows/reapply-patches.md +1 -1
  46. package/pp-core/workflows/ship.md +1 -1
  47. package/pp-core/workflows/thread.md +1 -1
  48. package/pp-core/workflows/verify-work.md +6 -5
@@ -240,7 +240,7 @@ function intelUpdate(planningDir) {
240
240
  return disabledResponse();
241
241
  return {
242
242
  action: 'spawn_agent',
243
- message: 'Run pp-tools intel update or spawn gsd-intel-updater agent for full refresh',
243
+ message: 'Run pp-tools intel update or spawn pp-intel-updater agent for full refresh',
244
244
  };
245
245
  }
246
246
  /**
@@ -210,6 +210,119 @@ function error(message, reason = ERROR_REASON.UNKNOWN) {
210
210
  }
211
211
  process.exit(1);
212
212
  }
213
+ // ─── Pareto visual brand: banner engine (Phase 17 / UIBR-01, UIBR-02) ─────────
214
+ //
215
+ // A hand-rolled ANSI banner emitter (no color library — CLAUDE.md constraint).
216
+ // The pure/impure split (formatBanner vs banner) lets the whole degrade ladder
217
+ // be asserted by injecting `level`, with no PTY. Branding is routed to fd 2
218
+ // (stderr) ONLY; output() (fd 1) is left byte-for-byte unchanged, so machine-
219
+ // readable payloads physically cannot carry branding bytes (UIBR-02, D-03).
220
+ /**
221
+ * Pareto Blue — the single signal color for the banner rule (D-01). Every
222
+ * banner rule renders in this hue at every color tier; only the per-phase Crew
223
+ * glyph carries the phase accent. #2251FF.
224
+ */
225
+ const PARETO_BLUE = [34, 81, 255];
226
+ /**
227
+ * Frozen phase→Crew-identity map (mirrors the ERROR_REASON frozen-object idiom
228
+ * at ~163). Keyed by the six Crew phases; each entry carries the locked glyph
229
+ * (D-01) and its accent at three color tiers. Accent hexes are verbatim from
230
+ * pareto-skills/pp-brand/SKILL.md Crew Accent Palette (D-02).
231
+ */
232
+ const CREW = Object.freeze({
233
+ discovery: { glyph: '◎', ascii: '(o)', rgb: [246, 180, 55], c256: 221, c16: '33' }, // Amber #F6B437
234
+ plan: { glyph: '◆', ascii: '<>', rgb: [20, 111, 244], c256: 33, c16: '34' }, // Steel #146FF4
235
+ build: { glyph: '⬢', ascii: '#', rgb: [34, 81, 255], c256: 27, c16: '34' }, // Pareto Blue #2251FF
236
+ validate: { glyph: '◈', ascii: '<*>', rgb: [62, 207, 142], c256: 42, c16: '32' }, // Mint #3ECF8E
237
+ deploy: { glyph: '▲', ascii: '^', rgb: [255, 107, 74], c256: 209, c16: '31' }, // Coral #FF6B4A
238
+ run: { glyph: '▶', ascii: '>', rgb: [168, 132, 255], c256: 141, c16: '35' }, // Violet #A884FF
239
+ });
240
+ /**
241
+ * Wrap `text` in the SGR foreground escape for the given color `level`, always
242
+ * reset-terminated. level>=3 → 24-bit truecolor; 2 → 256-color; 1 → 16-color;
243
+ * 0 → plain text, no escapes at all (D-04 ladder bottom).
244
+ */
245
+ function paint(text, rgb, level, c256, c16) {
246
+ const [r, g, b] = rgb;
247
+ if (level >= 3)
248
+ return `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
249
+ if (level === 2)
250
+ return `\x1b[38;5;${c256}m${text}\x1b[0m`;
251
+ if (level === 1)
252
+ return `\x1b[${c16}m${text}\x1b[0m`;
253
+ return text;
254
+ }
255
+ /**
256
+ * Detect the terminal color capability of `stream` (default: process.stderr,
257
+ * since banners target fd 2). Returns 0 = none, 1 = 16-color, 2 = 256-color,
258
+ * 3 = truecolor. Gates on COLOR CAPABILITY only — never on the runtime — so the
259
+ * brand renders on any color-capable TTY and degrades cleanly on no-color /
260
+ * non-TTY environments (D-04). Honors NO_COLOR (no-color.org) and FORCE_COLOR.
261
+ */
262
+ function colorLevel(stream = process.stderr) {
263
+ const env = process.env;
264
+ // 1. NO_COLOR present-and-nonempty disables color (no-color.org).
265
+ if (env.NO_COLOR != null && env.NO_COLOR !== '')
266
+ return 0;
267
+ // 2. FORCE_COLOR override (force a specific tier, e.g. on a pipe in tests).
268
+ const fc = env.FORCE_COLOR;
269
+ if (fc === '0' || fc === 'false')
270
+ return 0;
271
+ if (fc === '1' || fc === 'true')
272
+ return 1;
273
+ if (fc === '2')
274
+ return 2;
275
+ if (fc === '3')
276
+ return 3;
277
+ // 3. Not a TTY → plain (piped, redirected, tool-harness capture).
278
+ if (!stream || !stream.isTTY)
279
+ return 0;
280
+ // 4. Truecolor advertised.
281
+ if (env.COLORTERM === 'truecolor' || env.COLORTERM === '24bit')
282
+ return 3;
283
+ // 5. 256-color terminals.
284
+ const term = env.TERM || '';
285
+ if (/-256(color)?$/.test(term))
286
+ return 2;
287
+ if (term === 'dumb')
288
+ return 0;
289
+ // 6. Known ANSI terminal families → 16-color floor; unknown TTY → safe 16.
290
+ if (/xterm|screen|vt100|vt220|rxvt|color|ansi|cygwin|linux|tmux/i.test(term))
291
+ return 1;
292
+ return 1;
293
+ }
294
+ /**
295
+ * PURE: build the three-line brand banner for `phaseKey` at color `level`. No
296
+ * I/O and no env reads — `level` is injected so every ladder tier is unit-
297
+ * testable without a PTY. The rule always renders in Pareto Blue (the D-01
298
+ * signal color); only the glyph carries the phase accent. At level 0 the rule
299
+ * is plain ASCII and the glyph is kept as a plain char — zero escapes (D-04).
300
+ *
301
+ * `stageText` is treated as an opaque literal: it is interpolated verbatim and
302
+ * never parsed, so embedded \x1b sequences are never re-interpreted into new
303
+ * SGR state (V5 / T-17-01 ANSI-injection mitigation).
304
+ */
305
+ function formatBanner(phaseKey, stageText, level) {
306
+ const RULE = '━'.repeat(51);
307
+ const crew = CREW[phaseKey] ?? CREW.build;
308
+ if (level === 0) {
309
+ return `${RULE}\n ${crew.glyph} pp-core ► ${stageText}\n${RULE}\n`;
310
+ }
311
+ const rule = paint(RULE, PARETO_BLUE, level, 27, '34');
312
+ const glyph = paint(crew.glyph, crew.rgb, level, crew.c256, crew.c16);
313
+ return `${rule}\n ${glyph} pp-core ► ${stageText}\n${rule}\n`;
314
+ }
315
+ /**
316
+ * IMPURE: render the banner for `phaseKey`/`stageText` and write it to fd 2
317
+ * (stderr) via the back-pressure-safe writeAllSync. The color level is detected
318
+ * from opts.stream (default process.stderr) unless opts.forceLevel is given.
319
+ * NEVER touches output()/stdout — fd separation is the structural UIBR-02
320
+ * guarantee (D-03, T-17-02).
321
+ */
322
+ function banner(phaseKey, stageText, opts = {}) {
323
+ const level = opts.forceLevel ?? colorLevel(opts.stream ?? process.stderr);
324
+ writeAllSync(2, formatBanner(phaseKey, stageText, level));
325
+ }
213
326
  module.exports = {
214
327
  GSD_TEMP_DIR,
215
328
  ensureGsdTempDir,
@@ -219,4 +332,11 @@ module.exports = {
219
332
  setJsonErrorMode,
220
333
  getJsonErrorMode,
221
334
  error,
335
+ // Pareto visual brand banner engine (Phase 17 / UIBR-01, UIBR-02)
336
+ PARETO_BLUE,
337
+ CREW,
338
+ paint,
339
+ colorLevel,
340
+ formatBanner,
341
+ banner,
222
342
  };
@@ -44,7 +44,7 @@ function routeExtractMessages({ args, cwd, raw, error, _pipeline }) {
44
44
  // args[0] = 'extract-messages' (family name), args[1] = project positional
45
45
  const projectArg = args[1];
46
46
  if (!projectArg || projectArg.startsWith('--')) {
47
- error('Usage: gsd-tools extract-messages <project> [--session <id>] [--limit N] [--path <dir>]\nRun scan-sessions first to see available projects.', ERROR_REASON.USAGE);
47
+ error('Usage: pp-tools extract-messages <project> [--session <id>] [--limit N] [--path <dir>]\nRun scan-sessions first to see available projects.', ERROR_REASON.USAGE);
48
48
  return;
49
49
  }
50
50
  // cmdExtractMessages is async — do NOT return the Promise.
@@ -344,7 +344,7 @@ function getMilestonePhaseFilter(cwd, versionOverride, phaseIdConvention) {
344
344
  const hasVersionedMilestonesGlobal = /^#{1,3}\s+.*v\d+\.\d+/mi.test(roadmapContent);
345
345
  const hasPhaseHeadings = /#{2,4}\s*(?:\[[^\]]+\]\s*)?Phase\s+[\w]/i.test(roadmapContent);
346
346
  if (!hasVersionedMilestonesGlobal && hasPhaseHeadings && phaseIdConvention === 'milestone-prefixed') {
347
- console.warn('[gsd] Deprecated: free-form ROADMAP.md detected (no versioned milestone headings). ' +
347
+ console.warn('[pp-core] Deprecated: free-form ROADMAP.md detected (no versioned milestone headings). ' +
348
348
  'The project has phase_id_convention set to "milestone-prefixed" in config.json but the ' +
349
349
  'ROADMAP does not use versioned milestone headings. Run `pp-tools roadmap upgrade --convention milestone-prefixed` to migrate (dry-run by default).');
350
350
  }
@@ -427,8 +427,8 @@ function convertClaudeCommandToKimiSkill(content, skillName, _runtime = null, cm
427
427
  const kimiSkillName = normalizeKimiSkillName(skillName);
428
428
  const names = cmdNames || readGsdCommandNames();
429
429
  const description = frontmatter
430
- ? extractFrontmatterField(frontmatter, 'description') || `Run GSD workflow ${kimiSkillName}.`
431
- : `Run GSD workflow ${kimiSkillName}.`;
430
+ ? extractFrontmatterField(frontmatter, 'description') || `Run pp-core workflow ${kimiSkillName}.`
431
+ : `Run pp-core workflow ${kimiSkillName}.`;
432
432
  const normalizedBody = convertGsdCommandReferencesToKimiSkillInvocations(frontmatter ? body : content, names);
433
433
  return `---\nname: ${kimiSkillName}\ndescription: ${yamlQuote(toSingleLine(description))}\n---\nInvoke this pp-core skill with \`/skill:${kimiSkillName}\`.\n\n${normalizedBody}`;
434
434
  }
@@ -348,7 +348,7 @@ function pruneSkillDirs(skillsDir, retainedNames, prefix, manifest) {
348
348
  // The dir must also be in the manifest to be considered GSD-owned.
349
349
  // A user-created gsd-* dir that isn't in the manifest is preserved with a warning.
350
350
  if (!canonicalStems.has(entry.slice(prefix.length))) {
351
- process.stderr.write(`[gsd] Warning: ${entry} matches GSD prefix '${prefix}' but is not in the manifest — preserving (user-owned or unknown)\n`);
351
+ process.stderr.write(`[pp-core] Warning: ${entry} matches GSD prefix '${prefix}' but is not in the manifest — preserving (user-owned or unknown)\n`);
352
352
  continue;
353
353
  }
354
354
  isGsdOwned = true;
@@ -920,13 +920,13 @@ function cmdWorktreeReapOrphans(cwd) {
920
920
  }
921
921
  catch (err) {
922
922
  // Surface failure as a one-line warning; keep exit-zero so workflows don't break.
923
- process.stderr.write(`[gsd] worktree.reap-orphans failed: ${err && err.message ? err.message : String(err)}\n`);
923
+ process.stderr.write(`[pp-core] worktree.reap-orphans failed: ${err && err.message ? err.message : String(err)}\n`);
924
924
  result = [];
925
925
  }
926
926
  const skippedCount = result.filter((r) => r.status === 'skipped').length;
927
927
  if (skippedCount > 0) {
928
928
  // Surface skipped entries so operators are aware of unresolved orphans.
929
- process.stderr.write(`[gsd] worktree.reap-orphans: ${skippedCount} orphan(s) skipped (run with DEBUG=1 for details)\n`);
929
+ process.stderr.write(`[pp-core] worktree.reap-orphans: ${skippedCount} orphan(s) skipped (run with DEBUG=1 for details)\n`);
930
930
  }
931
931
  process.stdout.write(`${JSON.stringify({ ok: true, reaped: result.filter((r) => r.status === 'reaped').length, entries: result }, null, 2)}\n`);
932
932
  }
@@ -709,6 +709,29 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
709
709
  break;
710
710
  }
711
711
 
712
+ case 'banner': {
713
+ // Pareto brand banner (Phase 17 / UIBR-02). Workflows shell out via
714
+ // `pp_run banner <phaseKey> "<STAGE TEXT>"`. The banner reaches the
715
+ // terminal ONLY via io.banner → fd 2 (stderr); output()/stdout is never
716
+ // touched, so machine-readable payloads physically cannot carry branding
717
+ // bytes (D-03, T-17-02). The `--raw` flag is already stripped upstream and
718
+ // is irrelevant here — stdout stays clean regardless.
719
+ const phaseKey = args[1];
720
+ const stageText = args[2] ?? '';
721
+ if (!phaseKey || !Object.prototype.hasOwnProperty.call(io.CREW, phaseKey)) {
722
+ // Unknown key → fail loud, never render a partial/garbage banner
723
+ // (T-17-03, ASVS V5). io.error writes to fd 2 and exits non-zero.
724
+ error(
725
+ `banner: unknown phase key "${phaseKey ?? ''}" — expected one of: ${Object.keys(io.CREW).join(', ')}`,
726
+ ERROR_REASON.SDK_MISSING_ARG,
727
+ );
728
+ }
729
+ // stageText is passed as an opaque literal — no re-interpretation of
730
+ // embedded escapes (V5 / T-17-01 ANSI-injection mitigation).
731
+ io.banner(phaseKey, stageText);
732
+ break;
733
+ }
734
+
712
735
  case 'generate-client-context': {
713
736
  // generate-client-context --from-json <path> [--output <path>] [--force]
714
737
  // generate-client-context --read [--output <path>]
@@ -4,24 +4,86 @@ Visual patterns for user-facing pp-core output. Orchestrators @-reference this f
4
4
 
5
5
  ## Stage Banners
6
6
 
7
- Use for major workflow transitions.
7
+ Use for major workflow transitions. The banner is a three-line block: a rule, a
8
+ title line ` {glyph} pp-core ► {STAGE NAME}`, and a closing rule.
8
9
 
9
10
  ```
10
11
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
11
- pp-core ► {STAGE NAME}
12
+ {glyph} pp-core ► {STAGE NAME}
12
13
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13
14
  ```
14
15
 
16
+ **Color rule (D-01):** the two rules are **ALWAYS Pareto Blue `#2251FF`** — the
17
+ single signal color. Only the **glyph** carries the phase accent (the per-phase
18
+ Crew color below). The rule hue never changes with the phase; this keeps the
19
+ brand's one signal color constant while the glyph communicates which Crew phase
20
+ is active.
21
+
22
+ ### Phase → glyph → accent-hex mapping (D-02)
23
+
24
+ Each major transition belongs to one of the six Pareto Crew phases. The glyph and
25
+ its accent color are fixed per phase (all glyphs are BMP for wide font coverage):
26
+
27
+ | Crew phase | phaseKey | Glyph | Codepoint | Accent | Hex | RGB | ASCII fallback | Stage banners |
28
+ |-----------|----------|:-----:|-----------|--------|-----|-----|:--------------:|---------------|
29
+ | Discovery | `discovery` | ◎ | U+25CE BULLSEYE | Amber | `#F6B437` | 246,180,55 | `(o)` | QUESTIONING · RESEARCHING · DEFINING REQUIREMENTS · CREATING ROADMAP |
30
+ | Plan | `plan` | ◆ | U+25C6 BLACK DIAMOND | Steel | `#146FF4` | 20,111,244 | `<>` | PLANNING PHASE {N} · PATTERN MAPPING |
31
+ | Build | `build` | ⬢ | U+2B22 BLACK HEXAGON | Pareto Blue | `#2251FF` | 34,81,255 | `#` | EXECUTING WAVE {N} |
32
+ | Validate | `validate` | ◈ | U+25C8 WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND | Mint | `#3ECF8E` | 62,207,142 | `<*>` | VERIFYING · PHASE {N} COMPLETE ✓ |
33
+ | Deploy | `deploy` | ▲ | U+25B2 BLACK UP-POINTING TRIANGLE | Coral | `#FF6B4A` | 255,107,74 | `^` | ship · PR BRANCH · MILESTONE COMPLETE 🎉 |
34
+ | Run | `run` | ▶ | U+25B6 BLACK RIGHT-POINTING TRIANGLE | Violet | `#A884FF` | 168,132,255 | `>` | autonomous · progress · resume |
35
+
36
+ Build's accent equals Pareto Blue by design, so at the Build transition the glyph
37
+ and rule share a hue.
38
+
15
39
  **Stage names (uppercase):**
16
- - `QUESTIONING`
17
- - `RESEARCHING`
18
- - `DEFINING REQUIREMENTS`
19
- - `CREATING ROADMAP`
20
- - `PLANNING PHASE {N}`
21
- - `EXECUTING WAVE {N}`
22
- - `VERIFYING`
23
- - `PHASE {N} COMPLETE ✓`
24
- - `MILESTONE COMPLETE 🎉`
40
+ - `QUESTIONING` (Discovery ◎)
41
+ - `RESEARCHING` (Discovery ◎)
42
+ - `DEFINING REQUIREMENTS` (Discovery ◎)
43
+ - `CREATING ROADMAP` (Discovery ◎)
44
+ - `PLANNING PHASE {N}` (Plan ◆)
45
+ - `PATTERN MAPPING PHASE {N}` (Plan ◆)
46
+ - `EXECUTING WAVE {N}` (Build ⬢)
47
+ - `VERIFYING` (Validate ◈)
48
+ - `PHASE {N} COMPLETE ✓` (Validate ◈)
49
+ - `PR BRANCH` (Deploy ▲)
50
+ - `MILESTONE COMPLETE 🎉` (Deploy ▲)
51
+
52
+ ### How banners are emitted (the shell-out call)
53
+
54
+ Banners are **not** printed as LLM prose. Workflows emit them via the CLI, which
55
+ writes the rendered banner to **stderr (fd 2)** and auto-degrades on non-TTY:
56
+
57
+ ```bash
58
+ pp_run banner <phaseKey> "<STAGE TEXT>"
59
+ ```
60
+
61
+ For example, at the research transition a workflow runs
62
+ `pp_run banner discovery "RESEARCHING PHASE {X}"`; at wave start it runs
63
+ `pp_run banner build "EXECUTING WAVE {N}"`. The `<phaseKey>` is the Crew key from
64
+ the table above; the stage text is passed as an opaque literal.
65
+
66
+ **Degrade ladder (D-04):** the emitter gates on **color capability, not runtime**.
67
+ It detects the terminal level from fd 2 and steps down cleanly:
68
+
69
+ - **truecolor (level 3):** 24-bit `\x1b[38;2;R;G;Bm` — full accent hex.
70
+ - **256-color (level 2):** nearest xterm-256 index for rule and glyph.
71
+ - **16-color (level 1):** basic ANSI SGR for rule and glyph.
72
+ - **none (level 0):** plain ASCII — no escapes at all; the glyph is kept as a
73
+ plain character (or its ASCII fallback where a terminal can't render it).
74
+
75
+ Because level 0 is exactly the non-TTY / piped / no-color case, branding
76
+ auto-degrades in precisely the environments where ANSI wouldn't render anyway,
77
+ and `NO_COLOR` / `FORCE_COLOR` are honored.
78
+
79
+ **Double-print rule (Pitfall 4):** the inline ASCII block shown above is the
80
+ **documented visual spec only**. A workflow that adopts the `pp_run banner` call
81
+ MUST drop its own inline `━━━ / pp-core ► {STAGE} / ━━━` block at that transition —
82
+ otherwise the banner prints twice. Keep the inline block here in `ui-brand.md`;
83
+ remove it from the adopting workflow.
84
+
85
+ The `✓` / `🎉` status symbols below remain additive to the stage text (e.g.
86
+ `PHASE {N} COMPLETE ✓`).
25
87
 
26
88
  ---
27
89
 
@@ -145,10 +145,10 @@ pp-core/
145
145
  - Key files: install.js - handles npx installation
146
146
  - Subdirectories: None
147
147
 
148
- **commands/gsd/**
149
- - Purpose: Slash command definitions for Claude Code
150
- - Contains: *.md files (one per command)
151
- - Key files: new-project.md, plan-phase.md, execute-plan.md
148
+ **commands/**
149
+ - Purpose: Slash command definitions for Claude Code (pp-* flat-hyphen layout)
150
+ - Contains: pp-*.md files (one per command)
151
+ - Key files: pp-new-project.md, pp-plan-phase.md, pp-execute-phase.md
152
152
  - Subdirectories: None (flat structure)
153
153
 
154
154
  **pp-core/references/**
@@ -206,7 +206,7 @@ pp-core/
206
206
  ## Where to Add New Code
207
207
 
208
208
  **New Slash Command:**
209
- - Primary code: `commands/gsd/{command-name}.md`
209
+ - Primary code: `commands/pp-{command-name}.md`
210
210
  - Tests: `tests/commands/{command-name}.test.js` (if testing implemented)
211
211
  - Documentation: Update `README.md` with new command
212
212
 
@@ -232,7 +232,7 @@ The database has a `posts` table and `follows` table. No feed query or feed UI e
232
232
 
233
233
  ## Goal
234
234
 
235
- A `gsd backup` CLI command creates a reproducible database snapshot that can be restored by `gsd restore` (a separate phase).
235
+ A `myapp backup` CLI command creates a reproducible database snapshot that can be restored by `myapp restore` (a separate phase).
236
236
 
237
237
  ## Background
238
238
 
@@ -242,8 +242,8 @@ No backup tooling exists. The project uses PostgreSQL. Developers currently use
242
242
 
243
243
  1. **Backup creation**: CLI command executes a full database backup.
244
244
  - Current: No `backup` subcommand exists in the CLI
245
- - Target: `gsd backup` connects to the database (via `DATABASE_URL` env or `--db` flag), runs pg_dump, writes output to `./backups/YYYY-MM-DD_HH-MM-SS.dump`
246
- - Acceptance: Running `gsd backup` on a test database creates a `.dump` file; running `pg_restore` on that file recreates the database without error
245
+ - Target: `myapp backup` connects to the database (via `DATABASE_URL` env or `--db` flag), runs pg_dump, writes output to `./backups/YYYY-MM-DD_HH-MM-SS.dump`
246
+ - Acceptance: Running `myapp backup` on a test database creates a `.dump` file; running `pg_restore` on that file recreates the database without error
247
247
 
248
248
  2. **Network retry**: Transient network failures are retried automatically.
249
249
  - Current: pg_dump fails immediately on network error
@@ -258,13 +258,13 @@ No backup tooling exists. The project uses PostgreSQL. Developers currently use
258
258
  ## Boundaries
259
259
 
260
260
  **In scope:**
261
- - `gsd backup` subcommand (full dump only)
261
+ - `myapp backup` subcommand (full dump only)
262
262
  - Output to `./backups/` directory (created if missing)
263
263
  - Network retry (3 attempts)
264
264
  - Partial file cleanup on failure
265
265
 
266
266
  **Out of scope:**
267
- - `gsd restore` — that is Phase 3
267
+ - `myapp restore` — that is Phase 3
268
268
  - Incremental backups — separate backlog item (full dump only for now)
269
269
  - S3 or remote storage — separate backlog item
270
270
  - Encryption — separate backlog item
@@ -277,8 +277,8 @@ No backup tooling exists. The project uses PostgreSQL. Developers currently use
277
277
 
278
278
  ## Acceptance Criteria
279
279
 
280
- - [ ] `gsd backup` creates a `.dump` file in `./backups/YYYY-MM-DD_HH-MM-SS.dump` format
281
- - [ ] `gsd backup` uses `DATABASE_URL` env var or `--db` flag for connection
280
+ - [ ] `myapp backup` creates a `.dump` file in `./backups/YYYY-MM-DD_HH-MM-SS.dump` format
281
+ - [ ] `myapp backup` uses `DATABASE_URL` env var or `--db` flag for connection
282
282
  - [ ] 3 retries on network failure, then exit code 1 with stderr message
283
283
  - [ ] `--no-retry` flag skips retries and fails immediately on first error
284
284
  - [ ] No partial `.dump` file left after a failed backup
@@ -1,6 +1,6 @@
1
1
  # Add Backlog Item Workflow
2
2
 
3
- Invoked by `/pp:capture --backlog` (`commands/gsd/capture.md`).
3
+ Invoked by `/pp:capture --backlog` (`commands/pp-capture.md`).
4
4
 
5
5
  Adds an idea to the ROADMAP.md backlog parking lot using 999.x numbering. Backlog items
6
6
  are unsequenced ideas that aren't ready for active planning — they live outside the normal
@@ -342,10 +342,10 @@ Read `frontend` and `hasUiSpec` from `GATE` (in-context).
342
342
  **Otherwise (frontend phase + no UI-SPEC):** For each active step hook (the `kind == "step"` set from above, in array order):
343
343
 
344
344
  ```
345
- Skill(skill="gsd-${ref.skill}", args="${PHASE_NUM}")
345
+ Skill(skill="pp-${ref.skill}", args="${PHASE_NUM}")
346
346
  ```
347
347
 
348
- (Prepend `gsd-` to `ref.skill` — so `ui-phase` → `pp-ui-phase`. Bare `${PHASE_NUM}` args — autonomous style, same pattern as the verify:post dispatch.) Entries where `kind == "gate"` are silently ignored — autonomous is always pipeline mode, there is no blocking gate here.
348
+ (Prepend `pp-` to `ref.skill` — so `ui-phase` → `pp-ui-phase`. Bare `${PHASE_NUM}` args — autonomous style, same pattern as the verify:post dispatch.) Entries where `kind == "gate"` are silently ignored — autonomous is always pipeline mode, there is no blocking gate here.
349
349
 
350
350
  After all step hooks return, re-read:
351
351
 
@@ -465,7 +465,7 @@ If no active code-review step hook exists: display "Code review skipped (code-re
465
465
  For each active code-review step hook, dispatch the skill using the registry-provided stem:
466
466
 
467
467
  ```
468
- Skill(skill="gsd-${ref.skill}", args="${PHASE_NUM}")
468
+ Skill(skill="pp-${ref.skill}", args="${PHASE_NUM}")
469
469
  ```
470
470
 
471
471
  Parse status from REVIEW.md frontmatter. If "clean" or "skipped": proceed to 3d. If findings found after the capability-dispatched review, auto-invoke the consolidated fix entry point:
@@ -590,7 +590,7 @@ For each entry in `activeHooks` in array order where `kind == "step"` and `ref.s
590
590
  - Invoke:
591
591
 
592
592
  ```
593
- Skill(skill="gsd-${ref.skill}", args="${PHASE_NUM}")
593
+ Skill(skill="pp-${ref.skill}", args="${PHASE_NUM}")
594
594
  ```
595
595
 
596
596
  (i.e. prepend `pp-` to `ref.skill` — so `ui-review` → `pp-ui-review`.)
@@ -1,6 +1,6 @@
1
1
  # Debug Workflow
2
2
 
3
- Invoked by `/pp:debug` (`commands/gsd/debug.md`).
3
+ Invoked by `/pp:debug` (`commands/pp-debug.md`).
4
4
 
5
5
  Systematic debugging using the scientific method with subagent isolation.
6
6
  Orchestrates symptom gathering, session creation, and delegation to `pp-debug-session-manager`.