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.
Files changed (150) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +61 -0
  3. package/QUICKSTART.md +13 -8
  4. package/README.md +84 -153
  5. package/bin/backfill.mjs +0 -0
  6. package/bin/check-doc-runtime-claims.mjs +0 -0
  7. package/bin/check-docs-substrings.mjs +73 -0
  8. package/bin/check-everything-mirror.mjs +0 -0
  9. package/bin/check-routing-targets.mjs +0 -0
  10. package/bin/check-scripts-citation-drift.mjs +210 -0
  11. package/bin/check-skill-count.mjs +110 -0
  12. package/bin/check-skill-law-tag.mjs +0 -0
  13. package/bin/check-skill-mirror.mjs +0 -0
  14. package/bin/check-skill-tiers.mjs +0 -0
  15. package/bin/check-test-imports-only.mjs +126 -0
  16. package/bin/check-third-party-shape.mjs +0 -0
  17. package/bin/companion-preference-status.mjs +231 -0
  18. package/bin/gateguard-clear.mjs +53 -0
  19. package/bin/generate-plugin-manifests.mjs +7 -1
  20. package/bin/harvest-friction.mjs +0 -0
  21. package/bin/hook-stats.mjs +0 -0
  22. package/bin/install.mjs +182 -26
  23. package/bin/lint-transcript.mjs +0 -0
  24. package/bin/mcp-server.mjs +215 -2
  25. package/bin/observe.mjs +0 -0
  26. package/bin/pre-commit-block-strays.sh +0 -0
  27. package/bin/refresh-third-party.mjs +315 -313
  28. package/bin/unified-cli.mjs +0 -0
  29. package/commands/audit.md +34 -0
  30. package/commands/companion-preference.md +58 -0
  31. package/commands/discipline.md +14 -0
  32. package/commands/distill.md +39 -0
  33. package/commands/goal-check.md +53 -0
  34. package/commands/grill-me.md +40 -0
  35. package/commands/grill-with-docs.md +38 -0
  36. package/commands/handoff.md +42 -0
  37. package/commands/proceed-with-the-recommendation.md +20 -0
  38. package/commands/recall.md +49 -0
  39. package/commands/reconcile.md +47 -0
  40. package/commands/superpowers.md +2 -2
  41. package/commands/verify-install.md +55 -0
  42. package/hooks/companion-preference.mjs +190 -0
  43. package/hooks/gateguard.mjs +60 -25
  44. package/hooks/goal-drift-stop.mjs +183 -0
  45. package/hooks/observe.sh +15 -1
  46. package/hooks/route-prompt.mjs +180 -0
  47. package/hooks/route-table.json +35 -0
  48. package/hooks/three-section-close.mjs +134 -132
  49. package/lib/cli-anything.mjs +0 -0
  50. package/lib/compound-engineering.mjs +0 -0
  51. package/lib/gateguard-state.mjs +54 -2
  52. package/lib/goal-drift-gate.mjs +50 -0
  53. package/lib/goal-state.mjs +285 -0
  54. package/lib/observe-event.mjs +0 -0
  55. package/lib/plugin-metadata.mjs +126 -12
  56. package/lib/pm-marketplace.mjs +0 -0
  57. package/lib/pm-skills.mjs +0 -0
  58. package/lib/recall-index.mjs +175 -0
  59. package/lib/resolve-home-dir.mjs +0 -0
  60. package/lib/skill-distill.mjs +222 -0
  61. package/lib/skill-tiers.mjs +0 -0
  62. package/lib/unified-plugin.mjs +0 -0
  63. package/llms.txt +1 -1
  64. package/package.json +11 -7
  65. package/plugins/beginner.json +8 -3
  66. package/plugins/continuous-improvement/.claude-plugin/marketplace.json +2 -2
  67. package/plugins/continuous-improvement/.claude-plugin/plugin.json +2 -2
  68. package/plugins/continuous-improvement/agents/README.md +2 -2
  69. package/plugins/continuous-improvement/bin/backfill.mjs +0 -0
  70. package/plugins/continuous-improvement/bin/gateguard-clear.mjs +53 -0
  71. package/plugins/continuous-improvement/bin/mcp-server.mjs +215 -2
  72. package/plugins/continuous-improvement/bin/observe.mjs +0 -0
  73. package/plugins/continuous-improvement/commands/audit.md +34 -0
  74. package/plugins/continuous-improvement/commands/companion-preference.md +58 -0
  75. package/plugins/continuous-improvement/commands/discipline.md +14 -0
  76. package/plugins/continuous-improvement/commands/distill.md +39 -0
  77. package/plugins/continuous-improvement/commands/goal-check.md +53 -0
  78. package/plugins/continuous-improvement/commands/grill-me.md +40 -0
  79. package/plugins/continuous-improvement/commands/grill-with-docs.md +38 -0
  80. package/plugins/continuous-improvement/commands/handoff.md +42 -0
  81. package/plugins/continuous-improvement/commands/proceed-with-the-recommendation.md +20 -0
  82. package/plugins/continuous-improvement/commands/recall.md +49 -0
  83. package/plugins/continuous-improvement/commands/reconcile.md +47 -0
  84. package/plugins/continuous-improvement/commands/superpowers.md +2 -2
  85. package/plugins/continuous-improvement/commands/verify-install.md +55 -0
  86. package/plugins/continuous-improvement/hooks/companion-preference.mjs +190 -0
  87. package/plugins/continuous-improvement/hooks/gateguard.mjs +60 -25
  88. package/plugins/continuous-improvement/hooks/goal-drift-stop.mjs +183 -0
  89. package/plugins/continuous-improvement/hooks/hooks.json +18 -2
  90. package/plugins/continuous-improvement/hooks/observe.sh +15 -1
  91. package/plugins/continuous-improvement/hooks/route-prompt.mjs +180 -0
  92. package/plugins/continuous-improvement/hooks/route-table.json +35 -0
  93. package/plugins/continuous-improvement/hooks/three-section-close.mjs +134 -132
  94. package/plugins/continuous-improvement/lib/gateguard-state.mjs +137 -0
  95. package/plugins/continuous-improvement/lib/goal-drift-gate.mjs +50 -0
  96. package/plugins/continuous-improvement/lib/goal-state.mjs +285 -0
  97. package/plugins/continuous-improvement/lib/observe-event.mjs +0 -0
  98. package/plugins/continuous-improvement/lib/plugin-metadata.mjs +126 -12
  99. package/plugins/continuous-improvement/lib/recall-index.mjs +175 -0
  100. package/plugins/continuous-improvement/lib/resolve-home-dir.mjs +0 -0
  101. package/plugins/continuous-improvement/lib/skill-distill.mjs +222 -0
  102. package/plugins/continuous-improvement/skills/README.md +8 -0
  103. package/plugins/continuous-improvement/skills/audit/SKILL.md +73 -0
  104. package/plugins/continuous-improvement/skills/deploy-receipt/SKILL.md +13 -17
  105. package/plugins/continuous-improvement/skills/gateguard/SKILL.md +36 -17
  106. package/plugins/continuous-improvement/skills/goal-monitor/SKILL.md +81 -0
  107. package/plugins/continuous-improvement/skills/grill-me/SKILL.md +66 -0
  108. package/plugins/continuous-improvement/skills/grill-with-docs/SKILL.md +252 -0
  109. package/plugins/continuous-improvement/skills/handoff/SKILL.md +59 -0
  110. package/plugins/continuous-improvement/skills/para-memory-files/SKILL.md +1 -1
  111. package/plugins/continuous-improvement/skills/proceed-with-the-recommendation/SKILL.md +82 -6
  112. package/plugins/continuous-improvement/skills/ralph/SKILL.md +1 -0
  113. package/plugins/continuous-improvement/skills/recall/SKILL.md +50 -0
  114. package/plugins/continuous-improvement/skills/reconcile/SKILL.md +80 -0
  115. package/plugins/continuous-improvement/skills/recovery-classification/SKILL.md +1 -0
  116. package/plugins/continuous-improvement/skills/safety-guard/SKILL.md +1 -0
  117. package/plugins/continuous-improvement/skills/skill-distillation/SKILL.md +57 -0
  118. package/plugins/continuous-improvement/skills/state-reconciliation/SKILL.md +1 -0
  119. package/plugins/continuous-improvement/skills/strategic-compact/SKILL.md +1 -0
  120. package/plugins/continuous-improvement/skills/superpowers/SKILL.md +76 -2
  121. package/plugins/continuous-improvement/skills/token-budget-advisor/SKILL.md +1 -1
  122. package/plugins/continuous-improvement/skills/verification-loop/SKILL.md +28 -20
  123. package/plugins/continuous-improvement/skills/wild-risa-balance/SKILL.md +1 -0
  124. package/plugins/continuous-improvement/skills/workspace-surface-audit/SKILL.md +1 -1
  125. package/plugins/continuous-improvement/skills/worktree-safety/SKILL.md +3 -2
  126. package/plugins/expert.json +27 -2
  127. package/skills/README.md +3 -0
  128. package/skills/audit.md +73 -0
  129. package/skills/deploy-receipt.md +13 -17
  130. package/skills/gateguard.md +36 -17
  131. package/skills/goal-monitor.md +81 -0
  132. package/skills/grill-me.md +66 -0
  133. package/skills/grill-with-docs.md +252 -0
  134. package/skills/handoff.md +59 -0
  135. package/skills/para-memory-files.md +1 -1
  136. package/skills/proceed-with-the-recommendation.md +82 -6
  137. package/skills/ralph.md +1 -0
  138. package/skills/recall.md +50 -0
  139. package/skills/reconcile.md +80 -0
  140. package/skills/recovery-classification.md +1 -0
  141. package/skills/safety-guard.md +1 -0
  142. package/skills/skill-distillation.md +57 -0
  143. package/skills/state-reconciliation.md +1 -0
  144. package/skills/strategic-compact.md +1 -0
  145. package/skills/superpowers.md +76 -2
  146. package/skills/token-budget-advisor.md +1 -1
  147. package/skills/verification-loop.md +28 -20
  148. package/skills/wild-risa-balance.md +1 -0
  149. package/skills/workspace-surface-audit.md +1 -1
  150. package/skills/worktree-safety.md +3 -2
@@ -11,13 +11,17 @@
11
11
  * node bin/mcp-server.mjs --mode beginner # explicit beginner
12
12
  */
13
13
  import { execSync } from "node:child_process";
14
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
14
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
15
15
  import { homedir } from "node:os";
16
16
  import { basename, dirname, join } from "node:path";
17
17
  import { createInterface } from "node:readline";
18
18
  import { fileURLToPath } from "node:url";
19
19
  import { createHash } from "node:crypto";
20
20
  import { PACKAGE_NAME, VERSION, getToolDefinitions, isPluginMode, } from "../lib/plugin-metadata.mjs";
21
+ import { formatDriftReport, parseGoalFromPlan, scoreObservations, } from "../lib/goal-state.mjs";
22
+ import { buildIndex, formatRecallHits, parseSince, query as queryRecall, } from "../lib/recall-index.mjs";
23
+ import { draftFromCandidate, extractTrajectories, findCandidates, formatCandidates, serializeDraft, } from "../lib/skill-distill.mjs";
24
+ import { MAX_CLEARED_FILES, clearFiles, resolveSessionDir, } from "../lib/gateguard-state.mjs";
21
25
  function getHomeDir() {
22
26
  return process.env.HOME || process.env.USERPROFILE || homedir();
23
27
  }
@@ -32,6 +36,12 @@ function getString(value, fallback = "") {
32
36
  function getNumber(value, fallback = 0) {
33
37
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
34
38
  }
39
+ // Draft ids are derived from slugified tool n-grams (src/lib/skill-distill.mts)
40
+ // and are joined into a filesystem path, so a caller-supplied id must match the
41
+ // safe shape before it is used to read/write/delete a draft file.
42
+ function isSafeDraftId(id) {
43
+ return /^draft-[a-z0-9-]+$/.test(id);
44
+ }
35
45
  function getBoolean(value, fallback = false) {
36
46
  return typeof value === "boolean" ? value : fallback;
37
47
  }
@@ -174,6 +184,12 @@ function countObservations(projectHash) {
174
184
  }
175
185
  }
176
186
  function getRecentObservations(projectHash, limit = 50) {
187
+ // Clamp a non-positive or non-integer limit to the default. slice(-0) would
188
+ // otherwise return the ENTIRE history (the limit:0 boundary), and a negative
189
+ // limit would drop rows from the front instead of taking the tail. ci_goal_check
190
+ // pre-rejects bad limits with a clear error(); this guards ci_observations and
191
+ // any other caller that passes a user-supplied limit straight through.
192
+ const cappedLimit = Number.isInteger(limit) && limit > 0 ? limit : 50;
177
193
  const observationsFile = join(INSTINCTS_DIR, projectHash, "observations.jsonl");
178
194
  if (!existsSync(observationsFile)) {
179
195
  return [];
@@ -182,7 +198,7 @@ function getRecentObservations(projectHash, limit = 50) {
182
198
  const lines = readFileSync(observationsFile, "utf8")
183
199
  .split("\n")
184
200
  .filter((line) => line.trim().length > 0);
185
- return lines.slice(-limit).flatMap((line) => {
201
+ return lines.slice(-cappedLimit).flatMap((line) => {
186
202
  try {
187
203
  return [JSON.parse(line)];
188
204
  }
@@ -195,6 +211,16 @@ function getRecentObservations(projectHash, limit = 50) {
195
211
  return [];
196
212
  }
197
213
  }
214
+ function readDistillObservations(projectHash) {
215
+ return getRecentObservations(projectHash, 100000).map((observation) => ({
216
+ ts: getString(observation.ts),
217
+ session: getString(observation.session),
218
+ session_id: getString(observation.session_id),
219
+ tool: getString(observation.tool),
220
+ input_summary: getString(observation.input_summary),
221
+ output_summary: getString(observation.output_summary),
222
+ }));
223
+ }
198
224
  function detectLevel(projectHash) {
199
225
  const observationCount = countObservations(projectHash);
200
226
  const instincts = readInstincts(projectHash);
@@ -480,6 +506,33 @@ function handleTool(name, params) {
480
506
  ].join("\n");
481
507
  return text(reflection);
482
508
  }
509
+ case "ci_gateguard_clear": {
510
+ // Beginner-available on purpose: the GateGuard hook fires for every
511
+ // install, so the clearance action must too. Resolves the session dir via
512
+ // gateguard-state (canonical), the same way the hook does, so the marker
513
+ // lands where the hook looks regardless of how each process spelled the
514
+ // project root.
515
+ const rawList = Array.isArray(params.file_paths) ? params.file_paths : [];
516
+ const listPaths = rawList.filter((value) => typeof value === "string" && value.length > 0);
517
+ const single = getString(params.file_path).trim();
518
+ const paths = single ? [...listPaths, single] : listPaths;
519
+ if (paths.length === 0) {
520
+ return error("file_paths is required — pass the file path(s) named in the GateGuard block reason, e.g. { file_paths: [\"src/x.ts\"] }.");
521
+ }
522
+ const sessionDir = resolveSessionDir();
523
+ const { cleared, skippedForCap } = clearFiles(sessionDir, paths);
524
+ const lines = [
525
+ "## GateGuard clearance",
526
+ "",
527
+ `**State file:** ${join(sessionDir, "gateguard-session.json")}`,
528
+ `**Cleared (${cleared.length}):** ${cleared.length > 0 ? cleared.join(", ") : "(none — already cleared)"}`,
529
+ ];
530
+ if (skippedForCap.length > 0) {
531
+ lines.push(`**Skipped — session cap of ${MAX_CLEARED_FILES} reached (${skippedForCap.length}):** ${skippedForCap.join(", ")}`, "Start a new session to reset the gate.");
532
+ }
533
+ lines.push("", "Retry the Edit/Write now — it will pass.");
534
+ return text(lines.join("\n"));
535
+ }
483
536
  case "ci_reinforce": {
484
537
  if (MODE !== "expert") {
485
538
  return error("ci_reinforce requires expert mode. Start server with --mode expert");
@@ -665,6 +718,166 @@ function handleTool(name, params) {
665
718
  }
666
719
  return text(lines.join("\n"));
667
720
  }
721
+ case "ci_goal_check": {
722
+ if (MODE !== "expert") {
723
+ return error("ci_goal_check requires expert mode");
724
+ }
725
+ const limit = getNumber(params.limit, 30);
726
+ if (!Number.isInteger(limit) || limit <= 0) {
727
+ return error(`limit must be a positive integer; got ${limit}. Omit it to score the default 30 most recent observations.`);
728
+ }
729
+ const explicit = getString(params.goal_file).trim();
730
+ const workspaceRoot = getWorkspaceRoot();
731
+ const candidates = explicit
732
+ ? [explicit]
733
+ : [
734
+ join(workspaceRoot, PLANNING_FILES.taskPlan),
735
+ join(INSTINCTS_DIR, project.hash, "goal.md"),
736
+ ];
737
+ let goalContent = "";
738
+ let goalSource = "";
739
+ for (const candidate of candidates) {
740
+ if (!existsSync(candidate)) {
741
+ continue;
742
+ }
743
+ try {
744
+ goalContent = readFileSync(candidate, "utf8");
745
+ goalSource = candidate;
746
+ break;
747
+ }
748
+ catch {
749
+ // try the next candidate
750
+ }
751
+ }
752
+ if (!goalContent) {
753
+ return text(`No goal source found. Looked for: ${candidates.join(", ")}.\nRun ci_plan_init (or /planning-with-files) to create ${PLANNING_FILES.taskPlan} with a '## Goal' section.`);
754
+ }
755
+ const goal = parseGoalFromPlan(goalContent);
756
+ if (!goal) {
757
+ return text(`Found ${goalSource} but it has no '## Goal' section. Add one — ci_plan_init seeds it. Optional '## Goal Keywords' and '## Goal Scope' sections sharpen the drift signal.`);
758
+ }
759
+ const goalObservations = getRecentObservations(project.hash, limit).map((observation) => ({
760
+ ts: getString(observation.ts),
761
+ tool: getString(observation.tool),
762
+ input_summary: getString(observation.input_summary),
763
+ output_summary: getString(observation.output_summary),
764
+ }));
765
+ const report = scoreObservations(goalObservations, goal, { window: limit });
766
+ return text(`## Goal Check\n\n**Goal source:** ${goalSource}\n\n${formatDriftReport(report)}`);
767
+ }
768
+ case "ci_recall": {
769
+ if (MODE !== "expert") {
770
+ return error("ci_recall requires expert mode");
771
+ }
772
+ const queryString = getString(params.query).trim();
773
+ if (!queryString) {
774
+ return error("query is required");
775
+ }
776
+ const k = getNumber(params.k, 5);
777
+ const since = getString(params.since).trim();
778
+ if (since && parseSince(since, Date.now()) === null) {
779
+ return error(`Could not parse since="${since}". Use an ISO timestamp (e.g. 2026-05-01) or a relative window like 7d, 24h, or 30m.`);
780
+ }
781
+ // Recall searches the full history, not just the recent window.
782
+ const recallObservations = getRecentObservations(project.hash, 100000).map((observation) => ({
783
+ ts: getString(observation.ts),
784
+ session: getString(observation.session),
785
+ session_id: getString(observation.session_id),
786
+ tool: getString(observation.tool),
787
+ input_summary: getString(observation.input_summary),
788
+ output_summary: getString(observation.output_summary),
789
+ }));
790
+ if (recallObservations.length === 0) {
791
+ return text("No observations yet. Hooks capture tool calls automatically; recall searches that history.");
792
+ }
793
+ const index = buildIndex(recallObservations);
794
+ const hits = queryRecall(index, queryString, { k, since: since || undefined });
795
+ return text(formatRecallHits(hits, queryString));
796
+ }
797
+ case "ci_distill_candidates": {
798
+ if (MODE !== "expert") {
799
+ return error("ci_distill_candidates requires expert mode");
800
+ }
801
+ const distillObservations = readDistillObservations(project.hash);
802
+ const candidates = findCandidates(extractTrajectories(distillObservations));
803
+ return text(formatCandidates(candidates));
804
+ }
805
+ case "ci_distill_propose": {
806
+ if (MODE !== "expert") {
807
+ return error("ci_distill_propose requires expert mode");
808
+ }
809
+ const id = getString(params.id).trim();
810
+ if (!id) {
811
+ return error("id is required — run ci_distill_candidates to list current candidate ids");
812
+ }
813
+ if (!isSafeDraftId(id)) {
814
+ return error(`Invalid draft id "${id}". Draft ids look like draft-<slug> (lowercase letters, digits, hyphens).`);
815
+ }
816
+ const distillObservations = readDistillObservations(project.hash);
817
+ const candidate = findCandidates(extractTrajectories(distillObservations)).find((entry) => entry.id === id);
818
+ if (!candidate) {
819
+ return error(`No candidate "${id}". Run ci_distill_candidates to list current ids.`);
820
+ }
821
+ const draft = serializeDraft(draftFromCandidate(candidate));
822
+ const draftsDir = join(INSTINCTS_DIR, project.hash, "drafts");
823
+ mkdirSync(draftsDir, { recursive: true });
824
+ const draftPath = join(draftsDir, `${id}.yaml`);
825
+ writeFileSync(draftPath, draft);
826
+ return text([
827
+ "## Draft written",
828
+ "",
829
+ `**Path:** ${draftPath}`,
830
+ "",
831
+ "Edit the body to capture the real recipe (preconditions, concrete steps, gotchas), then promote with:",
832
+ "",
833
+ ` ci_distill_promote id=${id}`,
834
+ "",
835
+ "```yaml",
836
+ draft.trimEnd(),
837
+ "```",
838
+ ].join("\n"));
839
+ }
840
+ case "ci_distill_promote": {
841
+ if (MODE !== "expert") {
842
+ return error("ci_distill_promote requires expert mode");
843
+ }
844
+ const id = getString(params.id).trim();
845
+ if (!id) {
846
+ return error("id is required");
847
+ }
848
+ if (!isSafeDraftId(id)) {
849
+ return error(`Invalid draft id "${id}". Draft ids look like draft-<slug> (lowercase letters, digits, hyphens).`);
850
+ }
851
+ const draftPath = join(INSTINCTS_DIR, project.hash, "drafts", `${id}.yaml`);
852
+ if (!existsSync(draftPath)) {
853
+ return error(`No draft at ${draftPath}. Run ci_distill_propose id=${id} first.`);
854
+ }
855
+ let parsed = null;
856
+ try {
857
+ parsed = parseYamlInstinct(readFileSync(draftPath, "utf8"));
858
+ }
859
+ catch {
860
+ parsed = null;
861
+ }
862
+ if (!parsed) {
863
+ return error(`Draft ${draftPath} could not be parsed as an instinct. Check the YAML shape.`);
864
+ }
865
+ const promoted = {
866
+ ...parsed,
867
+ confidence: 0.5,
868
+ source: "distilled",
869
+ scope: "project",
870
+ observation_count: 1,
871
+ };
872
+ writeInstinct(project.hash, promoted);
873
+ try {
874
+ rmSync(draftPath);
875
+ }
876
+ catch {
877
+ // best-effort cleanup; the live instinct is already written
878
+ }
879
+ return text(`Promoted **${promoted.id}** to a project instinct at confidence ${promoted.confidence} (SUGGEST tier). The draft has been consumed.`);
880
+ }
668
881
  case "ci_dashboard": {
669
882
  if (MODE !== "expert") {
670
883
  return error("ci_dashboard requires expert mode");
File without changes
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: audit
3
+ description: Audit a window of recent commits for real defects, confirm each finding before fixing, verify every surface a fix touches, then report confirmed/dismissed/no-op with evidence. Enforces Law 4 (Verify Before Reporting).
4
+ ---
5
+
6
+ # /audit — Confirm Recent Commits Before You Trust Them
7
+
8
+ Run the audit-driven loop over recent work: a merged commit with green CI is a claim, not a proof.
9
+
10
+ ## What it does
11
+
12
+ Takes a commit window, hunts for real defects one concern at a time, proves each finding against the actual code (false positives die before any edit), fixes on a branch with the smallest diff, verifies every surface the fix touches, and reports honestly. Backed by the `audit` skill.
13
+
14
+ ## The loop
15
+
16
+ ```
17
+ 1. Scope git log to pick the window (e.g. HEAD~10..HEAD, or main since last release)
18
+ 2. Find one pass per dimension: value/economy drift, concurrency, surface coverage, type/contract
19
+ 3. Confirm read the actual lines; state in one sentence why it is real, or dismiss it
20
+ 4. Fix one concern per commit; prefer a failing test first, then green
21
+ 5. Verify exercise EVERY surface (backend, frontend, admin, cache, migration), not just the edited one
22
+ 6. Report confirmed (with the proof), dismissed (with why), no-op (in scope, nothing to change)
23
+ ```
24
+
25
+ ## Default skeptical
26
+
27
+ Findings are hypotheses. Default each to a false positive until the code proves the bug — defaulting to "real" is how plausible-but-wrong fixes ship. For a thorough audit, fan the find pass out across dimensions with parallel reviewers, then verify each survivor adversarially.
28
+
29
+ ## Pairs with
30
+
31
+ - **`audit`** skill — the discipline this command runs.
32
+ - **`code-review`** / **`security-review`** — the per-dimension passes.
33
+ - **`reconcile`** — the safe branch→PR path once the audit produces a fix.
34
+ - **`recall`** — check whether a finding was already hit and fixed before.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: companion-preference
3
+ description: Inspect companion-preference hook telemetry — counts by CI skill, action breakdown, and companion-installed%.
4
+ ---
5
+
6
+ # /companion-preference
7
+
8
+ Read and aggregate the JSONL telemetry written by `hooks/companion-preference.mjs`. Reports per-skill totals, action breakdown (`observation`, `advisory`, `block`, `block-not-installed`), and the share of events where the companion plugin was installed at the time.
9
+
10
+ The dataset is the evidence base for a future `companions-first` default-flip decision — once a 7-day shadow shows the `companions-first` path firing on a meaningful share of routed Skill calls, with companions installed in the majority of them, the flip is grounded.
11
+
12
+ ## Trigger phrases
13
+
14
+ - `/companion-preference`
15
+ - `/companion-preference status`
16
+ - "show companion preference stats"
17
+ - "what does the companion-preference hook see"
18
+
19
+ ## What happens
20
+
21
+ 1. Run `node bin/companion-preference-status.mjs` from the repo root with the operator's chosen window. Default `--days 7`. Pass `--all` for the entire file or `--days N` for a different window.
22
+ 2. Render the table the CLI emits to the user verbatim. Do not paraphrase the numbers — the JSONL is authoritative.
23
+ 3. If the CLI prints "no telemetry recorded yet," check three things in order: (a) `~/.claude/settings.json` has `continuous_improvement.companion_preference` set (otherwise the hook is a no-op and writes nothing); (b) the user has invoked at least one mapped CI skill (`tdd-workflow`, `verification-loop`, `context-budget`, `ralph`, `learn-eval`) since the hook landed; (c) the hook's PreToolUse registration is intact in `plugins/continuous-improvement/hooks/hooks.json`.
24
+ 4. Offer one decision-ready next step based on the totals — e.g., "ratio of `observation` rows with `companion_installed=true` suggests `companions-first` is safe to flip for X but not Y."
25
+
26
+ ## Subcommands
27
+
28
+ ### `/companion-preference status` (default)
29
+
30
+ Same as `/companion-preference`.
31
+
32
+ ### `/companion-preference status --json`
33
+
34
+ Emit the machine-readable JSON report. Useful when you want to pipe the output into another tool or write your own aggregator.
35
+
36
+ ```bash
37
+ node bin/companion-preference-status.mjs --json --all
38
+ ```
39
+
40
+ ## CLI flags
41
+
42
+ | Flag | Effect |
43
+ |---|---|
44
+ | `--days N` | Only count events from the last N days (default 7). |
45
+ | `--all` | Ignore the window; count every row in the file. |
46
+ | `--json` | Emit a machine-readable JSON report. |
47
+ | `--path <file>` | Override the default JSONL path. Used by the test suite; rarely needed in practice. |
48
+ | `-h`, `--help` | Print CLI help and exit. |
49
+
50
+ ## Path resolution
51
+
52
+ By default the CLI reads `~/.claude/instincts/<project-hash>/companion-preference.jsonl`, where the hash is the same `sha256(projectRoot).slice(0, 12)` that the hook itself uses. The project root resolves via `CLAUDE_PROJECT_DIR` env var if set, else `git rev-parse --show-toplevel`, else the literal `"global"`. Hash and path scheme are reused verbatim from `hooks/companion-preference.mjs` to keep the read side aligned with the write side.
53
+
54
+ ## Companion skills
55
+
56
+ - `hooks/companion-preference.mjs` — the writer that produces the JSONL this command reads.
57
+ - `skills/superpowers.md` § "Companion-Preference Override" — the broader contract for the setting this command's dataset measures.
58
+ - `commands/dashboard.md` — the broader continuous-improvement status surface; this command is the dispatcher-bias-specific narrower view.
@@ -33,6 +33,20 @@ The Laws above are the *how*. These five principles are the *why*: code ships fr
33
33
 
34
34
  Code is a liability, not an asset. Speed without these five turns into someone else's incident at 3am — except the someone is you.
35
35
 
36
+ ## Goal-Driven Execution maps onto the Laws
37
+
38
+ "Goal-Driven Execution" is the operator's global principle #4 — tie every change to a stated goal, refuse scope creep, stop when the goal is met. It is not a separate Law here; it is the spine of four existing Laws:
39
+
40
+ | Sub-rule of Goal-Driven Execution | Lives in |
41
+ |---|---|
42
+ | Tie work to a stated goal; if none, ask | Law 2 — the `## Goal` in `task_plan.md` is the single source of truth |
43
+ | Catch drift away from that goal mid-session | Law 2 — the `goal-monitor` skill / `/goal-check` scores recent activity against the goal |
44
+ | Finish one thing; refuse "while I'm here" scope creep | Law 3 |
45
+ | Commit messages lead with the outcome, not the mechanism | Law 4 — "done" is an observed outcome |
46
+ | Iterate one change at a time toward the goal | Law 6 |
47
+
48
+ The `goal-monitor` primitive (`/goal-check`, `ci_goal_check`) is the measurable arm of this principle: it reads the `## Goal` section and reports ON GOAL / DRIFT / NO DATA. Run it at phase boundaries to confirm the work and the plan still agree.
49
+
36
50
  ## The Loop
37
51
 
38
52
  ```
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: distill
3
+ description: Distill repeated successful tool sequences from the observation log into reusable draft instincts, with an explicit propose-edit-promote ladder. Enforces Law 7 (Learn From Every Session).
4
+ ---
5
+
6
+ # /distill — Trajectory Distillation
7
+
8
+ Mine this project's observation log for tool sequences that recurred across multiple successful sessions, and turn the good ones into reusable instincts.
9
+
10
+ ## What it does
11
+
12
+ Groups observations into trajectories, keeps the ones that ended in a passing verification, and finds tool-sequence n-grams that recurred across distinct sessions. Backed by the `ci_distill_candidates` / `ci_distill_propose` / `ci_distill_promote` MCP tools (expert mode) and the `skill-distillation` skill.
13
+
14
+ ## The ladder
15
+
16
+ ```
17
+ ci_distill_candidates # list patterns that qualify (read-only)
18
+ ci_distill_propose id=<id> # write a DRAFT (placeholder body) to drafts/<id>.yaml
19
+ # ... edit the draft body to capture the real recipe ...
20
+ ci_distill_promote id=<id> # promote to a live instinct at 0.5 confidence (SUGGEST)
21
+ ```
22
+
23
+ Drafts never affect behavior until promoted. The draft starts at 0.4 confidence in a `drafts/` subdirectory the instinct loader ignores; promotion writes a live instinct at 0.5 (SUGGEST tier).
24
+
25
+ ## Candidate criteria
26
+
27
+ - The trajectory must have ended in success (`verify-exit-0` or `reflection-pass`).
28
+ - The tool sequence must have recurred at least 3 times across at least 2 distinct sessions.
29
+ - A pattern repeated only within one session is rejected — that is repetition, not a reusable skill.
30
+
31
+ ## Why the human edit step
32
+
33
+ A tool sequence is evidence, not a recipe. `Read → Edit → Bash → Edit → Bash` is a TDD loop, but the value is in the preconditions and concrete steps. Editing the draft body before promotion is the guard against fabricating confident skills from coincidental call ordering.
34
+
35
+ ## Pairs with
36
+
37
+ - **`skill-distillation`** skill — the discipline this command runs.
38
+ - **`continuous-improvement`** (core SKILL.md, Law 7 — Learn From Every Session).
39
+ - **`recall`** — before promoting, check whether an existing instinct already covers the pattern.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: goal-check
3
+ description: Check whether recent tool activity still relates to the stated goal in task_plan.md, reporting a drift score and the top off-goal tool calls. Enforces Law 2 (Plan Is Sacred).
4
+ ---
5
+
6
+ # /goal-check — Goal Drift Check
7
+
8
+ Score this session's recent tool activity against the stated goal and report whether the work is still ON GOAL or has DRIFTed.
9
+
10
+ ## What it does
11
+
12
+ Reads the `## Goal` section of `task_plan.md` (plus optional `## Goal Keywords` and `## Goal Scope` sections), scores the most recent observations from `~/.claude/instincts/<project-hash>/observations.jsonl`, and reports a drift score with the top off-goal tool calls. Backed by the `ci_goal_check` MCP tool (expert mode) and the `goal-monitor` skill.
13
+
14
+ ## How to invoke
15
+
16
+ ```
17
+ ci_goal_check # last 30 observations vs task_plan.md
18
+ ci_goal_check limit=50 # widen the observation window
19
+ ci_goal_check goal_file=docs/x.md # score against a specific plan file
20
+ ```
21
+
22
+ Goal source resolution order: `task_plan.md` in the project root, then `~/.claude/instincts/<project-hash>/goal.md`, then an explicit `goal_file`.
23
+
24
+ ## Output shape
25
+
26
+ ```
27
+ ## Goal Check
28
+
29
+ **Goal source:** /home/me/repo/task_plan.md
30
+
31
+ **Status:** DRIFT
32
+ **Score:** 12% (1/8 matched, threshold 30%)
33
+ **Reason:** Only 1/8 recent observations relate to the goal (threshold 0.3).
34
+ **Goal keywords:** oauth, jwt, login, session
35
+
36
+ **Top off-goal activity (most recent 5):**
37
+ - [2026-05-28T12:01:00Z] Edit — src/marketing/landing.ts
38
+ - ...
39
+
40
+ _Drift detected. Either steer back to the goal, or update the `## Goal` section in your plan if the goal has legitimately changed._
41
+ ```
42
+
43
+ ## Acting on the result
44
+
45
+ - **ON GOAL** — the plan and the work agree; proceed.
46
+ - **DRIFT** — steer back to the goal, or update `## Goal` if it has legitimately changed. Keeping the plan and the work in disagreement is the Law 2 violation this command catches.
47
+ - **NO DATA** — the observation window is still filling; keep working.
48
+
49
+ ## Pairs with
50
+
51
+ - **`goal-monitor`** skill — the discipline this command runs.
52
+ - **`continuous-improvement`** (core SKILL.md, Law 2 — Plan Is Sacred).
53
+ - **`planning-with-files`** — creates the `task_plan.md` whose `## Goal` section this command reads.
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: grill-me
3
+ description: "Interview the user relentlessly about a plan or design until shared understanding is reached. Ported from mattpocock/skills under MIT."
4
+ ---
5
+
6
+ # /grill-me
7
+
8
+ Stress-test the current plan or design by interviewing the user one question at a time, walking every branch of the decision tree, and recommending an answer for each.
9
+
10
+ ## Trigger phrases
11
+
12
+ - `/grill-me`
13
+ - "grill me"
14
+ - "stress-test this plan"
15
+ - "interview me about this"
16
+ - "what am I missing?"
17
+
18
+ ## What happens
19
+
20
+ 1. Identify the current plan or design from the conversation — the high-level goal, the assumptions in play, the decisions already made.
21
+ 2. Walk the decision tree top-down. For each unresolved branch, ask exactly **one question** with a **recommended answer**.
22
+ 3. Before asking, check whether the codebase already answers the question (`grep`, `ls`, file reads). If it does, use that and skip the question.
23
+ 4. Resolve dependencies in order — do not ask about deployment before the data model is pinned.
24
+ 5. Stop when the plan is shippable cold to a fresh agent. Do not interview past the point of usefulness.
25
+
26
+ ## Five interview rules
27
+
28
+ 1. **One question at a time.** Never multi-question; force depth on every branch.
29
+ 2. **Always recommend.** Every question carries "my answer would be X because Y".
30
+ 3. **Explore before asking.** Code answers beat user-attention answers.
31
+ 4. **Walk the tree, do not jump.** Order matters.
32
+ 5. **Stop when shippable.** End state is a plan a fresh agent could execute, not an infinite interview.
33
+
34
+ ## Skill file
35
+
36
+ Full behavior is defined in [`skills/grill-me.md`](../skills/grill-me.md). The verbatim upstream cold-storage copy lives at [`third-party/mattpocock-skills/skills/productivity/grill-me/SKILL.md`](../third-party/mattpocock-skills/skills/productivity/grill-me/SKILL.md); SHA pin in [`third-party/MANIFEST.md`](../third-party/MANIFEST.md).
37
+
38
+ ## Attribution
39
+
40
+ Ported from [mattpocock/skills `productivity/grill-me`](https://github.com/mattpocock/skills/blob/main/skills/productivity/grill-me/SKILL.md) (MIT, © 2026 Matt Pocock).
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: grill-with-docs
3
+ description: "Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates CONTEXT.md + ADRs inline as decisions crystallise. Ported from mattpocock/skills under MIT."
4
+ ---
5
+
6
+ # /grill-with-docs
7
+
8
+ Stress-test the current plan or design by interviewing the user one question at a time AND updating the project's domain-language doc (`CONTEXT.md`) and architecture decision records (`docs/adr/`) inline as decisions land.
9
+
10
+ ## Trigger phrases
11
+
12
+ - `/grill-with-docs`
13
+ - "grill me and update the docs"
14
+ - "stress-test this against our domain model"
15
+ - "let's nail down the language and ADR this"
16
+
17
+ ## What happens
18
+
19
+ 1. Read `CONTEXT.md` (or `CONTEXT-MAP.md` + per-context `CONTEXT.md`) and `docs/adr/` if they exist. Use them as the source of truth for project language and prior decisions.
20
+ 2. Walk the decision tree top-down. One question at a time with a recommended answer.
21
+ 3. Challenge fuzzy terms against the glossary. Sharpen vague language. Stress-test relationships with concrete scenarios. Cross-reference user statements against the code.
22
+ 4. When a term is resolved, update `CONTEXT.md` immediately (lazy-create if missing). Use the format in the skill's Appendix A.
23
+ 5. Offer an ADR only when all three are true: hard to reverse, surprising without context, result of a real trade-off. Use the format in Appendix B.
24
+
25
+ ## When to fire this instead of `/grill-me`
26
+
27
+ | Skill | Use when |
28
+ |---|---|
29
+ | `/grill-me` | Conversation-only grilling; no project to update yet, or no docs convention. |
30
+ | `/grill-with-docs` | Project has `CONTEXT.md` or is ready to start one; decisions should persist past the session. |
31
+
32
+ ## Skill file
33
+
34
+ Full behavior, format specs, and 7 Laws fit are defined in [`skills/grill-with-docs.md`](../skills/grill-with-docs.md). The verbatim upstream cold-storage copies live at [`third-party/mattpocock-skills/skills/engineering/grill-with-docs/`](../third-party/mattpocock-skills/skills/engineering/grill-with-docs/) (`SKILL.md`, `CONTEXT-FORMAT.md`, `ADR-FORMAT.md`); SHA pin in [`third-party/MANIFEST.md`](../third-party/MANIFEST.md).
35
+
36
+ ## Attribution
37
+
38
+ Ported from [mattpocock/skills `engineering/grill-with-docs`](https://github.com/mattpocock/skills/blob/main/skills/engineering/grill-with-docs/SKILL.md) (MIT, © 2026 Matt Pocock). Mattpocock calls this his most powerful skill: "It's hard to explain how powerful this is. It might be the single coolest technique in this repo."
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: handoff
3
+ description: "Compact the current conversation into a handoff document for another agent to pick up. Ported from mattpocock/skills under MIT."
4
+ argument-hint: "What will the next session be used for?"
5
+ ---
6
+
7
+ # /handoff
8
+
9
+ Hand the current session off to a fresh agent by writing a brief, mktemp-backed markdown summary they can pick up cold.
10
+
11
+ ## Trigger phrases
12
+
13
+ - `/handoff`
14
+ - `/handoff <what the next session will focus on>`
15
+ - "write a handoff doc"
16
+ - "compact this into a handoff"
17
+
18
+ ## What happens
19
+
20
+ 1. Read the current conversation (and the user's argument, if given) to identify the goal, current state, decisions made, open questions, next concrete step, and skills to load.
21
+ 2. Generate a unique path with `mktemp -t handoff-XXXXXX.md` and read it (it will be empty).
22
+ 3. Write the handoff doc to that path. Reference PRDs, plans, ADRs, issues, commits, and diffs by path or URL — do not duplicate their content.
23
+ 4. Suggest the skills the next session should load.
24
+
25
+ ## What goes in the doc
26
+
27
+ A one-screen brief, in this order:
28
+
29
+ 1. **Goal** — one sentence on the outcome the user is steering toward.
30
+ 2. **Current state** — what is actually true on disk / in the system right now.
31
+ 3. **Decisions made this session** — only what is not already captured in commits or other artifacts.
32
+ 4. **Open questions** — blocking choices the next agent needs the user to answer.
33
+ 5. **Next concrete step** — the single action the next agent should take first.
34
+ 6. **Skills to load** — names of the skills the next session should activate.
35
+
36
+ ## Skill file
37
+
38
+ Full behavior is defined in [`skills/handoff.md`](../skills/handoff.md). The verbatim upstream cold-storage copy lives at [`third-party/mattpocock-skills/skills/in-progress/handoff/SKILL.md`](../third-party/mattpocock-skills/skills/in-progress/handoff/SKILL.md); SHA pin in [`third-party/MANIFEST.md`](../third-party/MANIFEST.md).
39
+
40
+ ## Attribution
41
+
42
+ Ported from [mattpocock/skills `in-progress/handoff`](https://github.com/mattpocock/skills/blob/main/skills/in-progress/handoff/SKILL.md) (MIT, © 2026 Matt Pocock).
@@ -18,6 +18,26 @@ Invoke immediately after the agent has offered a numbered list of recommendation
18
18
  - "execute the recommendations"
19
19
  - "yes do it" / "all of them"
20
20
 
21
+ ## Fast-path: `--once` mode
22
+
23
+ For a single-item, `safe`-tagged confirmation, append `--once` to skip P-MAG, Plan, Reflect, and the three-section close. Runs Phase 1 + Phase 3 + Phase 4 only and ends with one line: `Done: <item>. Verified: <check + output>.`
24
+
25
+ Trigger phrases:
26
+
27
+ - `/proceed-with-the-recommendation --once`
28
+ - `/proceed --once`
29
+ - "proceed once with that" / "just do that one"
30
+ - Any standard trigger phrase plus the literal `--once` suffix
31
+
32
+ Hard preconditions (the skill refuses `--once` and falls back to the full flow if any fail):
33
+
34
+ - Recommendation list has exactly one item
35
+ - Item is tagged `safe` (not `caution`, not `needs-approval`)
36
+ - Item touches ≤3 files, ≤150 LOC, and none of `.github/`, `bin/`, `lib/`, `src/`, `third-party/`
37
+ - Item is not destructive (no deploy, force-push, DB drop, secret rotation)
38
+
39
+ Full behavior is defined in [`skills/proceed-with-the-recommendation.md`](../skills/proceed-with-the-recommendation.md) under § "Fast-Path: `--once` Mode".
40
+
21
41
  ## What happens
22
42
 
23
43
  1. **Pre-flight (Law 1)** — restate the recommendation list in original order, tag each `safe` / `caution` / `needs-approval`