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.
Files changed (67) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +10 -0
  3. package/QUICKSTART.md +1 -1
  4. package/README.md +7 -6
  5. package/bin/check-landing-version.mjs +63 -0
  6. package/bin/check-scripts-citation-drift.mjs +61 -13
  7. package/bin/generate-plugin-manifests.mjs +2 -0
  8. package/bin/install.mjs +29 -60
  9. package/commands/production-readiness-review.md +5 -4
  10. package/commands/simplicity-review.md +35 -0
  11. package/commands/verify-install.md +2 -2
  12. package/hooks/gateguard.mjs +22 -3
  13. package/hooks/query-cost-nudge.mjs +1 -0
  14. package/hooks/session.mjs +85 -0
  15. package/hooks/typecheck-stop.mjs +2 -1
  16. package/lib/plugin-metadata.mjs +18 -20
  17. package/llms.txt +1 -1
  18. package/package.json +6 -4
  19. package/plugins/beginner.json +1 -1
  20. package/plugins/continuous-improvement/.claude-plugin/marketplace.json +2 -2
  21. package/plugins/continuous-improvement/.claude-plugin/plugin.json +2 -2
  22. package/plugins/continuous-improvement/README.md +1 -0
  23. package/plugins/continuous-improvement/commands/production-readiness-review.md +5 -4
  24. package/plugins/continuous-improvement/commands/simplicity-review.md +35 -0
  25. package/plugins/continuous-improvement/commands/verify-install.md +2 -2
  26. package/plugins/continuous-improvement/hooks/gateguard.mjs +22 -3
  27. package/plugins/continuous-improvement/hooks/hooks.json +15 -16
  28. package/plugins/continuous-improvement/hooks/query-cost-nudge.mjs +1 -0
  29. package/plugins/continuous-improvement/hooks/session.mjs +85 -0
  30. package/plugins/continuous-improvement/hooks/typecheck-stop.mjs +2 -1
  31. package/plugins/continuous-improvement/lib/plugin-metadata.mjs +18 -20
  32. package/plugins/continuous-improvement/scripts/README.md +33 -0
  33. package/plugins/continuous-improvement/scripts/detect-deploy-target.sh +66 -0
  34. package/plugins/continuous-improvement/scripts/get-deployed-sha.sh +113 -0
  35. package/plugins/continuous-improvement/scripts/git-state-snapshot.sh +48 -0
  36. package/plugins/continuous-improvement/scripts/resolve-verify-ladder.mjs +241 -0
  37. package/plugins/continuous-improvement/scripts/route-recommendation.mjs +178 -0
  38. package/plugins/continuous-improvement/scripts/route-recommendation.routes.json +213 -0
  39. package/plugins/continuous-improvement/scripts/run-synthetic.mjs +298 -0
  40. package/plugins/continuous-improvement/scripts/scan-past-mistakes.mjs +285 -0
  41. package/plugins/continuous-improvement/skills/README.md +1 -0
  42. package/plugins/continuous-improvement/skills/deploy-receipt/SKILL.md +2 -2
  43. package/plugins/continuous-improvement/skills/gateguard/SKILL.md +2 -2
  44. package/plugins/continuous-improvement/skills/proceed-with-the-recommendation/SKILL.md +3 -2
  45. package/plugins/continuous-improvement/skills/reconcile/SKILL.md +1 -1
  46. package/plugins/continuous-improvement/skills/simplicity-review/SKILL.md +80 -0
  47. package/plugins/continuous-improvement/skills/verification-loop/SKILL.md +5 -5
  48. package/plugins/continuous-improvement/skills/workspace-surface-audit/SKILL.md +1 -1
  49. package/plugins/continuous-improvement/skills/worktree-safety/SKILL.md +1 -1
  50. package/plugins/expert.json +1 -1
  51. package/scripts/README.md +33 -0
  52. package/scripts/detect-deploy-target.sh +66 -0
  53. package/scripts/get-deployed-sha.sh +113 -0
  54. package/scripts/git-state-snapshot.sh +48 -0
  55. package/scripts/resolve-verify-ladder.mjs +241 -0
  56. package/scripts/route-recommendation.mjs +178 -0
  57. package/scripts/route-recommendation.routes.json +213 -0
  58. package/scripts/run-synthetic.mjs +298 -0
  59. package/scripts/scan-past-mistakes.mjs +285 -0
  60. package/skills/deploy-receipt.md +2 -2
  61. package/skills/gateguard.md +2 -2
  62. package/skills/proceed-with-the-recommendation.md +3 -2
  63. package/skills/reconcile.md +1 -1
  64. package/skills/simplicity-review.md +80 -0
  65. package/skills/verification-loop.md +5 -5
  66. package/skills/workspace-surface-audit.md +1 -1
  67. package/skills/worktree-safety.md +1 -1
@@ -210,6 +210,16 @@ function buildMutatingFileReason(toolName, filePaths, stateFilePath) {
210
210
  " `_gateguard_facts_presented: true`; Claude Code's strict schema rejects that, so use A or B.)",
211
211
  ].join("\n");
212
212
  }
213
+ function isGitBraceSelector(value) {
214
+ const selector = value.trim();
215
+ if (/^(?:u|upstream|push|-?\d+)$/i.test(selector))
216
+ return true;
217
+ if (/^(?:now|today|yesterday|tomorrow|noon|midnight|tea)$/i.test(selector))
218
+ return true;
219
+ if (/^\d{4}-\d{1,2}-\d{1,2}(?:[ T].*)?$/.test(selector))
220
+ return true;
221
+ return !selector.startsWith("#") && /(?:^|[.\s])ago$/i.test(selector);
222
+ }
213
223
  function findUnquotedBraceRef(command) {
214
224
  let quote = null;
215
225
  for (let i = 0; i < command.length; i++) {
@@ -224,17 +234,26 @@ function findUnquotedBraceRef(command) {
224
234
  continue;
225
235
  }
226
236
  if (ch === "@" && command[i + 1] === "{") {
237
+ const braceEnd = command.indexOf("}", i + 2);
238
+ if (braceEnd === -1)
239
+ continue;
240
+ const selector = command.slice(i + 2, braceEnd);
241
+ // Deny only recognized Git selector grammar. PowerShell hashtables can
242
+ // contain comments, quoted braces, or arbitrary key expressions.
243
+ if (!isGitBraceSelector(selector)) {
244
+ i = braceEnd;
245
+ continue;
246
+ }
227
247
  // Expand to the whitespace-delimited word that carries this @{ ref, then
228
248
  // single-quote that whole word in the suggested fix.
229
249
  let wordStart = i;
230
250
  while (wordStart > 0 && !/\s/.test(command[wordStart - 1]))
231
251
  wordStart--;
232
- let wordEnd = i;
252
+ let wordEnd = braceEnd + 1;
233
253
  while (wordEnd < command.length && !/\s/.test(command[wordEnd]))
234
254
  wordEnd++;
235
255
  const word = command.slice(wordStart, wordEnd);
236
- const braceEnd = command.indexOf("}", i);
237
- const ref = braceEnd === -1 ? command.slice(i, wordEnd) : command.slice(i, braceEnd + 1);
256
+ const ref = command.slice(i, braceEnd + 1);
238
257
  const fixed = `${command.slice(0, wordStart)}'${word}'${command.slice(wordEnd)}`;
239
258
  return { ref, fixed };
240
259
  }
@@ -61,6 +61,7 @@ function collectChangedFiles(root) {
61
61
  return [
62
62
  ...parseChangedFiles(run(["diff", "--name-only", "--diff-filter=ACMR"])),
63
63
  ...parseChangedFiles(run(["diff", "--cached", "--name-only", "--diff-filter=ACMR"])),
64
+ ...parseChangedFiles(run(["ls-files", "--others", "--exclude-standard"])),
64
65
  ];
65
66
  }
66
67
  // Marker key: the sanitized session_id when present (the normal case), else a
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync } from "node:child_process";
3
+ import { createHash } from "node:crypto";
4
+ import { readFileSync, readdirSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { resolveHomeDir } from "../lib/resolve-home-dir.mjs";
7
+ function read(path) {
8
+ try {
9
+ return readFileSync(path, "utf8");
10
+ }
11
+ catch {
12
+ return "";
13
+ }
14
+ }
15
+ function eventFromStdin() {
16
+ const raw = read(0);
17
+ if (!raw)
18
+ return null;
19
+ try {
20
+ const payload = JSON.parse(raw);
21
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
22
+ return null;
23
+ const event = payload.hook_event_name ?? payload.hook_type ?? payload.event_type;
24
+ return event === "SessionStart" || event === "SessionEnd" ? event : "unknown";
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ function projectRoot() {
31
+ if (process.env.CLAUDE_PROJECT_DIR)
32
+ return process.env.CLAUDE_PROJECT_DIR;
33
+ try {
34
+ return execFileSync("git", ["rev-parse", "--show-toplevel"], {
35
+ encoding: "utf8",
36
+ stdio: ["ignore", "pipe", "ignore"],
37
+ }).trim() || "global";
38
+ }
39
+ catch {
40
+ return "global";
41
+ }
42
+ }
43
+ function yamlFiles(dir) {
44
+ try {
45
+ return readdirSync(dir)
46
+ .filter((name) => name.endsWith(".yaml"))
47
+ .map((name) => join(dir, name));
48
+ }
49
+ catch {
50
+ return [];
51
+ }
52
+ }
53
+ function main() {
54
+ const event = eventFromStdin();
55
+ if (event === null)
56
+ return;
57
+ if (event === "SessionEnd") {
58
+ process.stderr.write("[continuous-improvement] Session ending. Run /continuous-improvement to reflect and capture learnings.\n");
59
+ return;
60
+ }
61
+ const home = resolveHomeDir();
62
+ if (!home)
63
+ return;
64
+ const instinctsRoot = join(home, ".claude", "instincts");
65
+ const hash = createHash("sha256").update(projectRoot()).digest("hex").slice(0, 12);
66
+ const projectDir = join(instinctsRoot, hash);
67
+ const files = [...yamlFiles(projectDir), ...yamlFiles(join(instinctsRoot, "global"))];
68
+ const observations = read(join(projectDir, "observations.jsonl")).split(/\r?\n/).filter(Boolean).length;
69
+ let level = observations >= 20 || files.length > 0 ? "ANALYZE" : "CAPTURE";
70
+ for (const file of files) {
71
+ const value = Number(read(file).match(/^confidence:\s*([0-9]*\.?[0-9]+)/m)?.[1]);
72
+ if (Number.isFinite(value) && value >= 0.7) {
73
+ level = "AUTO-APPLY";
74
+ break;
75
+ }
76
+ if (Number.isFinite(value) && value >= 0.5)
77
+ level = "SUGGEST";
78
+ }
79
+ process.stderr.write(`[continuous-improvement] Level: ${level} | Observations: ${observations} | Instincts: ${files.length}\n`);
80
+ }
81
+ try {
82
+ main();
83
+ }
84
+ catch {
85
+ }
@@ -51,7 +51,8 @@ function collectChangedFiles(root) {
51
51
  };
52
52
  const unstaged = run(["diff", "--name-only", "--diff-filter=ACMR"]);
53
53
  const staged = run(["diff", "--cached", "--name-only", "--diff-filter=ACMR"]);
54
- return [...parseChangedFiles(unstaged), ...parseChangedFiles(staged)];
54
+ const untracked = run(["ls-files", "--others", "--exclude-standard"]);
55
+ return [...parseChangedFiles(unstaged), ...parseChangedFiles(staged), ...parseChangedFiles(untracked)];
55
56
  }
56
57
  function hasNpmTypecheckScript(root) {
57
58
  try {
@@ -26,7 +26,7 @@ const KEYWORDS = [
26
26
  "transcript-linter",
27
27
  ];
28
28
  const CLAUDE_PLUGIN_CATEGORY = "productivity";
29
- const SHARED_PLUGIN_DESCRIPTION = "The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 27 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.";
29
+ const SHARED_PLUGIN_DESCRIPTION = "The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.";
30
30
  // Four vendored upstream companions registered alongside the CI plugin.
31
31
  // Each entry points at a pinned-SHA snapshot under third-party/<name>/.
32
32
  // See third-party/MANIFEST.md for refresh recipes and per-snapshot
@@ -457,76 +457,74 @@ export function getClaudePluginManifest() {
457
457
  };
458
458
  }
459
459
  export function getPluginHooksConfig() {
460
+ // Cold Node startup on loaded Windows hosts has exceeded five seconds.
461
+ const hookTimeoutSeconds = 30;
460
462
  const gateguardCommand = {
461
463
  type: "command",
462
464
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gateguard.mjs\"",
463
- timeout: 5,
465
+ timeout: hookTimeoutSeconds,
464
466
  };
465
467
  const companionPreferenceCommand = {
466
468
  type: "command",
467
469
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/companion-preference.mjs\"",
468
- timeout: 5,
470
+ timeout: hookTimeoutSeconds,
469
471
  };
470
472
  const hookPackCommand = {
471
473
  type: "command",
472
474
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/hook-pack.mjs\"",
473
- timeout: 5,
475
+ timeout: hookTimeoutSeconds,
474
476
  };
475
477
  const observeCommand = {
476
478
  type: "command",
477
- command: "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/observe.sh\"",
478
- timeout: 5,
479
+ command: "node \"${CLAUDE_PLUGIN_ROOT}/bin/observe.mjs\"",
480
+ timeout: hookTimeoutSeconds,
479
481
  };
480
482
  const sessionCommand = {
481
483
  type: "command",
482
- command: "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session.sh\"",
483
- timeout: 5,
484
+ command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session.mjs\"",
485
+ timeout: hookTimeoutSeconds,
484
486
  };
485
487
  const threeSectionCloseCommand = {
486
488
  type: "command",
487
489
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/three-section-close.mjs\"",
488
- timeout: 5,
490
+ timeout: hookTimeoutSeconds,
489
491
  };
490
492
  const goalDriftStopCommand = {
491
493
  type: "command",
492
494
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/goal-drift-stop.mjs\"",
493
- timeout: 5,
495
+ timeout: hookTimeoutSeconds,
494
496
  };
495
497
  const workflowDistillCommand = {
496
498
  type: "command",
497
499
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/workflow-distill.mjs\"",
498
- timeout: 5,
500
+ timeout: hookTimeoutSeconds,
499
501
  };
500
502
  const typecheckStopCommand = {
501
503
  type: "command",
502
504
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/typecheck-stop.mjs\"",
503
- // Longer than the 5s hooks: tsc is slower. Opt-in via CLAUDE_TYPECHECK_GATE
504
- // (off by default) and near-zero cost when off / no TS file changed; on an
505
- // internal timeout it fails open (allow) rather than blocking.
506
- timeout: 30,
505
+ timeout: hookTimeoutSeconds,
507
506
  };
508
507
  const queryCostNudgeCommand = {
509
508
  type: "command",
510
509
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/query-cost-nudge.mjs\"",
511
- timeout: 5,
510
+ timeout: hookTimeoutSeconds,
512
511
  };
513
512
  const routePromptCommand = {
514
513
  type: "command",
515
514
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/route-prompt.mjs\"",
516
- timeout: 5,
515
+ timeout: hookTimeoutSeconds,
517
516
  };
518
517
  const recallBriefingCommand = {
519
518
  type: "command",
520
519
  command: "node \"${CLAUDE_PLUGIN_ROOT}/hooks/recall-briefing.mjs\"",
521
- timeout: 5,
520
+ timeout: hookTimeoutSeconds,
522
521
  };
523
522
  return {
524
- description: "Gateguard fact-forcing PreToolUse, companion-preference enforcement, observation, session lifecycle, 3-section-close discipline, goal-drift Stop gate, opt-in workflow-distill Stop nudge, opt-in typecheck Stop gate, opt-in query-cost Stop nudge, and UserPromptSubmit lazy-routing plus opt-in proactive recall-briefing hooks for continuous-improvement.",
525
523
  hooks: {
526
524
  // gateguard runs FIRST on PreToolUse so its block decision short-circuits
527
525
  // before companion-preference sees the call. companion-preference runs
528
526
  // second on Skill tool calls; it is a no-op under ci-first (the default)
529
- // and never blocks under companions-first. observe.sh only runs on
527
+ // and never blocks under companions-first. The observer only runs on
530
528
  // PostToolUse: gateguard-blocked calls are intentionally not observed so
531
529
  // PreToolUse stays at two subprocesses on the hot path. route-prompt
532
530
  // fires on UserPromptSubmit and emits a system-reminder when a prompt
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # continuous-improvement
2
2
 
3
- > The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 27 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.
3
+ > The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.
4
4
 
5
5
  ## What This Is
6
6
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.20.0",
4
- "description": "Claude Code that gets sharper every session: the persistent-memory and runtime-discipline layer built on the 7 Laws of AI Agent Discipline. It grounds every edit in real facts before it lands and, through the Mulahazah engine, turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Shipped as 27 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts. Beginner: one /plugin install command. Expert: adds MCP tools and session hooks.",
3
+ "version": "3.21.0",
4
+ "description": "Claude Code that gets sharper every session: the persistent-memory and runtime-discipline layer built on the 7 Laws of AI Agent Discipline. It grounds every edit in real facts before it lands and, through the Mulahazah engine, turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts. Beginner: one /plugin install command. Expert: adds MCP tools and session hooks.",
5
5
  "keywords": [
6
6
  "claude-code",
7
7
  "claude-code-plugin",
@@ -56,10 +56,11 @@
56
56
  "verify:routing-targets": "node bin/check-routing-targets.mjs",
57
57
  "verify:doc-runtime-claims": "node bin/check-doc-runtime-claims.mjs",
58
58
  "verify:test-imports-only": "node bin/check-test-imports-only.mjs",
59
- "verify:scripts-citation-drift": "node bin/check-scripts-citation-drift.mjs",
59
+ "verify:landing-version": "node bin/check-landing-version.mjs",
60
+ "verify:scripts-citation-drift": "node bin/check-scripts-citation-drift.mjs && node bin/check-scripts-citation-drift.mjs plugins/continuous-improvement",
60
61
  "verify:third-party-shape": "node bin/check-third-party-shape.mjs",
61
62
  "verify:tool-count": "node bin/check-tool-count.mjs",
62
- "verify:all": "npm run verify:skill-mirror && npm run verify:skill-tiers && npm run verify:skill-law-tag && npm run verify:skill-count && npm run verify:skill-count-prose && npm run verify:command-count && npm run verify:docs-substrings && npm run verify:everything-mirror && npm run verify:routing-targets && npm run verify:doc-runtime-claims && npm run verify:test-imports-only && npm run verify:scripts-citation-drift && npm run verify:third-party-shape && npm run verify:tool-count && npm run typecheck"
63
+ "verify:all": "npm run verify:skill-mirror && npm run verify:skill-tiers && npm run verify:skill-law-tag && npm run verify:skill-count && npm run verify:skill-count-prose && npm run verify:command-count && npm run verify:docs-substrings && npm run verify:everything-mirror && npm run verify:routing-targets && npm run verify:doc-runtime-claims && npm run verify:test-imports-only && npm run verify:landing-version && npm run verify:scripts-citation-drift && npm run verify:third-party-shape && npm run verify:tool-count && npm run typecheck"
63
64
  },
64
65
  "files": [
65
66
  ".claude-plugin/",
@@ -74,6 +75,7 @@
74
75
  "hooks/",
75
76
  "commands/",
76
77
  "skills/",
78
+ "scripts/",
77
79
  "templates/",
78
80
  "plugins/",
79
81
  "instinct-packs/"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.20.0",
3
+ "version": "3.21.0",
4
4
  "mode": "beginner",
5
5
  "description": "Beginner mode: see what your agent learned, list its instincts, and request a session reflection. Bundles three grounding skills (gateguard, tdd-workflow, verification-loop) so research, memory, tests, and verification happen by default — every edit starts from facts, not guesses.",
6
6
  "tools": [
@@ -7,8 +7,8 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "continuous-improvement",
10
- "description": "The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 27 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.",
11
- "version": "3.20.0",
10
+ "description": "The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.",
11
+ "version": "3.21.0",
12
12
  "source": "./",
13
13
  "author": {
14
14
  "name": "naimkatiman"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.20.0",
4
- "description": "The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 27 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.",
3
+ "version": "3.21.0",
4
+ "description": "The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.",
5
5
  "author": {
6
6
  "name": "naimkatiman",
7
7
  "url": "https://github.com/naimkatiman"
@@ -10,6 +10,7 @@ Included surfaces:
10
10
  - `commands/`
11
11
  - `agents/` — `code-reviewer`, `security-auditor`, `test-engineer` personas (auto-discovered Claude Code subagents; pattern from addy/agent-skills)
12
12
  - `hooks/`
13
+ - `scripts/`
13
14
  - `bin/mcp-server.mjs`
14
15
  - `bin/observe.mjs`
15
16
  - `bin/backfill.mjs`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: production-readiness-review
3
- description: "Parallel multi-agent readiness gate — fan blind reviewers across performance, security, UI/UX, and test coverage, each grounding findings in real code/logs/live data, then reconcile into one deduplicated, severity-ranked punch-list. Reports only; never fixes, merges, or deploys."
3
+ description: "Parallel multi-agent readiness gate — fan blind reviewers across performance, security, UI/UX, test coverage, and simplicity, each grounding findings in real code/logs/live data, then reconcile into one deduplicated, severity-ranked punch-list. Reports only; never fixes, merges, or deploys."
4
4
  ---
5
5
 
6
6
  # /production-readiness-review
@@ -20,11 +20,12 @@ Pure routing over existing skills and agents. Adds no new code.
20
20
  ## Behavior
21
21
 
22
22
  1. **Scope** — establish ground truth: the diff under review and which changes are recent (`git diff`; `reconcile` fallback for branch/base state). Recent changes get extra scrutiny because they are the likeliest source of self-inflicted defects.
23
- 2. **Fan out** — `superpowers:dispatching-parallel-agents` launches four reviewers, each blind to the others. Every reviewer is instructed to ground each finding in real code, logs, or live queries, and never to assume or fabricate state:
23
+ 2. **Fan out** — `superpowers:dispatching-parallel-agents` launches five reviewers, each blind to the others. Every reviewer is instructed to ground each finding in real code, logs, or live queries, and never to assume or fabricate state:
24
24
  - **Performance & bundle-size** — hot paths, N+1 queries, unbounded work, regressions.
25
25
  - **Security & data-access** (`security-auditor`) — authn/authz, input handling, injection, secret exposure, unsafe data access.
26
26
  - **UI/UX correctness** — verified live with Playwright when the MCP is available, else static review of the changed surface.
27
27
  - **Test coverage & flaky/stale mocks** (`test-engineer`) — uncovered branches, stale mocks, timing-flaky tests.
28
+ - **Simplicity & over-engineering** (`simplicity-review`) — code that could reuse an existing file, a stdlib or native feature, or fewer lines; reports trim opportunities via the reuse ladder and never flags input validation, data-loss handling, security, or accessibility.
28
29
  3. **Reconcile** — a final pass dedupes findings across reviewers, ranks each CRITICAL / HIGH / MEDIUM / LOW by severity and confidence, and explicitly flags any defect introduced by the changes under review.
29
30
  4. **Present** — emit the consolidated punch-list, severity-ranked, with file references. **Stop.**
30
31
 
@@ -42,7 +43,7 @@ Pure routing over existing skills and agents. Adds no new code.
42
43
 
43
44
  ## Composition
44
45
 
45
- Routes through: `reconcile` (scope/ground truth) → `superpowers:dispatching-parallel-agents` (fan-out) → the `security-auditor` and `test-engineer` agents (two of the four dimensions) → a reconciliation pass that ranks and dedupes. Each step falls back to its inline behavior when the preferred skill or agent is not installed.
46
+ Routes through: `reconcile` (scope/ground truth) → `superpowers:dispatching-parallel-agents` (fan-out) → the `security-auditor` and `test-engineer` agents and the `simplicity-review` skill (three of the five dimensions) → a reconciliation pass that ranks and dedupes. Each step falls back to its inline behavior when the preferred skill or agent is not installed.
46
47
 
47
48
  ## Example
48
49
 
@@ -50,4 +51,4 @@ Routes through: `reconcile` (scope/ground truth) → `superpowers:dispatching-pa
50
51
  /production-readiness-review #246
51
52
  ```
52
53
 
53
- Scopes PR #246's diff, fans four blind reviewers across performance, security, UI/UX, and test coverage, then returns one deduplicated severity-ranked punch-list — flagging anything the PR's own changes introduced — and stops for you to prioritize.
54
+ Scopes PR #246's diff, fans five blind reviewers across performance, security, UI/UX, test coverage, and simplicity, then returns one deduplicated severity-ranked punch-list — flagging anything the PR's own changes introduced — and stops for you to prioritize.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: simplicity-review
3
+ description: Review the current diff for over-engineering — flag code that could reuse an existing file, a stdlib or native feature, or fewer lines — and report GO/TRIM findings without touching code. Enforces Law 4 (Verify Before Reporting).
4
+ ---
5
+
6
+ # /simplicity-review — Judge the Diff Before You Ship It
7
+
8
+ Read the current change like the laziest senior dev in the room: could this have been smaller? Passing tests prove correctness, not minimality. Backed by the `simplicity-review` skill.
9
+
10
+ ## What it does
11
+
12
+ Takes the working-tree diff (vs HEAD by default; accepts an optional commit range or file list), reads each changed block, and walks a fixed reuse ladder:
13
+
14
+ ```
15
+ 1. Does this need to exist? -> skip it (YAGNI)
16
+ 2. Already in this codebase? -> reuse it
17
+ 3. Stdlib does it? -> use it
18
+ 4. Native platform feature? -> use it
19
+ 5. Installed dependency? -> use it
20
+ 6. One line? -> one line
21
+ 7. Only then: the minimum that works
22
+ ```
23
+
24
+ It reports `file:line`, what is over-built, the specific simpler path, and closes with `GO` (already minimal) or `TRIM` (findings to apply). It does not edit code.
25
+
26
+ ## Default skeptical
27
+
28
+ A finding is a hypothesis. Read the surrounding code and prove the simpler path exists and preserves behavior before asserting it; a wrong trim is worse than the over-build. Never flag input validation, data-loss-preventing error handling, security, or accessibility — lazy, not negligent.
29
+
30
+ ## Pairs with
31
+
32
+ - **`simplicity-review`** skill — the discipline this command runs.
33
+ - **`proceed-with-the-recommendation`** — apply the trims under the 7 Laws.
34
+ - **`verification-loop`** — the ladder to re-run on whatever you trim.
35
+ - **`production-readiness-review`** — the sibling diff review for performance, security, UI, and test coverage.
@@ -40,8 +40,8 @@ The observation hook appends one row per tool call to
40
40
  `<project-hash>` from the current repo, or check `~/.claude/instincts/global/`).
41
41
 
42
42
  - If it exists and has at least one row — capture is recording. Record `observe: ✓`.
43
- - If it is missing or empty record `observe: ✗ (observation hook not recording
44
- on Windows confirm Git Bash / WSL is installed, then re-run the installer)`.
43
+ - If it is missing or empty, record `observe: ✗ (observation hook not recording; re-run
44
+ the installer to migrate legacy Bash hook rows to the Node observer)`.
45
45
 
46
46
  ## Report
47
47
 
@@ -210,6 +210,16 @@ function buildMutatingFileReason(toolName, filePaths, stateFilePath) {
210
210
  " `_gateguard_facts_presented: true`; Claude Code's strict schema rejects that, so use A or B.)",
211
211
  ].join("\n");
212
212
  }
213
+ function isGitBraceSelector(value) {
214
+ const selector = value.trim();
215
+ if (/^(?:u|upstream|push|-?\d+)$/i.test(selector))
216
+ return true;
217
+ if (/^(?:now|today|yesterday|tomorrow|noon|midnight|tea)$/i.test(selector))
218
+ return true;
219
+ if (/^\d{4}-\d{1,2}-\d{1,2}(?:[ T].*)?$/.test(selector))
220
+ return true;
221
+ return !selector.startsWith("#") && /(?:^|[.\s])ago$/i.test(selector);
222
+ }
213
223
  function findUnquotedBraceRef(command) {
214
224
  let quote = null;
215
225
  for (let i = 0; i < command.length; i++) {
@@ -224,17 +234,26 @@ function findUnquotedBraceRef(command) {
224
234
  continue;
225
235
  }
226
236
  if (ch === "@" && command[i + 1] === "{") {
237
+ const braceEnd = command.indexOf("}", i + 2);
238
+ if (braceEnd === -1)
239
+ continue;
240
+ const selector = command.slice(i + 2, braceEnd);
241
+ // Deny only recognized Git selector grammar. PowerShell hashtables can
242
+ // contain comments, quoted braces, or arbitrary key expressions.
243
+ if (!isGitBraceSelector(selector)) {
244
+ i = braceEnd;
245
+ continue;
246
+ }
227
247
  // Expand to the whitespace-delimited word that carries this @{ ref, then
228
248
  // single-quote that whole word in the suggested fix.
229
249
  let wordStart = i;
230
250
  while (wordStart > 0 && !/\s/.test(command[wordStart - 1]))
231
251
  wordStart--;
232
- let wordEnd = i;
252
+ let wordEnd = braceEnd + 1;
233
253
  while (wordEnd < command.length && !/\s/.test(command[wordEnd]))
234
254
  wordEnd++;
235
255
  const word = command.slice(wordStart, wordEnd);
236
- const braceEnd = command.indexOf("}", i);
237
- const ref = braceEnd === -1 ? command.slice(i, wordEnd) : command.slice(i, braceEnd + 1);
256
+ const ref = command.slice(i, braceEnd + 1);
238
257
  const fixed = `${command.slice(0, wordStart)}'${word}'${command.slice(wordEnd)}`;
239
258
  return { ref, fixed };
240
259
  }
@@ -1,5 +1,4 @@
1
1
  {
2
- "description": "Gateguard fact-forcing PreToolUse, companion-preference enforcement, observation, session lifecycle, 3-section-close discipline, goal-drift Stop gate, opt-in workflow-distill Stop nudge, opt-in typecheck Stop gate, opt-in query-cost Stop nudge, and UserPromptSubmit lazy-routing plus opt-in proactive recall-briefing hooks for continuous-improvement.",
3
2
  "hooks": {
4
3
  "PreToolUse": [
5
4
  {
@@ -7,12 +6,12 @@
7
6
  {
8
7
  "type": "command",
9
8
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gateguard.mjs\"",
10
- "timeout": 5
9
+ "timeout": 30
11
10
  },
12
11
  {
13
12
  "type": "command",
14
13
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/companion-preference.mjs\"",
15
- "timeout": 5
14
+ "timeout": 30
16
15
  }
17
16
  ]
18
17
  },
@@ -22,7 +21,7 @@
22
21
  {
23
22
  "type": "command",
24
23
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/hook-pack.mjs\"",
25
- "timeout": 5
24
+ "timeout": 30
26
25
  }
27
26
  ]
28
27
  }
@@ -32,8 +31,8 @@
32
31
  "hooks": [
33
32
  {
34
33
  "type": "command",
35
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/observe.sh\"",
36
- "timeout": 5
34
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/bin/observe.mjs\"",
35
+ "timeout": 30
37
36
  }
38
37
  ]
39
38
  }
@@ -44,12 +43,12 @@
44
43
  {
45
44
  "type": "command",
46
45
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/route-prompt.mjs\"",
47
- "timeout": 5
46
+ "timeout": 30
48
47
  },
49
48
  {
50
49
  "type": "command",
51
50
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/recall-briefing.mjs\"",
52
- "timeout": 5
51
+ "timeout": 30
53
52
  }
54
53
  ]
55
54
  }
@@ -59,8 +58,8 @@
59
58
  "hooks": [
60
59
  {
61
60
  "type": "command",
62
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session.sh\"",
63
- "timeout": 5
61
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session.mjs\"",
62
+ "timeout": 30
64
63
  }
65
64
  ]
66
65
  }
@@ -70,8 +69,8 @@
70
69
  "hooks": [
71
70
  {
72
71
  "type": "command",
73
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session.sh\"",
74
- "timeout": 5
72
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session.mjs\"",
73
+ "timeout": 30
75
74
  }
76
75
  ]
77
76
  }
@@ -82,17 +81,17 @@
82
81
  {
83
82
  "type": "command",
84
83
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/three-section-close.mjs\"",
85
- "timeout": 5
84
+ "timeout": 30
86
85
  },
87
86
  {
88
87
  "type": "command",
89
88
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/goal-drift-stop.mjs\"",
90
- "timeout": 5
89
+ "timeout": 30
91
90
  },
92
91
  {
93
92
  "type": "command",
94
93
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/workflow-distill.mjs\"",
95
- "timeout": 5
94
+ "timeout": 30
96
95
  },
97
96
  {
98
97
  "type": "command",
@@ -102,7 +101,7 @@
102
101
  {
103
102
  "type": "command",
104
103
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/query-cost-nudge.mjs\"",
105
- "timeout": 5
104
+ "timeout": 30
106
105
  }
107
106
  ]
108
107
  }
@@ -61,6 +61,7 @@ function collectChangedFiles(root) {
61
61
  return [
62
62
  ...parseChangedFiles(run(["diff", "--name-only", "--diff-filter=ACMR"])),
63
63
  ...parseChangedFiles(run(["diff", "--cached", "--name-only", "--diff-filter=ACMR"])),
64
+ ...parseChangedFiles(run(["ls-files", "--others", "--exclude-standard"])),
64
65
  ];
65
66
  }
66
67
  // Marker key: the sanitized session_id when present (the normal case), else a