continuous-improvement 3.20.0 → 3.21.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +10 -0
- package/QUICKSTART.md +1 -1
- package/README.md +7 -6
- package/bin/check-landing-version.mjs +63 -0
- package/bin/check-scripts-citation-drift.mjs +61 -13
- package/bin/generate-plugin-manifests.mjs +2 -0
- package/bin/install.mjs +29 -60
- package/commands/production-readiness-review.md +5 -4
- package/commands/simplicity-review.md +35 -0
- package/commands/verify-install.md +2 -2
- package/hooks/gateguard.mjs +22 -3
- package/hooks/query-cost-nudge.mjs +1 -0
- package/hooks/session.mjs +85 -0
- package/hooks/typecheck-stop.mjs +2 -1
- package/lib/plugin-metadata.mjs +18 -20
- package/llms.txt +1 -1
- package/package.json +6 -4
- package/plugins/beginner.json +1 -1
- package/plugins/continuous-improvement/.claude-plugin/marketplace.json +2 -2
- package/plugins/continuous-improvement/.claude-plugin/plugin.json +2 -2
- package/plugins/continuous-improvement/README.md +1 -0
- package/plugins/continuous-improvement/commands/production-readiness-review.md +5 -4
- package/plugins/continuous-improvement/commands/simplicity-review.md +35 -0
- package/plugins/continuous-improvement/commands/verify-install.md +2 -2
- package/plugins/continuous-improvement/hooks/gateguard.mjs +22 -3
- package/plugins/continuous-improvement/hooks/hooks.json +15 -16
- package/plugins/continuous-improvement/hooks/query-cost-nudge.mjs +1 -0
- package/plugins/continuous-improvement/hooks/session.mjs +85 -0
- package/plugins/continuous-improvement/hooks/typecheck-stop.mjs +2 -1
- package/plugins/continuous-improvement/lib/plugin-metadata.mjs +18 -20
- package/plugins/continuous-improvement/scripts/README.md +33 -0
- package/plugins/continuous-improvement/scripts/detect-deploy-target.sh +66 -0
- package/plugins/continuous-improvement/scripts/get-deployed-sha.sh +113 -0
- package/plugins/continuous-improvement/scripts/git-state-snapshot.sh +48 -0
- package/plugins/continuous-improvement/scripts/resolve-verify-ladder.mjs +241 -0
- package/plugins/continuous-improvement/scripts/route-recommendation.mjs +178 -0
- package/plugins/continuous-improvement/scripts/route-recommendation.routes.json +213 -0
- package/plugins/continuous-improvement/scripts/run-synthetic.mjs +298 -0
- package/plugins/continuous-improvement/scripts/scan-past-mistakes.mjs +285 -0
- package/plugins/continuous-improvement/skills/README.md +1 -0
- package/plugins/continuous-improvement/skills/deploy-receipt/SKILL.md +2 -2
- package/plugins/continuous-improvement/skills/gateguard/SKILL.md +2 -2
- package/plugins/continuous-improvement/skills/proceed-with-the-recommendation/SKILL.md +3 -2
- package/plugins/continuous-improvement/skills/reconcile/SKILL.md +1 -1
- package/plugins/continuous-improvement/skills/simplicity-review/SKILL.md +80 -0
- package/plugins/continuous-improvement/skills/verification-loop/SKILL.md +5 -5
- package/plugins/continuous-improvement/skills/workspace-surface-audit/SKILL.md +1 -1
- package/plugins/continuous-improvement/skills/worktree-safety/SKILL.md +1 -1
- package/plugins/expert.json +1 -1
- package/scripts/README.md +33 -0
- package/scripts/detect-deploy-target.sh +66 -0
- package/scripts/get-deployed-sha.sh +113 -0
- package/scripts/git-state-snapshot.sh +48 -0
- package/scripts/resolve-verify-ladder.mjs +241 -0
- package/scripts/route-recommendation.mjs +178 -0
- package/scripts/route-recommendation.routes.json +213 -0
- package/scripts/run-synthetic.mjs +298 -0
- package/scripts/scan-past-mistakes.mjs +285 -0
- package/skills/deploy-receipt.md +2 -2
- package/skills/gateguard.md +2 -2
- package/skills/proceed-with-the-recommendation.md +3 -2
- package/skills/reconcile.md +1 -1
- package/skills/simplicity-review.md +80 -0
- package/skills/verification-loop.md +5 -5
- package/skills/workspace-surface-audit.md +1 -1
- package/skills/worktree-safety.md +1 -1
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/scan-past-mistakes.mjs
|
|
3
|
+
//
|
|
4
|
+
// Scan the three past-mistake surfaces named in Phase 0 P-MAG of
|
|
5
|
+
// `proceed-with-the-recommendation` and surface their content as a
|
|
6
|
+
// machine-readable list, so the skill's most-skipped phase becomes
|
|
7
|
+
// mechanically detectable: if the scan never runs, no output is emitted.
|
|
8
|
+
//
|
|
9
|
+
// Surfaces (all three are scanned every invocation):
|
|
10
|
+
// 1. observations.jsonl — JSONL lines whose type (or legacy event field)
|
|
11
|
+
// is "failure" or "correction". Last N (default 10) returned.
|
|
12
|
+
// 2. memory feedback — every feedback_*.md file in the project's
|
|
13
|
+
// auto-memory directory whose frontmatter declares `type: feedback`.
|
|
14
|
+
// 3. CLAUDE.md — rows extracted from a "## Past Mistakes" table
|
|
15
|
+
// in the project's CLAUDE.md (markdown table, first column = date).
|
|
16
|
+
//
|
|
17
|
+
// Defaults derive each path from the project root (positional arg; default
|
|
18
|
+
// cwd). All three can be overridden explicitly via flags for testing or
|
|
19
|
+
// non-default layouts.
|
|
20
|
+
//
|
|
21
|
+
// Usage:
|
|
22
|
+
// node scripts/scan-past-mistakes.mjs # cwd default
|
|
23
|
+
// node scripts/scan-past-mistakes.mjs <repo-root> # explicit root
|
|
24
|
+
// node scripts/scan-past-mistakes.mjs --json # JSON output
|
|
25
|
+
// node scripts/scan-past-mistakes.mjs \
|
|
26
|
+
// --observations <path> --memory-dir <dir> --claude-md <path>
|
|
27
|
+
// node scripts/scan-past-mistakes.mjs --max-observations 25
|
|
28
|
+
//
|
|
29
|
+
// Active-in-scope assessment is the LLM's job, not the script's. The script
|
|
30
|
+
// surfaces raw entries with citations; the skill body annotates each line
|
|
31
|
+
// with "Active in current scope: yes|no" based on the current task.
|
|
32
|
+
//
|
|
33
|
+
// Cited by:
|
|
34
|
+
// - skills/proceed-with-the-recommendation.md Phase 0 Rule 1
|
|
35
|
+
|
|
36
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
37
|
+
import { homedir } from "node:os";
|
|
38
|
+
import { join } from "node:path";
|
|
39
|
+
import { argv, cwd, exit, stdout } from "node:process";
|
|
40
|
+
|
|
41
|
+
function parseArgs() {
|
|
42
|
+
const args = argv.slice(2);
|
|
43
|
+
const out = {
|
|
44
|
+
json: false,
|
|
45
|
+
root: cwd(),
|
|
46
|
+
observations: null,
|
|
47
|
+
memoryDir: null,
|
|
48
|
+
claudeMd: null,
|
|
49
|
+
maxObservations: 10,
|
|
50
|
+
};
|
|
51
|
+
for (let i = 0; i < args.length; i++) {
|
|
52
|
+
const a = args[i];
|
|
53
|
+
if (a === "--json") {
|
|
54
|
+
out.json = true;
|
|
55
|
+
} else if (a === "--observations") {
|
|
56
|
+
out.observations = args[++i];
|
|
57
|
+
} else if (a === "--memory-dir") {
|
|
58
|
+
out.memoryDir = args[++i];
|
|
59
|
+
} else if (a === "--claude-md") {
|
|
60
|
+
out.claudeMd = args[++i];
|
|
61
|
+
} else if (a === "--max-observations") {
|
|
62
|
+
out.maxObservations = parseInt(args[++i], 10) || 10;
|
|
63
|
+
} else if (a === "-h" || a === "--help") {
|
|
64
|
+
stdout.write(
|
|
65
|
+
"usage: scan-past-mistakes.mjs [--json] [<repo-root>]\n" +
|
|
66
|
+
" [--observations <path>] [--memory-dir <dir>] [--claude-md <path>]\n" +
|
|
67
|
+
" [--max-observations <n>]\n",
|
|
68
|
+
);
|
|
69
|
+
exit(0);
|
|
70
|
+
} else {
|
|
71
|
+
out.root = a;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Map a project root to the auto-memory subdirectory name. Lowercases the
|
|
78
|
+
// Windows drive letter and replaces path separators with dashes, matching
|
|
79
|
+
// the convention used by `~/.claude/projects/<hash>/memory/` and
|
|
80
|
+
// `~/.claude/instincts/<hash>/`. On POSIX paths the leading slash becomes
|
|
81
|
+
// a leading dash, which is fine — the host has the same path on both
|
|
82
|
+
// surfaces and the resolved file existence is what's checked, not the
|
|
83
|
+
// hash format itself.
|
|
84
|
+
function projectHash(root) {
|
|
85
|
+
let p = root;
|
|
86
|
+
p = p.replace(/^([A-Za-z]):/, (_m, d) => d.toLowerCase() + ":");
|
|
87
|
+
p = p.replace(/:[\\/]/, "--");
|
|
88
|
+
p = p.replace(/[\\/]/g, "-");
|
|
89
|
+
return p;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function defaultObservationsPath(root) {
|
|
93
|
+
return join(homedir(), ".claude", "instincts", projectHash(root), "observations.jsonl");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function defaultMemoryDir(root) {
|
|
97
|
+
return join(homedir(), ".claude", "projects", projectHash(root), "memory");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function defaultClaudeMdPath(root) {
|
|
101
|
+
return join(root, "CLAUDE.md");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function scanObservations(path, maxN) {
|
|
105
|
+
if (!path || !existsSync(path)) return [];
|
|
106
|
+
const raw = readFileSync(path, "utf8");
|
|
107
|
+
const lines = raw.split(/\r?\n/);
|
|
108
|
+
const matches = [];
|
|
109
|
+
for (let i = 0; i < lines.length; i++) {
|
|
110
|
+
const line = lines[i].trim();
|
|
111
|
+
if (!line) continue;
|
|
112
|
+
let obj;
|
|
113
|
+
try {
|
|
114
|
+
obj = JSON.parse(line);
|
|
115
|
+
} catch {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Support both the current `type` field and the legacy `event` field
|
|
119
|
+
// (per feedback_observer_field_name_bug — pre-2026-05-06T00:38Z rows).
|
|
120
|
+
const t = obj.type ?? obj.event;
|
|
121
|
+
if (t !== "failure" && t !== "correction") continue;
|
|
122
|
+
const summary =
|
|
123
|
+
obj.summary ??
|
|
124
|
+
obj.output_summary ??
|
|
125
|
+
(typeof obj.tool_response === "string"
|
|
126
|
+
? obj.tool_response
|
|
127
|
+
: JSON.stringify(obj).slice(0, 240));
|
|
128
|
+
matches.push({
|
|
129
|
+
line: i + 1,
|
|
130
|
+
ts: obj.ts ?? obj.timestamp ?? null,
|
|
131
|
+
type: t,
|
|
132
|
+
summary,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// Last N (chronologically — JSONL is append-only).
|
|
136
|
+
return matches.slice(-maxN);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function parseFrontmatter(content) {
|
|
140
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
141
|
+
if (!m) return null;
|
|
142
|
+
const fm = {};
|
|
143
|
+
for (const line of m[1].split(/\r?\n/)) {
|
|
144
|
+
const kv = /^([A-Za-z][A-Za-z0-9_-]*):\s*(.*)$/.exec(line);
|
|
145
|
+
if (!kv) continue;
|
|
146
|
+
let value = kv[2].trim();
|
|
147
|
+
if (
|
|
148
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
149
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
150
|
+
) {
|
|
151
|
+
value = value.slice(1, -1);
|
|
152
|
+
}
|
|
153
|
+
fm[kv[1]] = value;
|
|
154
|
+
}
|
|
155
|
+
return fm;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function scanFeedbackMemories(dir) {
|
|
159
|
+
if (!dir || !existsSync(dir)) return [];
|
|
160
|
+
let entries;
|
|
161
|
+
try {
|
|
162
|
+
entries = readdirSync(dir);
|
|
163
|
+
} catch {
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
const out = [];
|
|
167
|
+
for (const file of entries) {
|
|
168
|
+
if (!file.startsWith("feedback_") || !file.endsWith(".md")) continue;
|
|
169
|
+
let content;
|
|
170
|
+
try {
|
|
171
|
+
content = readFileSync(join(dir, file), "utf8");
|
|
172
|
+
} catch {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const fm = parseFrontmatter(content);
|
|
176
|
+
if (!fm) continue;
|
|
177
|
+
// Only surface entries explicitly typed as feedback.
|
|
178
|
+
if (fm.type && fm.type !== "feedback") continue;
|
|
179
|
+
out.push({
|
|
180
|
+
file,
|
|
181
|
+
name: fm.name ?? null,
|
|
182
|
+
description: fm.description ?? null,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
out.sort((a, b) => a.file.localeCompare(b.file));
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function scanClaudeMdPastMistakes(path) {
|
|
190
|
+
if (!path || !existsSync(path)) return [];
|
|
191
|
+
const content = readFileSync(path, "utf8");
|
|
192
|
+
const headingIdx = content.search(/^##\s+Past Mistakes\s*$/m);
|
|
193
|
+
if (headingIdx === -1) return [];
|
|
194
|
+
|
|
195
|
+
// Slice from the heading to the start of the next ## heading (or EOF).
|
|
196
|
+
const fromHeading = content.slice(headingIdx);
|
|
197
|
+
const nextSectionRel = fromHeading.slice(2).search(/^##\s/m);
|
|
198
|
+
const section = nextSectionRel === -1 ? fromHeading : fromHeading.slice(0, nextSectionRel + 2);
|
|
199
|
+
|
|
200
|
+
const out = [];
|
|
201
|
+
for (const rawLine of section.split(/\r?\n/)) {
|
|
202
|
+
const line = rawLine.trim();
|
|
203
|
+
// Skip blank, heading, and the markdown table divider.
|
|
204
|
+
if (!line || line.startsWith("#")) continue;
|
|
205
|
+
if (/^\|[\s|:-]+\|$/.test(line)) continue;
|
|
206
|
+
if (!line.startsWith("|") || !line.endsWith("|")) continue;
|
|
207
|
+
|
|
208
|
+
// Parse pipe-delimited cells; strip leading/trailing pipe.
|
|
209
|
+
const inner = line.slice(1, -1);
|
|
210
|
+
const cells = inner.split("|").map((c) => c.trim());
|
|
211
|
+
if (cells.length < 2) continue;
|
|
212
|
+
|
|
213
|
+
// Header detection: literal "Date" first cell.
|
|
214
|
+
if (cells[0].toLowerCase() === "date") continue;
|
|
215
|
+
if (/^[-: ]+$/.test(cells[0])) continue;
|
|
216
|
+
|
|
217
|
+
out.push({
|
|
218
|
+
date: cells[0],
|
|
219
|
+
mistake: cells[1] ?? "",
|
|
220
|
+
lesson: cells[2] ?? null,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function pretty(scan) {
|
|
227
|
+
const total = scan.observations.length + scan.feedback.length + scan.claude_md.length;
|
|
228
|
+
if (total === 0) return "No prior mistakes recorded — proceed.\n";
|
|
229
|
+
|
|
230
|
+
const out = [`Past mistakes scanned: ${total} found across 3 surfaces.`, ""];
|
|
231
|
+
|
|
232
|
+
if (scan.observations.length > 0) {
|
|
233
|
+
out.push(`== observations.jsonl (${scan.observations.length}) ==`);
|
|
234
|
+
for (const o of scan.observations) {
|
|
235
|
+
const ts = o.ts ? `${o.ts} ` : "";
|
|
236
|
+
out.push(` [line ${o.line}] ${ts}${o.type}: ${o.summary}`);
|
|
237
|
+
}
|
|
238
|
+
out.push("");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (scan.feedback.length > 0) {
|
|
242
|
+
out.push(`== feedback memories (${scan.feedback.length}) ==`);
|
|
243
|
+
for (const f of scan.feedback) {
|
|
244
|
+
out.push(` [${f.file}] ${f.name ?? ""}`);
|
|
245
|
+
if (f.description) out.push(` — ${f.description}`);
|
|
246
|
+
}
|
|
247
|
+
out.push("");
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (scan.claude_md.length > 0) {
|
|
251
|
+
out.push(`== CLAUDE.md Past Mistakes (${scan.claude_md.length}) ==`);
|
|
252
|
+
for (const e of scan.claude_md) {
|
|
253
|
+
out.push(` [${e.date}] ${e.mistake}`);
|
|
254
|
+
if (e.lesson) out.push(` Lesson: ${e.lesson}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return out.join("\n") + "\n";
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function main() {
|
|
262
|
+
const args = parseArgs();
|
|
263
|
+
const obsPath = args.observations ?? defaultObservationsPath(args.root);
|
|
264
|
+
const memDir = args.memoryDir ?? defaultMemoryDir(args.root);
|
|
265
|
+
const claudeMd = args.claudeMd ?? defaultClaudeMdPath(args.root);
|
|
266
|
+
|
|
267
|
+
const scan = {
|
|
268
|
+
observations: scanObservations(obsPath, args.maxObservations),
|
|
269
|
+
feedback: scanFeedbackMemories(memDir),
|
|
270
|
+
claude_md: scanClaudeMdPastMistakes(claudeMd),
|
|
271
|
+
sources: {
|
|
272
|
+
observations: obsPath,
|
|
273
|
+
memory_dir: memDir,
|
|
274
|
+
claude_md: claudeMd,
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
if (args.json) {
|
|
279
|
+
stdout.write(JSON.stringify(scan, null, 2) + "\n");
|
|
280
|
+
} else {
|
|
281
|
+
stdout.write(pretty(scan));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
main();
|
package/skills/deploy-receipt.md
CHANGED
|
@@ -21,7 +21,7 @@ This skill defines the receipt that closes that gap, without modifying the vendo
|
|
|
21
21
|
Activate when ALL of the following are true:
|
|
22
22
|
|
|
23
23
|
1. A merge into the deploy branch (typically `main` or `master`) has just landed
|
|
24
|
-
2.
|
|
24
|
+
2. `bash "${CLAUDE_PLUGIN_ROOT}/scripts/detect-deploy-target.sh"` (source: `scripts/detect-deploy-target.sh`) returns a value other than `none` at the repo root. The script encodes the full file-marker table — `railway.toml` / `railway.json` → `railway`, `wrangler.toml` / `wrangler.jsonc` → `cloudflare`, `vercel.json` / `.vercel/` → `vercel`, `netlify.toml` → `netlify`, `fly.toml` → `fly`, `app.yaml` → `appengine`, `apprunner.yaml` → `apprunner`, `.github/workflows/*.yml` with a `deploy:` job → `gha-deploy`. First match wins, in that order. The script is the source of truth; the file list above is documentation
|
|
25
25
|
3. `finishing-a-development-branch` has reported "merged" — not "PR opened", not "review pending"
|
|
26
26
|
|
|
27
27
|
Do NOT activate when:
|
|
@@ -45,7 +45,7 @@ The skill is provider-aware but never hardcodes a specific API key or token shap
|
|
|
45
45
|
|
|
46
46
|
### Route A — Provider CLI (preferred when authenticated)
|
|
47
47
|
|
|
48
|
-
The CLI is the highest-fidelity source. Run
|
|
48
|
+
The CLI is the highest-fidelity source. Run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-deployed-sha.sh" <provider>` (source: `scripts/get-deployed-sha.sh`) — the script owns the per-provider pipeline (CLI + jq filter) and prints just the SHA on stdout. Inspect the pipeline shape without executing via `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-deployed-sha.sh" --show-command <provider>`.
|
|
49
49
|
|
|
50
50
|
Provider-to-pipeline map (cited from the script, not redefined here):
|
|
51
51
|
|
package/skills/gateguard.md
CHANGED
|
@@ -97,7 +97,7 @@ A second Claude/Codex/Maulana session can be running on the same host and the sa
|
|
|
97
97
|
|
|
98
98
|
**On the first Edit / Write / mutating Bash of a session:**
|
|
99
99
|
|
|
100
|
-
Run
|
|
100
|
+
Run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/git-state-snapshot.sh"` (source: `scripts/git-state-snapshot.sh`) and quote its JSON envelope verbatim. Example output:
|
|
101
101
|
|
|
102
102
|
```
|
|
103
103
|
{"head":"966ce51","upstream":"966ce51","dirty":0,"root":"/path/to/repo","branch":"main"}
|
|
@@ -115,7 +115,7 @@ If `upstream` is `"none"` or `branch` is `"detached"`, say so explicitly. Do not
|
|
|
115
115
|
|
|
116
116
|
**On every subsequent Edit / Write / mutating Bash, before allowing the action:**
|
|
117
117
|
|
|
118
|
-
Re-run
|
|
118
|
+
Re-run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/git-state-snapshot.sh"` (source: `scripts/git-state-snapshot.sh`) and diff against the baseline:
|
|
119
119
|
|
|
120
120
|
1. `head` — has it advanced past your baseline without your commits?
|
|
121
121
|
2. `upstream` — did upstream move while you worked?
|
|
@@ -135,7 +135,7 @@ Before research begins, the skill must read its own track record. The instinct s
|
|
|
135
135
|
|
|
136
136
|
### Rule 1 — Acknowledge before context (right context from the beginning)
|
|
137
137
|
|
|
138
|
-
Run
|
|
138
|
+
Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/scan-past-mistakes.mjs"` (source: `scripts/scan-past-mistakes.mjs`) at the project root. Scan three surfaces in one pass and surface every entry with a citation:
|
|
139
139
|
|
|
140
140
|
- `~/.claude/instincts/<project-hash>/observations.jsonl` — last N (default 10) entries with `type: failure` or `correction` (legacy `event` field also matched for pre-2026-05-06 rows)
|
|
141
141
|
- `~/.claude/projects/<project-hash>/memory/feedback_*.md` — every file whose frontmatter declares `type: feedback`; the canonical home of the operator's named corrections (e.g. `feedback_past_mistake_gate.md`, `feedback_no_git_add_all_on_windows.md`)
|
|
@@ -202,7 +202,7 @@ For each item in the ORIGINAL order:
|
|
|
202
202
|
|
|
203
203
|
### Routing Table (with Inline Fallbacks)
|
|
204
204
|
|
|
205
|
-
Run
|
|
205
|
+
Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/route-recommendation.mjs" "<item>"` (source: `scripts/route-recommendation.mjs`) to match a single recommendation item to its preferred chain + inline fallback. Default mode prints the matched row; `--json` for programmatic consumption; `--list` enumerates every row. The programmatic source of truth is `scripts/route-recommendation.routes.json` — the table below is the human-readable documentation that mirrors it. If they drift, the routes.json file wins.
|
|
206
206
|
|
|
207
207
|
Rows whose **Preferred skill** is not bundled with the `continuous-improvement` plugin carry a `(Reference behavior — does not require <skill>.)` marker on the fallback cell. The marker makes the soft-dependency contract visible at point of use: the inline fallback is fully self-contained and runs without that skill installed. Rows whose preferred skill ships with the plugin (`ralph`, `tdd-workflow`, `continuous-improvement`) carry no marker — the dedicated skill is always available.
|
|
208
208
|
|
|
@@ -213,6 +213,7 @@ Rows whose **Preferred skill** is not bundled with the `continuous-improvement`
|
|
|
213
213
|
| Fix bug / investigate failure | `superpowers:systematic-debugging` | Hypothesis → add logs/tests → reproduce → smallest fix → verify with the failing repro. (Reference behavior — does not require `superpowers:systematic-debugging`.) |
|
|
214
214
|
| Write tests / add coverage | `superpowers:test-driven-development` or `tdd-workflow` | RED (failing test) → GREEN (minimal code) → REFACTOR; one test, one behavior |
|
|
215
215
|
| Refactor / dead code cleanup | `simplify` | Find dupes/unused exports, delete in place, re-run type check and smallest test. (Reference behavior — does not require `simplify`.) |
|
|
216
|
+
| Over-engineering check on a diff | `simplicity-review` (bundled) | Walk the reuse ladder (existing file, stdlib, native feature, one line) over the current diff and report GO/TRIM without editing; apply trims, then re-run the smallest check. Never flags input validation, data-loss handling, security, or accessibility. |
|
|
216
217
|
| Security review / auth audit | `security-review` | Scan for hardcoded secrets, unsanitized input, missing authz, SQL string concat, open CORS. (Reference behavior — does not require `security-review`.) |
|
|
217
218
|
| Code review before merge | `superpowers:requesting-code-review` or `code-review` | Read diff top-to-bottom, flag CRITICAL / HIGH / MEDIUM. (Reference behavior — does not require `code-review`.) |
|
|
218
219
|
| Verify before shipping | `superpowers:verification-before-completion` | Smallest check that proves correctness: typecheck + one test + one curl. (Reference behavior — does not require `superpowers:verification-before-completion`.) |
|
package/skills/reconcile.md
CHANGED
|
@@ -40,7 +40,7 @@ When another session/loop may be active, do not assume the tree is yours:
|
|
|
40
40
|
- An in-progress `MERGE_HEAD` / `rebase-merge` you did not start means another actor is mid-operation. Do not "help" by editing conflicted files — wait, or hand off.
|
|
41
41
|
- Re-read the current branch immediately before any mutation; if it shifted since your snapshot, re-survey from the top.
|
|
42
42
|
- If `.git/index` keeps changing while you are idle, a writer is active. Pause and surface it rather than racing.
|
|
43
|
-
- If `gateguard` is installed, its Parallel-Actor Gate already captured this baseline on the session's first mutation (
|
|
43
|
+
- If `gateguard` is installed, its Parallel-Actor Gate already captured this baseline on the session's first mutation by running `bash "${CLAUDE_PLUGIN_ROOT}/scripts/git-state-snapshot.sh"` (source: `scripts/git-state-snapshot.sh`) and divergence-checks every later mutation — `reconcile` complements that gate, it does not replace it. Without gateguard, run the snapshot above yourself.
|
|
44
44
|
|
|
45
45
|
## Classify, Then Act
|
|
46
46
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: simplicity-review
|
|
3
|
+
tier: "2"
|
|
4
|
+
description: Enforces Law 4 (Verify Before Reporting) of the 7 Laws of AI Agent Discipline. Reviews the current diff for over-engineering (code that could reuse an existing file, a stdlib or native feature, or fewer lines) and reports trim findings without touching code, so 'it works' is never mistaken for 'it is the minimum that works'.
|
|
5
|
+
origin: continuous-improvement
|
|
6
|
+
user-invocable: true
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Simplicity Review — Flag the Over-Build Before It Ships
|
|
10
|
+
|
|
11
|
+
Law 4 says verify before reporting. "It compiles and the test passes" is a claim about correctness, not about whether the change is the minimum that works. This skill runs a diff-scoped review with one question: could this have been smaller? It reads the change like the laziest senior dev in the room, walks a fixed reuse ladder, and reports what to trim. It never edits code. The best code is the code you never wrote.
|
|
12
|
+
|
|
13
|
+
## When to Activate
|
|
14
|
+
|
|
15
|
+
- After writing a feature or fix, before opening a PR, when the diff feels larger than the task warranted.
|
|
16
|
+
- When you reached for a new file, a new dependency, or a wrapper component and a native or existing option might already cover it.
|
|
17
|
+
- As a routed step from `proceed-with-the-recommendation` at the "Refactor / dead code cleanup" line, as the repo-owned alternative to the built-in `simplify`.
|
|
18
|
+
- Before a release cut, over the diff since the last tag, as a last pass on accreted complexity.
|
|
19
|
+
|
|
20
|
+
## The Ladder
|
|
21
|
+
|
|
22
|
+
Read each added or changed block and stop at the first rung that holds:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
1. Does this need to exist? -> skip it (YAGNI)
|
|
26
|
+
2. Already in this codebase? -> reuse it
|
|
27
|
+
3. Stdlib does it? -> use it
|
|
28
|
+
4. Native platform feature? -> use it
|
|
29
|
+
5. Installed dependency? -> use it
|
|
30
|
+
6. One line? -> one line
|
|
31
|
+
7. Only then: the minimum that works
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Most real cuts come from rungs 2 to 4: a hand-rolled helper that duplicates an existing one, a component built where a native input, a stdlib call, or a platform primitive already does the job.
|
|
35
|
+
|
|
36
|
+
## Read Before You Cut
|
|
37
|
+
|
|
38
|
+
Lazy about the solution, never about the reading. The ladder shortens the solution, not the investigation. Trace the whole change and what it touches first. A "simpler" path proposed without reading the surrounding code is a guess, and a wrong trim is worse than the over-build.
|
|
39
|
+
|
|
40
|
+
## Safety Carve-Out (Never Flag)
|
|
41
|
+
|
|
42
|
+
Lazy, not negligent. These are never on the chopping block, no matter how many lines they cost:
|
|
43
|
+
|
|
44
|
+
- Input validation at trust boundaries.
|
|
45
|
+
- Error handling that prevents data loss.
|
|
46
|
+
- Security controls (authz checks, escaping, secret handling).
|
|
47
|
+
- Accessibility.
|
|
48
|
+
|
|
49
|
+
This aligns with `rules/common/security.md` and `rules/common/coding-style.md`. If a trim would weaken any of the above, it is not a finding.
|
|
50
|
+
|
|
51
|
+
## Output
|
|
52
|
+
|
|
53
|
+
A findings list. For each item:
|
|
54
|
+
|
|
55
|
+
- `file:line`
|
|
56
|
+
- `over-built:` what the code does the long way
|
|
57
|
+
- `simpler:` the specific shorter path (reuse existing `X` / stdlib `Y` / native `Z` / one line / delete)
|
|
58
|
+
- one-line rationale
|
|
59
|
+
|
|
60
|
+
Close with a verdict:
|
|
61
|
+
|
|
62
|
+
- `GO` — the diff is already at or near minimal; nothing to trim.
|
|
63
|
+
- `TRIM` — findings listed above; apply, then re-verify.
|
|
64
|
+
|
|
65
|
+
No score, no line-count target. A net-negative diff is a nice side effect, not the goal. Optimizing for fewer lines invites golfing and deletion of things that earn their keep; the ladder, not a number, decides.
|
|
66
|
+
|
|
67
|
+
## Review Only
|
|
68
|
+
|
|
69
|
+
This skill reports; it does not edit. Apply the trims yourself or route them through `proceed-with-the-recommendation`, then run the `verification-loop` ladder on what changed. This mirrors `audit`'s confirm-before-fix: a finding is a hypothesis until the simpler path is proven to exist and to preserve behavior.
|
|
70
|
+
|
|
71
|
+
## Overlap With `simplify`
|
|
72
|
+
|
|
73
|
+
The Claude Code built-in `simplify` and this skill share intent but differ in kind. `simplify` auto-applies broad reuse, efficiency, and altitude cleanups across changed code. `simplicity-review` is a repo-owned, Law-4-tagged, review-only lens scoped to over-engineering in the current diff, with an explicit safety carve-out, that feeds its findings into the 7-Laws flow. Use `simplify` when you want the fixes applied; use `simplicity-review` when you want the diff judged first.
|
|
74
|
+
|
|
75
|
+
## Pairs With
|
|
76
|
+
|
|
77
|
+
- **`verification-loop`** (Law 4) — the build/test/lint ladder you run after applying a trim.
|
|
78
|
+
- **`gateguard`** (Law 1) — the write-time reuse gate ("confirm no existing file serves the same purpose"); this skill catches at review time what slipped past it.
|
|
79
|
+
- **`proceed-with-the-recommendation`** — applies the trims under the 7 Laws.
|
|
80
|
+
- **`wild-risa-balance`** (Law 2) — the recommendation-layer analog: the same anti-padding instinct applied to advice instead of code.
|
|
@@ -23,10 +23,10 @@ Invoke this skill:
|
|
|
23
23
|
|
|
24
24
|
Every project has its own actual invocation for build / typecheck / lint / test / security / deploy-receipt. Hardcoding `npm run build` and `npm run test` works when the project happens to use those exact scripts; for everything else (pnpm, yarn, cargo, go, mise, just, custom scripts, monorepos with workspace-scoped commands) it returns "deps not installed" or "config not found" misreads from the wrong invocation. Phase 0 runs first so Phases 1–6 never have to guess.
|
|
25
25
|
|
|
26
|
-
**Run
|
|
26
|
+
**Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/resolve-verify-ladder.mjs"`** (source: `scripts/resolve-verify-ladder.mjs`) at the repo root. It encodes the full four-step resolution priority and emits the fenced block below. Use `--json` for machine consumption.
|
|
27
27
|
|
|
28
28
|
```
|
|
29
|
-
$ node scripts/resolve-verify-ladder.mjs
|
|
29
|
+
$ node "${CLAUDE_PLUGIN_ROOT}/scripts/resolve-verify-ladder.mjs"
|
|
30
30
|
verify-ladder (resolved):
|
|
31
31
|
build: npm run build (sniff:package.json:scripts.build)
|
|
32
32
|
typecheck: npm run typecheck (sniff:package.json:scripts.typecheck)
|
|
@@ -147,9 +147,9 @@ If either is `No`, the verification report goes back to the operator with the ex
|
|
|
147
147
|
|
|
148
148
|
For repos whose `verify-ladder.json` declares a `deploy_receipt` field — or whose sniff path detects an auto-deploy target — the verify is not complete until the deployed SHA matches the merge SHA and a healthcheck returns 200. Hand off to the `deploy-receipt` skill (Law 4 deploy-seam companion landed in PR #83) and treat its `Receipt status: COMPLETE` as the gate.
|
|
149
149
|
|
|
150
|
-
**Detection.** Run
|
|
150
|
+
**Detection.** Run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/detect-deploy-target.sh"` (source: `scripts/detect-deploy-target.sh`) at the repo root. Output is one of `railway` / `cloudflare` / `vercel` / `netlify` / `fly` / `appengine` / `apprunner` / `gha-deploy` / `none`. Anything except `none` triggers handoff to `deploy-receipt`; `none` means Phase 8 is skipped (no deploy seam exists).
|
|
151
151
|
|
|
152
|
-
**SHA extraction.** For the detected provider,
|
|
152
|
+
**SHA extraction.** For the detected provider, `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-deployed-sha.sh" <provider>` (source: `scripts/get-deployed-sha.sh`) returns the currently-deployed SHA via the provider CLI; `bash "${CLAUDE_PLUGIN_ROOT}/scripts/get-deployed-sha.sh" --show-command <provider>` prints the pipeline shape without executing (useful for dry-runs and citation). `deploy-receipt` owns the receipt's other components (health endpoint, build artifact, on-incomplete modes) and Route B/C fallbacks.
|
|
153
153
|
|
|
154
154
|
INCOMPLETE receipts move to "Immediate operator action" in the close, never to "ready". Library-only / package-published repos skip this phase entirely (no deploy seam exists).
|
|
155
155
|
|
|
@@ -164,7 +164,7 @@ Phase 8 confirms the deploy seam. Phase 9 confirms the deployed surface matches
|
|
|
164
164
|
|
|
165
165
|
**What the runner does:**
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/run-synthetic.mjs"` (source: `scripts/run-synthetic.mjs`); it encodes the lexical walk, interpreter map, env injection, and exit-code aggregation below. The prose is documentation, not the contract — when the two disagree, the script wins.
|
|
168
168
|
|
|
169
169
|
1. List every `*.synthetic.{sh,mjs,ts,py}` file in the resolved directory in lexical order.
|
|
170
170
|
2. For each file, set the input env vars: `BASE_URL` (production base from project config), `BASELINE_URL` (staging baseline from project config), `EXPECTED_SHA` (the merge SHA Phase 8 reported COMPLETE), `DEPLOY_BRANCH` (the deploy branch name), `RECEIPT_TIMESTAMP` (ISO-8601 of the receipt).
|
|
@@ -74,7 +74,7 @@ Probe and record (no destructive commands; quote results inline):
|
|
|
74
74
|
- **jq availability.** `command -v jq` (or `Get-Command jq`). When jq is missing, observation-pipeline hooks fall back to a thin schema and curl/JSON one-liners need a node/python rewrite.
|
|
75
75
|
- **Case-sensitive filesystem.** Test by creating two paths differing only in case in a tempdir. NTFS (Windows) and APFS (macOS default) are case-insensitive; Linux ext4 and case-sensitive APFS are case-sensitive. Affects `CLAUDE.md` vs `claude.md` resolution and import paths.
|
|
76
76
|
- **CWD baseline.** `pwd` (or `Get-Location`) recorded at session start. `tsc`, build scripts, and some test runners change CWD as a side effect; subsequent commands run from the wrong directory return "deps not installed" or "config not found" misreads.
|
|
77
|
-
- **Parallel-actor expectation.** Document whether a second Claude / Codex / Maulana session may operate on the same working tree. If yes, the `gateguard` Parallel-Actor Gate
|
|
77
|
+
- **Parallel-actor expectation.** Document whether a second Claude / Codex / Maulana session may operate on the same working tree. If yes, the `gateguard` Parallel-Actor Gate runs `bash "${CLAUDE_PLUGIN_ROOT}/scripts/git-state-snapshot.sh"` (source: `scripts/git-state-snapshot.sh`) to produce a single JSON envelope (`{head, upstream, dirty, root, branch}`) for the baseline and the divergence check. This skill records whether parallel-actor is expected; gateguard owns the runtime mechanics, so the audit doesn't restate the git-command triple.
|
|
78
78
|
|
|
79
79
|
Output the recorded grain as a single fenced block so it survives context compaction and any later phase can reference it without re-probing:
|
|
80
80
|
|
|
@@ -32,7 +32,7 @@ The continuous-improvement repo runs on Windows + Git Bash with `autocrlf=true`
|
|
|
32
32
|
|
|
33
33
|
Before any source-writing call, verify all five. Fail closed on any miss.
|
|
34
34
|
|
|
35
|
-
1. **Root validity** — `git rev-parse --show-toplevel` resolves; the resolved path matches CWD after symlink-safe canonicalization.
|
|
35
|
+
1. **Root validity** — `git rev-parse --show-toplevel` resolves; the resolved path matches CWD after symlink-safe canonicalization. Run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/git-state-snapshot.sh"` (source: `scripts/git-state-snapshot.sh`); its `root` field carries the canonicalized root, and its non-zero exit on `{"error":"not-a-git-repo"}` is itself the fail-closed signal — no second probe needed.
|
|
36
36
|
2. **`.git` presence** — `.git` exists (file pointer for worktrees, directory for primary checkout). A missing or unreadable `.git` is an immediate stop.
|
|
37
37
|
3. **Worktree registration** — `git worktree list` includes the resolved root with no `prunable` flag. Prunable worktrees can be deleted by another process at any moment.
|
|
38
38
|
4. **Branch alignment** — current branch matches the lease ledger; `HEAD` is not detached unless the unit explicitly asked for detached state. The snapshot script's `branch` field carries either the branch name or the literal `"detached"`, so detached-state is observable without a second probe.
|