liteagents 3.0.0 → 3.5.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/CHANGELOG.md +122 -1
- package/README.md +113 -169
- package/installer/cli.js +4 -2
- package/package.json +4 -3
- package/packages/ampcode/AGENT.md +10 -18
- package/packages/ampcode/agents/code-developer.md +11 -17
- package/packages/ampcode/agents/orchestrator.md +1 -1
- package/packages/ampcode/agents/quality-assurance.md +3 -1
- package/packages/ampcode/{commands/brainstorming.md → skills/brainstorming/SKILL.md} +2 -3
- package/packages/ampcode/{commands/branch-review.md → skills/branch-review/SKILL.md} +13 -13
- package/packages/{claude/commands/docs-builder.md → ampcode/skills/docs-builder/SKILL.md} +1 -1
- package/packages/ampcode/{commands/live-canvas.md → skills/live-canvas/SKILL.md} +8 -4
- package/packages/ampcode/{commands/refactor.md → skills/refactor/SKILL.md} +49 -7
- package/packages/ampcode/{commands/release.md → skills/release/SKILL.md} +4 -4
- package/packages/{claude/commands → ampcode/skills}/remember/AGENT_RULES.md +44 -84
- package/packages/ampcode/{commands/remember.md → skills/remember/SKILL.md} +11 -6
- package/packages/ampcode/{commands → skills}/remember/friction.cjs +0 -0
- package/packages/ampcode/{commands → skills}/remember/stub-check.cjs +28 -19
- package/packages/ampcode/{commands → skills}/remember/sync-rules.cjs +28 -19
- package/packages/{claude/commands → ampcode/skills}/remember/version-check.cjs +1 -1
- package/packages/ampcode/skills/root-cause/SKILL.md +220 -0
- package/packages/ampcode/{commands/trace-back → skills/root-cause}/find-polluter.sh +0 -0
- package/packages/{claude/commands/security.md → ampcode/skills/security/SKILL.md} +1 -1
- package/packages/{claude/commands/ship.md → ampcode/skills/ship/SKILL.md} +1 -1
- package/packages/ampcode/skills/skill-creator/LICENSE.txt +202 -0
- package/packages/ampcode/{commands/skill-creator.md → skills/skill-creator/SKILL.md} +1 -2
- package/packages/ampcode/{commands → skills}/skill-creator/scripts/init_skill.py +0 -0
- package/packages/ampcode/{commands → skills}/skill-creator/scripts/package_skill.py +0 -0
- package/packages/ampcode/{commands → skills}/skill-creator/scripts/quick_validate.py +0 -0
- package/packages/ampcode/{commands/stash.md → skills/stash/SKILL.md} +2 -1
- package/packages/{claude/commands/test-generate.md → ampcode/skills/test-generate/SKILL.md} +2 -2
- package/packages/ampcode/variants.json +2 -2
- package/packages/claude/CLAUDE.md +10 -17
- package/packages/claude/agents/code-developer.md +11 -17
- package/packages/claude/agents/orchestrator.md +2 -3
- package/packages/claude/agents/quality-assurance.md +3 -1
- package/packages/claude/skills/brainstorming/SKILL.md +1 -2
- package/packages/claude/{commands/branch-review.md → skills/branch-review/SKILL.md} +1 -1
- package/packages/{ampcode/commands/docs-builder.md → claude/skills/docs-builder/SKILL.md} +7 -7
- package/packages/claude/skills/live-canvas/SKILL.md +5 -1
- package/packages/claude/{commands/refactor.md → skills/refactor/SKILL.md} +45 -3
- package/packages/claude/{commands/release.md → skills/release/SKILL.md} +1 -1
- package/packages/{ampcode/commands → claude/skills}/remember/AGENT_RULES.md +38 -78
- package/packages/claude/{commands/remember.md → skills/remember/SKILL.md} +11 -6
- package/packages/claude/{commands → skills}/remember/friction.cjs +0 -0
- package/packages/claude/{commands → skills}/remember/stub-check.cjs +28 -19
- package/packages/claude/{commands → skills}/remember/sync-rules.cjs +28 -19
- package/packages/{ampcode/commands → claude/skills}/remember/version-check.cjs +3 -3
- package/packages/claude/skills/root-cause/SKILL.md +220 -0
- package/packages/{ampcode/commands/security.md → claude/skills/security/SKILL.md} +2 -2
- package/packages/{ampcode/commands/ship.md → claude/skills/ship/SKILL.md} +2 -2
- package/packages/claude/skills/skill-creator/SKILL.md +1 -2
- package/packages/claude/{commands/stash.md → skills/stash/SKILL.md} +2 -1
- package/packages/{ampcode/commands/test-generate.md → claude/skills/test-generate/SKILL.md} +3 -3
- package/packages/claude/variants.json +1 -2
- package/packages/droid/AGENTS.md +10 -15
- package/packages/droid/commands/brainstorming.md +1 -4
- package/packages/droid/commands/branch-review.md +11 -14
- package/packages/droid/commands/docs-builder.md +0 -3
- package/packages/droid/commands/live-canvas.md +7 -5
- package/packages/droid/commands/refactor.md +47 -8
- package/packages/droid/commands/release.md +2 -5
- package/packages/droid/commands/remember/AGENT_RULES.md +38 -78
- package/packages/droid/commands/remember/stub-check.cjs +28 -19
- package/packages/droid/commands/remember/sync-rules.cjs +28 -19
- package/packages/droid/commands/remember/version-check.cjs +1 -1
- package/packages/droid/commands/remember.md +6 -4
- package/packages/droid/commands/root-cause.md +218 -0
- package/packages/droid/commands/security.md +0 -3
- package/packages/droid/commands/ship.md +0 -3
- package/packages/droid/commands/skill-creator/LICENSE.txt +202 -0
- package/packages/droid/commands/skill-creator.md +0 -4
- package/packages/droid/commands/stash.md +0 -2
- package/packages/droid/commands/test-generate.md +1 -4
- package/packages/droid/droids/1-create-prd.md +6 -2
- package/packages/droid/droids/2-generate-tasks.md +1 -2
- package/packages/droid/droids/3-process-task-list.md +1 -2
- package/packages/droid/droids/code-developer.md +12 -19
- package/packages/droid/droids/feature-planner.md +1 -2
- package/packages/droid/droids/market-researcher.md +1 -2
- package/packages/droid/droids/orchestrator.md +1 -2
- package/packages/droid/droids/quality-assurance.md +4 -3
- package/packages/droid/droids/system-architect.md +1 -2
- package/packages/droid/droids/ui-designer.md +1 -2
- package/packages/opencode/AGENTS.md +10 -15
- package/packages/opencode/agent/code-developer.md +11 -17
- package/packages/opencode/agent/quality-assurance.md +3 -1
- package/packages/opencode/command/brainstorming.md +1 -4
- package/packages/opencode/command/branch-review.md +11 -15
- package/packages/opencode/command/docs-builder.md +0 -4
- package/packages/opencode/command/live-canvas.md +7 -5
- package/packages/opencode/command/refactor.md +47 -9
- package/packages/opencode/command/release.md +2 -5
- package/packages/opencode/command/remember/AGENT_RULES.md +38 -78
- package/packages/opencode/command/remember/stub-check.cjs +28 -19
- package/packages/opencode/command/remember/sync-rules.cjs +28 -19
- package/packages/opencode/command/remember/version-check.cjs +1 -1
- package/packages/opencode/command/remember.md +6 -4
- package/packages/opencode/command/root-cause.md +218 -0
- package/packages/opencode/command/security.md +0 -4
- package/packages/opencode/command/ship.md +0 -3
- package/packages/opencode/command/skill-creator/LICENSE.txt +202 -0
- package/packages/opencode/command/skill-creator.md +0 -4
- package/packages/opencode/command/stash.md +0 -3
- package/packages/opencode/command/test-generate.md +1 -5
- package/packages/opencode/opencode.jsonc +4 -24
- package/packages/subagentic-manual.md +147 -314
- package/packages/ampcode/commands/debug-method.md +0 -297
- package/packages/ampcode/commands/live-canvas/README.md +0 -264
- package/packages/ampcode/commands/optimize.md +0 -61
- package/packages/ampcode/commands/tdd-flow.md +0 -390
- package/packages/ampcode/commands/test-traps/example.ts +0 -158
- package/packages/ampcode/commands/test-traps.md +0 -378
- package/packages/ampcode/commands/trace-back.md +0 -176
- package/packages/ampcode/commands/verify-done.md +0 -152
- package/packages/claude/commands/optimize.md +0 -61
- package/packages/claude/plugins/live-canvas-marketplace/plugins/live-canvas-channel/README.md +0 -89
- package/packages/claude/skills/debug-method/CREATION-LOG.md +0 -119
- package/packages/claude/skills/debug-method/SKILL.md +0 -296
- package/packages/claude/skills/debug-method/test-academic.md +0 -14
- package/packages/claude/skills/debug-method/test-pressure-1.md +0 -58
- package/packages/claude/skills/debug-method/test-pressure-2.md +0 -68
- package/packages/claude/skills/debug-method/test-pressure-3.md +0 -69
- package/packages/claude/skills/live-canvas/README.md +0 -269
- package/packages/claude/skills/tdd-flow/SKILL.md +0 -392
- package/packages/claude/skills/test-traps/SKILL.md +0 -378
- package/packages/claude/skills/test-traps/example.ts +0 -158
- package/packages/claude/skills/trace-back/SKILL.md +0 -176
- package/packages/claude/skills/verify-done/SKILL.md +0 -152
- package/packages/droid/commands/debug-method.md +0 -297
- package/packages/droid/commands/live-canvas/README.md +0 -264
- package/packages/droid/commands/optimize.md +0 -61
- package/packages/droid/commands/tdd-flow.md +0 -390
- package/packages/droid/commands/test-traps/example.ts +0 -158
- package/packages/droid/commands/test-traps.md +0 -378
- package/packages/droid/commands/trace-back.md +0 -176
- package/packages/droid/commands/verify-done.md +0 -152
- package/packages/opencode/command/debug-method.md +0 -297
- package/packages/opencode/command/live-canvas/README.md +0 -264
- package/packages/opencode/command/optimize.md +0 -61
- package/packages/opencode/command/tdd-flow.md +0 -390
- package/packages/opencode/command/test-traps/example.ts +0 -158
- package/packages/opencode/command/test-traps.md +0 -378
- package/packages/opencode/command/trace-back.md +0 -176
- package/packages/opencode/command/verify-done.md +0 -152
- /package/packages/ampcode/{commands → skills}/docs-builder/docs-builder.cjs +0 -0
- /package/packages/ampcode/{commands → skills}/live-canvas/DESIGN_PRINCIPLES.md +0 -0
- /package/packages/ampcode/{commands → skills}/live-canvas/dev/post-variants.html +0 -0
- /package/packages/ampcode/{commands → skills}/live-canvas/templates/lab-banner.html +0 -0
- /package/packages/ampcode/{commands → skills}/live-canvas/templates/overlay-vanilla.js +0 -0
- /package/packages/claude/{commands → skills}/docs-builder/docs-builder.cjs +0 -0
- /package/packages/claude/skills/{trace-back → root-cause}/find-polluter.sh +0 -0
- /package/packages/droid/commands/{trace-back → root-cause}/find-polluter.sh +0 -0
- /package/packages/opencode/command/{trace-back → root-cause}/find-polluter.sh +0 -0
|
@@ -60,31 +60,40 @@ function lexists(p) {
|
|
|
60
60
|
* "the file is absent" and is still followed on write — or any parent
|
|
61
61
|
* directory may be a link pointing elsewhere. This runs across a whole fleet
|
|
62
62
|
* of repos, so a relative link only has to reach a sibling checkout.
|
|
63
|
+
*
|
|
64
|
+
* A link that stays INSIDE the repo is not an escape: a repo that keeps its
|
|
65
|
+
* rules or its config behind an in-repo symlink is an ordinary setup, and
|
|
66
|
+
* refusing it would strand that repo forever. So the leaf is followed by hand
|
|
67
|
+
* with readlink — which works on a dangling link, where realpath cannot — and
|
|
68
|
+
* each hop re-resolves the parents, because the file a link points at can sit
|
|
69
|
+
* behind a linked directory of its own.
|
|
63
70
|
*/
|
|
64
71
|
function escapesRepo(repo, target) {
|
|
65
72
|
let root;
|
|
66
73
|
try { root = fs.realpathSync(repo); } catch (e) { return true; }
|
|
67
74
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// The last component can be a link even when every directory above it is
|
|
84
|
-
// clean — that is the dangling-file case.
|
|
85
|
-
try { if (fs.lstatSync(resolved).isSymbolicLink()) return true; } catch (e) { /* absent: fine */ }
|
|
75
|
+
let p = path.resolve(target);
|
|
76
|
+
for (let hop = 0; hop < 40; hop++) {
|
|
77
|
+
// Resolve the existing part of the path. Walk up to the deepest ancestor
|
|
78
|
+
// that exists; anything below it cannot be a link yet.
|
|
79
|
+
const tail = [];
|
|
80
|
+
let dir = path.dirname(p);
|
|
81
|
+
while (!lexists(dir)) {
|
|
82
|
+
tail.unshift(path.basename(dir));
|
|
83
|
+
const up = path.dirname(dir);
|
|
84
|
+
if (up === dir) return true; // walked off the filesystem root
|
|
85
|
+
dir = up;
|
|
86
|
+
}
|
|
87
|
+
try { p = path.join(fs.realpathSync(dir), ...tail, path.basename(p)); }
|
|
88
|
+
catch (e) { return true; } // an ancestor is a dangling link
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
let to;
|
|
91
|
+
try { to = fs.readlinkSync(p); } catch (e) {
|
|
92
|
+
return p !== root && !p.startsWith(root + path.sep); // not a link: decide here
|
|
93
|
+
}
|
|
94
|
+
p = path.resolve(path.dirname(p), to);
|
|
95
|
+
}
|
|
96
|
+
return true; // a link cycle: refuse
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
/** Index range of the lines strictly between a marker pair, or null. */
|
|
@@ -50,31 +50,40 @@ function lexists(p) {
|
|
|
50
50
|
* "the file is absent" and is still followed on write — or any parent
|
|
51
51
|
* directory may be a link pointing elsewhere. This runs across a whole fleet
|
|
52
52
|
* of repos, so a relative link only has to reach a sibling checkout.
|
|
53
|
+
*
|
|
54
|
+
* A link that stays INSIDE the repo is not an escape: a repo that keeps its
|
|
55
|
+
* rules or its config behind an in-repo symlink is an ordinary setup, and
|
|
56
|
+
* refusing it would strand that repo forever. So the leaf is followed by hand
|
|
57
|
+
* with readlink — which works on a dangling link, where realpath cannot — and
|
|
58
|
+
* each hop re-resolves the parents, because the file a link points at can sit
|
|
59
|
+
* behind a linked directory of its own.
|
|
53
60
|
*/
|
|
54
61
|
function escapesRepo(repo, target) {
|
|
55
62
|
let root;
|
|
56
63
|
try { root = fs.realpathSync(repo); } catch (e) { return true; }
|
|
57
64
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// The last component can be a link even when every directory above it is
|
|
74
|
-
// clean — that is the dangling-file case.
|
|
75
|
-
try { if (fs.lstatSync(resolved).isSymbolicLink()) return true; } catch (e) { /* absent: fine */ }
|
|
65
|
+
let p = path.resolve(target);
|
|
66
|
+
for (let hop = 0; hop < 40; hop++) {
|
|
67
|
+
// Resolve the existing part of the path. Walk up to the deepest ancestor
|
|
68
|
+
// that exists; anything below it cannot be a link yet.
|
|
69
|
+
const tail = [];
|
|
70
|
+
let dir = path.dirname(p);
|
|
71
|
+
while (!lexists(dir)) {
|
|
72
|
+
tail.unshift(path.basename(dir));
|
|
73
|
+
const up = path.dirname(dir);
|
|
74
|
+
if (up === dir) return true; // walked off the filesystem root
|
|
75
|
+
dir = up;
|
|
76
|
+
}
|
|
77
|
+
try { p = path.join(fs.realpathSync(dir), ...tail, path.basename(p)); }
|
|
78
|
+
catch (e) { return true; } // an ancestor is a dangling link
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
let to;
|
|
81
|
+
try { to = fs.readlinkSync(p); } catch (e) {
|
|
82
|
+
return p !== root && !p.startsWith(root + path.sep); // not a link: decide here
|
|
83
|
+
}
|
|
84
|
+
p = path.resolve(path.dirname(p), to);
|
|
85
|
+
}
|
|
86
|
+
return true; // a link cycle: refuse
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
function templatePath() {
|
|
@@ -35,7 +35,7 @@ const path = require('path');
|
|
|
35
35
|
|
|
36
36
|
const PKG = 'liteagents';
|
|
37
37
|
// Per-kit config dir. This is the ONE line that differs across packages.
|
|
38
|
-
const CONFIG_DIR = '.
|
|
38
|
+
const CONFIG_DIR = '.claude';
|
|
39
39
|
const TTL_MS = 24 * 60 * 60 * 1000;
|
|
40
40
|
const DEADLINE_MS = 2000;
|
|
41
41
|
const NPM_LOOKUP_MS = 3000;
|
|
@@ -62,7 +62,7 @@ function isNewer(a, b) {
|
|
|
62
62
|
// --- installed version ---------------------------------------------------
|
|
63
63
|
|
|
64
64
|
// Walk up from this file looking for our own package.json. Finds it when
|
|
65
|
-
// running from a checkout; finds nothing when installed into ~/.
|
|
65
|
+
// running from a checkout; finds nothing when installed into ~/.claude, which
|
|
66
66
|
// is why the npm fallback exists.
|
|
67
67
|
function versionFromPackageJson() {
|
|
68
68
|
let dir = __dirname;
|
|
@@ -79,7 +79,7 @@ function versionFromPackageJson() {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// The installer stamps the release it wrote into <install root>/manifest.json.
|
|
82
|
-
// version-check.cjs sits at <root>/<commands|command>/remember/, so the root
|
|
82
|
+
// version-check.cjs sits at <root>/<skills|commands|command>/remember/, so the root
|
|
83
83
|
// two levels up. This is the fast path: reading a file beats spawning npm.
|
|
84
84
|
function versionFromManifest() {
|
|
85
85
|
try {
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: root-cause
|
|
3
|
+
description: Use when any test fails, bug appears, or behaviour surprises you, before proposing a fix - find the cause and prove it, by reading real evidence, tracing bad values back to their origin, comparing against a working case, and testing one hypothesis at a time
|
|
4
|
+
allowed-tools: Read, Grep, Glob
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Root Cause
|
|
8
|
+
|
|
9
|
+
**Find the cause before you change any code.**
|
|
10
|
+
|
|
11
|
+
## The Law
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
NO FIX WITHOUT A CAUSE YOU CAN POINT AT
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
A fix at the place the error *appeared* is a symptom fix. It is a failure even when
|
|
18
|
+
the symptom goes away, because the real cause is still there and will surface
|
|
19
|
+
somewhere else, later, with less context.
|
|
20
|
+
|
|
21
|
+
You cannot propose a fix until Phase 1 is done.
|
|
22
|
+
|
|
23
|
+
## When to Use
|
|
24
|
+
|
|
25
|
+
Any technical issue: a failing test, a production bug, unexpected behaviour, a
|
|
26
|
+
performance problem, a broken build, an integration that will not talk.
|
|
27
|
+
|
|
28
|
+
**Especially when it feels like overkill:**
|
|
29
|
+
- Under time pressure — emergencies are exactly when guessing is most tempting and most expensive
|
|
30
|
+
- "Just one quick fix" looks obvious
|
|
31
|
+
- You have already tried a fix and it did not work
|
|
32
|
+
- You do not fully understand the issue
|
|
33
|
+
|
|
34
|
+
Simple bugs have root causes too, and finding one takes minutes. Guess-and-check
|
|
35
|
+
takes hours and leaves damage behind.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Phase 1 — Gather Evidence
|
|
40
|
+
|
|
41
|
+
Do all of this **before** forming any opinion about the fix.
|
|
42
|
+
|
|
43
|
+
### 1. Read the error completely
|
|
44
|
+
|
|
45
|
+
Do not skim past it. Read the whole message, the whole stack trace, every warning
|
|
46
|
+
above it. Note line numbers, file paths, error codes. The answer is often written
|
|
47
|
+
there in full.
|
|
48
|
+
|
|
49
|
+
### 2. Reproduce it consistently
|
|
50
|
+
|
|
51
|
+
Can you trigger it on demand? What are the exact steps? Does it happen every time?
|
|
52
|
+
|
|
53
|
+
If it is not reproducible, gather more data. Do not start guessing — an
|
|
54
|
+
intermittent bug you cannot trigger is a bug you cannot prove you fixed.
|
|
55
|
+
|
|
56
|
+
### 3. Check what changed
|
|
57
|
+
|
|
58
|
+
Recent commits, the working diff, new dependencies, config edits, environment
|
|
59
|
+
differences between the place it works and the place it does not.
|
|
60
|
+
|
|
61
|
+
Be careful here: the most recent change is the most *available* suspect, not the
|
|
62
|
+
most likely one. Recency is a lead to test, never a conclusion.
|
|
63
|
+
|
|
64
|
+
### 4. Instrument the boundaries (multi-component systems)
|
|
65
|
+
|
|
66
|
+
When the path crosses components — CI → build → sign, API → service → database,
|
|
67
|
+
workflow → script → tool — do not reason about where it breaks. Measure it.
|
|
68
|
+
|
|
69
|
+
For each boundary, log what goes **in** and what comes **out**, and confirm
|
|
70
|
+
configuration and environment actually propagated across it.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
echo "=== layer 1: is the secret present in the workflow? ==="
|
|
74
|
+
echo "IDENTITY: ${IDENTITY:+SET}${IDENTITY:-UNSET}"
|
|
75
|
+
|
|
76
|
+
echo "=== layer 2: did it survive into the build script? ==="
|
|
77
|
+
env | grep IDENTITY || echo "IDENTITY not in environment"
|
|
78
|
+
|
|
79
|
+
echo "=== layer 3: what does the tool actually see? ==="
|
|
80
|
+
security find-identity -v
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Run it **once** to find which boundary fails, then investigate only that
|
|
84
|
+
component. This turns "somewhere in the pipeline" into a named layer.
|
|
85
|
+
|
|
86
|
+
### 5. Trace the bad value back to where it was born
|
|
87
|
+
|
|
88
|
+
When the error surfaces deep in the call stack, the place it exploded is almost
|
|
89
|
+
never the place it went wrong. Walk backwards.
|
|
90
|
+
|
|
91
|
+
**The chain:**
|
|
92
|
+
|
|
93
|
+
1. **Observe the symptom** — `git init` ran in the source directory
|
|
94
|
+
2. **Find the immediate cause** — the code that directly did it:
|
|
95
|
+
`execFileAsync('git', ['init'], { cwd: projectDir })`
|
|
96
|
+
3. **Ask what called this, and with what value** — `projectDir` was `''`, and an
|
|
97
|
+
empty `cwd` silently resolves to the process's own directory
|
|
98
|
+
4. **Keep going up** — who passed the empty string? and who gave it to *them*?
|
|
99
|
+
5. **Stop at the origin** — the point where a correct value first became wrong
|
|
100
|
+
|
|
101
|
+
Fix it **there**. Then, if the value is dangerous, validate it at each layer on
|
|
102
|
+
the way down as well, so the same mistake cannot recur through a different path.
|
|
103
|
+
|
|
104
|
+
**When you cannot trace it by reading, instrument it:**
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
async function gitInit(directory: string) {
|
|
108
|
+
console.error('DEBUG git init:', {
|
|
109
|
+
directory,
|
|
110
|
+
cwd: process.cwd(),
|
|
111
|
+
stack: new Error().stack,
|
|
112
|
+
});
|
|
113
|
+
await execFileAsync('git', ['init'], { cwd: directory });
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- Capture the **stack**, not just the value — it names the caller you are looking for
|
|
118
|
+
- Log **before** the dangerous operation, not in its failure handler
|
|
119
|
+
- Include surrounding context: the directory, the working directory, relevant environment
|
|
120
|
+
- In tests, write to standard error directly; a project logger may be suppressed
|
|
121
|
+
|
|
122
|
+
**When something pollutes a test run but you cannot tell which test:** bisect.
|
|
123
|
+
Run the tests one at a time and stop at the first one that leaves the mess behind.
|
|
124
|
+
`find-polluter.sh` in this skill's directory does exactly that.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Phase 2 — Compare Against Something That Works
|
|
129
|
+
|
|
130
|
+
You are looking for a difference, and the fastest way to see one is a side-by-side.
|
|
131
|
+
|
|
132
|
+
- **Find a working example** — similar code in the same codebase that behaves correctly
|
|
133
|
+
- **Read the reference completely** if you are following a pattern. Every line. Skimming a
|
|
134
|
+
reference and adapting "the idea" is how half-understood patterns ship
|
|
135
|
+
- **List every difference**, however small. Do not filter by "that can't matter" — that
|
|
136
|
+
judgement is exactly what you do not have yet
|
|
137
|
+
- **Check the dependencies**: what config, what environment, what other components does
|
|
138
|
+
the working one have that the broken one does not?
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Phase 3 — One Hypothesis, One Variable
|
|
143
|
+
|
|
144
|
+
- **State it in writing:** "I think X is the cause, because Y." Specific, not vague.
|
|
145
|
+
- **Test it with the smallest possible change.** One variable. A controlled test that
|
|
146
|
+
isolates your suspect beats a plausible story about the most recent commit.
|
|
147
|
+
- **Read the result honestly.** Confirmed → Phase 4. Not confirmed → form a *new*
|
|
148
|
+
hypothesis. Never stack a second fix on top of an unconfirmed first one.
|
|
149
|
+
- **Say when you do not know.** "I don't understand why X happens" is a real state and a
|
|
150
|
+
useful thing to report. Pretending to know produces confident wrong fixes.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Phase 4 — Fix at the Source
|
|
155
|
+
|
|
156
|
+
### 1. Write the failing test first
|
|
157
|
+
|
|
158
|
+
The simplest reproduction you can manage — an automated test if there is a suite, a
|
|
159
|
+
throwaway script if there is not.
|
|
160
|
+
|
|
161
|
+
**Run it against the unfixed code and watch it fail, for the reason you expect.** A
|
|
162
|
+
test written after the fix, or one that passes both before and after, proves nothing.
|
|
163
|
+
This is the step that converts your hypothesis into evidence.
|
|
164
|
+
|
|
165
|
+
### 2. Make one change
|
|
166
|
+
|
|
167
|
+
Fix the cause you identified. One change. No "while I'm here" improvements, no bundled
|
|
168
|
+
refactoring — those make it impossible to tell what actually worked.
|
|
169
|
+
|
|
170
|
+
### 3. Verify
|
|
171
|
+
|
|
172
|
+
Does the new test pass? Does the rest of the suite still pass? Is the original symptom
|
|
173
|
+
actually gone — checked, not assumed?
|
|
174
|
+
|
|
175
|
+
### 4. If the fix did not work, stop and count
|
|
176
|
+
|
|
177
|
+
Under three attempts: return to Phase 1 with what you just learned. The failed attempt
|
|
178
|
+
is evidence.
|
|
179
|
+
|
|
180
|
+
**Three or more failed fixes means you have the wrong model of the problem.** Do not
|
|
181
|
+
attempt a fourth. The pattern to watch for: each fix uncovers a new problem somewhere
|
|
182
|
+
else, or each one needs "just a bit of refactoring" to land.
|
|
183
|
+
|
|
184
|
+
That is an architecture question, not a hypothesis question. Stop and raise it.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Red Flags — Stop and Return to Phase 1
|
|
189
|
+
|
|
190
|
+
- "Quick fix now, investigate later"
|
|
191
|
+
- "Just try changing X and see"
|
|
192
|
+
- Several changes at once, then run the tests
|
|
193
|
+
- "Skip the test, I'll check it by hand"
|
|
194
|
+
- "It's probably X" — probably is not a cause
|
|
195
|
+
- "I don't fully understand this, but this might work"
|
|
196
|
+
- Listing fixes before tracing where the bad value came from
|
|
197
|
+
- "One more attempt" when two have already failed
|
|
198
|
+
- Each fix revealing a new problem somewhere else
|
|
199
|
+
|
|
200
|
+
## Quick Reference
|
|
201
|
+
|
|
202
|
+
| Phase | You do | Done when |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| **1. Evidence** | Read the error, reproduce, check changes, instrument boundaries, trace the value back | You can say what happened and where it started |
|
|
205
|
+
| **2. Compare** | Find a working case, read it fully, list every difference | You know what is different |
|
|
206
|
+
| **3. Hypothesis** | State one cause, test one variable | Confirmed, or you have a new hypothesis |
|
|
207
|
+
| **4. Fix** | Failing test first, one change, verify | The test that failed now passes, and nothing else broke |
|
|
208
|
+
|
|
209
|
+
## When There Really Is No Root Cause
|
|
210
|
+
|
|
211
|
+
It happens — a genuine race, an upstream bug, a hardware fault. But roughly nineteen
|
|
212
|
+
times in twenty, "no root cause" means the investigation stopped early.
|
|
213
|
+
|
|
214
|
+
Before you conclude it: can you reproduce it? Did you instrument every boundary? Did
|
|
215
|
+
you trace the value to its origin, or only to the last function you recognised?
|
|
216
|
+
|
|
217
|
+
## Related
|
|
218
|
+
|
|
219
|
+
- **AGENT_RULES.md → Testing Standards** — what makes the Phase 4 test a real one
|
|
220
|
+
- **`/test-generate`** — build out the suite once the cause is fixed
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: security
|
|
3
3
|
description: Security audit — recurring six, injection, auth, trust boundaries
|
|
4
|
-
usage: /security
|
|
5
4
|
argument-hint: [file, directory, or leave empty for full scan]
|
|
6
|
-
allowed-tools: Read, Grep, Glob, Bash(git log
|
|
5
|
+
allowed-tools: Read, Grep, Glob, Bash(git log:*), Bash(git grep:*), Bash(rg:*)
|
|
6
|
+
disable-model-invocation: true
|
|
7
7
|
---
|
|
8
8
|
Audit $ARGUMENTS for security vulnerabilities. **Reports, never edits** — it
|
|
9
9
|
verifies every claim, then hands the findings to whoever asked.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ship
|
|
3
3
|
description: Mechanical pre-deploy gate — tests, build, tree state
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
allowed-tools: Read, Grep, Glob, Bash(git:*), Bash(npm:*), Bash(pnpm:*), Bash(yarn:*), Bash(pytest:*), Bash(python:*), Bash(go:*), Bash(cargo:*), Bash(make:*)
|
|
5
|
+
disable-model-invocation: true
|
|
6
6
|
---
|
|
7
7
|
Mechanical pre-deploy / pre-merge gate. Every item here is answerable by
|
|
8
8
|
**running a command** and reading its exit code — no code judgment. Code
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skill-creator
|
|
3
3
|
description: Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
|
|
4
|
-
usage: /skill-creator <skill-type> <skill-description>
|
|
5
|
-
auto_trigger: false
|
|
6
4
|
license: Complete terms in LICENSE.txt
|
|
5
|
+
allowed-tools: Read, Grep, Glob
|
|
7
6
|
---
|
|
8
7
|
|
|
9
8
|
# Skill Creator
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stash
|
|
3
3
|
description: Stash session context [name]
|
|
4
|
-
usage: /stash ["optional-name"]
|
|
5
4
|
argument-hint: [optional stash name]
|
|
5
|
+
allowed-tools: Read, Grep, Glob
|
|
6
|
+
disable-model-invocation: true
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
Save session context for compaction recovery or handoffs.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: test-generate
|
|
3
3
|
description: Generate and run tests [file]
|
|
4
|
-
usage: /test-generate <file>
|
|
5
4
|
argument-hint: [file or symbol to test]
|
|
6
|
-
allowed-tools: Read, Edit, Write, Grep, Glob, Bash(npm test
|
|
5
|
+
allowed-tools: Read, Edit, Write, Grep, Glob, Bash(npm test:*), Bash(npx jest:*), Bash(npx vitest:*), Bash(pnpm test:*), Bash(yarn test:*), Bash(pytest:*), Bash(python:*), Bash(go test:*), Bash(cargo test:*), Bash(make test:*)
|
|
6
|
+
disable-model-invocation: true
|
|
7
7
|
---
|
|
8
8
|
Generate tests for $ARGUMENTS, then run them. This is a generate → run →
|
|
9
9
|
verify loop, not just file generation.
|
|
@@ -28,7 +28,7 @@ Match existing patterns:
|
|
|
28
28
|
or new test-runner config.
|
|
29
29
|
- Do **not** add test-only public methods or exports to production code to
|
|
30
30
|
make a test possible — if the test wants a hook the prod code doesn't
|
|
31
|
-
expose, stop and ask
|
|
31
|
+
expose, stop and ask.
|
|
32
32
|
|
|
33
33
|
## 3. Run
|
|
34
34
|
Execute the project's real test command, scoped to just the new tests
|
package/packages/droid/AGENTS.md
CHANGED
|
@@ -21,28 +21,23 @@ These subagents are available when using Claude Code CLI. Droid can reference th
|
|
|
21
21
|
| system-architect | Architect | Use for system design, architecture documents, technology selection, API design, and infrastructure planning |
|
|
22
22
|
| ui-designer | UX Expert | Use for UI/UX design, wireframes, prototypes, front-end specifications, and user experience optimization |
|
|
23
23
|
|
|
24
|
-
## Droid Commands (
|
|
25
|
-
|
|
26
|
-
| ID | Description | Usage |
|
|
27
|
-
|
|
28
|
-
| brainstorming | Refines rough ideas into fully-formed designs through collaborative questioning | /brainstorming <session-type> <topic> |
|
|
29
|
-
| docs-builder | Reorg a docs corpus, split an oversized doc, search it, keep pages current, index them | /docs-builder [reorg \| cleanup <file.md>] |
|
|
30
|
-
| live-canvas | Design UI variations and collect click-to-annotate feedback from the browser (batch mode only on Droid) | /live-canvas |
|
|
31
|
-
|
|
|
32
|
-
| refactor | Refactor code while maintaining behavior and tests | /refactor <code-section> | - |
|
|
24
|
+
## Droid Commands (13 total)
|
|
25
|
+
|
|
26
|
+
| ID | Description | Usage |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| brainstorming | Refines rough ideas into fully-formed designs through collaborative questioning | /brainstorming <session-type> <topic> |
|
|
29
|
+
| docs-builder | Reorg a docs corpus, split an oversized doc, search it, keep pages current, index them | /docs-builder [reorg \| cleanup <file.md>] |
|
|
30
|
+
| live-canvas | Design UI variations and collect click-to-annotate feedback from the browser (batch mode only on Droid) | /live-canvas |
|
|
31
|
+
| refactor | Refactor and optimize code while maintaining behavior and tests | /refactor <code-section> | - |
|
|
33
32
|
| remember | Consolidate stashes + friction into project memory | /remember | - |
|
|
34
33
|
| branch-review | Pre-merge review: general review + full security audit, verify pass, no fixes | /branch-review [target] [level] | - |
|
|
35
|
-
|
|
|
34
|
+
| root-cause | Find the cause before changing code - evidence, backward trace, one hypothesis, fix at the source | /root-cause <bug-or-error-description> |
|
|
36
35
|
| security | Security audit — recurring six, injection, auth, trust boundaries; reports, never fixes | /security [target] | - |
|
|
37
36
|
| ship | Mechanical pre-deploy gate — tests, build, tree state | /ship | - |
|
|
38
37
|
| release | Verify, sweep docs, cut a version — then hand back the merge/tag/publish sequence | /release | - |
|
|
39
|
-
| skill-creator | Guide for creating effective skills and extending Claude capabilities | /skill-creator <skill-type> <skill-description> |
|
|
38
|
+
| skill-creator | Guide for creating effective skills and extending Claude capabilities | /skill-creator <skill-type> <skill-description> |
|
|
40
39
|
| stash | Save session context for compaction recovery or handoffs | /stash ["optional-name"] | - |
|
|
41
|
-
| debug-method | Four-phase debugging framework - investigate root cause before any fixes | /debug-method <bug-or-error-description> | false |
|
|
42
|
-
| tdd-flow | Write test first, watch it fail, write minimal code to pass | /tdd-flow <feature-or-behavior-to-test> | true |
|
|
43
40
|
| test-generate | Generate tests, run them, verify each one actually exercises the code | /test-generate <file> | - |
|
|
44
|
-
| test-traps | Prevents testing mock behavior and production pollution with test-only methods | /test-traps <testing-scenario> | true |
|
|
45
|
-
| verify-done | Requires running verification commands before making any success claims | /verify-done <work-to-verify> | true |
|
|
46
41
|
|
|
47
42
|
All resources are auto-discovered from frontmatter in their respective directories:
|
|
48
43
|
- **Agents**: `./droids/*.md`
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: brainstorming
|
|
3
2
|
description: Use when creating or developing, before writing code or implementation plans - refines rough ideas into fully-formed designs through collaborative questioning, alternative exploration, and incremental validation. Don't use during clear 'mechanical' processes
|
|
4
|
-
usage: /brainstorming <session-type> <topic>
|
|
5
|
-
auto_trigger: false
|
|
6
3
|
---
|
|
7
4
|
|
|
8
5
|
# Brainstorming Ideas Into Designs
|
|
@@ -43,7 +40,7 @@ Start by understanding the current project context, then ask questions one at a
|
|
|
43
40
|
|
|
44
41
|
**Implementation (if continuing):**
|
|
45
42
|
- Ask: "Ready to set up for implementation?"
|
|
46
|
-
- Create isolated workspace
|
|
43
|
+
- Create isolated workspace for implementation
|
|
47
44
|
- Create detailed implementation plan
|
|
48
45
|
|
|
49
46
|
## Key Principles
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: branch-review
|
|
3
2
|
description: Review a branch before merge [target] [level]
|
|
4
|
-
usage: /branch-review [target] [low|medium|high|max]
|
|
5
3
|
argument-hint: [file, branch (e.g. main), range (main..HEAD), or empty] [effort level]
|
|
6
|
-
allowed-tools: Read, Grep, Glob, Agent, Bash(git diff *), Bash(git log *), Bash(git show *), Bash(git status *), Bash(git grep *), Bash(git rev-parse *), Bash(git merge-base *), Bash(rg *)
|
|
7
4
|
---
|
|
8
5
|
Pre-merge review gate. Two stages — **general review** then a **full security
|
|
9
6
|
audit** — followed by an adversarial verify pass. It **never edits code**: it
|
|
@@ -11,7 +8,7 @@ reports findings and hands them back. Fixing is a separate, separately
|
|
|
11
8
|
authorized action.
|
|
12
9
|
|
|
13
10
|
Only **Critical** and **High** findings block the merge. Everything else is
|
|
14
|
-
appended to the **fix ledger** (`.
|
|
11
|
+
appended to the **fix ledger** (`.factory/remember/fix-ledger.md`) — a local,
|
|
15
12
|
cumulative list, living beside `MEMORY.md`, that `/refactor` (no arguments)
|
|
16
13
|
works through between features. Like its neighbours it is a private working
|
|
17
14
|
artifact, usually gitignored; it persists across reviews, it is not a
|
|
@@ -44,17 +41,17 @@ at the current HEAD SHA.
|
|
|
44
41
|
review of a report. (Same rule `/security` carries inside stage 2.)
|
|
45
42
|
- **No edits — two exceptions.** You have no authorization to change code,
|
|
46
43
|
even for a finding you are certain about. Report it. The only files you may
|
|
47
|
-
write are `.
|
|
48
|
-
delete) and `.
|
|
44
|
+
write are `.factory/remember/fix-ledger.md` (append bullets; never rewrite or
|
|
45
|
+
delete) and `.factory/remember/last-review.md` (overwrite; the review record
|
|
49
46
|
described at the end of this file).
|
|
50
47
|
- **Prove it with two checks, because neither sees what the other does.**
|
|
51
48
|
`git status --porcelain`, at start and again before you report, proves no
|
|
52
49
|
**tracked** file changed — that is the "never edits code" guarantee, and it
|
|
53
|
-
is the one that matters. It cannot police your own two writes: `.
|
|
50
|
+
is the one that matters. It cannot police your own two writes: `.factory/`
|
|
54
51
|
is normally gitignored, so porcelain stays empty whether you wrote the
|
|
55
52
|
allowed files, wrote nothing, or overwrote `MEMORY.md`. `git status
|
|
56
|
-
--ignored` does not close it either — it collapses to `!! .
|
|
57
|
-
directory, not the files. So also take `md5sum .
|
|
53
|
+
--ignored` does not close it either — it collapses to `!! .factory/`, the
|
|
54
|
+
directory, not the files. So also take `md5sum .factory/remember/*` before
|
|
58
55
|
you start and again before you report, and show the comparison: only
|
|
59
56
|
`fix-ledger.md` and `last-review.md` may differ.
|
|
60
57
|
|
|
@@ -95,7 +92,7 @@ Record the **HEAD SHA** you reviewed, and **report the target you resolved**
|
|
|
95
92
|
(the literal range or path) in your output, so the orchestrator can see what
|
|
96
93
|
was actually read rather than assuming.
|
|
97
94
|
|
|
98
|
-
**Re-review after fixes: read `.
|
|
95
|
+
**Re-review after fixes: read `.factory/remember/last-review.md` first.** Its
|
|
99
96
|
`sha:` line is the previously-reviewed commit and its `blockers:` list is what
|
|
100
97
|
you owe an answer on — take both from the file, never from the orchestrator's
|
|
101
98
|
recollection, for the same reason `/release` does. Then:
|
|
@@ -231,7 +228,7 @@ check before escalating.
|
|
|
231
228
|
|
|
232
229
|
### Ledger (non-blocking — medium / low)
|
|
233
230
|
Not in the report. **Append** each one as a single bullet to
|
|
234
|
-
`.
|
|
231
|
+
`.factory/remember/fix-ledger.md` (create the file with the header below if
|
|
235
232
|
missing):
|
|
236
233
|
|
|
237
234
|
```
|
|
@@ -256,7 +253,7 @@ with `UNVERIFIED:` so `/refactor` retests before acting.
|
|
|
256
253
|
The **snippet is the anchor**: 20–60 verbatim characters from the line,
|
|
257
254
|
unique enough for `git grep -F` to find it after lines shift. No line
|
|
258
255
|
numbers, no TODO comments in code — the ledger is the single writer. Before
|
|
259
|
-
appending, dedupe with **plain `grep -F "<snippet>" .
|
|
256
|
+
appending, dedupe with **plain `grep -F "<snippet>" .factory/remember/fix-ledger.md`**;
|
|
260
257
|
if it is already there, skip it. Do not touch existing bullets.
|
|
261
258
|
|
|
262
259
|
**A bullet you disprove is deleted, not annotated.** If you establish that an
|
|
@@ -280,7 +277,7 @@ Then a coverage line: stage 1 at level `<level>`, stage 2 full, stage 3 —
|
|
|
280
277
|
each `ran ✓/✗` with its evidence. A stage you did not actually run is a **✗**, never an
|
|
281
278
|
assumed pass.
|
|
282
279
|
|
|
283
|
-
**Write the review record** to `.
|
|
280
|
+
**Write the review record** to `.factory/remember/last-review.md`, overwriting
|
|
284
281
|
it. `/release` reads this file; a SHA that lives only in a chat message is
|
|
285
282
|
gone after a compaction or a handover, and the only remaining source is the
|
|
286
283
|
orchestrator — the one party this command already refuses to take a review's
|
|
@@ -326,7 +323,7 @@ does not move — which means nothing was fixed, which is the correct outcome.
|
|
|
326
323
|
|
|
327
324
|
End with:
|
|
328
325
|
- **Reviewed at HEAD `<sha>` on `<branch>`, target `<resolved range or path>`,
|
|
329
|
-
tree clean at start; at exit clean or the two `.
|
|
326
|
+
tree clean at start; at exit clean or the two `.factory/remember/` paths
|
|
330
327
|
only.**
|
|
331
328
|
- **Fix ledger: N open, M added this run** (N = bullet count). When N > 0,
|
|
332
329
|
add: "N fixes waiting — run `/refactor` between features." The ledger is a
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: docs-builder
|
|
3
2
|
description: Reorg a docs corpus, split an oversized doc, search it, keep pages current, index them
|
|
4
|
-
usage: /docs-builder [reorg | cleanup <file.md> | search <query words...>]
|
|
5
3
|
argument-hint: [reorg | cleanup <file.md> | search <query words...> — empty asks first run vs. drift]
|
|
6
|
-
allowed-tools: Read, Write, Edit, Grep, Glob, Task, AskUserQuestion, Bash(node:*), Bash(git:*), Bash(rg:*)
|
|
7
4
|
---
|
|
8
5
|
|
|
9
6
|
# docs-builder
|