continuous-improvement 3.9.2 → 3.11.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 +61 -0
- package/QUICKSTART.md +13 -8
- package/README.md +84 -153
- package/bin/backfill.mjs +0 -0
- package/bin/check-doc-runtime-claims.mjs +0 -0
- package/bin/check-docs-substrings.mjs +73 -0
- package/bin/check-everything-mirror.mjs +0 -0
- package/bin/check-routing-targets.mjs +0 -0
- package/bin/check-scripts-citation-drift.mjs +210 -0
- package/bin/check-skill-count.mjs +110 -0
- package/bin/check-skill-law-tag.mjs +0 -0
- package/bin/check-skill-mirror.mjs +0 -0
- package/bin/check-skill-tiers.mjs +0 -0
- package/bin/check-test-imports-only.mjs +126 -0
- package/bin/check-third-party-shape.mjs +0 -0
- package/bin/companion-preference-status.mjs +231 -0
- package/bin/gateguard-clear.mjs +53 -0
- package/bin/generate-plugin-manifests.mjs +7 -1
- package/bin/harvest-friction.mjs +0 -0
- package/bin/hook-stats.mjs +0 -0
- package/bin/install.mjs +182 -26
- package/bin/lint-transcript.mjs +0 -0
- package/bin/mcp-server.mjs +215 -2
- package/bin/observe.mjs +0 -0
- package/bin/pre-commit-block-strays.sh +0 -0
- package/bin/refresh-third-party.mjs +315 -313
- package/bin/unified-cli.mjs +0 -0
- package/commands/audit.md +34 -0
- package/commands/companion-preference.md +58 -0
- package/commands/discipline.md +14 -0
- package/commands/distill.md +39 -0
- package/commands/goal-check.md +53 -0
- package/commands/grill-me.md +40 -0
- package/commands/grill-with-docs.md +38 -0
- package/commands/handoff.md +42 -0
- package/commands/proceed-with-the-recommendation.md +20 -0
- package/commands/recall.md +49 -0
- package/commands/reconcile.md +47 -0
- package/commands/superpowers.md +2 -2
- package/commands/verify-install.md +55 -0
- package/hooks/companion-preference.mjs +190 -0
- package/hooks/gateguard.mjs +60 -25
- package/hooks/goal-drift-stop.mjs +183 -0
- package/hooks/observe.sh +15 -1
- package/hooks/route-prompt.mjs +180 -0
- package/hooks/route-table.json +35 -0
- package/hooks/three-section-close.mjs +134 -132
- package/lib/cli-anything.mjs +0 -0
- package/lib/compound-engineering.mjs +0 -0
- package/lib/gateguard-state.mjs +54 -2
- package/lib/goal-drift-gate.mjs +50 -0
- package/lib/goal-state.mjs +285 -0
- package/lib/observe-event.mjs +0 -0
- package/lib/plugin-metadata.mjs +126 -12
- package/lib/pm-marketplace.mjs +0 -0
- package/lib/pm-skills.mjs +0 -0
- package/lib/recall-index.mjs +175 -0
- package/lib/resolve-home-dir.mjs +0 -0
- package/lib/skill-distill.mjs +222 -0
- package/lib/skill-tiers.mjs +0 -0
- package/lib/unified-plugin.mjs +0 -0
- package/llms.txt +1 -1
- package/package.json +11 -7
- package/plugins/beginner.json +8 -3
- package/plugins/continuous-improvement/.claude-plugin/marketplace.json +2 -2
- package/plugins/continuous-improvement/.claude-plugin/plugin.json +2 -2
- package/plugins/continuous-improvement/agents/README.md +2 -2
- package/plugins/continuous-improvement/bin/backfill.mjs +0 -0
- package/plugins/continuous-improvement/bin/gateguard-clear.mjs +53 -0
- package/plugins/continuous-improvement/bin/mcp-server.mjs +215 -2
- package/plugins/continuous-improvement/bin/observe.mjs +0 -0
- package/plugins/continuous-improvement/commands/audit.md +34 -0
- package/plugins/continuous-improvement/commands/companion-preference.md +58 -0
- package/plugins/continuous-improvement/commands/discipline.md +14 -0
- package/plugins/continuous-improvement/commands/distill.md +39 -0
- package/plugins/continuous-improvement/commands/goal-check.md +53 -0
- package/plugins/continuous-improvement/commands/grill-me.md +40 -0
- package/plugins/continuous-improvement/commands/grill-with-docs.md +38 -0
- package/plugins/continuous-improvement/commands/handoff.md +42 -0
- package/plugins/continuous-improvement/commands/proceed-with-the-recommendation.md +20 -0
- package/plugins/continuous-improvement/commands/recall.md +49 -0
- package/plugins/continuous-improvement/commands/reconcile.md +47 -0
- package/plugins/continuous-improvement/commands/superpowers.md +2 -2
- package/plugins/continuous-improvement/commands/verify-install.md +55 -0
- package/plugins/continuous-improvement/hooks/companion-preference.mjs +190 -0
- package/plugins/continuous-improvement/hooks/gateguard.mjs +60 -25
- package/plugins/continuous-improvement/hooks/goal-drift-stop.mjs +183 -0
- package/plugins/continuous-improvement/hooks/hooks.json +18 -2
- package/plugins/continuous-improvement/hooks/observe.sh +15 -1
- package/plugins/continuous-improvement/hooks/route-prompt.mjs +180 -0
- package/plugins/continuous-improvement/hooks/route-table.json +35 -0
- package/plugins/continuous-improvement/hooks/three-section-close.mjs +134 -132
- package/plugins/continuous-improvement/lib/gateguard-state.mjs +137 -0
- package/plugins/continuous-improvement/lib/goal-drift-gate.mjs +50 -0
- package/plugins/continuous-improvement/lib/goal-state.mjs +285 -0
- package/plugins/continuous-improvement/lib/observe-event.mjs +0 -0
- package/plugins/continuous-improvement/lib/plugin-metadata.mjs +126 -12
- package/plugins/continuous-improvement/lib/recall-index.mjs +175 -0
- package/plugins/continuous-improvement/lib/resolve-home-dir.mjs +0 -0
- package/plugins/continuous-improvement/lib/skill-distill.mjs +222 -0
- package/plugins/continuous-improvement/skills/README.md +8 -0
- package/plugins/continuous-improvement/skills/audit/SKILL.md +73 -0
- package/plugins/continuous-improvement/skills/deploy-receipt/SKILL.md +13 -17
- package/plugins/continuous-improvement/skills/gateguard/SKILL.md +36 -17
- package/plugins/continuous-improvement/skills/goal-monitor/SKILL.md +81 -0
- package/plugins/continuous-improvement/skills/grill-me/SKILL.md +66 -0
- package/plugins/continuous-improvement/skills/grill-with-docs/SKILL.md +252 -0
- package/plugins/continuous-improvement/skills/handoff/SKILL.md +59 -0
- package/plugins/continuous-improvement/skills/para-memory-files/SKILL.md +1 -1
- package/plugins/continuous-improvement/skills/proceed-with-the-recommendation/SKILL.md +82 -6
- package/plugins/continuous-improvement/skills/ralph/SKILL.md +1 -0
- package/plugins/continuous-improvement/skills/recall/SKILL.md +50 -0
- package/plugins/continuous-improvement/skills/reconcile/SKILL.md +80 -0
- package/plugins/continuous-improvement/skills/recovery-classification/SKILL.md +1 -0
- package/plugins/continuous-improvement/skills/safety-guard/SKILL.md +1 -0
- package/plugins/continuous-improvement/skills/skill-distillation/SKILL.md +57 -0
- package/plugins/continuous-improvement/skills/state-reconciliation/SKILL.md +1 -0
- package/plugins/continuous-improvement/skills/strategic-compact/SKILL.md +1 -0
- package/plugins/continuous-improvement/skills/superpowers/SKILL.md +76 -2
- package/plugins/continuous-improvement/skills/token-budget-advisor/SKILL.md +1 -1
- package/plugins/continuous-improvement/skills/verification-loop/SKILL.md +28 -20
- package/plugins/continuous-improvement/skills/wild-risa-balance/SKILL.md +1 -0
- package/plugins/continuous-improvement/skills/workspace-surface-audit/SKILL.md +1 -1
- package/plugins/continuous-improvement/skills/worktree-safety/SKILL.md +3 -2
- package/plugins/expert.json +27 -2
- package/skills/README.md +3 -0
- package/skills/audit.md +73 -0
- package/skills/deploy-receipt.md +13 -17
- package/skills/gateguard.md +36 -17
- package/skills/goal-monitor.md +81 -0
- package/skills/grill-me.md +66 -0
- package/skills/grill-with-docs.md +252 -0
- package/skills/handoff.md +59 -0
- package/skills/para-memory-files.md +1 -1
- package/skills/proceed-with-the-recommendation.md +82 -6
- package/skills/ralph.md +1 -0
- package/skills/recall.md +50 -0
- package/skills/reconcile.md +80 -0
- package/skills/recovery-classification.md +1 -0
- package/skills/safety-guard.md +1 -0
- package/skills/skill-distillation.md +57 -0
- package/skills/state-reconciliation.md +1 -0
- package/skills/strategic-compact.md +1 -0
- package/skills/superpowers.md +76 -2
- package/skills/token-budget-advisor.md +1 -1
- package/skills/verification-loop.md +28 -20
- package/skills/wild-risa-balance.md +1 -0
- package/skills/workspace-surface-audit.md +1 -1
- package/skills/worktree-safety.md +3 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// skill-distill.mts — Pure trajectory → draft-skill distillation.
|
|
2
|
+
//
|
|
3
|
+
// No I/O. Scans observation rows for repeated tool sequences that ended in a
|
|
4
|
+
// successful verification, and proposes DRAFT instincts capturing the pattern.
|
|
5
|
+
// The MCP tools ci_distill_candidates / ci_distill_propose / ci_distill_promote
|
|
6
|
+
// (src/bin/mcp-server.mts) wire the file reads and writes around these
|
|
7
|
+
// functions.
|
|
8
|
+
//
|
|
9
|
+
// Closed-loop "Learn From Every Session" (Law 7) on the SUCCESS side: the
|
|
10
|
+
// friction harvester (src/bin/harvest-friction.mts) already turns failures into
|
|
11
|
+
// instincts; this turns repeated wins into reusable drafts. Drafts never enter
|
|
12
|
+
// the suggestion pool — they require explicit promotion — so a coincidental
|
|
13
|
+
// tool sequence cannot cargo-cult itself into enforced behavior.
|
|
14
|
+
const MIN_TRAJECTORY_LENGTH = 4;
|
|
15
|
+
const GAP_MS = 10 * 60 * 1000;
|
|
16
|
+
const NGRAM_SIZES = [3, 4, 5];
|
|
17
|
+
const DEFAULT_MIN_OCCURRENCES = 3;
|
|
18
|
+
const DEFAULT_MIN_SESSIONS = 2;
|
|
19
|
+
const DRAFT_CONFIDENCE = 0.4;
|
|
20
|
+
const VERIFY_CMD = /\b(npm\s+(run\s+)?(test|verify(:[\w-]+)?|build)|pnpm\s+(test|build)|yarn\s+(test|build)|pytest|cargo\s+test|go\s+test|jest|vitest|make\s+test)\b/i;
|
|
21
|
+
const FAILURE_MARKER = /\b(error|errors|fail|failed|failing|not found|denied|cannot|exception|traceback)\b|exit code [1-9]/i;
|
|
22
|
+
const SUCCESS_MARKER = /\b(pass|passed|passing|success|succeeded|green|0 failures|all tests)\b|\bok\b/i;
|
|
23
|
+
const REFLECTION_MARKER = /\b(verified|phase[- ]?4|verify:all green|all tests pass)\b/i;
|
|
24
|
+
const NOISE_TOOL = /^(ci_|mcp__|TodoWrite$)/;
|
|
25
|
+
function session(obs) {
|
|
26
|
+
return (obs.session ?? obs.session_id ?? "").toString();
|
|
27
|
+
}
|
|
28
|
+
function text(obs) {
|
|
29
|
+
return `${obs.input_summary ?? ""}\n${obs.output_summary ?? ""}`;
|
|
30
|
+
}
|
|
31
|
+
function classifyTrajectorySuccess(observations) {
|
|
32
|
+
for (const obs of observations) {
|
|
33
|
+
if ((obs.tool ?? "") === "Bash") {
|
|
34
|
+
const input = (obs.input_summary ?? "").toString();
|
|
35
|
+
const output = (obs.output_summary ?? "").toString();
|
|
36
|
+
if (VERIFY_CMD.test(input) && !FAILURE_MARKER.test(output) && (output === "" || SUCCESS_MARKER.test(output))) {
|
|
37
|
+
return "verify-exit-0";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
for (const obs of observations) {
|
|
42
|
+
if (REFLECTION_MARKER.test(text(obs))) {
|
|
43
|
+
return "reflection-pass";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Split a chronological observation list into contiguous trajectories. A
|
|
50
|
+
* boundary occurs on session change or a time gap longer than GAP_MS. Only
|
|
51
|
+
* trajectories of at least MIN_TRAJECTORY_LENGTH observations are returned;
|
|
52
|
+
* each is classified as succeeded or not.
|
|
53
|
+
*/
|
|
54
|
+
export function extractTrajectories(observations) {
|
|
55
|
+
const out = [];
|
|
56
|
+
let group = [];
|
|
57
|
+
const flush = () => {
|
|
58
|
+
if (group.length < MIN_TRAJECTORY_LENGTH) {
|
|
59
|
+
group = [];
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const successReason = classifyTrajectorySuccess(group);
|
|
63
|
+
out.push({
|
|
64
|
+
observations: group,
|
|
65
|
+
session: session(group[0]),
|
|
66
|
+
startTs: (group[0].ts ?? "").toString(),
|
|
67
|
+
endTs: (group[group.length - 1].ts ?? "").toString(),
|
|
68
|
+
succeeded: successReason !== null,
|
|
69
|
+
successReason,
|
|
70
|
+
});
|
|
71
|
+
group = [];
|
|
72
|
+
};
|
|
73
|
+
for (const obs of observations) {
|
|
74
|
+
if (group.length === 0) {
|
|
75
|
+
group.push(obs);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const prev = group[group.length - 1];
|
|
79
|
+
const sessionChanged = session(obs) !== session(prev);
|
|
80
|
+
const prevMs = Date.parse((prev.ts ?? "").toString());
|
|
81
|
+
const curMs = Date.parse((obs.ts ?? "").toString());
|
|
82
|
+
const prevValid = !Number.isNaN(prevMs);
|
|
83
|
+
const curValid = !Number.isNaN(curMs);
|
|
84
|
+
const gapTooBig = (prevValid && curValid && curMs - prevMs > GAP_MS) || (prevValid !== curValid);
|
|
85
|
+
if (sessionChanged || gapTooBig) {
|
|
86
|
+
flush();
|
|
87
|
+
}
|
|
88
|
+
group.push(obs);
|
|
89
|
+
}
|
|
90
|
+
flush();
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function toolSequence(trajectory) {
|
|
94
|
+
return trajectory.observations
|
|
95
|
+
.map((obs) => (obs.tool ?? "").toString())
|
|
96
|
+
.filter((tool) => tool.length > 0 && !NOISE_TOOL.test(tool));
|
|
97
|
+
}
|
|
98
|
+
// Tool names are external data (observations.jsonl). The candidate id is later
|
|
99
|
+
// joined into a draft file path, so it must be slugified to [a-z0-9-] to keep a
|
|
100
|
+
// hostile tool name (`../`, `/`, `\`) from escaping the drafts directory.
|
|
101
|
+
function slugifyNgram(ngram) {
|
|
102
|
+
const slug = ngram
|
|
103
|
+
.join("-")
|
|
104
|
+
.toLowerCase()
|
|
105
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
106
|
+
.replace(/-+/g, "-")
|
|
107
|
+
.replace(/^-+|-+$/g, "");
|
|
108
|
+
return slug.length > 0 ? slug : "sequence";
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Mine repeated tool-sequence n-grams from SUCCESSFUL trajectories. A candidate
|
|
112
|
+
* must occur at least `minOccurrences` times across at least `minSessions`
|
|
113
|
+
* distinct sessions — so a pattern repeated within a single session is rejected.
|
|
114
|
+
* Sorted by occurrences then n-gram length, both descending.
|
|
115
|
+
*/
|
|
116
|
+
export function findCandidates(trajectories, opts = {}) {
|
|
117
|
+
const minOccurrences = opts.minOccurrences ?? DEFAULT_MIN_OCCURRENCES;
|
|
118
|
+
const minSessions = opts.minSessions ?? DEFAULT_MIN_SESSIONS;
|
|
119
|
+
const aggregates = new Map();
|
|
120
|
+
for (const trajectory of trajectories) {
|
|
121
|
+
if (!trajectory.succeeded)
|
|
122
|
+
continue;
|
|
123
|
+
const sequence = toolSequence(trajectory);
|
|
124
|
+
const outcome = trajectory.successReason ?? "unknown";
|
|
125
|
+
for (const size of NGRAM_SIZES) {
|
|
126
|
+
for (let i = 0; i + size <= sequence.length; i += 1) {
|
|
127
|
+
const ngram = sequence.slice(i, i + size);
|
|
128
|
+
const key = ngram.join(">");
|
|
129
|
+
let aggregate = aggregates.get(key);
|
|
130
|
+
if (!aggregate) {
|
|
131
|
+
aggregate = { ngram, occurrences: 0, sessions: new Set(), outcomes: new Set() };
|
|
132
|
+
aggregates.set(key, aggregate);
|
|
133
|
+
}
|
|
134
|
+
aggregate.occurrences += 1;
|
|
135
|
+
aggregate.sessions.add(trajectory.session);
|
|
136
|
+
aggregate.outcomes.add(outcome);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const candidates = [];
|
|
141
|
+
for (const aggregate of aggregates.values()) {
|
|
142
|
+
if (aggregate.occurrences < minOccurrences)
|
|
143
|
+
continue;
|
|
144
|
+
if (aggregate.sessions.size < minSessions)
|
|
145
|
+
continue;
|
|
146
|
+
candidates.push({
|
|
147
|
+
id: `draft-${slugifyNgram(aggregate.ngram)}`,
|
|
148
|
+
ngram: aggregate.ngram,
|
|
149
|
+
occurrences: aggregate.occurrences,
|
|
150
|
+
sessions: [...aggregate.sessions],
|
|
151
|
+
outcomes: [...aggregate.outcomes],
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
candidates.sort((a, b) => b.occurrences !== a.occurrences ? b.occurrences - a.occurrences : b.ngram.length - a.ngram.length);
|
|
155
|
+
return candidates;
|
|
156
|
+
}
|
|
157
|
+
/** Turn a candidate into a DRAFT instinct with a placeholder body for the user to fill in. */
|
|
158
|
+
export function draftFromCandidate(candidate) {
|
|
159
|
+
const arrow = candidate.ngram.join(" → ");
|
|
160
|
+
const outcome = candidate.outcomes.join(", ");
|
|
161
|
+
return {
|
|
162
|
+
id: candidate.id,
|
|
163
|
+
trigger: `Auto-detected pattern: ${candidate.ngram.join(" then ")} (seen ${candidate.occurrences}x across ${candidate.sessions.length} sessions)`,
|
|
164
|
+
body: [
|
|
165
|
+
"When this situation recurs, follow the proven sequence that worked before:",
|
|
166
|
+
"",
|
|
167
|
+
` ${arrow}`,
|
|
168
|
+
"",
|
|
169
|
+
`This pattern succeeded in ${candidate.occurrences} run(s) across ${candidate.sessions.length} session(s) (outcome: ${outcome}).`,
|
|
170
|
+
"Replace this placeholder with the concrete steps, preconditions, and gotchas before promoting —",
|
|
171
|
+
"the tool sequence alone is evidence, not a recipe.",
|
|
172
|
+
].join("\n"),
|
|
173
|
+
confidence: DRAFT_CONFIDENCE,
|
|
174
|
+
domain: "workflow",
|
|
175
|
+
ngram: candidate.ngram,
|
|
176
|
+
occurrences: candidate.occurrences,
|
|
177
|
+
sessions: candidate.sessions.length,
|
|
178
|
+
outcome,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Serialize a draft to the instinct YAML format (key: value lines, `---`, body)
|
|
183
|
+
* so it round-trips through the same parser that reads live instincts. Stored
|
|
184
|
+
* under drafts/ so it is not picked up as a live instinct until promoted.
|
|
185
|
+
*/
|
|
186
|
+
export function serializeDraft(draft) {
|
|
187
|
+
return [
|
|
188
|
+
`id: ${draft.id}`,
|
|
189
|
+
`trigger: "${draft.trigger}"`,
|
|
190
|
+
`confidence: ${draft.confidence}`,
|
|
191
|
+
`domain: ${draft.domain}`,
|
|
192
|
+
"source: distilled",
|
|
193
|
+
"status: draft",
|
|
194
|
+
`evidence_ngram: "${draft.ngram.join(">")}"`,
|
|
195
|
+
`evidence_occurrences: ${draft.occurrences}`,
|
|
196
|
+
`evidence_sessions: ${draft.sessions}`,
|
|
197
|
+
`evidence_outcome: "${draft.outcome}"`,
|
|
198
|
+
"---",
|
|
199
|
+
draft.body,
|
|
200
|
+
"",
|
|
201
|
+
].join("\n");
|
|
202
|
+
}
|
|
203
|
+
/** Render candidates as a markdown block for the MCP tool output. */
|
|
204
|
+
export function formatCandidates(candidates, limit = 10) {
|
|
205
|
+
if (candidates.length === 0) {
|
|
206
|
+
return "No distillation candidates found. A candidate needs a tool sequence that recurred across multiple successful sessions. Keep working — patterns accrue as the observation log grows.";
|
|
207
|
+
}
|
|
208
|
+
const shown = candidates.slice(0, limit);
|
|
209
|
+
const lines = [
|
|
210
|
+
`## Distillation Candidates (${candidates.length})`,
|
|
211
|
+
"",
|
|
212
|
+
"Repeated tool sequences from successful sessions. Propose a draft with `ci_distill_propose id=<id>`, edit its body, then `ci_distill_promote id=<id>`.",
|
|
213
|
+
"",
|
|
214
|
+
];
|
|
215
|
+
for (const candidate of shown) {
|
|
216
|
+
lines.push(`- **${candidate.id}**`, ` Sequence: ${candidate.ngram.join(" → ")}`, ` Seen ${candidate.occurrences}x across ${candidate.sessions.length} session(s) — outcome: ${candidate.outcomes.join(", ")}`);
|
|
217
|
+
}
|
|
218
|
+
if (candidates.length > limit) {
|
|
219
|
+
lines.push("", `_…and ${candidates.length - limit} more._`);
|
|
220
|
+
}
|
|
221
|
+
return lines.join("\n");
|
|
222
|
+
}
|
package/lib/skill-tiers.mjs
CHANGED
|
File without changes
|
package/lib/unified-plugin.mjs
CHANGED
|
File without changes
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# continuous-improvement
|
|
2
2
|
|
|
3
|
-
> Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline —
|
|
3
|
+
> Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline — 25 bundled skills, gating hooks, the Mulahazah auto-leveling instinct engine, and a GitHub Action transcript linter.
|
|
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.
|
|
4
|
-
"description": "Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline —
|
|
3
|
+
"version": "3.11.0",
|
|
4
|
+
"description": "Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline — 25 bundled skills, gating hooks, the Mulahazah auto-leveling instinct engine, and a GitHub Action transcript linter. Beginner: one /plugin install command. Expert: adds MCP tools and session hooks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
7
7
|
"claude-code-skill",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"type": "git",
|
|
23
23
|
"url": "git+https://github.com/naimkatiman/continuous-improvement.git"
|
|
24
24
|
},
|
|
25
|
-
"homepage": "https://
|
|
25
|
+
"homepage": "https://continuous-improvement.dev",
|
|
26
26
|
"bugs": {
|
|
27
27
|
"url": "https://github.com/naimkatiman/continuous-improvement/issues"
|
|
28
28
|
},
|
|
@@ -32,21 +32,25 @@
|
|
|
32
32
|
"ci": "bin/unified-cli.mjs"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"build": "tsc -p tsconfig.json && node bin/generate-plugin-manifests.mjs",
|
|
35
|
+
"build": "tsc -p tsconfig.json && node bin/generate-plugin-manifests.mjs && node -e \"const fs=require('node:fs'); for (const f of fs.readdirSync('bin')) { if (f.endsWith('.mjs')) fs.chmodSync('bin/'+f, 0o755); } for (const f of fs.readdirSync('hooks')) { if (f.endsWith('.mjs')) fs.chmodSync('hooks/'+f, 0o755); } for (const f of fs.readdirSync('lib')) { if (f.endsWith('.mjs')) fs.chmodSync('lib/'+f, 0o755); } for (const f of fs.readdirSync('plugins/continuous-improvement/bin')) { if (f.endsWith('.mjs')) fs.chmodSync('plugins/continuous-improvement/bin/'+f, 0o755); } for (const f of fs.readdirSync('plugins/continuous-improvement/lib')) { if (f.endsWith('.mjs')) fs.chmodSync('plugins/continuous-improvement/lib/'+f, 0o755); } for (const f of fs.readdirSync('plugins/continuous-improvement/hooks')) { if (f.endsWith('.mjs')) fs.chmodSync('plugins/continuous-improvement/hooks/'+f, 0o755); } for (const f of fs.readdirSync('scripts')) { if (f.endsWith('.mjs')) fs.chmodSync('scripts/'+f, 0o755); } for (const f of fs.readdirSync('synthetic-checks')) { if (f.endsWith('.mjs')) fs.chmodSync('synthetic-checks/'+f, 0o755); } \"",
|
|
36
36
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
-
"clean": "node -e \"const fs=require('node:fs'); for (const dir of ['bin','test','lib']) { if (!fs.existsSync(dir)) continue; for (const file of fs.readdirSync(dir)) { if (file.endsWith('.mjs')) fs.rmSync(dir
|
|
37
|
+
"clean": "node -e \"const fs=require('node:fs'); for (const dir of ['bin','hooks','test','lib']) { if (!fs.existsSync(dir)) continue; for (const file of fs.readdirSync(dir)) { if (file.endsWith('.mjs')) fs.rmSync(dir+'/'+file, { force: true }); } }\"",
|
|
38
38
|
"hooks:stats": "node bin/hook-stats.mjs",
|
|
39
39
|
"test": "npm run build && node --test test/*.test.mjs",
|
|
40
40
|
"lint": "node bin/lint-transcript.mjs --help",
|
|
41
|
-
"verify:generated": "npm run build && git diff --exit-code -- .claude-plugin bin test lib plugins",
|
|
41
|
+
"verify:generated": "npm run build && git diff --exit-code -- .claude-plugin bin hooks test lib plugins",
|
|
42
42
|
"verify:skill-mirror": "node bin/check-skill-mirror.mjs",
|
|
43
43
|
"verify:skill-tiers": "node bin/check-skill-tiers.mjs",
|
|
44
44
|
"verify:skill-law-tag": "node bin/check-skill-law-tag.mjs",
|
|
45
|
+
"verify:skill-count": "node bin/check-skill-count.mjs",
|
|
45
46
|
"verify:docs-substrings": "node bin/check-docs-substrings.mjs",
|
|
46
47
|
"verify:everything-mirror": "node bin/check-everything-mirror.mjs",
|
|
47
48
|
"verify:routing-targets": "node bin/check-routing-targets.mjs",
|
|
48
49
|
"verify:doc-runtime-claims": "node bin/check-doc-runtime-claims.mjs",
|
|
49
|
-
"verify:
|
|
50
|
+
"verify:test-imports-only": "node bin/check-test-imports-only.mjs",
|
|
51
|
+
"verify:scripts-citation-drift": "node bin/check-scripts-citation-drift.mjs",
|
|
52
|
+
"verify:third-party-shape": "node bin/check-third-party-shape.mjs",
|
|
53
|
+
"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: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 typecheck"
|
|
50
54
|
},
|
|
51
55
|
"files": [
|
|
52
56
|
".claude-plugin/",
|
package/plugins/beginner.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "continuous-improvement",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"mode": "beginner",
|
|
5
5
|
"description": "Beginner mode: see what your agent learned, list its instincts, and request a session reflection. Bundles four discipline skills (gateguard, para-memory-files, tdd-workflow, verification-loop) so research, memory, tests, and verification happen by default.",
|
|
6
6
|
"tools": [
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
{
|
|
16
16
|
"name": "ci_reflect",
|
|
17
17
|
"what": "Reflect on what you did this session"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "ci_gateguard_clear",
|
|
21
|
+
"what": "Clear the GateGuard gate for files after presenting facts"
|
|
18
22
|
}
|
|
19
23
|
],
|
|
20
24
|
"setup": {
|
|
@@ -46,8 +50,9 @@
|
|
|
46
50
|
"hooks": {
|
|
47
51
|
"included": [
|
|
48
52
|
"PreToolUse",
|
|
49
|
-
"PostToolUse"
|
|
53
|
+
"PostToolUse",
|
|
54
|
+
"UserPromptSubmit"
|
|
50
55
|
],
|
|
51
|
-
"description": "Silently captures every tool call as observations. Lightweight and non-blocking."
|
|
56
|
+
"description": "Silently captures every tool call as observations and routes prompts to the matching discipline skill via the route table. Lightweight and non-blocking."
|
|
52
57
|
}
|
|
53
58
|
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
"plugins": [
|
|
8
8
|
{
|
|
9
9
|
"name": "continuous-improvement",
|
|
10
|
-
"description": "Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline —
|
|
11
|
-
"version": "3.
|
|
10
|
+
"description": "Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline — 25 bundled skills, gating hooks, the Mulahazah auto-leveling instinct engine, and a GitHub Action transcript linter.",
|
|
11
|
+
"version": "3.11.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.
|
|
4
|
-
"description": "Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline —
|
|
3
|
+
"version": "3.11.0",
|
|
4
|
+
"description": "Stops Claude Code from skipping research, claiming 'done' without verifying, and repeating yesterday's mistakes. The 7 Laws of AI Agent Discipline — 25 bundled skills, gating hooks, the Mulahazah auto-leveling instinct engine, and a GitHub Action transcript linter.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "naimkatiman",
|
|
7
7
|
"url": "https://github.com/naimkatiman"
|
|
@@ -40,7 +40,7 @@ Pick this only when **independent** investigations can run in parallel and produ
|
|
|
40
40
|
|
|
41
41
|
- `/ship` → fans out to `code-reviewer` + `security-auditor` + `test-engineer` in parallel, then synthesizes their reports into a go/no-go decision
|
|
42
42
|
|
|
43
|
-
This is the only orchestration pattern this repo endorses. See
|
|
43
|
+
This is the only orchestration pattern this repo endorses. See `references/orchestration-patterns.md` for the full pattern catalog and anti-patterns.
|
|
44
44
|
|
|
45
45
|
## Decision matrix
|
|
46
46
|
|
|
@@ -107,7 +107,7 @@ The personas in this repo are designed to work as Claude Code subagents and as A
|
|
|
107
107
|
- **As subagents:** auto-discovered when this plugin is enabled (no path config needed). Use the Agent tool with `subagent_type: code-reviewer` (or `security-auditor`, `test-engineer`). `/ship` is the canonical example.
|
|
108
108
|
- **As Agent Teams teammates** (experimental, requires `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`): reference the same persona name when spawning a teammate. The persona's body is **appended to** the teammate's system prompt as additional instructions (not a replacement), so your persona text sits on top of the team-coordination instructions the lead installs (SendMessage, task-list tools, etc.).
|
|
109
109
|
|
|
110
|
-
Subagents only report results back to the main agent. Agent Teams let teammates message each other directly. Use subagents when reports are enough; use Agent Teams when sub-agents need to challenge each other's findings (e.g. competing-hypothesis debugging). See
|
|
110
|
+
Subagents only report results back to the main agent. Agent Teams let teammates message each other directly. Use subagents when reports are enough; use Agent Teams when sub-agents need to challenge each other's findings (e.g. competing-hypothesis debugging). See `references/orchestration-patterns.md` for the full mapping.
|
|
111
111
|
|
|
112
112
|
Plugin agents do not support `hooks`, `mcpServers`, or `permissionMode` frontmatter — those fields are silently ignored. Avoid relying on them when authoring new personas here.
|
|
113
113
|
|
|
File without changes
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* gateguard-clear — record GateGuard clearance for files from the Bash route.
|
|
4
|
+
*
|
|
5
|
+
* The GateGuard PreToolUse hook blocks the first Edit/Write per file and prints
|
|
6
|
+
* the session-state path in its block reason. After presenting the required
|
|
7
|
+
* facts, run this to clear the gate so the retry is allowed. Bash is not gated
|
|
8
|
+
* (unless the command is destructive), so this surface always works — including
|
|
9
|
+
* where the ci_gateguard_clear MCP tool is not connected.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node bin/gateguard-clear.mjs <file_path> [<file_path>...] [--state <path>]
|
|
13
|
+
*
|
|
14
|
+
* Default resolves the session dir canonically, the same way the hook does.
|
|
15
|
+
* --state <path> writes that exact gateguard-session.json — the path the block
|
|
16
|
+
* reason prints — bypassing resolution for any residual env mismatch.
|
|
17
|
+
*/
|
|
18
|
+
import { dirname, join } from "node:path";
|
|
19
|
+
import { MAX_CLEARED_FILES, clearFiles, resolveSessionDir, } from "../lib/gateguard-state.mjs";
|
|
20
|
+
function main() {
|
|
21
|
+
const argv = process.argv.slice(2);
|
|
22
|
+
const files = [];
|
|
23
|
+
let stateFile = "";
|
|
24
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
25
|
+
const arg = argv[i];
|
|
26
|
+
if (arg === "--state") {
|
|
27
|
+
stateFile = argv[i + 1] ?? "";
|
|
28
|
+
i += 1;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
files.push(arg);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (argv.includes("--state") && stateFile === "") {
|
|
35
|
+
process.stderr.write("--state requires a <gateguard-session.json> path argument\n");
|
|
36
|
+
process.exit(2);
|
|
37
|
+
}
|
|
38
|
+
if (files.length === 0) {
|
|
39
|
+
process.stderr.write("usage: gateguard-clear <file_path> [<file_path>...] [--state <gateguard-session.json>]\n");
|
|
40
|
+
process.exit(2);
|
|
41
|
+
}
|
|
42
|
+
// clearFiles writes <sessionDir>/gateguard-session.json. With --state the
|
|
43
|
+
// caller hands us the full state-file path the block reason printed, so the
|
|
44
|
+
// session dir is its parent.
|
|
45
|
+
const sessionDir = stateFile ? dirname(stateFile) : resolveSessionDir();
|
|
46
|
+
const { cleared, skippedForCap } = clearFiles(sessionDir, files);
|
|
47
|
+
process.stdout.write(`Cleared ${cleared.length}: ${cleared.length > 0 ? cleared.join(", ") : "(none — already cleared)"}\n`);
|
|
48
|
+
if (skippedForCap.length > 0) {
|
|
49
|
+
process.stdout.write(`Skipped — session cap of ${MAX_CLEARED_FILES} reached: ${skippedForCap.join(", ")}\n`);
|
|
50
|
+
}
|
|
51
|
+
process.stdout.write(`State: ${join(sessionDir, "gateguard-session.json")}\n`);
|
|
52
|
+
}
|
|
53
|
+
main();
|