continuous-improvement 3.16.0 → 3.18.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 (33) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +165 -100
  4. package/bin/audit-actions.mjs +433 -0
  5. package/bin/check-command-count.mjs +114 -0
  6. package/bin/portfolio-health.mjs +298 -0
  7. package/commands/intent-driven-development.md +36 -0
  8. package/commands/reconcile.md +34 -7
  9. package/hooks/gateguard.mjs +137 -3
  10. package/lib/gateguard-state.mjs +5 -1
  11. package/lib/plugin-metadata.mjs +1 -1
  12. package/llms.txt +1 -1
  13. package/package.json +12 -6
  14. package/plugins/beginner.json +1 -1
  15. package/plugins/continuous-improvement/.claude-plugin/marketplace.json +2 -2
  16. package/plugins/continuous-improvement/.claude-plugin/plugin.json +2 -2
  17. package/plugins/continuous-improvement/commands/intent-driven-development.md +36 -0
  18. package/plugins/continuous-improvement/commands/reconcile.md +34 -7
  19. package/plugins/continuous-improvement/hooks/gateguard.mjs +137 -3
  20. package/plugins/continuous-improvement/lib/gateguard-state.mjs +5 -1
  21. package/plugins/continuous-improvement/lib/plugin-metadata.mjs +1 -1
  22. package/plugins/continuous-improvement/skills/README.md +2 -1
  23. package/plugins/continuous-improvement/skills/gateguard/SKILL.md +10 -0
  24. package/plugins/continuous-improvement/skills/intent-driven-development/SKILL.md +161 -0
  25. package/plugins/continuous-improvement/skills/reconcile/SKILL.md +52 -4
  26. package/plugins/expert.json +1 -1
  27. package/skills/gateguard.md +10 -0
  28. package/skills/intent-driven-development.md +161 -0
  29. package/skills/reconcile.md +52 -4
  30. package/templates/actions_security_checklist.md +39 -0
  31. package/templates/experiment_template.md +38 -0
  32. package/templates/portfolio_event.schema.json +69 -0
  33. package/templates/release_receipt_template.md +37 -0
package/package.json CHANGED
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.16.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 26 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.18.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.",
5
5
  "keywords": [
6
6
  "claude-code",
7
+ "claude-code-plugin",
7
8
  "claude-code-skill",
9
+ "claude",
10
+ "anthropic",
8
11
  "ai-agent",
12
+ "ai-agents",
9
13
  "agent-skill",
10
14
  "ai-discipline",
11
15
  "mulahazah",
12
- "instinct",
16
+ "instinct-learning",
13
17
  "hooks",
14
18
  "mcp",
15
- "mcp-server",
16
19
  "github-action",
17
20
  "transcript-linter"
18
21
  ],
@@ -30,7 +33,9 @@
30
33
  "continuous-improvement": "bin/install.mjs",
31
34
  "ci-lint-transcript": "bin/lint-transcript.mjs",
32
35
  "ci": "bin/unified-cli.mjs",
33
- "ci-plan-pack": "bin/plan-pack.mjs"
36
+ "ci-plan-pack": "bin/plan-pack.mjs",
37
+ "ci-audit-actions": "bin/audit-actions.mjs",
38
+ "ci-portfolio-health": "bin/portfolio-health.mjs"
34
39
  },
35
40
  "scripts": {
36
41
  "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); } \"",
@@ -45,6 +50,7 @@
45
50
  "verify:skill-law-tag": "node bin/check-skill-law-tag.mjs",
46
51
  "verify:skill-count": "node bin/check-skill-count.mjs",
47
52
  "verify:skill-count-prose": "node bin/check-skill-count-prose.mjs",
53
+ "verify:command-count": "node bin/check-command-count.mjs",
48
54
  "verify:docs-substrings": "node bin/check-docs-substrings.mjs",
49
55
  "verify:everything-mirror": "node bin/check-everything-mirror.mjs",
50
56
  "verify:routing-targets": "node bin/check-routing-targets.mjs",
@@ -53,7 +59,7 @@
53
59
  "verify:scripts-citation-drift": "node bin/check-scripts-citation-drift.mjs",
54
60
  "verify:third-party-shape": "node bin/check-third-party-shape.mjs",
55
61
  "verify:tool-count": "node bin/check-tool-count.mjs",
56
- "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: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"
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"
57
63
  },
58
64
  "files": [
59
65
  ".claude-plugin/",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.16.0",
3
+ "version": "3.18.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 26 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.16.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 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.18.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.16.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 26 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.18.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.",
5
5
  "author": {
6
6
  "name": "naimkatiman",
7
7
  "url": "https://github.com/naimkatiman"
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: intent-driven-development
3
+ description: "Turn an ambiguous or high-impact change into scoped, verifiable acceptance criteria (observable AC-NNN, explicit scope, named verification methods, and a [revised] protocol that forbids silently dropping a criterion) before or alongside implementation. Enforces Law 2 (Plan Is Sacred)."
4
+ argument-hint: "[the change to scope into acceptance criteria]"
5
+ ---
6
+
7
+ # /intent-driven-development
8
+
9
+ Convert an ambiguous or high-impact request into observable acceptance criteria before you build, so "done" is a fact two people would agree on and the agreed plan is held sacred (Law 2). Produce useful criteria without ceremony: inspect context first, expose only genuine ambiguity, choose verification that fits the risk.
10
+
11
+ ## Trigger phrases
12
+
13
+ - `/intent-driven-development`
14
+ - `/intent-driven-development <the change>`
15
+ - "define acceptance criteria"
16
+ - "scope this change" / "make this testable"
17
+ - "de-risk this before we build it"
18
+ - "prepare implementation requirements for another agent"
19
+
20
+ Do not trigger for trivial edits, one-line fixes, active debugging, code review, or requests whose acceptance conditions are already clear.
21
+
22
+ ## What happens
23
+
24
+ 1. **Inspect and scope.** Read the repo, docs, schemas, and tests for technical facts before asking. Capture product or business constraints only from the user or a product artifact, never inferred from code.
25
+ 2. **Choose depth.** Quick Capture (3-7 criteria, low or moderate risk) or Full Acceptance Brief (security, data, migration, cross-system, or handoff).
26
+ 3. **Write criteria.** Each `AC-NNN` names a scenario, a trigger, an expected observable result, a prohibited side effect when meaningful, a verification method, and a priority. No vague words without defined evidence.
27
+ 4. **Proceed or hand off.** Record the criteria and continue for a clear request; present blockers and wait when a change is risky. If a criterion cannot be met mid-build, mark it `[revised]`, increment the revision, and re-present only the changed criteria.
28
+
29
+ ## Skill file
30
+
31
+ Full behavior is defined in [`skills/intent-driven-development.md`](../skills/intent-driven-development.md).
32
+
33
+ ## Pairs with
34
+
35
+ - `/grill-me`: grill-me clarifies a fuzzy input; this skill turns the agreed intent into verifiable criteria.
36
+ - `/roast`: roast validates the idea, then scope the survivor into acceptance criteria.
@@ -1,22 +1,22 @@
1
1
  ---
2
2
  name: reconcile
3
- description: Establish git ground truth (branch, status, stashes, worktrees, ahead/behind) before any mutation, halt on protected or destructive operations, and verify a push actually landed. Enforces Law 1 (Research Before Executing).
3
+ description: Establish git ground truth (branch, status, stashes, worktrees, ahead/behind) before any mutation, halt on protected or destructive operations, then carry the known-good state through a single-concern commit, a push, an open PR, and — after the PR merges — a fast-forward of the default branch. Enforces Law 1 (Research Before Executing).
4
4
  ---
5
5
 
6
- # /reconcile — Ground-Truth Git State Before You Touch It
6
+ # /reconcile — Ground Truth, Then Commit, Push, and Open the PR
7
7
 
8
- Read the repo's real state before acting on it: a branch that shifted, a push that did not land, or another session mid-merge will burn a whole session if you assume instead of check.
8
+ Read the repo's real state before acting on it: a branch that shifted, a push that did not land, or another session mid-merge will burn a whole session if you assume instead of check. Once the state is known, `/reconcile` carries the work through to an open PR and back to an up-to-date default branch.
9
9
 
10
10
  ## What it does
11
11
 
12
- Snapshots the full git state in one pass, detects a concurrent writer, classifies the upstream relationship, then acts only on the known state — stopping at every operation that is hard to reverse. Backed by the `reconcile` skill.
12
+ Snapshots the full git state in one pass, detects a concurrent writer, classifies the upstream relationship, then acts only on the known state — stopping at every operation that is hard to reverse. When work is ready, it stages by filename, commits one concern, pushes a feature branch, verifies the push landed, and opens a PR. After a human merges, it fast-forwards the default branch and checks it out. Backed by the `reconcile` skill.
13
13
 
14
14
  ## Establish ground truth
15
15
 
16
16
  ```
17
17
  git branch --show-current
18
18
  git status --porcelain=v1 # but trust git diff --stat for real drift (autocrlf)
19
- git rev-list --left-right --count @{u}...HEAD # behind / ahead
19
+ git rev-list --left-right --count '@{u}...HEAD' # behind / ahead (quote the ref — bare @{u} trips the Bash parser)
20
20
  git stash list
21
21
  git worktree list
22
22
  ls .git/MERGE_HEAD .git/rebase-merge .git/rebase-apply 2>/dev/null # in-progress op = another actor; do not race
@@ -31,7 +31,22 @@ behind -> git pull --ff-only
31
31
  diverged -> rebase/merge deliberately; never blind --force
32
32
  ```
33
33
 
34
- STOP for authorization before: pushing to a protected branch (this repo = feature branch + PR, never direct push to main), `--force` / `--force-with-lease`, `reset --hard`, `clean -fd`, or removing a dirty worktree. Never stage with `git add -A` on a Windows autocrlf tree (it commits phantom line-ending-only changes) — stage by explicit filename.
34
+ STOP for authorization before: pushing to a protected branch (this repo = feature branch + PR, never direct push to main), merging the PR you opened, `--force` / `--force-with-lease`, `reset --hard`, `clean -fd`, force-deleting a branch (`branch -D`), or removing a dirty worktree. Never stage with `git add -A` on a Windows autocrlf tree (it commits phantom line-ending-only changes) — stage by explicit filename.
35
+
36
+ ## Commit and open the PR (self-contained)
37
+
38
+ Reimplements the commit → push → PR tail inline, so it works with no companion plugin installed:
39
+
40
+ ```
41
+ git switch main && git pull --ff-only origin main # branch from a fresh base
42
+ git switch -c <type>/<slug> # only if not already on a feature branch
43
+ git add path/one path/two # stage by name, one concern
44
+ git commit -m "feat(scope): <observable outcome>" # single-line -m; never a multi-line here-doc on Windows
45
+ git push -u origin <type>/<slug>
46
+ gh pr create --fill --base main # open one PR, then STOP — the merge is a human decision
47
+ ```
48
+
49
+ `/reconcile` never merges the PR, never uses `--admin` / `--force` / `--no-verify`, never auto-merges on green CI, and never deploys.
35
50
 
36
51
  ## Verify the push landed
37
52
 
@@ -39,9 +54,21 @@ STOP for authorization before: pushing to a protected branch (this repo = featur
39
54
  git ls-remote origin refs/heads/<branch> # remote tip must equal local HEAD, else it did not land
40
55
  ```
41
56
 
57
+ ## Sync the default branch after the PR merges
58
+
59
+ "Latest work on main" is true only once the PR merges, and on a protected branch that merge is a human action. After it lands:
60
+
61
+ ```
62
+ git switch main # or master
63
+ git pull --ff-only origin main # fast-forward only; if it will not ff, main diverged — re-survey, do not force
64
+ git rev-parse HEAD # confirm this equals the squash-merge SHA
65
+ git branch -d <type>/<slug> # delete the merged feature branch (safe -d, never -D)
66
+ ```
67
+
42
68
  ## Pairs with
43
69
 
44
70
  - **`reconcile`** skill — the discipline this command runs.
45
71
  - **`gateguard`** / **`safety-guard`** — runtime + destructive-op guardrails.
46
72
  - **`recall`** — recall whether the same git op failed here before.
47
- - **`audit`** — the loop that often produces the fix `reconcile` then ships.
73
+ - **`audit`** — the loop that often produces the fix `/reconcile` then ships.
74
+ - **`/ship`** — the TDD-gated single-defect variant; `commit-commands:commit-push-pr` is the external-plugin equivalent of the commit → PR tail.
@@ -35,7 +35,7 @@
35
35
  import { readFileSync } from "node:fs";
36
36
  import { dirname, join } from "node:path";
37
37
  import { fileURLToPath } from "node:url";
38
- import { MAX_CLEARED_FILES, canonicalizeFileKey, isCapReached, isFileCleared, loadState, markFileCleared, resolveSessionDir, saveState, } from "../lib/gateguard-state.mjs";
38
+ import { MAX_CLEARED_FILES, canonicalizeFileKey, canonicalizeProjectRoot, isCapReached, isFileCleared, loadState, markFileCleared, resolveProjectRoot, resolveSessionDir, saveState, } from "../lib/gateguard-state.mjs";
39
39
  const TOOL_ROUTE = {
40
40
  Read: "allow",
41
41
  Grep: "allow",
@@ -69,8 +69,20 @@ const DESTRUCTIVE_PATTERNS = [
69
69
  "Remove-Item -Recurse",
70
70
  "Remove-Item -Force",
71
71
  ];
72
+ // Flags whose VALUE is human prose (a commit message, a PR body) or a filename —
73
+ // never a command to execute. Their contents must not trip the destructive scan:
74
+ // `git commit -m "drop the stale format helper"` and `gh pr create --body "…"`
75
+ // were stranding finished work on their own wording. `-c` is deliberately
76
+ // EXCLUDED — `bash -c "rm -rf /"` carries a real command and must still gate.
77
+ const MESSAGE_FLAG_RE = /(^|\s)(-m|--message|-F|--file|--body|--body-file|--title|--notes|-C|--reuse-message)(=|\s+)('[^']*'|"[^"]*"|\S+)/g;
78
+ // Blank the value of every message/body flag so only executable command syntax
79
+ // remains for the destructive-pattern scan. The flag itself is preserved so a
80
+ // flag like `-F` never accidentally merges with its neighbours.
81
+ function stripMessageArgs(command) {
82
+ return command.replace(MESSAGE_FLAG_RE, (_match, lead, flag) => `${lead}${flag} `);
83
+ }
72
84
  function isDestructiveBash(command) {
73
- const lower = command.toLowerCase();
85
+ const lower = stripMessageArgs(command).toLowerCase();
74
86
  return DESTRUCTIVE_PATTERNS.some((p) => lower.includes(p.toLowerCase()));
75
87
  }
76
88
  function classifyTool(toolName, toolInput) {
@@ -95,6 +107,60 @@ function extractFilePaths(toolInput) {
95
107
  return [toolInput.command];
96
108
  return [];
97
109
  }
110
+ // --- Path exclusions -------------------------------------------------------
111
+ // Opt-in: skip the fact-forcing gate for low-risk paths a user edits
112
+ // constantly (an LLM-maintained prose wiki, a generated scratch dir). Set the
113
+ // CI_GATEGUARD_EXCLUDE env var to a comma-separated list of path substrings;
114
+ // each is matched case-insensitively against the forward-slash-normalized file
115
+ // path. Unset/empty (the default) changes nothing — every mutating file call is
116
+ // gated exactly as before. A call whose targets mix excluded and non-excluded
117
+ // paths still gates the non-excluded ones.
118
+ const EXCLUDE_FRAGMENTS = String(process.env.CI_GATEGUARD_EXCLUDE ?? "")
119
+ .split(",")
120
+ .map((fragment) => fragment.trim().replace(/\\/g, "/").toLowerCase())
121
+ .filter((fragment) => fragment !== "");
122
+ function isExcludedPath(filePath) {
123
+ if (EXCLUDE_FRAGMENTS.length === 0 || typeof filePath !== "string" || filePath === "") {
124
+ return false;
125
+ }
126
+ const normalized = filePath.replace(/\\/g, "/").toLowerCase();
127
+ return EXCLUDE_FRAGMENTS.some((fragment) => normalized.includes(fragment));
128
+ }
129
+ // --- Target lock (opt-in) --------------------------------------------------
130
+ // A fact-list can't catch a wrong-repo / wrong-worktree write — you can present
131
+ // perfect facts about the wrong file. CI_GATEGUARD_TARGET_LOCK=block denies a
132
+ // mutating call whose ABSOLUTE target canonicalizes outside the session project
133
+ // root. Default (unset) checks nothing, so existing sessions — including
134
+ // legitimate out-of-root edits to ~/.claude or /tmp — are unaffected. This is
135
+ // the warn-first rollout: ship non-enforcing, flip to block per session.
136
+ const TARGET_LOCK_ON = String(process.env.CI_GATEGUARD_TARGET_LOCK ?? "").toLowerCase() === "block";
137
+ // Relative paths resolve under cwd (= the project root) and always pass; only an
138
+ // absolute path into a different tree can be out-of-root. Drive-letter (d:/,
139
+ // D:\), POSIX-absolute (/x), and UNC (\\host) forms all count as absolute.
140
+ function isAbsolutePathString(p) {
141
+ return /^[A-Za-z]:[\\/]/.test(p) || p.startsWith("/") || p.startsWith("\\\\");
142
+ }
143
+ function isTargetOutsideRoot(filePath, projectRoot) {
144
+ if (!isAbsolutePathString(filePath))
145
+ return false;
146
+ const root = canonicalizeProjectRoot(projectRoot);
147
+ if (root === "global" || root === "")
148
+ return false; // no known root — do not guess
149
+ const target = canonicalizeFileKey(filePath);
150
+ return target !== root && !target.startsWith(`${root}/`);
151
+ }
152
+ function buildTargetLockReason(strayPath, projectRoot) {
153
+ return [
154
+ `Target is outside the session project root — refusing a possible wrong-repo / wrong-worktree write.`,
155
+ "",
156
+ ` Target: ${strayPath.replace(/\\/g, "/")}`,
157
+ ` Session root: ${canonicalizeProjectRoot(projectRoot)}`,
158
+ "",
159
+ "If this is intentional, confirm you are in the right worktree (cwd / CLAUDE_PROJECT_DIR),",
160
+ "or unset CI_GATEGUARD_TARGET_LOCK for this session. Target lock is opt-in; it fires only",
161
+ "when CI_GATEGUARD_TARGET_LOCK=block.",
162
+ ].join("\n");
163
+ }
98
164
  // The call site only reads this inside the block branch, where at least one
99
165
  // path is uncleared; an all-cleared batch returns "" and is never consumed.
100
166
  function firstUnclearedFilePath(toolInput, state) {
@@ -144,6 +210,47 @@ function buildMutatingFileReason(toolName, filePaths, stateFilePath) {
144
210
  " `_gateguard_facts_presented: true`; Claude Code's strict schema rejects that, so use A or B.)",
145
211
  ].join("\n");
146
212
  }
213
+ function findUnquotedBraceRef(command) {
214
+ let quote = null;
215
+ for (let i = 0; i < command.length; i++) {
216
+ const ch = command[i];
217
+ if (quote) {
218
+ if (ch === quote)
219
+ quote = null;
220
+ continue;
221
+ }
222
+ if (ch === '"' || ch === "'") {
223
+ quote = ch;
224
+ continue;
225
+ }
226
+ if (ch === "@" && command[i + 1] === "{") {
227
+ // Expand to the whitespace-delimited word that carries this @{ ref, then
228
+ // single-quote that whole word in the suggested fix.
229
+ let wordStart = i;
230
+ while (wordStart > 0 && !/\s/.test(command[wordStart - 1]))
231
+ wordStart--;
232
+ let wordEnd = i;
233
+ while (wordEnd < command.length && !/\s/.test(command[wordEnd]))
234
+ wordEnd++;
235
+ 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);
238
+ const fixed = `${command.slice(0, wordStart)}'${word}'${command.slice(wordEnd)}`;
239
+ return { ref, fixed };
240
+ }
241
+ }
242
+ return null;
243
+ }
244
+ function buildBraceRefReason(hit) {
245
+ return [
246
+ `Unquoted git ref ${hit.ref} — Claude Code's Bash parser trips on the braces and blocks this`,
247
+ "post-hoc, costing a retry. Quote the ref and run the SAME command:",
248
+ "",
249
+ ` ${hit.fixed}`,
250
+ "",
251
+ "Single quotes stop the shell from touching the braces; git reads the ref as-is.",
252
+ ].join("\n");
253
+ }
147
254
  function buildDestructiveBashReason(command) {
148
255
  return [
149
256
  `Destructive command requested: ${command}`,
@@ -199,6 +306,16 @@ function main() {
199
306
  const toolName = typeof payload.tool_name === "string" ? payload.tool_name : "";
200
307
  const toolInput = payload.tool_input ?? {};
201
308
  const gate = classifyTool(toolName, toolInput);
309
+ // Unquoted @{…} refs trip the built-in Bash parser — catch them first, for
310
+ // both routine and destructive commands, so the quoted fix surfaces before the
311
+ // opaque post-hoc block (and before the destructive rollback demand).
312
+ if (toolName === "Bash" && typeof toolInput.command === "string") {
313
+ const braceHit = findUnquotedBraceRef(toolInput.command);
314
+ if (braceHit) {
315
+ emitDeny(buildBraceRefReason(braceHit));
316
+ return;
317
+ }
318
+ }
202
319
  if (gate === "allow") {
203
320
  emitAllow();
204
321
  return;
@@ -215,7 +332,24 @@ function main() {
215
332
  const sessionDir = resolveSessionDir(sessionId);
216
333
  const stateFilePath = join(sessionDir, "gateguard-session.json");
217
334
  const state = loadState(sessionDir);
218
- const filePaths = extractFilePaths(toolInput);
335
+ const allTargetPaths = extractFilePaths(toolInput);
336
+ const filePaths = allTargetPaths.filter((path) => !isExcludedPath(path));
337
+ if (allTargetPaths.length > 0 && filePaths.length === 0) {
338
+ emitAllow(); // every target is under a CI_GATEGUARD_EXCLUDE path; skip the gate
339
+ return;
340
+ }
341
+ // Target lock runs before the fact gate and independent of clearance: a
342
+ // wrong-repo write is wrong even with perfect facts. Excluded paths were
343
+ // already filtered out above, so an explicitly-excluded scratch dir outside
344
+ // the root is never target-locked.
345
+ if (TARGET_LOCK_ON) {
346
+ const projectRoot = resolveProjectRoot();
347
+ const stray = filePaths.find((path) => isTargetOutsideRoot(path, projectRoot));
348
+ if (stray) {
349
+ emitDeny(buildTargetLockReason(stray, projectRoot));
350
+ return;
351
+ }
352
+ }
219
353
  const filePath = firstUnclearedFilePath(toolInput, state);
220
354
  const factsFlagged = toolInput._gateguard_facts_presented === true;
221
355
  const alreadyCleared = filePaths.length > 0 && filePaths.every((path) => isFileCleared(state, path));
@@ -59,7 +59,11 @@ function sanitizeSessionId(sessionId) {
59
59
  return "";
60
60
  return sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 64);
61
61
  }
62
- function resolveProjectRoot() {
62
+ // Exported for the target-lock gate (RISA 2 / G2): the hook compares a mutating
63
+ // call's absolute target against this root to catch wrong-repo / wrong-worktree
64
+ // writes. Returns "global" when no CLAUDE_PROJECT_DIR and no git toplevel — the
65
+ // caller treats that as "no known root, do not guess".
66
+ export function resolveProjectRoot() {
63
67
  const fromEnv = process.env.CLAUDE_PROJECT_DIR;
64
68
  if (fromEnv)
65
69
  return fromEnv;
@@ -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 26 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 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.";
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
@@ -29,7 +29,8 @@ skill set on disk.
29
29
  - `grill-me` — Enforces Law 1 (Research Before Executing) of the 7 Laws of AI Agent Discipline. Interview the user relentlessly about a plan or design until shared understanding is reached, resolving every branch of the decision tree before any code is written. Ported from mattpocock/skills under MIT.
30
30
  - `grill-with-docs` — Enforces Law 1 (Research Before Executing) and Law 7 (Learn From Every Session) of the 7 Laws of AI Agent Discipline. 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.
31
31
  - `handoff` — Enforces Law 5 (Reflect After Every Session) of the 7 Laws of AI Agent Discipline. Compact the current conversation into a handoff document for another agent to pick up. Ported from mattpocock/skills under MIT.
32
- - `reconcile` — Enforces Law 1 (Research Before Executing) of the 7 Laws of AI Agent Discipline. Establishes git ground truth branch, status, stashes, worktrees, ahead/behind before any mutation, halts on protected or destructive operations, and verifies a push actually landed instead of assuming it did.
32
+ - `intent-driven-development` — Enforces Law 2 (Plan Is Sacred) of the 7 Laws of AI Agent Discipline. Turn an ambiguous or high-impact change into scoped, verifiable acceptance criteria (observable AC-NNN, explicit in/out scope, named verification methods, and a [revised] protocol that forbids silently dropping a criterion) before or alongside implementation, so the plan that gets built is the plan that was agreed, not an invented default. Use when clarifying a feature, defining acceptance criteria, de-risking a security/data/migration/integration change, or preparing implementation requirements for another agent. Do not trigger for trivial edits, straightforward fixes, active debugging, or code review.
33
+ - `reconcile` — Enforces Law 1 (Research Before Executing) of the 7 Laws of AI Agent Discipline. Establishes git ground truth — branch, status, stashes, worktrees, ahead/behind — before any mutation, halts on protected or destructive operations, then carries the known-good state through to a landed PR: stage by filename, commit one concern, push the feature branch, verify the push landed, open the PR, and after the PR merges fast-forward the default branch and check it out.
33
34
  - `recovery-classification` — Enforces Law 4 (Verify Before Reporting) of the 7 Laws of AI Agent Discipline. After any failure in the verification ladder or auto-loop, classify the failure class before retrying — provider, tool-schema, deterministic-policy, git, worktree, runtime — so retry-vs-pause-vs-self-heal-vs-stop is an intentional decision, not a generic 'try again'.
34
35
  - `roast` — Enforces Law 1 (Research Before Executing) of the 7 Laws of AI Agent Discipline. Convene a 5-persona adversarial council (Contrarian, Expansionist, Logician, Researcher, Buyer) that attacks an idea from every angle, then a Judge returns one GO / RESHAPE / KILL verdict plus the cheapest 48-hour test to de-risk it — so you pressure-test an idea before sinking time into building the wrong thing.
35
36
  - `safety-guard` — Enforces Law 3 (One Thing at a Time) of the 7 Laws of AI Agent Discipline by scoping edits to a directory and blocking destructive shell commands. Use this skill to prevent destructive operations when working on production systems or running agents autonomously.
@@ -150,6 +150,14 @@ The block reason prints the exact `gateguard-session.json` path and the clearanc
150
150
 
151
151
  The inline `_gateguard_facts_presented: true` retry still works on harnesses that forward unknown tool params, but Claude Code's strict tool schema (`additionalProperties: false`) rejects it with `InputValidationError` — use one of the above on Claude Code.
152
152
 
153
+ ### Excluding low-risk paths
154
+
155
+ Set the `CI_GATEGUARD_EXCLUDE` environment variable to opt specific low-risk paths out of the gate entirely — an LLM-maintained prose wiki, a generated scratch directory, anything where the fact-forcing pause costs more than it saves. The value is a comma-separated list of path substrings, each matched case-insensitively against the forward-slash-normalized file path, so `/mywiki/` excludes `D:\Vault\MyWiki\notes\x.md`. Unset or empty (the default) changes nothing: every mutating file call is gated exactly as before, and a call that touches a mix of excluded and non-excluded paths still gates the non-excluded ones. Set it per project in `.claude/settings.json` under `env`, or globally in `~/.claude/settings.json`.
156
+
157
+ ### Locking edits to the current repo
158
+
159
+ A fact-list can't catch a wrong-repo or wrong-worktree write — you can present perfect facts about the wrong file, in the wrong checkout. Set `CI_GATEGUARD_TARGET_LOCK=block` to make the runtime hook (`hooks/gateguard.mjs`) refuse any mutating call whose **absolute** target canonicalizes outside the session project root (`CLAUDE_PROJECT_DIR`, or the git toplevel). Relative paths resolve under the current directory (= the root) and always pass; only an absolute path into a different tree is denied, and the deny reason names both the stray target and the expected root. This runs before the fact gate and independent of clearance — a wrong-repo write is wrong even with facts. Unset (the default) checks nothing, so legitimate out-of-root edits (`~/.claude`, a `/tmp` scratch file, a sibling repo) are unaffected; turn it on per session in a multi-worktree or headless run where cross-repo writes are the real risk. Paths already covered by `CI_GATEGUARD_EXCLUDE` are never target-locked.
160
+
153
161
  ### Limitations and guarantees
154
162
 
155
163
  - **Honor system.** Clearance is recorded by `ci_gateguard_clear`, the `gateguard-clear.mjs` CLI, a manual state-file write, or the inline `_gateguard_facts_presented` flag where the harness allows it (see "Clearing the gate" above). The hook can't verify the investigation actually happened; the 50-file cap — counted per session — bounds damage from stuck loops or rogue agents.
@@ -175,6 +183,8 @@ The standalone `gateguard-ai` Python/CLI package referenced in earlier drafts of
175
183
  - Let the gate fire naturally. Don't try to pre-answer the gate questions — the investigation itself is what improves quality.
176
184
  - Customize gate messages for your domain. If your project has specific conventions, add them to the gate prompts.
177
185
  - Use `.gateguard.yml` to ignore paths like `.venv/`, `node_modules/`, `.git/`.
186
+ - For the shipped runtime hook, set `CI_GATEGUARD_EXCLUDE` (comma-separated path substrings) to exclude low-risk paths from the gate — see [Excluding low-risk paths](#excluding-low-risk-paths).
187
+ - In multi-worktree or headless runs, set `CI_GATEGUARD_TARGET_LOCK=block` so a write into the wrong repo/worktree is refused — see [Locking edits to the current repo](#locking-edits-to-the-current-repo).
178
188
 
179
189
  ## Related Skills
180
190
 
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: intent-driven-development
3
+ tier: "2"
4
+ description: "Enforces Law 2 (Plan Is Sacred) of the 7 Laws of AI Agent Discipline. Turn an ambiguous or high-impact change into scoped, verifiable acceptance criteria (observable AC-NNN, explicit in/out scope, named verification methods, and a [revised] protocol that forbids silently dropping a criterion) before or alongside implementation, so the plan that gets built is the plan that was agreed, not an invented default. Use when clarifying a feature, defining acceptance criteria, de-risking a security/data/migration/integration change, or preparing implementation requirements for another agent. Do not trigger for trivial edits, straightforward fixes, active debugging, or code review."
5
+ origin: continuous-improvement
6
+ user-invocable: true
7
+ argument-hint: "[the change to scope into acceptance criteria]"
8
+ ---
9
+
10
+ # /intent-driven-development: scope the change before you build it
11
+
12
+ Law 2 says the plan is sacred: once a goal and its acceptance conditions are agreed, you do not silently drift from them. The cheapest way to honor that is to make the plan verifiable in the first place. A goal phrased as "make export work" cannot be held sacred because nobody can tell when it is met. This skill converts an ambiguous or high-impact request into observable acceptance criteria (`AC-001`, `AC-002`, ...) with named verification methods, so "done" is a fact two people would agree on, and a criterion can never be quietly dropped mid-build.
13
+
14
+ It produces useful criteria without turning specification into ceremony: inspect available context first, expose only genuine ambiguity, and choose verification that fits the work and its risk.
15
+
16
+ ## When to activate
17
+
18
+ - The user asks to clarify a feature, define acceptance criteria, or de-risk a change before implementation.
19
+ - The request touches security, authentication, persistent data, migrations, external APIs, or compliance.
20
+ - The user wants a handoff artifact another agent or team can implement without inventing requirements.
21
+ - The request is ambiguous enough that the expected outcome is not yet observable or testable.
22
+ - The user types `/intent-driven-development`, "define acceptance criteria", "scope this change", or "make this testable".
23
+
24
+ Do not activate for trivial edits, one-line fixes, active debugging, code review, or implementation requests whose acceptance conditions are already clear.
25
+
26
+ ## How it works
27
+
28
+ 1. **Inspect context first.** Read the repository, docs, schemas, and test infrastructure for technical facts before asking any question. Treat product and business constraints as something only the user or a product artifact can supply.
29
+ 2. **Choose depth.** Quick Capture (3-7 criteria, low or moderate risk) or Full Acceptance Brief (security, data, migration, cross-system, or handoff).
30
+ 3. **Ask minimally.** Only ask questions whose answers cannot be inferred and that materially change scope or behavior. Group related questions into one batch.
31
+ 4. Write observable criteria. Each AC-NNN names a scenario, a trigger, an expected observable result, a prohibited side effect when meaningful, a verification method, and a priority. Do not use "correctly" or "securely" without defined evidence.
32
+ 5. **Proceed or hand off.** For a clear request with no blocking risk, record the criteria and continue. For a risky change, present the blockers and wait for confirmation.
33
+ 6. **Hold the plan sacred.** If a criterion cannot be met due to a constraint found mid-build, do not silently drop or work around it. Mark it `[revised]`, state the constraint, adjust scope or verification, increment the revision number, and re-present only the changed criteria before continuing.
34
+
35
+ ## Operating rules
36
+
37
+ 1. Inspect available repository, docs, issue, design, and test context before asking for technical facts that can be discovered locally.
38
+ 2. Do not infer product or business constraints from code. Business rules, compliance obligations, contractual SLAs, pricing, data-retention policy, prioritization, and target users cannot be read from a repository. Record them as assumptions flagged for confirmation, never as discovered facts. The repository tells you how the system behaves today, not what the business requires it to do.
39
+ 3. Ask only questions whose answers are required and cannot be safely inferred.
40
+ 4. Do not block implementation by default. When the user has asked to implement a sufficiently clear change, record key assumptions and criteria briefly, then proceed or hand them to the implementation workflow.
41
+ 5. Require explicit confirmation before proceeding only when an unresolved decision could create material security exposure, data loss, irreversible migration, contractual or API breakage, meaningful cost, or destructive external action.
42
+ 6. Do not write an acceptance document into a repository, alter project files, create a branch, commit, or invoke another skill unless the user requests it or the active workflow requires it.
43
+ 7. Treat automated tests as evidence, not truth. Prefer automation when reliable and proportionate; allow manual UX, accessibility, security, legal, or operational verification where automation cannot establish the outcome.
44
+ 8. Never include real secrets, credentials, tokens, private keys, personal data, or production payloads in criteria, fixtures, examples, or saved artifacts. Use redacted or synthetic values.
45
+ 9. Do not run destructive tests, migrations, security probes, load tests, paid external calls, or operations against production data without explicit authorization and an identified safe environment.
46
+ 10. When a criterion cannot be satisfied due to a constraint discovered during implementation, update it (`[revised]`, state the constraint, adjust scope or verification), increment the revision, and re-present only the changed criteria. Require confirmation only if the revision changes a blocking decision or reduces a safety or correctness guarantee.
47
+
48
+ ## Choose the depth
49
+
50
+ Use the smallest useful output.
51
+
52
+ ### Quick Capture
53
+
54
+ For a clear but non-trivial change with low or moderate risk. Produce: Goal; In scope and out of scope; Assumptions; 3-7 acceptance criteria with verification methods; blocking questions if any. Do not delay implementation for approval unless a blocking risk exists or the user asked for a spec first.
55
+
56
+ ### Full Acceptance Brief
57
+
58
+ For ambiguous, cross-system, security-sensitive, data-changing, migration, compliance, or high-cost changes, or when the user wants a handoff artifact. Produce the full template below and request confirmation for unresolved blocking decisions before risky implementation.
59
+
60
+ ### Existing specification review
61
+
62
+ When the user already supplied a PRD, issue, plan, or criteria: review it instead of restarting discovery. Identify missing scope boundaries, unsafe assumptions, contradictions, and unverifiable requirements. Return corrected or supplemental criteria.
63
+
64
+ ## Write acceptance criteria
65
+
66
+ Use `AC-001`, `AC-002`, and so on. Criteria and tests need not map one-to-one. For each applicable criterion include: scenario or starting condition; action or trigger; expected observable behavior; prohibited side effect when meaningful; verification method (automated test, integration check, manual UX review, accessibility check, security review, operational check, or stakeholder acceptance); environment or safety constraint when verification could affect data, services, cost, or secrets; priority (Required, Important, or Optional).
67
+
68
+ Do not use "correctly", "securely", "fast", "intuitive", or "robust" without defining observable evidence or recording them as a human-review judgment.
69
+
70
+ Cover only the boundaries that apply:
71
+
72
+ | Category | Include when | Typical evidence |
73
+ | --- | --- | --- |
74
+ | Happy path | New or changed user-visible behavior | Successful workflow or state transition |
75
+ | Validation | The change accepts input | Malformed or boundary value rejected without mutation |
76
+ | Authorization/privacy | Data or actions have access boundaries | Denied access and no sensitive disclosure |
77
+ | Persistence/migration | Stored data or schemas change | Backward read, migration, rollback, or backup behavior |
78
+ | Compatibility | Public APIs, files, events, or clients may break | Existing contract or fixture stays valid |
79
+ | Failure recovery | Network, service, or async failure exists | No partial state, or clear retry and degraded behavior |
80
+ | Idempotency/concurrency | Repeats or simultaneous writes are plausible | No duplicate side effect or invalid final state |
81
+ | Performance | A user or service threshold matters | Defined measurement conditions and threshold |
82
+ | UX/accessibility | A person interacts with the result | Keyboard, feedback, error recovery, visual or manual review |
83
+
84
+ ## Output template (Full Acceptance Brief)
85
+
86
+ Omit irrelevant sections for Quick Capture.
87
+
88
+ ```markdown
89
+ # Acceptance Brief: <Change Name>
90
+
91
+ **Status:** Draft | Approved | Implemented | Verified
92
+ **Revision:** <number>
93
+ **Prepared for:** <user/team/agent, when known>
94
+
95
+ ## Goal
96
+ <One observable outcome sentence.>
97
+
98
+ ## Scope
99
+ **In scope:** <behavior included>
100
+ **Out of scope:** <adjacent work excluded>
101
+
102
+ ## Context
103
+ **Discovered facts** (technical, verified from repository or artifact)
104
+ **Product/business constraints** (supplied by user or artifact, never inferred from code, or "none supplied yet")
105
+ **Assumptions** (unverified claims to confirm)
106
+ **Dependencies and constraints**
107
+
108
+ ## Risk Review
109
+ | Risk area | Applies? | Required handling |
110
+ | --- | --- | --- |
111
+ | Security/privacy | Yes/No | <redaction, authorization, review> |
112
+ | Persistent data/migration | Yes/No | <compatibility, backup, rollback> |
113
+ | External effects/cost | Yes/No | <sandbox, test environment, authorization> |
114
+ | Compatibility/API | Yes/No | <contract to preserve or version> |
115
+ | UX/accessibility | Yes/No | <manual or automated evidence> |
116
+
117
+ ## Acceptance Criteria
118
+ ### AC-001: <observable behavior>
119
+ - **Scenario:** <starting condition>
120
+ - **Action:** <single trigger>
121
+ - **Expected:** <observable result>
122
+ - **Must not:** <prohibited side effect, if applicable>
123
+ - **Verification:** <method and intended evidence>
124
+ - **Environment/safety:** <constraints, if applicable>
125
+ - **Priority:** Required | Important | Optional
126
+
127
+ ## Blocking Decisions
128
+ - [ ] <only decisions that prevent safe or correct progress>
129
+
130
+ ## Verification Plan
131
+ | Criterion | Verification evidence | Status |
132
+ | --- | --- | --- |
133
+ | AC-001 | <test, check, or review command or evidence type> | Pending |
134
+ ```
135
+
136
+ ## Pass/fail rubric
137
+
138
+ A brief passes only if every answer is "yes". Any "no" means revise before returning it.
139
+
140
+ - [ ] Does every required criterion have a scenario, an observable expected result, and a named verification method?
141
+ - [ ] Are vague terms ("correctly", "secure", "fast", "robust") either replaced with observable evidence or marked as human judgment?
142
+ - [ ] Are product and business constraints listed as supplied or assumed, with none silently inferred from code?
143
+ - [ ] Is scope explicit, with out-of-scope items named?
144
+ - [ ] Are blocking decisions limited to choices that actually affect safety or correctness, not preferences?
145
+
146
+ A failing criterion: `AC-001: The export works correctly and is secure.` (no scenario, no observable result, no verification, "correctly" and "secure" undefined). A passing one names the scenario, the expected result, the prohibited side effect, and the verification method, so two people would agree it was met.
147
+
148
+ ## How it fits the 7 Laws
149
+
150
+ | Law | Role of this skill |
151
+ |---|---|
152
+ | Law 2 (Plan Is Sacred) | The acceptance brief **is** the sacred plan: observable criteria, explicit scope, and a `[revised]` protocol that forbids silently dropping or working around a criterion mid-build. |
153
+ | Law 1 (Research Before Executing) | Rule 1 inspects repo, docs, schemas, and tests for technical facts before asking, and refuses to infer business rules from code. |
154
+ | Law 4 (Verify Before Reporting) | Every criterion carries a named verification method and a pass/fail rubric, so "done" is falsifiable rather than asserted. |
155
+
156
+ ## Pairs with
157
+
158
+ - [`grill-me`](./grill-me.md): interviews a fuzzy request to a shippable spec. Reach for `grill-me` when the input is unclear, then this skill to turn the agreed intent into verifiable criteria.
159
+ - [`roast`](./roast.md): validates whether the idea should exist at all. Roast first, then scope the survivor into acceptance criteria.
160
+ - [`goal-monitor`](./goal-monitor.md): the runtime drift gate. The `## Goal` and criteria this skill produces are what goal-monitor scores a session against.
161
+ - [`verification-loop`](./verification-loop.md): runs the per-project verify ladder. The criteria's verification methods feed its evidence step.