@minhduydev/mdpi 0.3.2 → 0.4.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.
Files changed (36) hide show
  1. package/README.md +2 -1
  2. package/dist/index.js +202 -4
  3. package/dist/template/.pi/README.md +29 -8
  4. package/dist/template/.pi/VERSION +1 -1
  5. package/dist/template/.pi/agents/general.md +1 -1
  6. package/dist/template/.pi/agents/review.md +1 -1
  7. package/dist/template/.pi/extensions/templates-injector.ts +1 -1
  8. package/dist/template/.pi/packages.json +13 -0
  9. package/dist/template/.pi/prompts/audit.md +4 -1
  10. package/dist/template/.pi/prompts/create.md +1 -0
  11. package/dist/template/.pi/prompts/fix.md +7 -1
  12. package/dist/template/.pi/prompts/gc.md +3 -0
  13. package/dist/template/.pi/prompts/init.md +3 -0
  14. package/dist/template/.pi/prompts/plan.md +5 -2
  15. package/dist/template/.pi/prompts/research.md +3 -0
  16. package/dist/template/.pi/prompts/ship.md +7 -1
  17. package/dist/template/.pi/prompts/verify.md +4 -1
  18. package/dist/template/.pi/skills/INDEX.md +49 -12
  19. package/dist/template/.pi/skills/accessibility-audit/SKILL.md +8 -2
  20. package/dist/template/.pi/skills/baseline-ui/SKILL.md +211 -0
  21. package/dist/template/.pi/skills/dcp-hygiene/SKILL.md +106 -0
  22. package/dist/template/.pi/skills/design-taste-frontend/SKILL.md +53 -42
  23. package/dist/template/.pi/skills/fixing-accessibility/SKILL.md +509 -0
  24. package/dist/template/.pi/skills/frontend-design/SKILL.md +59 -46
  25. package/dist/template/.pi/skills/frontend-ui-engineering/SKILL.md +21 -27
  26. package/dist/template/.pi/skills/memory-system/SKILL.md +118 -0
  27. package/dist/template/.pi/skills/oklch-color-workflow/SKILL.md +426 -0
  28. package/dist/template/.pi/skills/production-hardening/SKILL.md +652 -0
  29. package/dist/template/.pi/skills/ui-craft-principles/SKILL.md +564 -0
  30. package/dist/template/.pi/skills/ui-quality-audit/SKILL.md +329 -0
  31. package/dist/template/.pi/templates/DESIGN.md +76 -0
  32. package/dist/template/.pi/workflows/INDEX.md +2 -1
  33. package/dist/template/.pi/workflows/frontend-feature-workflow.md +343 -0
  34. package/dist/template/.pi/workflows/quality-loop.md +3 -1
  35. package/package.json +1 -1
  36. /package/dist/template/.pi/templates/{design.md → feature-design.md} +0 -0
package/README.md CHANGED
@@ -38,6 +38,7 @@ npx mdpi init
38
38
  | Command | What it does |
39
39
  |---------|--------------|
40
40
  | `mdpi init` | Scaffold the curated `.pi/` kit into the current repo + write `.version` + `.template-manifest.json` (SHA-256 file map). Idempotent; `--force` overwrites template files (preserves user files), `--quiet` for CI. `--only <cats>` installs only the listed category dirs (`agents,prompts,skills,templates,workflows,context,extensions`) and trims settings.json to match. |
41
+ | `mdpi install` | Install the kit's declared npm packages — core (`.pi/settings.json:packages`) + optional (`.pi/packages.json`). Shells out to `pi install npm:<pkg>` (idempotent, safe to re-run). `--core` / `--optional` scope; `--check` dry-runs and reports installed/missing; `--yes` skips the confirm prompt. |
41
42
  | `mdpi upgrade` | Bring `.pi/` up to the bundled template version. Manifest-based: overwrites only user-unmodified files, preserves user edits, lists orphans. `--check` dry-run, `--force` overwrite modified, `--prune-all` delete orphans. |
42
43
  | `mdpi new <kind> [name]` | Scaffold a new kit component (`skill\|prompt\|agent\|workflow\|template`) from a lint-passing skeleton. `-d <text>` sets the description; `--force` overwrites. The skill skeleton comes with frontmatter + When to Use/NOT so it passes `mdpi lint` immediately. |
43
44
  | `mdpi lint [skills\|docs\|all]` | Governance: SKILL.md frontmatter (pi `name`+`description`), H1, When to Use/NOT, line limits, references/ depth, **dead cross-ref detection** (skills referencing non-existent skills), + README count/slash-command drift. `--json` for machine output. |
@@ -53,4 +54,4 @@ npx mdpi init
53
54
 
54
55
  ## What's in the kit
55
56
 
56
- `agents/` (7) · `prompts/` (11) · `skills/` (67 + INDEX) · `templates/` (11) · `workflows/` (6) · `context/` (2) · `extensions/` (2 TS) · `settings.json` · `AGENTS.md` · `README.md` · `QUALITY.md` · `.env.example` · `guard.example.json` · `subagents.json` · `artifacts/example/` (template examples).
57
+ `agents/` (7) · `prompts/` (11) · `skills/` (67 + INDEX) · `templates/` (11) · `workflows/` (6) · `context/` (2) · `extensions/` (2 TS) · `settings.json` · `packages.json` · `AGENTS.md` · `README.md` · `QUALITY.md` · `.env.example` · `guard.example.json` · `subagents.json` · `artifacts/example/` (template examples).
package/dist/index.js CHANGED
@@ -5,10 +5,12 @@ import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statS
5
5
  import * as p from "@clack/prompts";
6
6
  import color from "picocolors";
7
7
  import { createHash } from "node:crypto";
8
+ import { homedir } from "node:os";
9
+ import { spawn, spawnSync } from "node:child_process";
8
10
  import { fileURLToPath } from "node:url";
9
11
  import { mkdir, readdir } from "node:fs/promises";
10
12
  //#region package.json
11
- var version = "0.3.2";
13
+ var version = "0.4.1";
12
14
  //#endregion
13
15
  //#region src/utils/manifest.ts
14
16
  /**
@@ -78,6 +80,192 @@ function fileModificationStatus(filePath, relativePath, manifest) {
78
80
  return hashFile(filePath) === templateHash ? "unmodified" : "modified";
79
81
  }
80
82
  //#endregion
83
+ //#region src/commands/install.ts
84
+ /**
85
+ * mdpi install — install the npm packages this kit depends on.
86
+ *
87
+ * The kit references two kinds of external packages:
88
+ * - **core**: declared in `.pi/settings.json:packages` (auto-loaded by pi at
89
+ * startup — e.g. `@sting8k/pi-srcwalk`, `pi-hermes-memory`). Single source
90
+ * of truth = settings.json; this command reads it, does not duplicate it.
91
+ * - **optional**: declared in `.pi/packages.json` (recommended add-ons the
92
+ * user opts into — e.g. `@davecodes/pi-dcp`, `pi-guard`).
93
+ *
94
+ * `mdpi install` shells out to `pi install <id>` for each declared package.
95
+ * `pi install` is idempotent (re-running on an already-installed package is a
96
+ * no-op), so this command is safe to re-run.
97
+ *
98
+ * Flags:
99
+ * (default) install core + optional
100
+ * --core only settings.json:packages
101
+ * --optional only packages.json:optional
102
+ * --check dry-run: list declared packages + report which are already
103
+ * installed under ~/.pi/agent/npm/node_modules (no shell-out)
104
+ * --yes skip the confirmation prompt (for CI)
105
+ *
106
+ * Why a dedicated command instead of `mdpi init` doing it: init copies files
107
+ * only and must work offline / without `pi` on PATH. Package installation is a
108
+ * separate, network-dependent step the user controls explicitly. `mdpi init`
109
+ * reminds the user to run `mdpi install` next.
110
+ */
111
+ /** Path to pi's global npm install dir (where `pi install npm:foo` lands). */
112
+ function globalNpmDir() {
113
+ return join(homedir(), ".pi", "agent", "npm", "node_modules");
114
+ }
115
+ /**
116
+ * Extract the npm package name from a `npm:<name>` source id.
117
+ * `npm:@davecodes/pi-dcp` → `@davecodes/pi-dcp`. Non-npm ids return null
118
+ * (presence check only supports npm sources).
119
+ */
120
+ function npmNameFromId(id) {
121
+ if (!id.startsWith("npm:")) return null;
122
+ return id.slice(4);
123
+ }
124
+ /** Is a package already installed in pi's global npm dir? */
125
+ function isInstalled(id) {
126
+ const name = npmNameFromId(id);
127
+ if (!name) return false;
128
+ return existsSync(join(globalNpmDir(), name));
129
+ }
130
+ /** Read core packages from `.pi/settings.json:packages`. */
131
+ function readCorePackages(piDir) {
132
+ const path = join(piDir, "settings.json");
133
+ if (!existsSync(path)) return [];
134
+ let json;
135
+ try {
136
+ json = JSON.parse(readFileSync(path, "utf-8"));
137
+ } catch {
138
+ return [];
139
+ }
140
+ const packages = json.packages;
141
+ if (!Array.isArray(packages)) return [];
142
+ return packages.filter((id) => typeof id === "string" && id.length > 0).map((id) => ({
143
+ id,
144
+ source: "core"
145
+ }));
146
+ }
147
+ /** Read optional packages from `.pi/packages.json:optional`. */
148
+ function readOptionalPackages(piDir) {
149
+ const path = join(piDir, "packages.json");
150
+ if (!existsSync(path)) return [];
151
+ let json;
152
+ try {
153
+ json = JSON.parse(readFileSync(path, "utf-8"));
154
+ } catch {
155
+ return [];
156
+ }
157
+ const optional = json.optional;
158
+ if (!Array.isArray(optional)) return [];
159
+ const out = [];
160
+ for (const entry of optional) {
161
+ if (typeof entry !== "object" || entry === null) continue;
162
+ const id = entry.id;
163
+ if (typeof id !== "string" || id.length === 0) continue;
164
+ const note = entry.note;
165
+ out.push({
166
+ id,
167
+ note: typeof note === "string" ? note : void 0,
168
+ source: "optional"
169
+ });
170
+ }
171
+ return out;
172
+ }
173
+ /** Run `pi install <id>`. Resolves true on exit 0, false otherwise. */
174
+ function runPiInstall(id, quiet) {
175
+ return new Promise((resolve) => {
176
+ const child = spawn("pi", ["install", id], { stdio: quiet ? "ignore" : "inherit" });
177
+ child.on("error", (err) => {
178
+ if (!quiet) console.error(color.red(` pi install ${id} failed to start: ${err.message}`));
179
+ resolve(false);
180
+ });
181
+ child.on("exit", (code) => resolve(code === 0));
182
+ });
183
+ }
184
+ /** Check whether `pi` is on PATH. */
185
+ function hasPi() {
186
+ try {
187
+ return spawnSync("pi", ["--version"], { stdio: "ignore" }).status === 0;
188
+ } catch {
189
+ return false;
190
+ }
191
+ }
192
+ async function installCommand(options = {}) {
193
+ const quiet = process.argv.includes("--quiet");
194
+ if (!quiet) p.intro(color.bgCyan(color.black(" mdpi install ")));
195
+ const piDir = options.piDir || join(process.cwd(), ".pi");
196
+ if (!existsSync(piDir)) {
197
+ if (!quiet) {
198
+ p.log.error(".pi/ not found — run `mdpi init` first");
199
+ p.outro(color.red("Failed"));
200
+ }
201
+ process.exitCode = 1;
202
+ return;
203
+ }
204
+ const core = readCorePackages(piDir);
205
+ const optional = readOptionalPackages(piDir);
206
+ const wantCore = options.core || !options.core && !options.optional;
207
+ const wantOptional = options.optional || !options.core && !options.optional;
208
+ const selected = [...wantCore ? core : [], ...wantOptional ? optional : []];
209
+ if (selected.length === 0) {
210
+ if (!quiet) {
211
+ p.log.warn("No packages declared (settings.json:packages empty and packages.json:optional empty)");
212
+ p.outro("Nothing to do");
213
+ }
214
+ return;
215
+ }
216
+ if (options.check) {
217
+ console.log(`\n${color.bold("mdpi install --check")} — declared packages\n`);
218
+ const installed = selected.filter((pkg) => isInstalled(pkg.id));
219
+ const missing = selected.filter((pkg) => !isInstalled(pkg.id));
220
+ for (const pkg of selected) {
221
+ const mark = isInstalled(pkg.id) ? color.green("✓ installed") : color.yellow("✗ missing");
222
+ const note = pkg.note ? color.gray(` — ${pkg.note}`) : "";
223
+ console.log(` ${mark} ${color.cyan(pkg.id)}${note}`);
224
+ }
225
+ console.log(`\n ${color.green(`${installed.length}`)} installed · ${color.yellow(`${missing.length}`)} missing · ${selected.length} total`);
226
+ if (missing.length > 0) console.log(`\n Run ${color.cyan("mdpi install")} to install the missing ${missing.length} package(s).`);
227
+ if (!quiet) p.outro(missing.length === 0 ? color.green("All installed") : color.yellow("Some missing"));
228
+ process.exitCode = missing.length === 0 ? 0 : 1;
229
+ return;
230
+ }
231
+ if (!hasPi()) {
232
+ if (!quiet) {
233
+ p.log.error("`pi` not found on PATH — install pi first (npm i -g @earendil-works/pi-coding-agent)");
234
+ p.outro(color.red("Failed"));
235
+ }
236
+ process.exitCode = 1;
237
+ return;
238
+ }
239
+ const missing = selected.filter((pkg) => !isInstalled(pkg.id));
240
+ const alreadyOk = selected.length - missing.length;
241
+ if (!quiet && !options.yes) {
242
+ const scope = wantCore && wantOptional ? "core + optional" : wantCore ? "core" : "optional";
243
+ const confirm = await p.confirm({
244
+ message: `Install ${missing.length} missing package(s) [${scope}]?${alreadyOk > 0 ? ` (${alreadyOk} already installed, skipped)` : ""}`,
245
+ initialValue: true
246
+ });
247
+ if (p.isCancel(confirm) || !confirm) {
248
+ p.outro("Cancelled");
249
+ return;
250
+ }
251
+ }
252
+ if (quiet) console.log(`mdpi: installing ${missing.length}/${selected.length} packages (core=${wantCore} optional=${wantOptional})`);
253
+ else p.log.info(`Installing ${missing.length} missing package(s) of ${selected.length} declared`);
254
+ let ok = 0;
255
+ let fail = 0;
256
+ for (const pkg of missing) {
257
+ if (!quiet) p.log.step(`${color.cyan(pkg.id)}${pkg.note ? color.gray(` — ${pkg.note}`) : ""}`);
258
+ if (await runPiInstall(pkg.id, quiet)) ok++;
259
+ else fail++;
260
+ }
261
+ if (quiet) console.log(`mdpi: done — ${ok} installed, ${fail} failed, ${alreadyOk} already present`);
262
+ else {
263
+ p.note(`${ok} installed · ${fail} failed · ${alreadyOk} already present\n\n` + (fail > 0 ? `${color.red("Some installs failed — check pi output above.")}\n` : `${color.green("All declared packages are now installed.")}\n`) + `Re-run anytime: ${color.cyan("mdpi install")} (idempotent).`, "Install complete");
264
+ p.outro(fail === 0 ? color.green("Ready!") : color.red("Partial failure"));
265
+ }
266
+ process.exitCode = fail === 0 ? 0 : 1;
267
+ }
268
+ //#endregion
81
269
  //#region src/utils/template.ts
82
270
  /** Shared template + version helpers used by init / upgrade / doctor. */
83
271
  const DEFAULT_SKIP_DIRS = [
@@ -499,8 +687,9 @@ function lintAll(piDir, opts = {}) {
499
687
  * mdpi doctor — .pi/ health check.
500
688
  *
501
689
  * Verifies: mdpi version match, manifest valid, settings.json valid JSON, kit
502
- * dirs present (skills/prompts/agents/templates/workflows/extensions), orphan
503
- * detection (manifest files no longer in template), and a lint summary.
690
+ * dirs present (skills/prompts/agents/templates/workflows/extensions), package
691
+ * install status (core settings.json + optional packages.json vs installed),
692
+ * orphan detection (manifest files no longer in template), and a lint summary.
504
693
  */
505
694
  function row(ok, label, detail) {
506
695
  console.log(` ${ok ? color.green("✓") : color.red("✗")} ${label}: ${detail}`);
@@ -559,6 +748,11 @@ async function doctorCommand(options = {}) {
559
748
  row(countMd("templates") > 0, "templates", `${countMd("templates")} templates`);
560
749
  row(countMd("workflows") > 0, "workflows", `${countMd("workflows")} workflows`);
561
750
  row(countExt("extensions", ".ts") > 0, "extensions", `${countExt("extensions", ".ts")} extensions`);
751
+ const corePkgs = readCorePackages(piDir);
752
+ const optPkgs = readOptionalPackages(piDir);
753
+ const allPkgs = [...corePkgs, ...optPkgs];
754
+ const installedPkgs = allPkgs.filter((pkg) => isInstalled(pkg.id)).length;
755
+ row(allPkgs.length > 0, "packages", allPkgs.length === 0 ? "none declared (settings.json:packages + packages.json:optional)" : `${installedPkgs}/${allPkgs.length} installed` + (installedPkgs < allPkgs.length ? color.yellow(` (run mdpi install)`) : "") + ` — core ${corePkgs.length}, optional ${optPkgs.length}`);
562
756
  if (templateRoot) row(orphans === 0, "orphans", orphans === 0 ? "none (template-removed files)" : `${orphans} orphan(s) — run mdpi upgrade --prune-all`);
563
757
  const lr = lintSkills(piDir);
564
758
  console.log(` ${lr.ok ? color.green("✓") : color.red("✗")} lint: ${lr.stats.failed} errors · ${lr.stats.warnings} warnings (run ${color.cyan("mdpi lint")} for detail)`);
@@ -622,6 +816,7 @@ const ALWAYS_ENTRIES = [
622
816
  "scripts",
623
817
  "artifacts/example",
624
818
  "settings.json",
819
+ "packages.json",
625
820
  "AGENTS.md",
626
821
  "README.md",
627
822
  "QUALITY.md",
@@ -760,7 +955,7 @@ async function initCommand(options = {}) {
760
955
  console.log(`mdpi: installed ${fileCount} files to ${piDir} (v${version})${subset}`);
761
956
  } else {
762
957
  const subsetNote = only ? `Subset: ${[...only].join(", ")} (+ always-on config).\n\nsettings.json trimmed to drop references to excluded\nskills/prompts/extensions dirs.\n\nNote: mdpi upgrade compares against the FULL template —\nrun \`mdpi upgrade --check\` before applying.\n\n` : "";
763
- p.note(`Pi kit installed at:\n${piDir}\n\n${fileCount} template files tracked via manifest.\n\n` + subsetNote + `Next: open pi in this repo to use the kit.`, "Installation complete");
958
+ p.note(`Pi kit installed at:\n${piDir}\n\n${fileCount} template files tracked via manifest.\n\n` + subsetNote + `Next: run ${color.cyan("mdpi install")} to install the kit's npm packages,\nthen open pi in this repo to use the kit.`, "Installation complete");
764
959
  p.outro(color.green("Ready!"));
765
960
  }
766
961
  }
@@ -1152,6 +1347,9 @@ cli.help();
1152
1347
  cli.command("init", "Scaffold a Pi coding-agent kit (.pi/) into the current repo").option("--force", "Overwrite existing .pi/ template files (preserves extra user files)").option("-y, --yes", "Skip prompts, use defaults (for CI)").option("--only <cats>", "Install only these categories (comma-sep: agents,prompts,skills,templates,workflows,context,extensions)").action(async (options) => {
1153
1348
  await initCommand(options);
1154
1349
  });
1350
+ cli.command("install", "Install the kit's declared npm packages (core from settings.json + optional from packages.json)").option("--core", "Only install core packages (settings.json:packages)").option("--optional", "Only install optional packages (packages.json:optional)").option("--check", "Dry-run: list declared packages + report installed/missing").option("-y, --yes", "Skip confirmation prompt (for CI)").action(async (options) => {
1351
+ await installCommand(options);
1352
+ });
1155
1353
  cli.command("upgrade", "Bring .pi/ up to the bundled template version").option("--force", "Overwrite user-modified files (default: preserve them)").option("--check", "Dry-run: report what would change without writing").option("--prune-all", "Delete orphan files (template-removed since install)").action(async (options) => {
1156
1354
  await upgradeCommand(options);
1157
1355
  });
@@ -241,22 +241,43 @@ This kit ships **2 custom TypeScript extensions** and uses **2 external npm pack
241
241
  | `workflows-runner` | Parses DAG workflows from `.pi/workflows/*.md`, returns execution plan with `subagent()` calls | Production |
242
242
  | `templates-injector` | Auto-injects `project.md`, `tech-stack.md`, `state.md` into system prompt | Production |
243
243
 
244
- ### External packages (auto-loaded from global)
244
+ ### External packages
245
245
 
246
- | Package | Purpose | Why external |
247
- |---------|---------|--------------|
248
- | `@davecodes/pi-dcp` | Dynamic context pruning (dedup, error purge, compress tool) | Battle-tested, superset of what we'd write |
249
- | `jdiamond/pi-guard` | Tool permission system (bash AST parser, path globs, default ruleset) | Proper bash AST parser handles `\|`, `&&`, `xargs` — regex can't |
246
+ The kit depends on external npm packages, split into two sets:
250
247
 
251
- Install with `pi install npm:@davecodes/pi-dcp npm:pi-guard`. The pi-guard config example lives at `.pi/guard.example.json` copy the `guard` block into `.pi/settings.json` to enable.
248
+ - **Core** declared in `.pi/settings.json:packages`, auto-loaded by pi at
249
+ startup. Single source of truth = `settings.json`.
250
+ - **Optional** — declared in `.pi/packages.json`, recommended add-ons you opt
251
+ into.
252
+
253
+ | Package | Set | Purpose | Why external |
254
+ |---------|-----|---------|--------------|
255
+ | `@tintinweb/pi-subagents` | core | Subagent dispatch (`subagent()` tool) | Battle-tested pi-native package |
256
+ | `@sting8k/pi-srcwalk` | core | `semantic_*` code navigation tools | Trigram-indexed search, deep |
257
+ | `pi-hermes-memory` | core | Long-term memory (`memory`/`memory_search`/`session_search`/`skill_manage`) | Mature, 368 tests, FTS5 + two-tier |
258
+ | `@davecodes/pi-dcp` | optional | Dynamic context pruning (dedup, error purge, compress tool) | Superset of the kit's former dcp-strategies extension |
259
+ | `pi-guard` | optional | Tool permission system (bash AST parser, path globs) | AST parser handles `\|`, `&&`, `xargs` — regex can't |
260
+
261
+ Install the full set with one command (idempotent, safe to re-run):
262
+
263
+ ```bash
264
+ mdpi install # core + optional
265
+ mdpi install --core # only settings.json:packages
266
+ mdpi install --optional # only packages.json:optional
267
+ mdpi install --check # dry-run: report installed/missing
268
+ ```
269
+
270
+ `mdpi install` shells out to `pi install npm:<pkg>` for each declared package.
271
+ The pi-guard config example lives at `.pi/guard.example.json` — copy the `guard`
272
+ block into `.pi/settings.json` to enable its rules.
252
273
 
253
274
  ### Removed (intentionally)
254
275
 
255
276
  | Extension | Reason | Replaced by |
256
277
  |-----------|--------|-------------|
257
278
  | `commands-dispatcher` | Pi's built-in prompt template loader already does this | pi core (no install needed) |
258
- | `dcp-strategies` | Superseded by `@davecodes/pi-dcp` (active globally) | `pi install npm:@davecodes/pi-dcp` |
259
- | `pi-guard` (local) | Superseded by `jdiamond/pi-guard` (proper AST parser) | `pi install npm:pi-guard` |
279
+ | `dcp-strategies` | Superseded by `@davecodes/pi-dcp` (active globally) | `mdpi install --optional` |
280
+ | `pi-guard` (local) | Superseded by `jdiamond/pi-guard` (proper AST parser) | `mdpi install --optional` |
260
281
 
261
282
  ---
262
283
 
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.4.1
@@ -2,7 +2,7 @@
2
2
  name: general
3
3
  description: General-purpose subagent for small, well-defined implementation tasks (1-3 files)
4
4
  tools: read, grep, find, ls, bash, edit, write, semantic_query, semantic_inspect, semantic_grep, semantic_show
5
- model: ollama-cloud/glm-5.2
5
+ model: opencode-go/deepseek-v4-flash
6
6
  ---
7
7
 
8
8
  You are Pi — a surgical implementer.
@@ -2,7 +2,7 @@
2
2
  name: review
3
3
  description: Read-only code review, debugging, and security audit specialist with severity-ranked findings
4
4
  tools: read, grep, find, ls, bash, semantic_query, semantic_inspect, semantic_grep, semantic_show
5
- model: ollama-cloud/glm-5.2
5
+ model: opencode-go/minimax-m3
6
6
  ---
7
7
 
8
8
  You are Pi — a read-only review specialist.
@@ -21,7 +21,7 @@ import * as fs from "node:fs";
21
21
  import * as path from "node:path";
22
22
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
23
23
 
24
- const ALWAYS_INJECT = ["project.md", "tech-stack.md", "state.md"];
24
+ const ALWAYS_INJECT = ["project.md", "tech-stack.md", "state.md", "DESIGN.md"];
25
25
 
26
26
  function readTemplate(cwd: string, name: string): string | null {
27
27
  // Prefer live file at .pi/{name} (filled by /init — real project state);
@@ -0,0 +1,13 @@
1
+ {
2
+ "$comment": "Optional packages recommended by this kit. `mdpi install` installs these alongside the core packages declared in settings.json:packages. Core lives there (single source of truth); this file only lists the opt-in set. Edit freely — adding an entry here makes `mdpi install` pick it up.",
3
+ "optional": [
4
+ {
5
+ "id": "npm:@davecodes/pi-dcp",
6
+ "note": "Dynamic context pruning — dedup, error purge, compress tool. Superset of the kit's former dcp-strategies extension."
7
+ },
8
+ {
9
+ "id": "npm:pi-guard",
10
+ "note": "Tool permission system (bash AST parser, path globs, default ruleset). Config example at .pi/guard.example.json."
11
+ }
12
+ ]
13
+ }
@@ -39,6 +39,7 @@ Find all occurrences of a code pattern in the codebase, review each for issues,
39
39
  | `security-and-hardening` | Pattern involves auth, secrets, validation, input | Identify vulnerability patterns in audited code |
40
40
  | `code-review-and-quality` | Occurrences > 5 | Assess correctness and structural quality across results |
41
41
  | `fallow` | Occurrences > 20 or scope is project-wide | Structural analysis for dead code, duplication, complexity |
42
+ | `dcp-hygiene` | Output (after workflow execution) | Compress closed grep+read occurrence output when `compress` is available |
42
43
 
43
44
  ## Execution
44
45
 
@@ -67,7 +68,7 @@ For small audits, execute directly without workflow overhead:
67
68
 
68
69
  | Scenario | Action |
69
70
  |----------|--------|
70
- | Workflow phase fails | Retry once with adjusted prompt, then escalate |
71
+ | Workflow phase fails | Retry once with adjusted prompt, then escalate. If retry also fails, **save the failure** to `memory(action: "add", target: "failure", category: "failure")` — the pattern, scope, and what went wrong. |
71
72
  | No occurrences found | Report: "Pattern not found in codebase." |
72
73
  | Audit timeout | Report partial results with what was covered |
73
74
  | Subagent returns failure | Read error, retry once, then escalate |
@@ -81,6 +82,8 @@ For small audits, execute directly without workflow overhead:
81
82
 
82
83
  ## Output
83
84
 
85
+ > **DCP hygiene:** Before writing the final report, if the `compress` tool is available, compress the closed discovery work-stream (`semantic_grep` results + per-occurrence `read` output) per the `dcp-hygiene` skill — occurrences and findings are captured in the report and `.pi/artifacts/$SLUG/audit.md`. Skip if `compress` is unavailable.
86
+
84
87
  1. **Pattern:** [pattern searched]
85
88
  2. **Occurrences found:** [count]
86
89
  3. **Files affected:** [count]
@@ -25,6 +25,7 @@ Before creating, verify:
25
25
  - If active slug exists with a `spec.md`, ask user: continue with `/ship` or start new?
26
26
  - Check `git status --porcelain` — if uncommitted changes, ask user to stash, commit, or continue
27
27
  - Use `vcc_recall` to search session history for prior decisions on this topic — avoid repeating explored/rejected approaches
28
+ - Use `memory_search({ project: "$(cat .pi/artifacts/.active 2>/dev/null || echo '')" })` for durable prior decisions across sessions
28
29
 
29
30
  ## Load Skills
30
31
 
@@ -21,6 +21,7 @@ Systematically debug and fix the reported issue.
21
21
 
22
22
  Before fixing:
23
23
  - Use `vcc_recall` to search for prior fix attempts on the same issue — avoid repeating failed approaches
24
+ - Use `memory_search({ query: "<issue keywords>", target: "failure", category: "failure" })` for durable cross-session failed approaches
24
25
  - Check that the codebase builds/tests pass at baseline (confirm the bug is not a pre-existing state)
25
26
 
26
27
  ## Load Skills
@@ -32,6 +33,7 @@ Before fixing:
32
33
  | `verification-before-completion` | Always | Evidence-before-claims; verify fix actually resolves the bug |
33
34
  | `defense-in-depth` | After fix is verified | Harden the layer so the bug becomes structurally impossible |
34
35
  | `testing-anti-patterns` | If writing tests | Ensure regression test isn't a mock-only test |
36
+ | `dcp-hygiene` | Phase 5 Report | Compress the closed reproduce+isolate work-stream when `compress` is available |
35
37
 
36
38
  ## Phase 1: Reproduce
37
39
 
@@ -59,6 +61,8 @@ If `--attach` provided, read the attached log/error file for context.
59
61
 
60
62
  ## Phase 4: Verify
61
63
 
64
+ > **DCP hygiene (mid-command):** The fix is applied — the root cause is now captured; the reproduce/isolate reads and greps are no longer needed verbatim. If `compress` is available, compress the closed Phase 1-2 reproduce+isolate work-stream per the `dcp-hygiene` skill before running gates. Keep the root cause (file:line) and reproduction command in the summary. Skip if `compress` is unavailable.
65
+
62
66
  Run verification gates:
63
67
 
64
68
  ```bash
@@ -80,7 +84,7 @@ Then, load `defense-in-depth` skill and add validation at the data entry layer.
80
84
  |----------|--------|
81
85
  | Cannot reproduce issue | Report reproduction steps attempted, ask for clarification |
82
86
  | Root cause ambiguous | Trace backward through call stack, add instrumentation |
83
- | Verification fails 2x | Stop, report blocker with learnings from both attempts |
87
+ | Verification fails 2x | Stop, report blocker with learnings from both attempts. **Also:** save to `memory(action: "add", target: "failure", category: "failure", content: "[root cause + approach tried + error + reproduction]")` so future sessions don't repeat the failed approach. |
84
88
  | Fix causes regression | Revert fix, report regression with evidence |
85
89
 
86
90
  ## Stop Conditions
@@ -92,6 +96,8 @@ Then, load `defense-in-depth` skill and add validation at the data entry layer.
92
96
 
93
97
  ## Phase 5: Report
94
98
 
99
+ > **DCP hygiene:** Before reporting, if the `compress` tool is available, compress the closed Phase 1-3 exploratory work-stream (reproduce bash + isolate grep/inspect/read output) per the `dcp-hygiene` skill — the root cause and fix are now captured in this report and the artifact. Skip if `compress` is unavailable; the artifact already holds the facts.
100
+
95
101
  1. Root cause (with file:line)
96
102
  2. Fix applied
97
103
  3. Verification results (typecheck, lint, test)
@@ -31,6 +31,7 @@ Run structural analysis, update quality grades, and open cleanup PRs.
31
31
  | `code-cleanup` | Phase 4 (cleanup PRs) | Safe code removal patterns |
32
32
  | `verification-before-completion` | After cleanup PRs | Verify typecheck + lint pass before merging |
33
33
  | `observability-and-instrumentation` | If removing instrumented code | Check that cleanup doesn't break monitoring/logging |
34
+ | `dcp-hygiene` | Phase 5 Report | Compress the closed Fallow scan + grading output when `compress` is available |
34
35
 
35
36
  ## Execution
36
37
 
@@ -75,6 +76,8 @@ If `--dry-run` (default), skip actual cleanup and report what would be cleaned.
75
76
 
76
77
  ### Phase 5: Report
77
78
 
79
+ > **DCP hygiene:** Before reporting, if the `compress` tool is available, compress the closed Phase 1-3 Fallow scan + grading output (the large JSON and finding lists) per the `dcp-hygiene` skill — grades and prioritized findings are captured in this report and `.pi/QUALITY.md`. Skip if `compress` is unavailable.
80
+
78
81
  1. **Quality Grades:** Per-domain status (before → after)
79
82
  2. **Issues Found:** Count by severity
80
83
  3. **Cleanup PRs:** Opened / not needed / skipped (dry-run)
@@ -56,6 +56,7 @@ Before initializing:
56
56
  | `documentation-and-adrs` | Always (Mode 1) | Doc conventions, ADR format when architectural decisions arise |
57
57
  | `verification-before-completion` | Before writing AGENTS.md | Validate commands before documenting them |
58
58
  | `brainstorming` | Conditionally: when ambiguous requirements arise | Refine project vision before initializing |
59
+ | `dcp-hygiene` | Output (after `--deep` runs) | Compress closed detection + srcwalk/fallow work-stream when `compress` is available |
59
60
 
60
61
  ---
61
62
 
@@ -171,6 +172,8 @@ Write to `.pi/user.md` with the captured preferences.
171
172
 
172
173
  ## Output
173
174
 
175
+ > **DCP hygiene:** If `--deep` ran and `compress` is available, compress the closed Phase 1 detection + git-history + srcwalk/fallow work-stream per the `dcp-hygiene` skill — tech stack, validated commands, and structure are captured in `AGENTS.md` and `tech-stack.md`. Skip if `compress` is unavailable (non-deep init produces little output).
176
+
174
177
  Report what was created:
175
178
  1. AGENTS.md (if core setup ran)
176
179
  2. tech-stack.md (if core setup ran)
@@ -36,12 +36,13 @@ Before planning:
36
36
  | `incremental-implementation` | Always | Thin vertical slice discipline — each task is verify-after-each |
37
37
  | `subagent-driven-development` | Multi-wave plan | Plan tasks for fresh subagent dispatch per task |
38
38
  | `source-driven-development` | Level 1-3 | Ground decisions in official docs when researching dependencies |
39
+ | `dcp-hygiene` | Phase 8 Report | Compress closed git-history + research work-stream when `compress` is available |
39
40
 
40
41
  ## Phase 0: Institutional Research (Mandatory)
41
42
 
42
43
  ### Step 1: Search institutional memory
43
44
 
44
- Use `vcc_recall` to search for bugfixes and existing plans. If relevant observations found, incorporate them.
45
+ Use `vcc_recall` to search for bugfixes and existing plans. Also use `memory_search({ query: "<plan topic>", target: "failure", category: "insight" })` for durable institutional knowledge. If relevant observations found, incorporate them.
45
46
 
46
47
  ### Step 2: Mine git history
47
48
 
@@ -216,7 +217,7 @@ Scan plan against AGENTS.md hard constraints:
216
217
  | Plan already exists | Ask user: overwrite or skip? |
217
218
  | Missing spec artifact | Report: "No spec found. Run `/create` first." |
218
219
  | Subagent research fails | Retry once with adjusted prompt, then proceed with existing knowledge |
219
- | Verification fails 2x | Stop, report blocker with file:line evidence |
220
+ | Verification fails 2x | Stop, report blocker with file:line evidence. **Also:** save the failed approach to `memory(action: "add", target: "failure", category: "failure")` — the plan decomposition or approach that failed, and why. |
220
221
 
221
222
  ## Stop Conditions
222
223
 
@@ -227,6 +228,8 @@ Scan plan against AGENTS.md hard constraints:
227
228
 
228
229
  ## Phase 8: Report
229
230
 
231
+ > **DCP hygiene:** Before reporting, if the `compress` tool is available, compress the closed Phase 0-2 institutional-research + git-history + scout work-stream per the `dcp-hygiene` skill — observable truths, artifacts, and dependency waves are captured in `plan.md` and `tasks.json`. Skip if `compress` is unavailable.
232
+
230
233
  1. **Discovery Level:** [0-3] with rationale
231
234
  2. **Must-Haves:** [N] observable truths, [M] required artifacts, [K] key links
232
235
  3. **Context Budget:** [Estimated usage]
@@ -62,6 +62,7 @@ Before starting, analyze the research topic complexity:
62
62
  | `srcwalk` | Codebase research | Navigate codebase with repo maps, symbol search, callers/callees |
63
63
  | `opensrc` | Researching dependencies | Inspect library source for internal behavior |
64
64
  | `gemini-large-context` | Large codebase or multi-repo | Analyze beyond typical context limits |
65
+ | `dcp-hygiene` | Phase 3 Synthesize (+ mid-research if `--thorough`) | Compress closed search/verify work-streams when `compress` is available |
65
66
 
66
67
  ## Direct Execution (Simple Research)
67
68
 
@@ -82,6 +83,8 @@ Cross-check findings:
82
83
 
83
84
  ### Phase 3: Synthesize
84
85
 
86
+ > **DCP hygiene:** If `compress` is available, compress the closed Phase 1-2 search/verify work-stream per the `dcp-hygiene` skill — questions, answers, confidence, and sources are captured in the findings. For `--thorough` (~100+ calls), compress every ~30 calls mid-research to keep context bounded. Skip if `compress` is unavailable.
87
+
85
88
  If within active work, write findings to `.pi/artifacts/$SLUG/research.md`. Otherwise report inline.
86
89
 
87
90
  ## Workflow Execution (Complex Research)
@@ -21,6 +21,7 @@ Execute spec tasks, verify each passes, run review, mark complete.
21
21
 
22
22
  Before shipping:
23
23
  - Use `vcc_recall` to search for failed approaches to avoid repeating
24
+ - Use `memory_search({ query: "<feature keywords>", target: "failure", category: "failure" })` for durable cross-session failures and prior decisions
24
25
  - Verify `.pi/artifacts/$(cat .pi/artifacts/.active)/spec.md` exists (if not, tell user to run `/create` first)
25
26
  - If `plan.md` exists, verify it references the current spec
26
27
  - Workspace check: create branch if needed, install deps if needed
@@ -37,6 +38,7 @@ Before shipping:
37
38
  | `code-review-and-quality` | Phase 5 review | 5-axis review: correctness, readability, architecture, security, performance |
38
39
  | `doubt-driven-development` | High-risk features | In-flight adversarial review before merge |
39
40
  | `context-engineering` | Batch workflow (≥5 independent tasks) | Context budget management for parallel subagent handoffs |
41
+ | `dcp-hygiene` | Phase 7 Report (+ Phase 2/3→4 transition) | Compress closed implement/verify work-streams when `compress` is available |
40
42
 
41
43
  ## Phase 1: Route to Execution
42
44
 
@@ -118,6 +120,8 @@ If routed to workflow mode:
118
120
 
119
121
  ## Phase 4: Verification Gate
120
122
 
123
+ > **DCP hygiene (mid-command):** Implementation is complete — the diff is now the source of truth, not the edit/read history. If `compress` is available, compress the closed Phase 2/3 implementation work-stream (file reads + edits) per the `dcp-hygiene` skill before running gates. Keep task results, commits, and affected-file lists in the summary. Skip if `compress` is unavailable.
124
+
121
125
  **Delegate to `/verify` — do not duplicate the gate logic here.** Run the canonical verification protocol defined in `prompts/verify.md` (Phase 1 Completeness → Phase 2 Correctness → Phase 4 Phantom Detection). Concretely:
122
126
 
123
127
  1. Invoke `/verify all --full` semantics (or run the same steps inline if already mid-session): load `verification-before-completion`, run typecheck + lint + test gates, use **full mode** for shipping (incremental is for iteration only), record stamp to `.pi/artifacts/verify.log` after all gates pass, run phantom completion detection, and do goal-backward verification (observable truths from plan/spec satisfied).
@@ -182,7 +186,7 @@ Ask user before closing. If confirmed:
182
186
 
183
187
  | Scenario | Action |
184
188
  |----------|--------|
185
- | Task verification fails 2x | Stop, report blocker with file:line evidence |
189
+ | Task verification fails 2x | Stop, report blocker with file:line evidence. **Also:** save the failed approach to `memory(action: "add", target: "failure", category: "failure")` — what was tried, why it failed, the error, and the task description. |
186
190
  | Subagent returns failure | Read error, retry once with adjusted prompt, then escalate |
187
191
  | Review finds critical issue | Fix inline, re-run Phase 4, continue |
188
192
  | Batch workflow failure | Fall back to sequential execution |
@@ -190,6 +194,8 @@ Ask user before closing. If confirmed:
190
194
 
191
195
  ## Phase 7: Report
192
196
 
197
+ > **DCP hygiene:** Before reporting, if the `compress` tool is available, compress the closed implementation + verification work-stream (file reads, edits, gate bash output) per the `dcp-hygiene` skill — task results, commits, and gate results are captured in this report and `progress.md`. Skip if `compress` is unavailable.
198
+
193
199
  1. **Execution Summary:** tasks completed/total, waves executed, commits made
194
200
  2. **Task Results:** per-task status, files modified, commit hashes
195
201
  3. **Verification Gate Results:** typecheck, lint, test, build — pass/fail
@@ -41,6 +41,7 @@ Check implementation against PRD before shipping.
41
41
  | `verification-before-completion` | Always | Evidence-before-claims; phantom detection; verification cache protocol; Worker Distrust Protocol |
42
42
  | `code-review-and-quality` | Phase 4 coherence check | Cross-reference artifacts for correctness |
43
43
  | `testing-anti-patterns` | Phase 3 after tests pass | Detect mock-only tests, production pollution, and fragile assertions |
44
+ | `dcp-hygiene` | Phase 5 Report | Compress the closed gate output (typecheck/lint/test) when `compress` is available |
44
45
 
45
46
  ## Phase 0: Verification Cache
46
47
 
@@ -115,7 +116,7 @@ Load `verification-before-completion` skill. Follow its phantom completion detec
115
116
  | Scenario | Action |
116
117
  |----------|--------|
117
118
  | Gate fails | Report which gate failed with exact error |
118
- | Verification fails 2x | Stop, report blocker with file:line evidence |
119
+ | Verification fails 2x | Stop, report blocker with file:line evidence. **Also:** save the failure to `memory(action: "add", target: "failure", category: "failure")` — the gate that failed, the error, and what was tried. |
119
120
  | Cache stamp mismatch | Run gates fresh — don't reuse stale cache |
120
121
  | Phantom artifacts detected | Report PHANTOM score, block completion |
121
122
 
@@ -128,6 +129,8 @@ Load `verification-before-completion` skill. Follow its phantom completion detec
128
129
 
129
130
  ## Phase 5: Report
130
131
 
132
+ > **DCP hygiene:** Before reporting, if the `compress` tool is available, compress the closed Phase 2 gate output (typecheck/lint/test/bash) per the `dcp-hygiene` skill — results are recorded in the report table and the verification cache. Skip if `compress` is unavailable.
133
+
131
134
  Append to `.pi/artifacts/$SLUG/progress.md`: `Verification: [PASS|PARTIAL|FAIL] - [summary]`
132
135
 
133
136
  1. **Result**: READY TO SHIP / NEEDS WORK / BLOCKED