continuous-improvement 3.22.0 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/git-state.mjs CHANGED
@@ -112,7 +112,8 @@ function isSha(value) {
112
112
  * comparison that authorizes a mutation.
113
113
  *
114
114
  * Fails closed: null, empty, surrounding whitespace, shell metacharacters,
115
- * `..`, refspec syntax (`@{`), a leading `-`, a trailing `/` or `.lock`, and
115
+ * `..`, refspec syntax (`@{`), a leading `-`, empty path components,
116
+ * dot-prefixed or dot-suffixed components, components ending `.lock`, and
116
117
  * anything over 255 characters all return false rather than being sanitized
117
118
  * into something that then looks valid.
118
119
  */
@@ -129,6 +130,13 @@ export function isSafeRefName(name) {
129
130
  return false;
130
131
  if (name.includes("..") || name.includes("@{"))
131
132
  return false;
133
+ const components = name.split("/");
134
+ if (components.some((component) => component.length === 0 ||
135
+ component.startsWith(".") ||
136
+ component.endsWith(".") ||
137
+ component.endsWith(".lock"))) {
138
+ return false;
139
+ }
132
140
  return SAFE_REF.test(name);
133
141
  }
134
142
  /**
@@ -154,8 +162,8 @@ export function classifyHead(rawBranch, exitCode = 0) {
154
162
  * Parse `git rev-list --left-right --count @{u}...HEAD` output, which is
155
163
  * `"<behind>\t<ahead>"`.
156
164
  *
157
- * Returns null for empty, malformed, negative, or non-integer output. Callers
158
- * must treat null as "unknown" — never as zero.
165
+ * Returns null for empty, malformed, negative, non-integer, or unsafe-integer
166
+ * output. Callers must treat null as "unknown" — never as zero.
159
167
  */
160
168
  export function parseRevListCounts(raw) {
161
169
  if (typeof raw !== "string")
@@ -168,9 +176,9 @@ export function parseRevListCounts(raw) {
168
176
  return null;
169
177
  const behind = Number(parts[0]);
170
178
  const ahead = Number(parts[1]);
171
- if (!Number.isInteger(behind) || behind < 0)
179
+ if (!Number.isSafeInteger(behind) || behind < 0)
172
180
  return null;
173
- if (!Number.isInteger(ahead) || ahead < 0)
181
+ if (!Number.isSafeInteger(ahead) || ahead < 0)
174
182
  return null;
175
183
  return { behind, ahead };
176
184
  }
@@ -312,6 +320,17 @@ export function baselineShifted(before, after) {
312
320
  export function assessGitState(input) {
313
321
  const findings = [];
314
322
  const protectedList = input.protectedBranches ?? DEFAULT_PROTECTED_BRANCHES;
323
+ if (Object.hasOwn(input, "headCommit")) {
324
+ const commit = (input.headCommit ?? "").trim();
325
+ findings.push({
326
+ id: "head-commit",
327
+ label: "HEAD commit",
328
+ detail: isSha(commit)
329
+ ? commit.slice(0, 12)
330
+ : "unborn or not a usable commit — create or verify the first commit before mutating",
331
+ severity: isSha(commit) ? "ok" : "blocker",
332
+ });
333
+ }
315
334
  if (input.head.kind === "branch") {
316
335
  const onProtected = isProtectedBranch(input.head.branch, protectedList);
317
336
  findings.push({
@@ -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 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.";
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 29 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
@@ -386,7 +386,7 @@ const EXPERT_TOOL_ENTRIES = [
386
386
  ];
387
387
  const MODE_METADATA = {
388
388
  beginner: {
389
- 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.",
389
+ description: "Beginner mode: see what your agent learned, list its instincts, and request a session reflection. Bundles the ship fast path plus grounding skills (gateguard, tdd-workflow, verification-loop) so one-defect delivery, research, tests, and verification happen by default — every edit starts from facts, not guesses.",
390
390
  hooks: ["PreToolUse", "PostToolUse", "UserPromptSubmit"],
391
391
  hookDescription: "Silently captures every tool call as observations and routes prompts to the matching skill via the route table. Lightweight and non-blocking.",
392
392
  },
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # continuous-improvement
2
2
 
3
- > The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.
3
+ > The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 29 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.
4
4
 
5
5
  ## What This Is
6
6
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.22.0",
4
- "description": "Claude Code that gets sharper every session: the persistent-memory and runtime-discipline layer built on the 7 Laws of AI Agent Discipline. It grounds every edit in real facts before it lands and, through the Mulahazah engine, turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts. Beginner: one /plugin install command. Expert: adds MCP tools and session hooks.",
3
+ "version": "3.23.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 29 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts. Beginner: one /plugin install command. Expert: adds MCP tools and session hooks.",
5
5
  "keywords": [
6
6
  "claude-code",
7
7
  "claude-code-plugin",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.22.0",
3
+ "version": "3.23.0",
4
4
  "mode": "beginner",
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.",
5
+ "description": "Beginner mode: see what your agent learned, list its instincts, and request a session reflection. Bundles the ship fast path plus grounding skills (gateguard, tdd-workflow, verification-loop) so one-defect delivery, research, tests, and verification happen by default — every edit starts from facts, not guesses.",
6
6
  "tools": [
7
7
  {
8
8
  "name": "ci_status",
@@ -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 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.",
11
- "version": "3.22.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 29 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.23.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.22.0",
4
- "description": "The persistent-memory and runtime-discipline layer for Claude Code. It remembers the corrections you already gave, grounds every edit in real facts before it lands, and — through the Mulahazah engine — turns each fix into a reusable instinct, so a lesson learned once is applied automatically next time with no re-teaching. Built on the 7 Laws of AI Agent Discipline (research, plan, verify, reflect, learn) and shipped as 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.",
3
+ "version": "3.23.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 29 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"
@@ -54,6 +54,7 @@ function parseArgs(args) {
54
54
  verifyPush: null,
55
55
  root: cwd(),
56
56
  };
57
+ let cwdProvided = false;
57
58
  for (let i = 0; i < args.length; i++) {
58
59
  const arg = args[i] ?? "";
59
60
  if (arg === "--json")
@@ -63,6 +64,9 @@ function parseArgs(args) {
63
64
  else if (arg === "--explain")
64
65
  options.explain = true;
65
66
  else if (arg === "--verify-push") {
67
+ if (options.verifyPush !== null) {
68
+ throw new Error("--verify-push may only be provided once");
69
+ }
66
70
  const value = args[i + 1];
67
71
  if (value === undefined || value.startsWith("--")) {
68
72
  throw new Error("--verify-push requires a branch name");
@@ -74,11 +78,15 @@ function parseArgs(args) {
74
78
  i++;
75
79
  }
76
80
  else if (arg === "--cwd") {
81
+ if (cwdProvided) {
82
+ throw new Error("--cwd may only be provided once");
83
+ }
77
84
  const value = args[i + 1];
78
- if (value === undefined || value.startsWith("--")) {
85
+ if (value === undefined || value.startsWith("--") || value.trim().length === 0) {
79
86
  throw new Error("--cwd requires a directory");
80
87
  }
81
88
  options.root = value;
89
+ cwdProvided = true;
82
90
  i++;
83
91
  }
84
92
  else if (arg === "--help" || arg === "-h") {
@@ -88,6 +96,14 @@ function parseArgs(args) {
88
96
  throw new Error(`unknown argument: ${arg}`);
89
97
  }
90
98
  }
99
+ const actions = [
100
+ options.snapshot ? "--snapshot" : null,
101
+ options.explain ? "--explain" : null,
102
+ options.verifyPush !== null ? "--verify-push" : null,
103
+ ].filter((action) => action !== null);
104
+ if (actions.length > 1) {
105
+ throw new Error(`mutually exclusive action modes: ${actions.join(", ")}`);
106
+ }
91
107
  return options;
92
108
  }
93
109
  /** Probe each in-progress marker through `--git-path`, which is worktree-correct. */
@@ -160,20 +176,35 @@ function main() {
160
176
  const status = git(["status", "--porcelain=v1"], options.root);
161
177
  const drift = git(["diff", "--name-only", "--ignore-all-space"], options.root);
162
178
  const dirty = accountDirty(status.code === 0 ? status.stdout : null, drift.code === 0 ? drift.stdout : null);
179
+ const inProgress = probeInProgress(options.root);
180
+ const baseFindings = assessGitState({
181
+ headCommit: headSha.code === 0 ? headSha.stdout.trim() : null,
182
+ head,
183
+ upstreamRef,
184
+ counts,
185
+ inProgress,
186
+ dirty,
187
+ });
163
188
  if (options.snapshot) {
164
- // Field-compatible with scripts/git-state-snapshot.sh, plus `contentDrift`
165
- // and `inProgress`, which the shell version cannot report.
189
+ // Field-compatible with scripts/git-state-snapshot.sh, plus `contentDrift`,
190
+ // `inProgress`, and a fail-closed blocker summary the shell version cannot
191
+ // report. An unborn HEAD is a git repo, but not a usable mutation baseline;
192
+ // do not emit an empty `head` field that looks like success.
166
193
  const upstreamSha = upstreamRef === null ? "none" : git(["rev-parse", "--short", "@{u}"], options.root).stdout.trim() || "none";
194
+ const shortHead = headSha.code === 0 ? git(["rev-parse", "--short", "HEAD"], options.root).stdout.trim() : "";
195
+ const blockers = baseFindings.filter((finding) => finding.severity === "blocker").map((finding) => finding.id);
167
196
  stdout.write(`${JSON.stringify({
168
- head: git(["rev-parse", "--short", "HEAD"], options.root).stdout.trim(),
197
+ head: shortHead.length > 0 ? shortHead : "unborn",
169
198
  upstream: upstreamSha,
170
199
  dirty: dirty.reported,
171
200
  root: repoRoot,
172
201
  branch: head.branch ?? "detached",
173
202
  contentDrift: dirty.contentDrift,
174
- inProgress: probeInProgress(options.root),
203
+ inProgress,
204
+ blocked: blockers.length > 0,
205
+ blockers,
175
206
  })}\n`);
176
- exit(0);
207
+ exit(blockers.length > 0 ? 1 : 0);
177
208
  return;
178
209
  }
179
210
  if (options.verifyPush !== null) {
@@ -191,14 +222,7 @@ function main() {
191
222
  exit(verdict.verdict === "landed" ? 0 : 1);
192
223
  return;
193
224
  }
194
- const inProgress = probeInProgress(options.root);
195
- const findings = assessGitState({
196
- head,
197
- upstreamRef,
198
- counts,
199
- inProgress,
200
- dirty,
201
- });
225
+ const findings = [...baseFindings];
202
226
  const stashes = git(["stash", "list"], options.root);
203
227
  const stashCount = stashes.code === 0
204
228
  ? stashes.stdout.split(/\r?\n/).filter((line) => line.trim().length > 0).length
@@ -42,6 +42,9 @@ Four boundaries where the obvious command lies:
42
42
  - **Detached HEAD** — the `--show-current` form of `git branch` prints "" and exits 0, indistinguishable from success. `symbolic-ref --quiet` exits non-zero instead. Detached blocks.
43
43
  - **Linked worktree** — `.git` is a *file* there, so a `.git/`-relative marker probe exits 2 exactly as it does on a clean tree: a real conflicted merge reads as clean. Use `rev-parse --git-path`.
44
44
  - **autocrlf** — `git status` overstates drift. Stage by explicit filename, never `git add -A`.
45
+ - **Unborn HEAD** — `git init` with no commit is a real repo with no usable baseline; `rev-parse HEAD` fails. Reported as `head: "unborn"` and blocked, never as an empty field that reads like success.
46
+
47
+ `--snapshot` shares the exit contract (`0` clear / `1` blocked / `2` not a repo) and adds `contentDrift`, `inProgress`, `blocked`, `blockers` to the shell script's envelope. It still writes the JSON on a blocker, so tolerate exit 1 when capturing a baseline under `set -e`.
45
48
 
46
49
  ## Then act, with gates
47
50
 
@@ -1,57 +1,13 @@
1
1
  ---
2
2
  name: ship
3
- description: "Single-defect fast path walk one bug from ground-truth audit through a TDD fix, full verification, a single-concern commit, and an open PR, then stop. Never auto-merges, never deploys. For multi-PR rollouts use /release-train instead."
3
+ description: "Compatibility entry point for the native ship skill. Passes one defect request through unchanged."
4
+ argument-hint: "[one-line defect description]"
4
5
  ---
5
6
 
6
7
  # /ship
7
8
 
8
- The one-defect fast path. `/release-train` is for stacked multi-PR rollouts and `/proceed-with-the-recommendation` walks an arbitrary recommendation list; `/ship` is the common case: fix one defect, open one PR, hand it back for review.
9
+ Invoke the native `ship` skill with this complete defect request:
9
10
 
10
- Pure routing over existing skills. It adds no new orchestration logic and it does NOT bypass branch protection, force-push, auto-merge, or deploy.
11
+ $ARGUMENTS
11
12
 
12
- ## Usage
13
-
14
- ```
15
- /ship <one-line description of the defect>
16
- ```
17
-
18
- If the description is ambiguous or names more than one concern, `/ship` halts and asks you to narrow it — one defect per run.
19
-
20
- ## Behavior
21
-
22
- In order, for the single defect:
23
-
24
- 1. **Ground truth** — `reconcile` (or its inline fallback): confirm the working tree is clean and on a feature branch cut from an up-to-date `origin/<base>`. If on a protected branch or a stale base, halt and ask.
25
- 2. **Reproduce (RED)** — `tdd-workflow`: write a failing test that reproduces the defect; watch it fail. Pre-test implementation code is deleted, not kept.
26
- 3. **Fix (GREEN)** — write the minimal change that makes the test pass; watch it pass. One concern only.
27
- 4. **Verify** — `verification-loop`: run the project's verify ladder (build, types, tests). Build-green is evidence of mechanism, not of the fix — confirm the defect itself no longer reproduces.
28
- 5. **Commit** — one commit, one concern, staged by explicit filename (never `git add -A`). Use a Windows-safe commit message: a single-line `-m` (repeat `-m` for paragraphs) or `git commit -F <tempfile>` — no multi-line here-docs/here-strings.
29
- 6. **Open PR** — `commit-commands:commit-push-pr` (or `gh pr create`): push the branch and open a single-concern PR that cites the plan or issue. **Stop here.** The merge is yours.
30
- 7. **Deploy receipt (advisory)** — after you merge, `deploy-receipt` verifies the deployed SHA matches the merge SHA. Advisory only; `/ship` does not deploy.
31
-
32
- ## Hard stops (halt and ask, never improvise)
33
-
34
- - Ambiguous or multi-concern defect description.
35
- - Working tree not clean, or branch is protected / cut from a stale base.
36
- - Any verification step fails with a non-obvious fix.
37
- - The fix would touch more than 15 non-generated files (that is no longer one concern — split it, or use `/release-train`).
38
- - Push would target a protected branch.
39
-
40
- ## Anti-patterns this command refuses
41
-
42
- - **Auto-merge.** Never merges the PR it opens, even when CI is green.
43
- - **Deploy.** Never runs a deploy; `deploy-receipt` only verifies after you merge.
44
- - **Bypass.** No `--admin`, `--force`, `--no-verify`.
45
- - **Bundled concerns.** Will not fold an unrelated fix into the same commit; logs it as a deferred follow-up instead.
46
-
47
- ## Composition
48
-
49
- Routes through, in order: `reconcile` → `tdd-workflow` → `verification-loop` → `commit-commands:commit-push-pr` → `deploy-receipt`. Each step falls back to its inline behavior when the preferred skill is not installed.
50
-
51
- ## Example
52
-
53
- ```
54
- /ship registration form accepts a negative deposit amount
55
- ```
56
-
57
- Reconciles git state, writes a failing test asserting deposits must be positive, implements the guard, runs the verify ladder, commits one concern with a single-line message, opens the PR, and stops for your review.
13
+ Follow that skill exactly. Do not reconstruct or duplicate its Git, worktree, TDD, return, cleanup, merge, or deploy rules here. If the native skill is unavailable, stop and tell the operator to update or reinstall `continuous-improvement`.
@@ -112,7 +112,8 @@ function isSha(value) {
112
112
  * comparison that authorizes a mutation.
113
113
  *
114
114
  * Fails closed: null, empty, surrounding whitespace, shell metacharacters,
115
- * `..`, refspec syntax (`@{`), a leading `-`, a trailing `/` or `.lock`, and
115
+ * `..`, refspec syntax (`@{`), a leading `-`, empty path components,
116
+ * dot-prefixed or dot-suffixed components, components ending `.lock`, and
116
117
  * anything over 255 characters all return false rather than being sanitized
117
118
  * into something that then looks valid.
118
119
  */
@@ -129,6 +130,13 @@ export function isSafeRefName(name) {
129
130
  return false;
130
131
  if (name.includes("..") || name.includes("@{"))
131
132
  return false;
133
+ const components = name.split("/");
134
+ if (components.some((component) => component.length === 0 ||
135
+ component.startsWith(".") ||
136
+ component.endsWith(".") ||
137
+ component.endsWith(".lock"))) {
138
+ return false;
139
+ }
132
140
  return SAFE_REF.test(name);
133
141
  }
134
142
  /**
@@ -154,8 +162,8 @@ export function classifyHead(rawBranch, exitCode = 0) {
154
162
  * Parse `git rev-list --left-right --count @{u}...HEAD` output, which is
155
163
  * `"<behind>\t<ahead>"`.
156
164
  *
157
- * Returns null for empty, malformed, negative, or non-integer output. Callers
158
- * must treat null as "unknown" — never as zero.
165
+ * Returns null for empty, malformed, negative, non-integer, or unsafe-integer
166
+ * output. Callers must treat null as "unknown" — never as zero.
159
167
  */
160
168
  export function parseRevListCounts(raw) {
161
169
  if (typeof raw !== "string")
@@ -168,9 +176,9 @@ export function parseRevListCounts(raw) {
168
176
  return null;
169
177
  const behind = Number(parts[0]);
170
178
  const ahead = Number(parts[1]);
171
- if (!Number.isInteger(behind) || behind < 0)
179
+ if (!Number.isSafeInteger(behind) || behind < 0)
172
180
  return null;
173
- if (!Number.isInteger(ahead) || ahead < 0)
181
+ if (!Number.isSafeInteger(ahead) || ahead < 0)
174
182
  return null;
175
183
  return { behind, ahead };
176
184
  }
@@ -312,6 +320,17 @@ export function baselineShifted(before, after) {
312
320
  export function assessGitState(input) {
313
321
  const findings = [];
314
322
  const protectedList = input.protectedBranches ?? DEFAULT_PROTECTED_BRANCHES;
323
+ if (Object.hasOwn(input, "headCommit")) {
324
+ const commit = (input.headCommit ?? "").trim();
325
+ findings.push({
326
+ id: "head-commit",
327
+ label: "HEAD commit",
328
+ detail: isSha(commit)
329
+ ? commit.slice(0, 12)
330
+ : "unborn or not a usable commit — create or verify the first commit before mutating",
331
+ severity: isSha(commit) ? "ok" : "blocker",
332
+ });
333
+ }
315
334
  if (input.head.kind === "branch") {
316
335
  const onProtected = isProtectedBranch(input.head.branch, protectedList);
317
336
  findings.push({
@@ -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 28 bundled skills, instinct-aware hooks, an MCP toolset for recall and reflection, and a GitHub Action transcript linter that feeds real work history back into sharper instincts.";
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 29 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
@@ -386,7 +386,7 @@ const EXPERT_TOOL_ENTRIES = [
386
386
  ];
387
387
  const MODE_METADATA = {
388
388
  beginner: {
389
- 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.",
389
+ description: "Beginner mode: see what your agent learned, list its instincts, and request a session reflection. Bundles the ship fast path plus grounding skills (gateguard, tdd-workflow, verification-loop) so one-defect delivery, research, tests, and verification happen by default — every edit starts from facts, not guesses.",
390
390
  hooks: ["PreToolUse", "PostToolUse", "UserPromptSubmit"],
391
391
  hookDescription: "Silently captures every tool call as observations and routes prompts to the matching skill via the route table. Lightweight and non-blocking.",
392
392
  },
@@ -20,6 +20,7 @@ skill set on disk.
20
20
  - `gateguard` — Enforces Law 1 (Research Before Executing) of the 7 Laws of AI Agent Discipline. Fact-forcing gate that blocks Edit/Write/Bash (including MultiEdit) and demands concrete investigation (importers, data schemas, user instruction) before allowing the action. Measurably improves output quality by +2.25 points vs ungated agents.
21
21
  - `model-forward` — Enforces all 7 Laws as a standing stance — go with Claude Code and the model, not against it. Skills are scaffolding that merges into the model over time; the durable core is goal-driven execution (the higher the stated goal, the better) plus self-discipline guardrails.
22
22
  - `recall` — Enforces Law 1 (Research Before Executing) of the 7 Laws of AI Agent Discipline. Makes past sessions first-class research material by searching the observation log with BM25 ranking, so 'have I hit this before?' is answerable before re-deriving a fix or repeating a mistake.
23
+ - `ship` — Enforces Law 1 (Research Before Executing), Law 3 (One Thing at a Time), and Law 4 (Verify Before Reporting) of the 7 Laws of AI Agent Discipline. Fix one defect through TDD and one PR, isolate unrelated dirty checkouts in an owner-locked clean worktree, and return only eligible clean checkouts to the detected default branch. Use for urgent hotfixes, bug fixes from a messy checkout, or requests to ship one defect without stashing current work.
23
24
  - `tdd-workflow` — Enforces Law 3 (One Thing at a Time) and Law 4 (Verify Before Reporting) of the 7 Laws of AI Agent Discipline. Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
24
25
  - `verification-loop` — Enforces Law 4 (Verify Before Reporting) of the 7 Laws of AI Agent Discipline. A comprehensive verification system for agent coding sessions covering build, types, lint, tests, security, and diff with a PASS/FAIL report.
25
26
 
@@ -62,7 +62,11 @@ The ground-truth pass has to work wherever the agent runs, not only in Bash. `ci
62
62
  | `scripts/git-state-snapshot.sh` | needs Git Bash | yes | yes | root/branch only | reports `detached` | reports `none` |
63
63
  | Hand-run probe list above | yes | yes | yes | correct | non-zero exit | non-zero exit |
64
64
 
65
- Smoke-test on the OS you actually ship on. Both surfaces emit the same `{head, upstream, dirty, root, branch}` envelope — `ci-reconcile --snapshot` adds `contentDrift` and `inProgress` — and a test pins that parity so the two cannot drift apart silently.
65
+ Smoke-test on the OS you actually ship on. Both surfaces emit the same `{head, upstream, dirty, root, branch}` envelope — `ci-reconcile --snapshot` adds `contentDrift`, `inProgress`, `blocked` and `blockers` — and a test pins that parity so the two cannot drift apart silently.
66
+
67
+ `--snapshot` follows the same exit-code contract as the default mode: `0` clear, `1` at least one blocker, `2` not a git repository. It still writes the envelope on a blocker, so a script that wants the JSON regardless must tolerate exit 1 (`set -e` will otherwise abort on a detached HEAD or an unborn repo).
68
+
69
+ An **unborn HEAD** — `git init` with no commit yet — is a real git repository with no usable baseline. `git rev-parse HEAD` fails there, so the shell script reports `not-a-git-repo` and the envelope's `head` field would otherwise be empty in a way that reads like success. `ci-reconcile` reports `head: "unborn"` with `blocked: true` and blocks the mutation instead.
66
70
 
67
71
  ## Detect a Concurrent Writer
68
72
 
@@ -75,7 +79,7 @@ When another session/loop may be active, do not assume the tree is yours:
75
79
  # ... do work ...
76
80
  npx ci-reconcile --snapshot # compare head + branch against the baseline
77
81
  ```
78
- If either field moved, another writer got there first — re-survey from the top instead of committing onto an unexpected base. A missing or unparseable field counts as *shifted*; "we could not tell" is never "nothing moved".
82
+ If either field moved, another writer got there first — re-survey from the top instead of committing onto an unexpected base. A missing or unparseable field counts as *shifted*; "we could not tell" is never "nothing moved". Both calls exit 1 if the tree is blocked, so capture the baseline without `set -e` (or guard it) when a blocker is expected.
79
83
  - More than one entry in `git worktree list --porcelain` means a sibling checkout exists that another session may be writing to. The runner flags this.
80
84
  - If the git index keeps changing while you are idle, a writer is active. Pause and surface it rather than racing.
81
85
  - If `gateguard` is installed, its Parallel-Actor Gate already captured this baseline on the session's first mutation by running `bash "${CLAUDE_PLUGIN_ROOT}/scripts/git-state-snapshot.sh"` (source: `scripts/git-state-snapshot.sh`) and divergence-checks every later mutation — `reconcile` complements that gate, it does not replace it. That shell snapshot needs Git Bash and derives its `dirty` count from `git status`, which overstates drift on an `autocrlf` tree; `ci-reconcile --snapshot` is the same envelope without either limitation. Without gateguard, run one of them yourself.
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: ship
3
+ tier: "1"
4
+ description: >-
5
+ Enforces Law 1 (Research Before Executing), Law 3 (One Thing at a Time), and Law 4 (Verify Before Reporting) of the 7 Laws of AI Agent Discipline. Fix one defect through TDD and one PR, isolate unrelated dirty checkouts in an owner-locked clean worktree, and return only eligible clean checkouts to the detected default branch. Use for urgent hotfixes, bug fixes from a messy checkout, or requests to ship one defect without stashing current work.
6
+ origin: continuous-improvement
7
+ user-invocable: true
8
+ disable-model-invocation: true
9
+ argument-hint: "[one-line defect description]"
10
+ ---
11
+
12
+ # Ship
13
+
14
+ Fix one defect, open one PR, and hand it back for review. Use `release-train` for stacked multi-PR rollouts and `proceed-with-the-recommendation` for an arbitrary recommendation list.
15
+
16
+ Preserve branch protection. Never force-push, auto-merge, or deploy from this skill.
17
+
18
+ ## Request
19
+
20
+ Treat `$ARGUMENTS` as the defect request when supplied. Otherwise use the single concrete defect from the active conversation. Halt and ask for one narrower defect when the request is empty, ambiguous, or contains more than one concern.
21
+
22
+ ## Workflow
23
+
24
+ Run these steps in order:
25
+
26
+ 1. **Capture ground truth and resolve the base**: run the read-only `reconcile` probes. Record the initiating checkout's absolute root, branch, HEAD, real tracked drift, staged drift, untracked files, in-progress Git operations, registered worktrees, and task ownership. Ownership requires the current session ID in the authoritative worktree lease or an equivalent active harness task ledger that names this exact checkout; merely starting there is not proof. Set `return_allowed=true` only when the initiating checkout is clean, that ownership proof matches the current session, and no other task reserves it. Without such a lease or ledger, fail closed with `return_allowed=false`. A dirty-tree blocker may continue only through the isolated path in step 2 after the changes are confirmed unrelated. Every other blocker still halts. After classification, make the fetch below the first allowed repository mutation and refresh the remote before choosing a base:
27
+ ```
28
+ git fetch --prune origin
29
+ git ls-remote --symref origin HEAD
30
+ ```
31
+ Use the live `refs/heads/<base>` returned for `HEAD`. Validate it with `git check-ref-format --branch "<base>"`. Compare it with `refs/remotes/origin/HEAD`, but never let a stale local symbolic ref override the live result. The query must also return the remote HEAD commit. If it succeeds without a symbolic ref, compare that remote HEAD commit with the resolved tips of `origin/main` and `origin/master`, and require exactly one matching candidate. Zero or multiple matches are ambiguous: halt instead of guessing. Halt on a fetch/query failure or if no verified base exists. Confirm `origin/<base>` resolves after the fetch, record its immutable commit as `<base-sha>`, require a full hexadecimal commit ID, and require that it equals the verified remote HEAD commit. Pin worktree creation to `<base-sha>`, not the mutable remote-tracking name.
32
+ 2. **Select a safe checkout**:
33
+ - Always perform the defect work in a separate isolated worktree created from the pinned `<base-sha>`. Do not reuse the initiating checkout, even when it is clean. One isolation path keeps ownership, retention, return, and cleanup behavior consistent.
34
+ - If dirty changes are not clearly unrelated to the defect, halt and ask. Never guess which changes belong to whom.
35
+ - Preserve the initiating checkout until the return decision in step 8. When it is dirty with unrelated work, protected, stale, ahead, or owned by another task, do not stash, switch, reset, clean, or copy its changes. Choose an absent absolute sibling or temporary path. Generate the feature branch from ASCII lowercase letters, digits, slash, underscore, and hyphen only (`[a-z0-9/_-]+`), require an alphanumeric first character, and validate the final name before any lookup. Prove the proposed branch is absent locally, then query the remote successfully and require empty output before using the name:
36
+ ```
37
+ git check-ref-format --branch "<feature-branch>"
38
+ git show-ref --verify "refs/heads/<feature-branch>"
39
+ git ls-remote --heads origin "refs/heads/<feature-branch>"
40
+ ```
41
+ The local command must report no ref. The remote command must complete without a network/authentication error and return no matching ref. If either branch exists, choose another unique name. Create a no-upstream worktree with an atomic owner lock:
42
+ ```
43
+ git worktree add --no-track --lock --reason "owner=<session-id>; purpose=/ship" -b "<feature-branch>" "<worktree-path>" "<base-sha>"
44
+ ```
45
+ - Use the current harness session ID as `<session-id>`. If it is unavailable, generate a unique recorded run token before creating the worktree and reuse that exact token through handoff and cleanup. Treat the lock reason as an advisory coordination ledger for compliant sessions, not as a filesystem write lock. Run `worktree-safety` in the new checkout and confirm its resolved root, `.git` pointer, registration, branch, pinned HEAD, and lock reason all match the current session. A missing or foreign owner blocks work. Recheck that envelope and observable branch, HEAD, and diff state before every source mutation. Halt when another writer cannot be excluded.
46
+ 3. **Reproduce (RED)**: use `tdd-workflow` to write a failing test that reproduces the defect and watch it fail. Delete any pre-test implementation code.
47
+ 4. **Fix (GREEN)**: write the minimal change that makes the failing test pass, then watch it pass. Keep one concern only.
48
+ 5. **Verify**: use `verification-loop` to run the project's verify ladder, including build, types, and relevant tests. A green build proves only the mechanism. Confirm the original defect no longer reproduces.
49
+ 6. **Commit**: make one single-concern commit, staged by explicit filename. Never use `git add -A` or `git add .`. Recheck the branch, HEAD, owner lock, and real diff immediately before staging and committing. Use a Windows-safe commit message with a single-line `-m`, repeated `-m` paragraphs, or `git commit -F <tempfile>`. Do not use multi-line here-docs or here-strings.
50
+ 7. **Push and open the PR**: confirm the feature branch has no upstream to the protected base. Re-run the remote collision query immediately before pushing, require empty output, then push its name explicitly without force:
51
+ ```
52
+ git ls-remote --heads origin "refs/heads/<feature-branch>"
53
+ git push -u origin "<feature-branch>"
54
+ ```
55
+ Verify the remote tip equals local HEAD. Use `commit-commands:commit-push-pr` only when it accepts the explicit base and head below; otherwise open the PR directly and cite the plan or issue:
56
+ ```
57
+ gh pr create --base "<base>" --head "<feature-branch>"
58
+ gh pr view "<pr-number-or-url>" --json baseRefName,headRefName,headRefOid
59
+ ```
60
+ Require `baseRefName=<base>`, `headRefName=<feature-branch>`, and `headRefOid` equal to local HEAD. Record that exact PR URL or number for cleanup. A mismatch halts. Do not merge it.
61
+ 8. **Return before stopping**:
62
+ - Confirm the fix checkout is clean and every commit is pushed. If the captured `return_allowed` value is true, immediately revalidate that the initiating checkout remains clean, current-session-owned, and unreserved. Freeze the final decision and its reason. Any drift changes the final value to false.
63
+ - Persist a local cleanup receipt at `<git-common-dir>/continuous-improvement/ship-receipts/<pr-number>.json` with the PR URL and number, base, base SHA, feature branch, feature tip SHA, absolute worktree path, owner token, initiating checkout path, and final `return_allowed` decision and reason. Write a sibling temporary file first, atomically rename it into place, then read and parse it back before continuing. Keep the local path and owner token out of the public PR body and comments. If later drift appears before a return mutation, atomically downgrade the receipt to `return_allowed=false`, read it back, and leave the initiating checkout unchanged.
64
+ - Only when the final `return_allowed=true`, meaning the initiating checkout was clean, owned by the current session, and not reserved by another task, consider returning it. Fetch immediately before any switch, revalidate the remote base, and prove no other worktree has `<base>` checked out:
65
+ ```
66
+ git fetch --prune origin
67
+ ```
68
+ If local `<base>` exists and is not the initiating checkout's current branch, require it to be an ancestor of `origin/<base>`, update that branch ref before switching, then switch only after every network and ref check has passed:
69
+ ```
70
+ git merge-base --is-ancestor "refs/heads/<base>" "origin/<base>"
71
+ git branch -f "<base>" "origin/<base>"
72
+ git switch "<base>"
73
+ ```
74
+ If local `<base>` does not exist, create it without switching, then switch:
75
+ ```
76
+ git branch --track "<base>" "origin/<base>"
77
+ git switch "<base>"
78
+ ```
79
+ If the initiating checkout is already on `<base>`, require ancestry and use `git merge --ff-only "origin/<base>"`; a non-fast-forward halts without switching branches. Verify local `<base>` equals `origin/<base>`. If the fetch, remote-base validation, checked-out-elsewhere check, ancestry preflight, branch update, branch creation, fast-forward, or switch fails, leave the initiating checkout's branch and files unchanged and report the blocker. Never switch first and pull afterward.
80
+ - When `return_allowed=false`, leave the initiating checkout's branch and path unchanged even if it appears clean later. Another task may own that state. Report the recorded reason instead of switching it.
81
+ - A dirty initiating checkout is the exception: leave its branch and files exactly as found. Return the shell to that path, but do not carry its changes onto `<base>`. Report that default-branch return is intentionally blocked by preserved local work.
82
+ - During PR review, only the recorded owner or an explicit operator-confirmed handoff may change the retained fix worktree. After every authorized review-fix commit and push, rerun the verification ladder, require a clean worktree, verify the remote feature tip equals local HEAD, and query the same PR again for base, head, and `headRefOid`. Atomically replace the receipt's feature tip SHA with that verified `headRefOid`, then read and parse the receipt back. Halt and retain the worktree if any verification or receipt refresh fails.
83
+ - Stop with the PR open for human review. Keep an isolated fix worktree registered and owner-locked until the PR is merged so review fixes remain safe.
84
+ 9. **Clean up after the PR merges**: run cleanup from the initiating checkout or another retained worktree, never from inside the worktree being removed. Refresh remote state and verify the actual PR merge commit is contained in the detected base, including for squash merges:
85
+ ```
86
+ git fetch --prune origin
87
+ gh pr view "<pr-number-or-url>" --json state,mergeCommit,baseRefName,headRefName,headRefOid
88
+ git merge-base --is-ancestor "<merge-sha>" "origin/<base>"
89
+ ```
90
+ Read `<git-common-dir>/continuous-improvement/ship-receipts/<pr-number>.json` and compare every field with the registered worktree, current refs, PR response, and initiating checkout before cleanup. Halt on a missing, malformed, or mismatched receipt. Halt unless the PR state is `MERGED`, its base and head still match the recorded receipt, its pre-merge `headRefOid` identifies the pushed feature tip, and the ancestry check succeeds. Cleanup may proceed only as the original owner recorded in the local receipt, or after an explicit operator-confirmed handoff that proves the original session is inactive, replaces the owner token in that receipt atomically, and reruns `worktree-safety`. Never silently treat a foreign lock as stale. Confirm the isolated worktree is clean, its HEAD equals both the receipt's feature tip SHA and the PR `headRefOid`, it still carries the authorized owner lock, and it has no observed competing writer. A missing remote feature ref after fetch is expected when GitHub deleted the merged branch; if that ref still exists, require its tip to equal the receipt's feature tip. Recheck immediately before unlock, then release the lock and remove only the named worktree without pausing between commands:
91
+ ```
92
+ git worktree unlock "<worktree-path>"
93
+ git worktree remove "<worktree-path>"
94
+ ```
95
+ If state shifts or removal fails, halt and re-establish ownership instead of forcing. Do not run repository-wide pruning. Return or refresh the initiating checkout on `<base>` only when its recorded `return_allowed` decision permits it, using the same fetch-before-switch, checked-out-elsewhere, ancestry, pre-update, create-if-missing, and already-on-base procedures from step 8, then verify local and remote HEADs match. Delete the local feature branch only if `git branch -d "<feature-branch>"` accepts it. Squash merges may make safe deletion refuse; retain and report the branch instead of forcing it. Remove the local receipt only after cleanup and every permitted return check succeeds. A dirty or foreign-owned initiating checkout remains untouched.
96
+ 10. **Deploy receipt (advisory)**: after the human merge and deployment, `deploy-receipt` may verify that the deployed SHA matches the merge SHA. This skill does not deploy.
97
+
98
+ ## Hard stops
99
+
100
+ - The defect description is ambiguous or includes multiple concerns.
101
+ - Dirty changes may overlap the defect or their ownership is unclear.
102
+ - The live remote default branch cannot be resolved and refreshed.
103
+ - The remote default is ambiguous because the live HEAD query has zero or multiple matching `main` or `master` candidates.
104
+ - The selected feature branch or worktree path already exists.
105
+ - The remote feature-branch collision query fails or returns an existing ref.
106
+ - `worktree-safety` cannot prove the new checkout is registered, aligned, and owner-locked to this session.
107
+ - The branch, HEAD, or owner lock shifts after the ground-truth snapshot.
108
+ - Any verification step fails with a non-obvious fix.
109
+ - The fix would touch more than 15 non-generated files. Split it or use `release-train`.
110
+ - A push would target a protected branch or the remote feature tip cannot be verified.
111
+ - Post-merge state or merge-commit ancestry cannot be verified.
112
+ - Cleanup would require force or discard dirty, untracked, or unpushed work.
113
+
114
+ ## Refuse these anti-patterns
115
+
116
+ - **Stashing unrelated work**: an isolated worktree removes the need.
117
+ - **Moving dirty changes across branches**: preservation takes priority over returning to the default branch.
118
+ - **Hardcoding `main`**: detect the live remote default and support `main` or `master`.
119
+ - **Giving the feature branch a protected upstream**: create with `--no-track` and push the feature name explicitly.
120
+ - **Force cleanup**: never use `git worktree remove --force`, `git branch -D`, `git reset --hard`, or `git clean -fd`.
121
+ - **Repository-wide cleanup**: remove only the named worktree created by this run.
122
+ - **Foreign checkout return**: never switch a checkout without a recorded current-session ownership decision.
123
+ - **Silent lock takeover**: require explicit operator-confirmed handoff when cleanup runs under a different session.
124
+ - **Auto-merge**: never merge the PR this skill opens, even when CI is green.
125
+ - **Deploy**: never run a deploy. `deploy-receipt` only verifies after a human merges and deploys.
126
+ - **Bypass**: never use `--admin`, `--force`, or `--no-verify`.
127
+ - **Bundled concerns**: log unrelated defects as deferred follow-ups instead of adding them to the commit.
128
+
129
+ ## Composition
130
+
131
+ Route through `reconcile`, mandatory `worktree-safety`, `tdd-workflow`, `verification-loop`, `commit-commands:commit-push-pr`, the safe-return and post-merge cleanup rules above, then advisory `deploy-receipt`. Fall back to equivalent inline checks when a companion skill is unavailable, except ownership: no proven single-writer ledger means no source mutation.
132
+
133
+ ## Example
134
+
135
+ ```
136
+ /ship registration form accepts a negative deposit amount
137
+ ```
138
+
139
+ If the initiating checkout contains unrelated feature work, leave it untouched. Create an owner-locked no-upstream worktree from the verified `<base-sha>`, reproduce and fix the defect, verify and push one commit, open one explicitly targeted PR, and return the shell to the initiating path. After the PR merges, read the local receipt, freshly verify the merge commit, and remove only the clean temporary worktree. Switch the initiating checkout to the default branch only when that checkout is clean and current-session-owned.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "3.22.0",
3
+ "version": "3.23.0",
4
4
  "mode": "expert",
5
5
  "description": "Expert mode: tune confidence, manage instincts, and persist plans on disk. Adds safety, token-budget, and strategic-compact skills plus the /learn-eval command so long sessions stay sharp and learnings survive context resets.",
6
6
  "tools": [
package/skills/README.md CHANGED
@@ -22,6 +22,7 @@ These add concrete enforcement to the 7 Laws. Tier-1 skills are the always-on mi
22
22
  | `gateguard` | PreToolUse fact-forcing gate that blocks Edit/Write/destructive Bash until concrete investigation is presented | Law 1 (Research) |
23
23
  | `model-forward` | Standing stance: go with Claude Code and the model, not against it — skills are scaffolding that merges into the model; the durable core is goal-driven execution + guardrails | All 7 Laws (stance) |
24
24
  | `recall` | BM25 search over the observation log so "have I hit this before?" is answerable before re-deriving a fix | Law 1 (Research) |
25
+ | `ship` | Single-defect delivery path that preserves unrelated dirty work in an owner-locked worktree, verifies through TDD, opens one PR, and safely returns eligible clean checkouts to `main` or `master` | Laws 1, 3, and 4 |
25
26
  | `tdd-workflow` | RED→GREEN→REFACTOR enforcement, 80%+ coverage gate across unit/integration/E2E | Law 3 (One Thing), Law 4 (Verify) |
26
27
  | `verification-loop` | Six-phase verification (build, types, lint, tests, security, diff) with a structured PASS/FAIL report | Law 4 (Verify Before Reporting) |
27
28