continuous-improvement 3.0.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/.claude-plugin/marketplace.json +78 -0
  2. package/CHANGELOG.md +210 -0
  3. package/LICENSE +21 -21
  4. package/QUICKSTART.md +101 -81
  5. package/README.md +224 -198
  6. package/SKILL.md +87 -9
  7. package/action.yml +33 -0
  8. package/bin/analyze.sh +161 -153
  9. package/bin/backfill.mjs +172 -0
  10. package/bin/check-docs-substrings.mjs +333 -0
  11. package/bin/check-everything-mirror.mjs +145 -0
  12. package/bin/check-routing-targets.mjs +151 -0
  13. package/bin/check-skill-law-tag.mjs +128 -0
  14. package/bin/check-skill-mirror.mjs +119 -0
  15. package/bin/check-skill-tiers.mjs +116 -0
  16. package/bin/check-third-party-shape.mjs +202 -0
  17. package/bin/generate-plugin-manifests.mjs +169 -0
  18. package/bin/harvest-friction.mjs +279 -0
  19. package/bin/hook-stats.mjs +258 -0
  20. package/bin/install.mjs +418 -456
  21. package/bin/lint-transcript.mjs +239 -0
  22. package/bin/mcp-server.mjs +842 -499
  23. package/bin/observe.mjs +148 -0
  24. package/bin/pre-commit-block-strays.sh +49 -0
  25. package/bin/refresh-third-party.mjs +416 -0
  26. package/bin/unified-cli.mjs +533 -0
  27. package/commands/continuous-improvement.md +115 -74
  28. package/commands/dashboard.md +56 -0
  29. package/commands/discipline.md +51 -0
  30. package/commands/harvest.md +76 -0
  31. package/commands/learn-eval.md +117 -0
  32. package/commands/planning-with-files.md +66 -0
  33. package/commands/proceed-with-the-recommendation.md +62 -0
  34. package/commands/ralph.md +103 -0
  35. package/commands/release-train.md +81 -0
  36. package/commands/seven-laws.md +16 -0
  37. package/commands/superpowers.md +153 -0
  38. package/commands/swarm.md +101 -0
  39. package/commands/workspace-surface-audit.md +77 -0
  40. package/hooks/observe.sh +172 -134
  41. package/hooks/session.sh +106 -106
  42. package/hooks/three-section-close.mjs +181 -0
  43. package/instinct-packs/go.json +58 -0
  44. package/instinct-packs/meta.json +16 -0
  45. package/instinct-packs/python.json +58 -0
  46. package/instinct-packs/react.json +58 -0
  47. package/lib/cli-anything.mjs +401 -0
  48. package/lib/compound-engineering.mjs +831 -0
  49. package/lib/observe-event.mjs +128 -0
  50. package/lib/plugin-metadata.mjs +432 -0
  51. package/lib/pm-marketplace.mjs +61 -0
  52. package/lib/pm-skills.mjs +1274 -0
  53. package/lib/resolve-home-dir.mjs +43 -0
  54. package/lib/skill-tiers.mjs +137 -0
  55. package/lib/unified-plugin.mjs +924 -0
  56. package/llms.txt +68 -0
  57. package/package.json +38 -15
  58. package/plugins/beginner.json +17 -6
  59. package/plugins/continuous-improvement/.claude-plugin/marketplace.json +20 -0
  60. package/plugins/continuous-improvement/.claude-plugin/plugin.json +26 -0
  61. package/plugins/continuous-improvement/LICENSE +21 -0
  62. package/plugins/continuous-improvement/README.md +56 -0
  63. package/plugins/continuous-improvement/bin/backfill.mjs +172 -0
  64. package/plugins/continuous-improvement/bin/mcp-server.mjs +886 -0
  65. package/plugins/continuous-improvement/bin/observe.mjs +148 -0
  66. package/plugins/continuous-improvement/commands/continuous-improvement.md +115 -0
  67. package/plugins/continuous-improvement/commands/dashboard.md +56 -0
  68. package/plugins/continuous-improvement/commands/discipline.md +51 -0
  69. package/plugins/continuous-improvement/commands/harvest.md +76 -0
  70. package/plugins/continuous-improvement/commands/learn-eval.md +117 -0
  71. package/plugins/continuous-improvement/commands/planning-with-files.md +66 -0
  72. package/plugins/continuous-improvement/commands/proceed-with-the-recommendation.md +62 -0
  73. package/plugins/continuous-improvement/commands/ralph.md +103 -0
  74. package/plugins/continuous-improvement/commands/release-train.md +81 -0
  75. package/plugins/continuous-improvement/commands/seven-laws.md +16 -0
  76. package/plugins/continuous-improvement/commands/superpowers.md +153 -0
  77. package/plugins/continuous-improvement/commands/swarm.md +101 -0
  78. package/plugins/continuous-improvement/commands/workspace-surface-audit.md +77 -0
  79. package/plugins/continuous-improvement/hooks/hooks.json +60 -0
  80. package/plugins/continuous-improvement/hooks/observe.sh +172 -0
  81. package/plugins/continuous-improvement/hooks/session.sh +106 -0
  82. package/plugins/continuous-improvement/hooks/three-section-close.mjs +181 -0
  83. package/plugins/continuous-improvement/instinct-packs/go.json +58 -0
  84. package/plugins/continuous-improvement/instinct-packs/meta.json +16 -0
  85. package/plugins/continuous-improvement/instinct-packs/python.json +58 -0
  86. package/plugins/continuous-improvement/instinct-packs/react.json +58 -0
  87. package/plugins/continuous-improvement/lib/observe-event.mjs +128 -0
  88. package/plugins/continuous-improvement/lib/plugin-metadata.mjs +432 -0
  89. package/plugins/continuous-improvement/lib/resolve-home-dir.mjs +43 -0
  90. package/plugins/continuous-improvement/skills/README.md +34 -0
  91. package/plugins/continuous-improvement/skills/continuous-improvement/SKILL.md +249 -0
  92. package/plugins/continuous-improvement/skills/deploy-receipt/SKILL.md +131 -0
  93. package/plugins/continuous-improvement/skills/gateguard/SKILL.md +155 -0
  94. package/plugins/continuous-improvement/skills/para-memory-files/SKILL.md +108 -0
  95. package/plugins/continuous-improvement/skills/proceed-with-the-recommendation/SKILL.md +454 -0
  96. package/plugins/continuous-improvement/skills/ralph/SKILL.md +221 -0
  97. package/plugins/continuous-improvement/skills/safety-guard/SKILL.md +76 -0
  98. package/plugins/continuous-improvement/skills/strategic-compact/SKILL.md +104 -0
  99. package/plugins/continuous-improvement/skills/superpowers/SKILL.md +212 -0
  100. package/plugins/continuous-improvement/skills/tdd-workflow/SKILL.md +411 -0
  101. package/plugins/continuous-improvement/skills/token-budget-advisor/SKILL.md +136 -0
  102. package/plugins/continuous-improvement/skills/verification-loop/SKILL.md +192 -0
  103. package/plugins/continuous-improvement/skills/wild-risa-balance/SKILL.md +191 -0
  104. package/plugins/continuous-improvement/skills/workspace-surface-audit/SKILL.md +147 -0
  105. package/plugins/continuous-improvement/templates/planning-with-files/findings.md +8 -0
  106. package/plugins/continuous-improvement/templates/planning-with-files/progress.md +7 -0
  107. package/plugins/continuous-improvement/templates/planning-with-files/task_plan.md +23 -0
  108. package/plugins/expert.json +34 -5
  109. package/skills/README.md +79 -0
  110. package/skills/deploy-receipt.md +131 -0
  111. package/skills/gateguard.md +155 -0
  112. package/skills/para-memory-files.md +108 -0
  113. package/skills/proceed-with-the-recommendation.md +454 -0
  114. package/skills/ralph.md +221 -0
  115. package/skills/safety-guard.md +76 -0
  116. package/skills/strategic-compact.md +104 -0
  117. package/skills/superpowers.md +212 -0
  118. package/skills/tdd-workflow.md +411 -0
  119. package/skills/token-budget-advisor.md +136 -0
  120. package/skills/verification-loop.md +192 -0
  121. package/skills/wild-risa-balance.md +191 -0
  122. package/skills/workspace-surface-audit.md +147 -0
  123. package/templates/planning-with-files/findings.md +8 -0
  124. package/templates/planning-with-files/progress.md +7 -0
  125. package/templates/planning-with-files/task_plan.md +23 -0
  126. package/templates/verify-ladder.example.json +47 -0
@@ -0,0 +1,258 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Hook Stats Reader
4
+ *
5
+ * Reads JSONL telemetry written by Claude Code Stop hooks (e.g. the
6
+ * three-section-close hook) from `<HOME>/.claude/hook-telemetry/*.jsonl`
7
+ * and prints per-hook aggregate counts over a recent time window.
8
+ *
9
+ * Each input line is JSON of the shape:
10
+ * {
11
+ * "ts": "<ISO timestamp>",
12
+ * "hook": "<hook-name>",
13
+ * "action": "pass" | "block" | "skip-short",
14
+ * "textLength": <number>,
15
+ * "missing": <string[]>,
16
+ * "durationMs": <number>
17
+ * }
18
+ *
19
+ * The reader is parse-tolerant: malformed lines are skipped silently so
20
+ * the CLI keeps working even when the hook has been crash-restarted mid
21
+ * append. The hook itself is fail-open; the reader matches that posture.
22
+ *
23
+ * Project hash:
24
+ * The hook keys telemetry files by a 12-char sha256 prefix of the
25
+ * *project* directory (the dir containing the transcript). For the CLI,
26
+ * the "project" is the current working directory: we normalize path
27
+ * separators to forward slash, lowercase on win32, then sha256 and
28
+ * slice the first 12 hex chars. Pass `--hash=<value>` to override.
29
+ *
30
+ * Usage:
31
+ * node bin/hook-stats.mjs [--hours=<n>] [--hash=<hash>] [--telemetry-dir=<path>]
32
+ * node bin/hook-stats.mjs --help
33
+ *
34
+ * Defaults:
35
+ * --hours 24
36
+ * --hash sha256(normalize(process.cwd())).slice(0, 12)
37
+ * --telemetry-dir <HOME>/.claude/hook-telemetry
38
+ *
39
+ * Exit codes:
40
+ * 0 — printed aggregate (or "no records" message)
41
+ * 1 — unexpected error
42
+ */
43
+ import { createHash } from "node:crypto";
44
+ import { readdirSync, readFileSync, statSync } from "node:fs";
45
+ import { platform } from "node:os";
46
+ import { join } from "node:path";
47
+ import { argv, cwd, exit, stderr, stdout } from "node:process";
48
+ import { resolveHomeDir } from "../lib/resolve-home-dir.mjs";
49
+ const USAGE = `Usage: node bin/hook-stats.mjs [options]
50
+
51
+ Reads JSONL telemetry from <HOME>/.claude/hook-telemetry/*.jsonl and
52
+ prints per-hook aggregate counts over a recent time window.
53
+
54
+ Options:
55
+ --hours=<n> Time window in hours (default: 24)
56
+ --hash=<hash> Only read this single <hash>.jsonl file
57
+ (default: sha256 of the current working directory,
58
+ normalized to forward slashes and lowercased on
59
+ Windows, then first 12 hex chars)
60
+ --telemetry-dir=<path> Override telemetry dir
61
+ (default: <HOME>/.claude/hook-telemetry)
62
+ --help Show this help and exit 0
63
+
64
+ Output:
65
+ One line per hook: "<hook> last <hours>h: pass=<n> block=<n>
66
+ skip-short=<n> total=<n> avg-duration=<X>ms".
67
+ If there are no records in the window: "no records in last <hours>h".
68
+
69
+ The reader is parse-tolerant: malformed JSONL lines are skipped silently.
70
+ `;
71
+ function parseArgs(rawArgs) {
72
+ const opts = {
73
+ hours: 24,
74
+ hash: null,
75
+ telemetryDir: null,
76
+ help: false,
77
+ };
78
+ for (const arg of rawArgs) {
79
+ if (arg === "--help" || arg === "-h") {
80
+ opts.help = true;
81
+ continue;
82
+ }
83
+ if (arg.startsWith("--hours=")) {
84
+ const raw = arg.slice("--hours=".length);
85
+ const n = Number(raw);
86
+ if (!Number.isFinite(n) || n <= 0) {
87
+ throw new Error(`invalid --hours value: ${raw}`);
88
+ }
89
+ opts.hours = n;
90
+ continue;
91
+ }
92
+ if (arg.startsWith("--hash=")) {
93
+ opts.hash = arg.slice("--hash=".length);
94
+ continue;
95
+ }
96
+ if (arg.startsWith("--telemetry-dir=")) {
97
+ opts.telemetryDir = arg.slice("--telemetry-dir=".length);
98
+ continue;
99
+ }
100
+ throw new Error(`unknown argument: ${arg}`);
101
+ }
102
+ return opts;
103
+ }
104
+ export function projectHashForCwd(workingDir) {
105
+ let normalized = workingDir.split("\\").join("/");
106
+ if (platform() === "win32")
107
+ normalized = normalized.toLowerCase();
108
+ return createHash("sha256").update(normalized).digest("hex").slice(0, 12);
109
+ }
110
+ function listJsonlFiles(dir, hashFilter) {
111
+ let entries;
112
+ try {
113
+ entries = readdirSync(dir);
114
+ }
115
+ catch {
116
+ return [];
117
+ }
118
+ const out = [];
119
+ for (const name of entries) {
120
+ if (!name.endsWith(".jsonl"))
121
+ continue;
122
+ if (hashFilter !== null) {
123
+ if (name !== `${hashFilter}.jsonl`)
124
+ continue;
125
+ }
126
+ const full = join(dir, name);
127
+ try {
128
+ const stat = statSync(full);
129
+ if (!stat.isFile())
130
+ continue;
131
+ }
132
+ catch {
133
+ continue;
134
+ }
135
+ out.push(full);
136
+ }
137
+ return out;
138
+ }
139
+ function safeJsonParse(line) {
140
+ try {
141
+ const parsed = JSON.parse(line);
142
+ if (parsed &&
143
+ typeof parsed === "object" &&
144
+ typeof parsed.hook === "string" &&
145
+ typeof parsed.ts === "string" &&
146
+ typeof parsed.action === "string") {
147
+ return parsed;
148
+ }
149
+ return null;
150
+ }
151
+ catch {
152
+ return null;
153
+ }
154
+ }
155
+ export function aggregate(records, cutoffMs) {
156
+ const byHook = new Map();
157
+ for (const rec of records) {
158
+ const tsMs = Date.parse(rec.ts);
159
+ if (!Number.isFinite(tsMs))
160
+ continue;
161
+ if (tsMs < cutoffMs)
162
+ continue;
163
+ let agg = byHook.get(rec.hook);
164
+ if (!agg) {
165
+ agg = {
166
+ hook: rec.hook,
167
+ pass: 0,
168
+ block: 0,
169
+ skipShort: 0,
170
+ total: 0,
171
+ durationSum: 0,
172
+ durationCount: 0,
173
+ };
174
+ byHook.set(rec.hook, agg);
175
+ }
176
+ agg.total += 1;
177
+ if (rec.action === "pass")
178
+ agg.pass += 1;
179
+ else if (rec.action === "block")
180
+ agg.block += 1;
181
+ else if (rec.action === "skip-short")
182
+ agg.skipShort += 1;
183
+ if (typeof rec.durationMs === "number" && Number.isFinite(rec.durationMs)) {
184
+ agg.durationSum += rec.durationMs;
185
+ agg.durationCount += 1;
186
+ }
187
+ }
188
+ return Array.from(byHook.values()).sort((a, b) => a.hook.localeCompare(b.hook));
189
+ }
190
+ function formatAggregate(agg, hours) {
191
+ const avg = agg.durationCount > 0
192
+ ? Math.round(agg.durationSum / agg.durationCount)
193
+ : 0;
194
+ return `${agg.hook} last ${hours}h: pass=${agg.pass} block=${agg.block} skip-short=${agg.skipShort} total=${agg.total} avg-duration=${avg}ms`;
195
+ }
196
+ function main() {
197
+ const opts = parseArgs(argv.slice(2));
198
+ if (opts.help) {
199
+ stdout.write(USAGE);
200
+ exit(0);
201
+ }
202
+ let telemetryDir;
203
+ if (opts.telemetryDir !== null) {
204
+ telemetryDir = opts.telemetryDir;
205
+ }
206
+ else {
207
+ const home = resolveHomeDir();
208
+ if (!home) {
209
+ stderr.write("no telemetry dir resolved\n");
210
+ exit(0);
211
+ }
212
+ telemetryDir = join(home, ".claude", "hook-telemetry");
213
+ }
214
+ const hashFilter = opts.hash ?? projectHashForCwd(cwd());
215
+ // When the user did not pass --hash, we still read all files (per spec).
216
+ // Only restrict to a single file when --hash is explicitly set.
217
+ const useHashFilter = opts.hash !== null;
218
+ const files = listJsonlFiles(telemetryDir, useHashFilter ? hashFilter : null);
219
+ const records = [];
220
+ for (const file of files) {
221
+ let content;
222
+ try {
223
+ content = readFileSync(file, "utf8");
224
+ }
225
+ catch {
226
+ continue;
227
+ }
228
+ for (const rawLine of content.split(/\r?\n/)) {
229
+ const line = rawLine.trim();
230
+ if (!line)
231
+ continue;
232
+ const rec = safeJsonParse(line);
233
+ if (rec)
234
+ records.push(rec);
235
+ }
236
+ }
237
+ const cutoffMs = Date.now() - opts.hours * 3600 * 1000;
238
+ const aggregates = aggregate(records, cutoffMs);
239
+ if (aggregates.length === 0) {
240
+ stdout.write(`no records in last ${opts.hours}h\n`);
241
+ exit(0);
242
+ }
243
+ for (const agg of aggregates) {
244
+ stdout.write(formatAggregate(agg, opts.hours) + "\n");
245
+ }
246
+ exit(0);
247
+ }
248
+ const invokedDirectly = argv[1] !== undefined && import.meta.url.endsWith(argv[1].split("\\").join("/"));
249
+ if (invokedDirectly || argv[1]?.endsWith("hook-stats.mjs")) {
250
+ try {
251
+ main();
252
+ }
253
+ catch (err) {
254
+ const message = err instanceof Error ? err.message : String(err);
255
+ stderr.write(`${message}\n`);
256
+ exit(1);
257
+ }
258
+ }