tracerkit 1.18.3 → 1.19.1

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/README.md CHANGED
@@ -21,7 +21,16 @@ Named after the tracer-bullet technique from _The Pragmatic Programmer_: **Trace
21
21
 
22
22
  AI assistants work best with small, well-scoped tasks — not sprawling layers or flat task lists. TracerKit structures every feature as **tracer-bullet vertical slices**: each phase cuts through every layer (schema → service → API → UI → tests) and is demoable on its own. Integration problems surface early, not at the end.
23
23
 
24
- Three skills drive the workflow: **define** (`/tk:prd`), **plan** (`/tk:plan`), **verify** (`/tk:check`). The AI reads your specs directly, counts progress, and marks completed work done. Pure Markdown, zero runtime deps.
24
+ Four skills drive the workflow: **define** (`/tk:prd`), **plan** (`/tk:plan`), **build** (`/tk:build`), **verify** (`/tk:check`). The AI reads your specs directly, counts progress, and marks completed work done. Pure Markdown, zero runtime deps.
25
+
26
+ ```
27
+ DEFINE PLAN BUILD VERIFY
28
+ /tk:prd ───▶ /tk:plan ───▶ /tk:build ───▶ /tk:check
29
+ │ │ │ │
30
+ ▼ ▼ ▼ ▼
31
+ PRD doc Phased plan Implement phase Pass/fail
32
+ + feedback loops + status
33
+ ```
25
34
 
26
35
  ## Get Started
27
36
 
@@ -111,7 +120,9 @@ AI: Phase 1 — Theme visible end-to-end
111
120
  Written .tracerkit/plans/dark-mode-support.md
112
121
  Run `/tk:check dark-mode-support` when ready?
113
122
 
114
- You: # open the plan, implement each phase, write tests...
123
+ You: /tk:build dark-mode-support
124
+ AI: Phase 1 — Theme visible end-to-end (3 remaining)
125
+ Implementing... all checks pass. Commit?
115
126
 
116
127
  You: /tk:check dark-mode-support
117
128
  AI: Status: done | Total: 5/5
@@ -131,49 +142,28 @@ AI: | Feature | Status | Age | Progress | Next
131
142
 
132
143
  See [Examples](docs/examples.md) for full walkthroughs.
133
144
 
134
- <details>
135
- <summary>GitHub Issues as storage backend</summary>
136
-
137
- Same skills, same workflow. Storage is configured per-project:
138
-
139
- ```bash
140
- tracerkit config storage github # set current project to use GitHub
141
- ```
142
-
143
- PRDs and plans become GitHub Issues with `tk:prd` and `tk:plan` labels. On `/tk:check` pass, issues are closed with `completed` reason and any related PRs are linked automatically. Each project can use a different backend; local is the default. See [Configuration](docs/configuration.md) for details.
144
-
145
- To migrate existing artifacts between backends:
146
-
147
- ```bash
148
- tracerkit migrate-storage # local→github or github→local (auto-detected)
149
- ```
150
-
151
- Direction is inferred from the current `storage` config. All artifacts are migrated, existing duplicates are skipped, and the config is flipped to the target backend. Source artifacts are left intact as backup.
152
-
153
- </details>
154
-
155
145
  ## Skills
156
146
 
157
- | Skill | What it does | Output |
158
- | ------------------ | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
159
- | `/tk:prd <idea>` | Interview → codebase scan → structured PRD | `.tracerkit/prds/<slug>.md` or GitHub Issue |
160
- | `/tk:plan <slug>` | PRD → phased vertical slices, each demoable on its own | `.tracerkit/plans/<slug>.md` or GitHub Issue |
161
- | `/tk:brief` | Feature dashboard with progress and suggested focus | Terminal only, no files |
162
- | `/tk:check [slug]` | Verify done-when checkboxes against codebase and tests | Verdict block in plan. On `done`: status updated (local) or issues closed + PRs linked (GitHub) |
147
+ | Skill | What it does | Output |
148
+ | ------------------ | ------------------------------------------------------ | --------------------------------------------------- |
149
+ | `/tk:prd <idea>` | Interview → codebase scan → structured PRD | `.tracerkit/prds/<slug>.md` |
150
+ | `/tk:plan <slug>` | PRD → phased vertical slices, each demoable on its own | `.tracerkit/plans/<slug>.md` |
151
+ | `/tk:build <slug>` | Implement next incomplete phase, run feedback loops | Code changes + checked items in plan |
152
+ | `/tk:brief` | Feature dashboard with progress and suggested focus | Terminal only, no files |
153
+ | `/tk:check [slug]` | Verify done-when checkboxes against codebase and tests | Verdict block in plan, status updated when all pass |
163
154
 
164
155
  ## Docs
165
156
 
166
- | Document | Description |
167
- | ------------------------------------------------ | ---------------------------------------------------------- |
168
- | [Examples](docs/examples.md) | Walk through end-to-end usage scenarios |
169
- | [CLI Reference](docs/cli-reference.md) | Commands: init, update, config, migrate-storage, uninstall |
170
- | [Configuration](docs/configuration.md) | Storage backends, GitHub options, custom paths |
171
- | [Metadata Lifecycle](docs/metadata-lifecycle.md) | Understand YAML frontmatter states and transitions |
172
- | [Comparison](docs/comparison.md) | Compare TracerKit to Spec Kit, Kiro, and OpenSpec |
173
- | [Cursor Setup](docs/cursor-setup.md) | Use TracerKit skills in Cursor |
174
- | [Gemini CLI Setup](docs/gemini-cli-setup.md) | Use TracerKit skills in Gemini CLI |
175
- | [Copilot Setup](docs/copilot-setup.md) | Use TracerKit skills in GitHub Copilot |
176
- | [OpenCode Setup](docs/opencode-setup.md) | Use TracerKit skills in OpenCode |
157
+ | Document | Description |
158
+ | ------------------------------------------------ | -------------------------------------------------- |
159
+ | [Examples](docs/examples.md) | Walk through end-to-end usage scenarios |
160
+ | [CLI Reference](docs/cli-reference.md) | Commands: init, update, uninstall |
161
+ | [Metadata Lifecycle](docs/metadata-lifecycle.md) | Understand YAML frontmatter states and transitions |
162
+ | [Comparison](docs/comparison.md) | Compare TracerKit to Spec Kit, Kiro, and OpenSpec |
163
+ | [Cursor Setup](docs/cursor-setup.md) | Use TracerKit skills in Cursor |
164
+ | [Gemini CLI Setup](docs/gemini-cli-setup.md) | Use TracerKit skills in Gemini CLI |
165
+ | [Copilot Setup](docs/copilot-setup.md) | Use TracerKit skills in GitHub Copilot |
166
+ | [OpenCode Setup](docs/opencode-setup.md) | Use TracerKit skills in OpenCode |
177
167
 
178
168
  ## Contributing
179
169
 
package/dist/bin.js CHANGED
@@ -1,99 +1,44 @@
1
1
  #!/usr/bin/env node
2
- import { a as e, f as t, i as n, l as r, n as i, o as a, p as o, r as s, s as c, t as l, u } from "./uninstall-CNw_7khV.js";
3
- import { existsSync as d, readFileSync as f, statSync as p } from "node:fs";
4
- import { dirname as m, join as h, resolve as g } from "node:path";
5
- import { fileURLToPath as _ } from "node:url";
6
- import { homedir as v } from "node:os";
7
- //#region src/commands/config.ts
8
- function y(e, t) {
9
- let [n, r] = t;
10
- return n ? r ? S(e, n, r) : x(e, n) : b(e);
11
- }
12
- function b(e) {
13
- let n = t(e), r = n.storage === "local" ? {
14
- storage: n.storage,
15
- paths: n.paths
16
- } : n;
17
- return JSON.stringify(r, null, 2).split("\n");
18
- }
19
- function x(e, n) {
20
- let r = w(t(e), n);
21
- return r === void 0 ? [`Unknown key: ${n}`] : typeof r == "object" ? [JSON.stringify(r, null, 2)] : [String(r)];
22
- }
23
- function S(e, t, n) {
24
- o(e, T(t, n));
25
- let r = [`✓ Set ${t} = ${n}`];
26
- return C(e, r), r;
27
- }
28
- function C(n, r) {
29
- u.some((e) => d(h(n, ".claude", "skills", e))) && (e(n, t(n)), r.push("✓ Skills re-rendered"));
30
- }
31
- function w(e, t) {
32
- let n = t.split("."), r = e;
33
- for (let e of n) {
34
- if (typeof r != "object" || !r) return;
35
- r = r[e];
36
- }
37
- return r;
38
- }
39
- function T(e, t) {
40
- let n = e.split("."), r = {}, i = r;
41
- for (let e = 0; e < n.length - 1; e++) {
42
- let t = {};
43
- i[n[e]] = t, i = t;
44
- }
45
- return i[n[n.length - 1]] = t, r;
46
- }
47
- //#endregion
2
+ import { a as e, i as t, n, r, s as i, t as a } from "./uninstall-4Qp75twq.js";
3
+ import { readFileSync as o } from "node:fs";
4
+ import { dirname as s, resolve as c } from "node:path";
5
+ import { fileURLToPath as l } from "node:url";
6
+ import { homedir as u } from "node:os";
48
7
  //#region src/cli.ts
49
- var { version: E } = JSON.parse(f(g(m(_(import.meta.url)), "..", "package.json"), "utf8")), D = Math.max(...a.map((e) => `${e.name} ${e.args}`.length)), O = [
8
+ var { version: d } = JSON.parse(o(c(s(l(import.meta.url)), "..", "package.json"), "utf8")), f = Math.max(...t.map((e) => `${e.name} ${e.args}`.length)), p = [
50
9
  "Usage: tracerkit <command> [path]",
51
10
  "",
52
11
  "Commands:",
53
- ...a.map((e) => ` ${`${e.name} ${e.args}`.padEnd(D + 2)}${e.desc}`),
12
+ ...t.map((e) => ` ${`${e.name} ${e.args}`.padEnd(f + 2)}${e.desc}`),
54
13
  "",
55
14
  "Options:",
56
15
  " --force Overwrite modified files during update",
57
16
  " --help, -h Show this help message",
58
17
  " --version, -v Print version",
59
18
  "",
60
- "init/update/uninstall default to the home directory when no path is given.",
61
- "config defaults to the current working directory."
19
+ "Defaults to the home directory when no path is given."
62
20
  ];
63
- function k(e) {
64
- if (!e) return !1;
65
- try {
66
- return p(g(e)).isDirectory();
67
- } catch {
68
- return !1;
69
- }
70
- }
71
- function A(e, t = v()) {
21
+ function m(e, t = u()) {
72
22
  let n = e.find((e) => !e.startsWith("-"));
73
- return n ? g(n) : t;
74
- }
75
- function j(e) {
76
- if (e.includes(r.help) || e.includes("-h")) return O;
77
- if (e.includes(r.version) || e.includes("-v")) return [`tracerkit/${E}`];
78
- let t = e[0], a = e.slice(1);
79
- if (c.includes(t)) return [`"${t}" has been removed — skills handle this now.`, "Run `tracerkit update` to get the latest skills."];
80
- switch (t) {
81
- case "init": return s(A(a));
23
+ return n ? c(n) : t;
24
+ }
25
+ function h(t) {
26
+ if (t.includes(i.help) || t.includes("-h")) return p;
27
+ if (t.includes(i.version) || t.includes("-v")) return [`tracerkit/${d}`];
28
+ let o = t[0], s = t.slice(1);
29
+ if (e.includes(o)) return [`"${o}" has been removed — skills handle this now.`, "Run `tracerkit update` to get the latest skills."];
30
+ switch (o) {
31
+ case "init": return n(m(s));
82
32
  case "update": {
83
- let e = a.includes(r.force), t = n(A(a.filter((e) => e !== r.force)), { force: e });
33
+ let e = s.includes(i.force), t = r(m(s.filter((e) => e !== i.force)), { force: e });
84
34
  return t.push("", "Updated to the latest TracerKit."), t.push("If using Claude Code, restart your session to load changes."), t;
85
35
  }
86
- case "config": {
87
- let e = k(a[0]);
88
- return y(e ? g(a[0]) : process.cwd(), e ? a.slice(1) : a);
89
- }
90
- case "uninstall": return l(A(a));
91
- case "migrate-storage": return i(k(a[0]) ? g(a[0]) : process.cwd());
92
- default: return O;
36
+ case "uninstall": return a(m(s));
37
+ default: return p;
93
38
  }
94
39
  }
95
40
  //#endregion
96
41
  //#region src/bin.ts
97
- var M = j(process.argv.slice(2));
98
- for (let e of M) console.log(e);
42
+ var g = h(process.argv.slice(2));
43
+ for (let e of g) console.log(e);
99
44
  //#endregion
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { c as e, i as t, n, o as r, r as i, t as a, u as o } from "./uninstall-CNw_7khV.js";
2
- export { r as COMMANDS, e as DEPRECATED_SKILLS, o as SKILL_NAMES, i as init, n as migrateStorage, a as uninstall, t as update };
1
+ import { c as e, i as t, n, o as r, r as i, t as a } from "./uninstall-4Qp75twq.js";
2
+ export { t as COMMANDS, r as DEPRECATED_SKILLS, e as SKILL_NAMES, n as init, a as uninstall, i as update };
@@ -0,0 +1,130 @@
1
+ import { existsSync as e, mkdirSync as t, readFileSync as n, readdirSync as r, rmSync as i, writeFileSync as a } from "node:fs";
2
+ import { dirname as o, join as s } from "node:path";
3
+ import { createHash as c } from "node:crypto";
4
+ import { fileURLToPath as l } from "node:url";
5
+ var u = [
6
+ "tk:brief",
7
+ "tk:prd",
8
+ "tk:plan",
9
+ "tk:build",
10
+ "tk:check"
11
+ ], d = ["tk:verify"], f = {
12
+ force: "--force",
13
+ help: "--help",
14
+ version: "--version"
15
+ }, p = [
16
+ "brief",
17
+ "progress",
18
+ "archive",
19
+ "config",
20
+ "migrate-storage"
21
+ ], m = [
22
+ {
23
+ name: "init",
24
+ args: "[path]",
25
+ desc: "Install skills to ~/.claude/skills/ (or [path] if given)"
26
+ },
27
+ {
28
+ name: "update",
29
+ args: "[path]",
30
+ desc: "Refresh unchanged files from latest version, skip modified"
31
+ },
32
+ {
33
+ name: "uninstall",
34
+ args: "[path]",
35
+ desc: "Remove TracerKit skill directories, keep .tracerkit/ artifacts"
36
+ }
37
+ ], h = s(o(l(import.meta.url)), "..", "skills");
38
+ function g(e, t = "") {
39
+ let n = r(e, { withFileTypes: !0 }), i = [];
40
+ for (let r of n) {
41
+ let n = t ? `${t}/${r.name}` : r.name;
42
+ r.isDirectory() ? i.push(...g(s(e, r.name), n)) : i.push(n);
43
+ }
44
+ return i.sort();
45
+ }
46
+ function _(e) {
47
+ return `.claude/skills/tk:${e}`;
48
+ }
49
+ function v(e) {
50
+ return e.slice(18);
51
+ }
52
+ function y(e, r) {
53
+ let i = r ?? g(h).map(_);
54
+ for (let r of i) {
55
+ let i = s(h, v(r)), c = s(e, r);
56
+ t(o(c), { recursive: !0 }), a(c, n(i, "utf8"));
57
+ }
58
+ return { copied: i };
59
+ }
60
+ function b(e) {
61
+ return c("sha256").update(e).digest("hex");
62
+ }
63
+ function x(t) {
64
+ let r = g(h).map(_), i = [], a = [], o = [];
65
+ for (let c of r) {
66
+ let r = s(t, c);
67
+ if (!e(r)) o.push(c);
68
+ else {
69
+ let e = n(s(h, v(c)), "utf8");
70
+ b(Buffer.from(e)) === b(n(r)) ? i.push(c) : a.push(c);
71
+ }
72
+ }
73
+ return {
74
+ unchanged: i,
75
+ modified: a,
76
+ missing: o
77
+ };
78
+ }
79
+ //#endregion
80
+ //#region src/commands/update.ts
81
+ function S(t, n) {
82
+ if (!u.some((n) => e(s(t, ".claude", "skills", n)))) throw Error("TracerKit not initialized — run `tracerkit init` first");
83
+ let { unchanged: r, modified: a, missing: o } = x(t), c = [];
84
+ for (let n of d) {
85
+ let r = s(t, ".claude", "skills", n);
86
+ e(r) && (i(r, {
87
+ recursive: !0,
88
+ force: !0
89
+ }), c.push(`✗ .claude/skills/${n}/ removed (deprecated)`));
90
+ }
91
+ let l = n?.force ?? !1, f = [
92
+ ...r,
93
+ ...o,
94
+ ...l ? a : []
95
+ ];
96
+ if (f.length > 0) {
97
+ y(t, f);
98
+ for (let e of r) c.push(`✓ ${e}`);
99
+ for (let e of o) c.push(`✓ ${e} (added)`);
100
+ if (l) for (let e of a) c.push(`✓ ${e} (replaced)`);
101
+ }
102
+ if (!l && a.length > 0) {
103
+ for (let e of a) c.push(`⚠ ${e} (skipped — modified)`);
104
+ c.push("", "Run `tracerkit update --force` to replace modified files with latest versions.");
105
+ }
106
+ return c;
107
+ }
108
+ //#endregion
109
+ //#region src/commands/init.ts
110
+ function C(t) {
111
+ if (u.some((n) => e(s(t, ".claude", "skills", n)))) return S(t, { force: !1 });
112
+ let { copied: n } = y(t);
113
+ return n.map((e) => `✓ ${e}`);
114
+ }
115
+ //#endregion
116
+ //#region src/commands/uninstall.ts
117
+ function w(t) {
118
+ if (!u.some((n) => e(s(t, ".claude", "skills", n)))) throw Error("TracerKit not initialized — nothing to uninstall");
119
+ let n = [];
120
+ for (let r of u) {
121
+ let a = s(t, ".claude", "skills", r);
122
+ e(a) && (i(a, {
123
+ recursive: !0,
124
+ force: !0
125
+ }), n.push(`✗ .claude/skills/${r}/ removed`));
126
+ }
127
+ return n;
128
+ }
129
+ //#endregion
130
+ export { p as a, u as c, m as i, C as n, d as o, S as r, f as s, w as t };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tracerkit",
3
- "version": "1.18.3",
4
- "description": "Spec-driven workflow for AI coding agents — PRD → plan → verify. Pure Markdown skills, zero runtime deps.",
3
+ "version": "1.19.1",
4
+ "description": "Spec-driven workflow for AI coding agents — PRD → plan → build → verify. Pure Markdown skills, zero runtime deps.",
5
5
  "license": "MIT",
6
6
  "author": {
7
7
  "name": "helderberto",
@@ -1,60 +1,27 @@
1
1
  ---
2
- description: Session briefing — shows active features, progress, and suggested focus. Use at the start of a session to orient.
2
+ description: Session briefing — shows active features, progress, and suggested focus. Use at the start of a session, when asking what to work on, or when checking active features.
3
3
  ---
4
4
 
5
- **Config**: read `.tracerkit/config.json` (default: `local`). Follow matching `<!-- if:local/github -->` blocks.
6
-
7
5
  # Session Briefing
8
6
 
9
7
  Overview of active features, progress, and suggested focus.
10
8
 
11
9
  ## Pre-loaded context
12
10
 
13
- <!-- if:local -->
14
-
15
11
  - Available PRDs: !`ls .tracerkit/prds/*.md 2>/dev/null || echo "(none)"`
16
- <!-- end:local -->
17
- <!-- if:github -->
18
- - Available PRDs: list open GitHub Issues with label `{{github.labels.prd}}`
19
- <!-- end:github -->
20
12
 
21
13
  ## Algorithm
22
14
 
23
15
  ### 1. Discover features
24
16
 
25
- <!-- if:local -->
26
-
27
17
  For each `.md` file in `.tracerkit/prds/`: parse frontmatter, extract `status` and `created`. Skip `status: done`. Slug = filename without `.md`.
28
18
 
29
- <!-- end:local -->
30
- <!-- if:github -->
31
-
32
- List open GitHub Issues with label `{{github.labels.prd}}`:
33
-
34
- 1. For each issue, parse the `<!-- tk:metadata -->` comment in the body
35
- 2. Extract `status` and `created` fields from the metadata
36
- 3. Also check labels: `tk:created`, `tk:in-progress`
37
- 4. Skip issues with `tk:done` label
38
- 5. The slug is extracted from the title: `[{{github.labels.prd}}] <slug>: ...`
39
- <!-- end:github -->
40
-
41
19
  ### 2. Count progress from plans
42
20
 
43
- <!-- if:local -->
44
-
45
21
  For each slug with a plan at `.tracerkit/plans/<slug>.md`:
46
22
 
47
23
  Count `- [x]` and `- [ ]` lines under each `## Phase N` heading. Sum → `checked/total`. First unchecked item → "Next" (strip trailing `[tag]`). No plan → `—`.
48
24
 
49
- <!-- end:local -->
50
- <!-- if:github -->
51
-
52
- For each slug, find plan issue with label `{{github.labels.plan}}` and matching title. If found:
53
-
54
- Count `- [x]` and `- [ ]` lines under each `## Phase N` heading. Sum → `checked/total`. First unchecked item → "Next" (strip trailing `[tag]`). No plan → `—`.
55
-
56
- <!-- end:github -->
57
-
58
25
  ### 3. Build the table
59
26
 
60
27
  Sort by `created` ascending (no-date last). Age from `created`:
@@ -89,13 +56,8 @@ Append below the table:
89
56
 
90
57
  ### 5. Offer next steps
91
58
 
92
- <!-- if:local -->
93
-
94
- Options: continue focused feature (read plan at `.tracerkit/plans/<slug>.md`), `/tk:prd` for new feature, `/tk:check <slug>` for progress.
95
-
96
- <!-- end:local -->
97
- <!-- if:github -->
98
-
99
- Options: continue focused feature (read plan issue), `/tk:prd` for new feature, `/tk:check <slug>` for progress.
59
+ Present options and wait for the user's choice:
100
60
 
101
- <!-- end:github -->
61
+ 1. Continue focused feature — read plan at `.tracerkit/plans/<slug>.md` (Recommended)
62
+ 2. Start new feature — `/tk:prd`
63
+ 3. Check progress — `/tk:check <slug>`
@@ -0,0 +1,164 @@
1
+ ---
2
+ description: Implement one phase of a plan. Reads plan, finds next incomplete phase, implements it, runs feedback loops, marks checkboxes, offers commit. One phase per invocation. Use when the user wants to implement, code, build, or work on the next phase of a plan.
3
+ argument-hint: '[slug]'
4
+ ---
5
+
6
+ # Build Phase
7
+
8
+ Implement the next incomplete phase of a plan — one phase per invocation.
9
+
10
+ **Context window**: recommend `/clear` before starting to maximize token budget.
11
+
12
+ **Interactive prompts**: present options as a numbered list and wait for the user's choice.
13
+
14
+ ## Pre-loaded context
15
+
16
+ - Available plans: !`ls .tracerkit/plans/*.md 2>/dev/null || echo "(none)"`
17
+
18
+ ## Input
19
+
20
+ The argument (if provided) is: $ARGUMENTS
21
+
22
+ Use argument as `<slug>`. If empty, list plans as numbered options and wait for the user's choice.
23
+
24
+ Accepts slug or `@file` reference:
25
+
26
+ ```
27
+ /tk:build dark-mode-support
28
+ /tk:build @.tracerkit/plans/dark-mode-support.md
29
+ ```
30
+
31
+ If argument starts with `@`, treat it as a file path — read that file directly as the plan.
32
+
33
+ ## Workflow
34
+
35
+ ### 1. Load the plan
36
+
37
+ Read `.tracerkit/plans/<slug>.md`. If missing, list plans as numbered options and wait for the user's choice.
38
+
39
+ ### 2. Find the next incomplete phase
40
+
41
+ Scan the plan for `## Phase N` headings. For each phase, count `- [ ]` and `- [x]` checkboxes.
42
+
43
+ The **next incomplete phase** is the first phase that has at least one unchecked `- [ ]` item.
44
+
45
+ If all phases are complete (zero unchecked items across all phases):
46
+
47
+ > All phases complete. Run `/tk:check <slug>` to verify.
48
+
49
+ Stop here.
50
+
51
+ ### 3. Present the phase
52
+
53
+ Show the phase title and its unchecked items:
54
+
55
+ ```
56
+ Phase N — <title> (M remaining)
57
+ - [ ] First unchecked item
58
+ - [ ] Second unchecked item
59
+ ```
60
+
61
+ ### 4. Offer a feature branch
62
+
63
+ If on the default branch (main/master), ask:
64
+
65
+ > Create branch `feat/<slug>`?
66
+ >
67
+ > 1. Yes, create branch (Recommended)
68
+ > 2. No, stay on current branch
69
+
70
+ If accepted, create and switch to the branch.
71
+
72
+ If already on a feature branch, skip this step.
73
+
74
+ ### 5. Implement the phase
75
+
76
+ Work through each unchecked item in order. For each item:
77
+
78
+ 1. Read the plan's architectural decisions and the current item's context
79
+ 2. Explore relevant code to understand existing patterns and conventions
80
+ 3. Implement the change — follow the project's conventions (CLAUDE.md, linter config, test setup)
81
+ 4. Write tests alongside implementation (follow the project's existing test patterns)
82
+
83
+ **Do not** impose coding rules, style, or conventions. Follow what the project already uses.
84
+
85
+ **Do not** implement items from other phases. Stay within the current phase boundary.
86
+
87
+ ### 6. Run feedback loops
88
+
89
+ After implementing the phase, detect and run available project scripts. Check `package.json` for these scripts (run only what exists):
90
+
91
+ | Script pattern | Purpose |
92
+ | ---------------------------------- | ------------- |
93
+ | `typecheck`, `tsc`, `type-check` | Type checking |
94
+ | `test`, `vitest`, `jest` | Tests |
95
+ | `lint`, `eslint` | Linting |
96
+ | `format:check`, `prettier --check` | Formatting |
97
+
98
+ Run each detected script. If any fails:
99
+
100
+ 1. Read the error output
101
+ 2. Fix the issue
102
+ 3. Re-run the failing script
103
+ 4. Repeat until all pass (max 3 attempts per script)
104
+
105
+ If a script still fails after 3 attempts, treat it as a **blocker** — pause and ask the user for help:
106
+
107
+ > **Blocker**: `<script>` fails after 3 attempts.
108
+ > Last error: `<error summary>`
109
+ >
110
+ > How to proceed?
111
+ >
112
+ > 1. I'll fix it — pause and wait
113
+ > 2. Skip this check and continue
114
+ > 3. Abort this phase
115
+
116
+ Wait for the user's response before continuing.
117
+
118
+ ### 7. Mark checkboxes
119
+
120
+ After all feedback loops pass, for each completed item change `- [ ]` → `- [x]` in `.tracerkit/plans/<slug>.md`.
121
+
122
+ ### 8. Offer commit
123
+
124
+ Present the changes and ask:
125
+
126
+ > Phase N complete — all checks pass. Commit?
127
+ >
128
+ > 1. Yes, commit
129
+ > 2. No, I'll review first
130
+
131
+ If the user chooses to commit:
132
+
133
+ 1. Stage the implementation files (not `.tracerkit/` artifacts unless the project dogfoods TracerKit)
134
+ 2. Create a commit with a message following the project's commit conventions
135
+ 3. Confirm: "Committed. Run `/tk:build <slug>` for Phase N+1, or `/tk:check <slug>` to verify."
136
+
137
+ If the user chooses to review:
138
+
139
+ > Ready for review. Run `/tk:build <slug>` again when ready to continue.
140
+
141
+ ### 9. Blockers during implementation
142
+
143
+ If implementation requires something the agent cannot provide (API key, external service, manual setup, design decision):
144
+
145
+ > **Blocker**: <description of what's needed>
146
+ >
147
+ > How to proceed?
148
+ >
149
+ > 1. I've resolved it — continue
150
+ > 2. Skip this item for now
151
+ > 3. Abort this phase
152
+
153
+ Wait for the user's response. Never guess or work around a blocker silently.
154
+
155
+ ## Rules
156
+
157
+ - **One phase per invocation** — never auto-advance to the next phase
158
+ - **Never modify PRD content** — the PRD is read-only
159
+ - **Never modify plan content** beyond marking checkboxes `[x]`
160
+ - **Never skip a phase** — phases must be completed in order
161
+ - **Never impose conventions** — follow the project's existing setup
162
+ - **HITL at every decision point** — commits, blockers, and branch creation require user approval
163
+ - **Feedback loops are mandatory** — always run available checks before marking items complete
164
+ - **Do not push to remote** — only commit locally