@imix-js/taproot 0.3.0 → 0.4.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/dist/adapters/index.d.ts +11 -1
- package/dist/adapters/index.js +113 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/commands/dod.d.ts +1 -0
- package/dist/commands/dod.js +24 -2
- package/dist/commands/dod.js.map +1 -1
- package/dist/commands/init.js +7 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.js +22 -5
- package/dist/commands/update.js.map +1 -1
- package/dist/core/configuration.js +25 -0
- package/dist/core/configuration.js.map +1 -1
- package/dist/core/dod-runner.d.ts +4 -2
- package/dist/core/dod-runner.js +30 -1
- package/dist/core/dod-runner.js.map +1 -1
- package/dist/core/test-cache.d.ts +39 -0
- package/dist/core/test-cache.js +187 -0
- package/dist/core/test-cache.js.map +1 -0
- package/dist/validators/types.d.ts +4 -0
- package/docs/agents.md +11 -0
- package/docs/cli.md +3 -1
- package/docs/configuration.md +45 -1
- package/docs/patterns.md +43 -0
- package/package.json +1 -1
- package/skills/backlog.md +7 -3
- package/skills/bug.md +13 -0
- package/skills/commit.md +14 -1
- package/skills/grill-me.md +1 -0
- package/skills/guide.md +1 -0
- package/skills/implement.md +19 -1
- package/skills/review-all.md +1 -1
- package/skills/review.md +1 -0
- package/skills/status.md +3 -2
package/dist/core/dod-runner.js
CHANGED
|
@@ -4,6 +4,7 @@ import { spawnSync } from 'child_process';
|
|
|
4
4
|
import { parseMarkdown } from './markdown-parser.js';
|
|
5
5
|
import { validateFormat } from '../validators/format-rules.js';
|
|
6
6
|
import { loadConfig } from './config.js';
|
|
7
|
+
import { runTestsPassingWithCache } from './test-cache.js';
|
|
7
8
|
const BUILTINS = {
|
|
8
9
|
'tests-passing': {
|
|
9
10
|
run: 'npm test',
|
|
@@ -203,7 +204,7 @@ export function readResolutions(implPath, cwd) {
|
|
|
203
204
|
}
|
|
204
205
|
return new Set(entries.map(e => e.condition));
|
|
205
206
|
}
|
|
206
|
-
export function runDodChecks(conditions, cwd, options) {
|
|
207
|
+
export async function runDodChecks(conditions, cwd, options) {
|
|
207
208
|
const results = [];
|
|
208
209
|
// Always run baseline when implPath is provided
|
|
209
210
|
if (options?.implPath) {
|
|
@@ -217,8 +218,36 @@ export function runDodChecks(conditions, cwd, options) {
|
|
|
217
218
|
const resolvedChecks = options?.implPath
|
|
218
219
|
? readResolutions(options.implPath, cwd)
|
|
219
220
|
: new Set();
|
|
221
|
+
const cfg = options?.config;
|
|
220
222
|
for (const entry of conditions) {
|
|
221
223
|
const resolved = resolveCondition(entry);
|
|
224
|
+
// Evidence-backed tests-passing: intercept when testsCommand is configured
|
|
225
|
+
if (resolved.name === 'tests-passing' && cfg?.testsCommand) {
|
|
226
|
+
if (!options?.implPath) {
|
|
227
|
+
// No implPath — fall back to builtin shell run (standalone mode)
|
|
228
|
+
results.push(runCondition(resolved.name, cfg.testsCommand, cwd, resolved.correction));
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const testResult = await runTestsPassingWithCache({
|
|
232
|
+
implPath: options.implPath,
|
|
233
|
+
cwd,
|
|
234
|
+
testsCommand: cfg.testsCommand,
|
|
235
|
+
testResultMaxAgeMs: cfg.testResultMaxAge !== undefined
|
|
236
|
+
? cfg.testResultMaxAge * 60 * 1000
|
|
237
|
+
: undefined,
|
|
238
|
+
testTimeoutMs: cfg.testTimeout !== undefined
|
|
239
|
+
? cfg.testTimeout * 1000
|
|
240
|
+
: undefined,
|
|
241
|
+
rerunTests: options?.rerunTests,
|
|
242
|
+
});
|
|
243
|
+
results.push({
|
|
244
|
+
name: resolved.name,
|
|
245
|
+
passed: testResult.passed,
|
|
246
|
+
output: testResult.output,
|
|
247
|
+
correction: testResult.correction,
|
|
248
|
+
});
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
222
251
|
if (resolved.agentCheck) {
|
|
223
252
|
const isResolved = resolvedChecks.has(resolved.name);
|
|
224
253
|
results.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dod-runner.js","sourceRoot":"","sources":["../../src/core/dod-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"dod-runner.js","sourceRoot":"","sources":["../../src/core/dod-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readResolutions } from './dod-runner.js';
|
|
2
|
+
export interface TestResult {
|
|
3
|
+
timestamp: string;
|
|
4
|
+
command: string;
|
|
5
|
+
exitCode: number;
|
|
6
|
+
summary: string;
|
|
7
|
+
}
|
|
8
|
+
/** Derive the cache path from an impl.md path.
|
|
9
|
+
* Strips 'taproot/' prefix and '/impl.md' suffix, maps into .taproot/.test-results/.
|
|
10
|
+
* Handles both absolute and relative implPath inputs. */
|
|
11
|
+
export declare function deriveCachePath(implPath: string, cwd: string): string;
|
|
12
|
+
/** Read a cached test result. Returns null if absent or malformed. */
|
|
13
|
+
export declare function readCache(cachePath: string): TestResult | null;
|
|
14
|
+
/** Returns true if the cached result is malformed JSON (exists but unparseable). */
|
|
15
|
+
export declare function isCacheCorrupt(cachePath: string): boolean;
|
|
16
|
+
/** Check whether a cached result is stale.
|
|
17
|
+
* Stale if: any tracked source file is newer than the cache timestamp,
|
|
18
|
+
* or (if no source files listed) the cache is older than testResultMaxAge. */
|
|
19
|
+
export declare function isCacheStale(cache: TestResult, implPath: string, cwd: string, testResultMaxAgeMs?: number): boolean;
|
|
20
|
+
/** Write a test result to the cache file, creating parent dirs as needed. */
|
|
21
|
+
export declare function writeCache(cachePath: string, result: TestResult): void;
|
|
22
|
+
/** Execute testsCommand, streaming output to the terminal while also capturing it.
|
|
23
|
+
* Returns the TestResult with the last N lines as summary. */
|
|
24
|
+
export declare function executeTestCommand(command: string, cwd: string, timeoutMs?: number): Promise<TestResult>;
|
|
25
|
+
/** Full evidence-backed tests-passing check.
|
|
26
|
+
* Returns { passed, output, correction, warnNoCache } */
|
|
27
|
+
export declare function runTestsPassingWithCache(options: {
|
|
28
|
+
implPath: string;
|
|
29
|
+
cwd: string;
|
|
30
|
+
testsCommand: string;
|
|
31
|
+
testResultMaxAgeMs?: number;
|
|
32
|
+
testTimeoutMs?: number;
|
|
33
|
+
rerunTests?: boolean;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
passed: boolean;
|
|
36
|
+
output: string;
|
|
37
|
+
correction: string;
|
|
38
|
+
}>;
|
|
39
|
+
export { readResolutions };
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, statSync } from 'fs';
|
|
2
|
+
import { join, resolve, relative, dirname } from 'path';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import { readResolutions } from './dod-runner.js';
|
|
5
|
+
const DEFAULT_TEST_TIMEOUT_MS = 300_000; // 300 seconds
|
|
6
|
+
const DEFAULT_MAX_AGE_MS = 60 * 60 * 1000; // 60 minutes
|
|
7
|
+
/** Derive the cache path from an impl.md path.
|
|
8
|
+
* Strips 'taproot/' prefix and '/impl.md' suffix, maps into .taproot/.test-results/.
|
|
9
|
+
* Handles both absolute and relative implPath inputs. */
|
|
10
|
+
export function deriveCachePath(implPath, cwd) {
|
|
11
|
+
const absImpl = resolve(cwd, implPath);
|
|
12
|
+
const relImpl = relative(cwd, absImpl).replace(/\\/g, '/');
|
|
13
|
+
// Strip leading 'taproot/' segment
|
|
14
|
+
const withoutRoot = relImpl.startsWith('taproot/')
|
|
15
|
+
? relImpl.slice('taproot/'.length)
|
|
16
|
+
: relImpl;
|
|
17
|
+
// Strip trailing '/impl.md'
|
|
18
|
+
const key = withoutRoot.endsWith('/impl.md')
|
|
19
|
+
? withoutRoot.slice(0, -'/impl.md'.length)
|
|
20
|
+
: withoutRoot;
|
|
21
|
+
return join(cwd, '.taproot', '.test-results', `${key}.json`);
|
|
22
|
+
}
|
|
23
|
+
/** Read a cached test result. Returns null if absent or malformed. */
|
|
24
|
+
export function readCache(cachePath) {
|
|
25
|
+
if (!existsSync(cachePath))
|
|
26
|
+
return null;
|
|
27
|
+
try {
|
|
28
|
+
const raw = readFileSync(cachePath, 'utf-8');
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
if (typeof parsed.exitCode !== 'number' || !parsed.timestamp)
|
|
31
|
+
return null;
|
|
32
|
+
return parsed;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Returns true if the cached result is malformed JSON (exists but unparseable). */
|
|
39
|
+
export function isCacheCorrupt(cachePath) {
|
|
40
|
+
if (!existsSync(cachePath))
|
|
41
|
+
return false;
|
|
42
|
+
try {
|
|
43
|
+
JSON.parse(readFileSync(cachePath, 'utf-8'));
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Check whether a cached result is stale.
|
|
51
|
+
* Stale if: any tracked source file is newer than the cache timestamp,
|
|
52
|
+
* or (if no source files listed) the cache is older than testResultMaxAge. */
|
|
53
|
+
export function isCacheStale(cache, implPath, cwd, testResultMaxAgeMs = DEFAULT_MAX_AGE_MS) {
|
|
54
|
+
const absImpl = resolve(cwd, implPath);
|
|
55
|
+
const cacheTs = Date.parse(cache.timestamp);
|
|
56
|
+
if (isNaN(cacheTs))
|
|
57
|
+
return true;
|
|
58
|
+
// Read source files from impl.md
|
|
59
|
+
const sourceFiles = readSourceFiles(absImpl, cwd);
|
|
60
|
+
if (sourceFiles.length === 0) {
|
|
61
|
+
// Fall back to max-age check
|
|
62
|
+
return Date.now() - cacheTs > testResultMaxAgeMs;
|
|
63
|
+
}
|
|
64
|
+
// Stale if any source file is newer than the cache
|
|
65
|
+
for (const src of sourceFiles) {
|
|
66
|
+
const absSrc = resolve(cwd, src);
|
|
67
|
+
if (!existsSync(absSrc))
|
|
68
|
+
continue;
|
|
69
|
+
try {
|
|
70
|
+
const mtime = statSync(absSrc).mtimeMs;
|
|
71
|
+
if (mtime > cacheTs)
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// ignore stat errors
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
function readSourceFiles(absImplPath, cwd) {
|
|
81
|
+
try {
|
|
82
|
+
const content = readFileSync(absImplPath, 'utf-8');
|
|
83
|
+
const match = content.match(/^## Source Files\s*\n([\s\S]*?)(?=\n## |\n$|$)/m);
|
|
84
|
+
if (!match)
|
|
85
|
+
return [];
|
|
86
|
+
const sources = [];
|
|
87
|
+
for (const m of match[1].matchAll(/`([^`]+)`/g)) {
|
|
88
|
+
sources.push(m[1]);
|
|
89
|
+
}
|
|
90
|
+
return sources;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Write a test result to the cache file, creating parent dirs as needed. */
|
|
97
|
+
export function writeCache(cachePath, result) {
|
|
98
|
+
mkdirSync(dirname(cachePath), { recursive: true });
|
|
99
|
+
writeFileSync(cachePath, JSON.stringify(result, null, 2), 'utf-8');
|
|
100
|
+
}
|
|
101
|
+
/** Execute testsCommand, streaming output to the terminal while also capturing it.
|
|
102
|
+
* Returns the TestResult with the last N lines as summary. */
|
|
103
|
+
export async function executeTestCommand(command, cwd, timeoutMs = DEFAULT_TEST_TIMEOUT_MS) {
|
|
104
|
+
return new Promise((resolvePromise) => {
|
|
105
|
+
const timestamp = new Date().toISOString();
|
|
106
|
+
const lines = [];
|
|
107
|
+
const child = spawn(command, { shell: true, cwd });
|
|
108
|
+
let timedOut = false;
|
|
109
|
+
const timer = setTimeout(() => {
|
|
110
|
+
timedOut = true;
|
|
111
|
+
child.kill();
|
|
112
|
+
}, timeoutMs);
|
|
113
|
+
function handleData(chunk, stream) {
|
|
114
|
+
const text = chunk.toString();
|
|
115
|
+
stream.write(text);
|
|
116
|
+
lines.push(...text.split('\n'));
|
|
117
|
+
}
|
|
118
|
+
child.stdout?.on('data', (chunk) => handleData(chunk, process.stdout));
|
|
119
|
+
child.stderr?.on('data', (chunk) => handleData(chunk, process.stderr));
|
|
120
|
+
child.on('close', (code) => {
|
|
121
|
+
clearTimeout(timer);
|
|
122
|
+
const exitCode = timedOut ? -1 : (code ?? 1);
|
|
123
|
+
const timeoutSecs = Math.round(timeoutMs / 1000);
|
|
124
|
+
const summaryLines = timedOut
|
|
125
|
+
? [`timed out after ${timeoutSecs}s`]
|
|
126
|
+
: lines.filter(l => l.trim()).slice(-20);
|
|
127
|
+
resolvePromise({
|
|
128
|
+
timestamp,
|
|
129
|
+
command,
|
|
130
|
+
exitCode,
|
|
131
|
+
summary: summaryLines.join('\n'),
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
child.on('error', (err) => {
|
|
135
|
+
clearTimeout(timer);
|
|
136
|
+
resolvePromise({
|
|
137
|
+
timestamp,
|
|
138
|
+
command,
|
|
139
|
+
exitCode: 127,
|
|
140
|
+
summary: err.message,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/** Full evidence-backed tests-passing check.
|
|
146
|
+
* Returns { passed, output, correction, warnNoCache } */
|
|
147
|
+
export async function runTestsPassingWithCache(options) {
|
|
148
|
+
const { implPath, cwd, testsCommand, rerunTests } = options;
|
|
149
|
+
const testResultMaxAgeMs = options.testResultMaxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
150
|
+
const testTimeoutMs = options.testTimeoutMs ?? DEFAULT_TEST_TIMEOUT_MS;
|
|
151
|
+
const cachePath = deriveCachePath(implPath, cwd);
|
|
152
|
+
// Warn and re-run if cache is corrupt
|
|
153
|
+
if (isCacheCorrupt(cachePath)) {
|
|
154
|
+
process.stderr.write(`Warning: Ignoring malformed cache at ${cachePath} — re-running tests.\n`);
|
|
155
|
+
}
|
|
156
|
+
let result = null;
|
|
157
|
+
if (!rerunTests) {
|
|
158
|
+
result = readCache(cachePath);
|
|
159
|
+
if (result && isCacheStale(result, implPath, cwd, testResultMaxAgeMs)) {
|
|
160
|
+
result = null; // stale — will re-execute
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Execute if no fresh cache
|
|
164
|
+
if (!result) {
|
|
165
|
+
result = await executeTestCommand(testsCommand, cwd, testTimeoutMs);
|
|
166
|
+
writeCache(cachePath, result);
|
|
167
|
+
}
|
|
168
|
+
if (result.exitCode === 0) {
|
|
169
|
+
return { passed: true, output: '', correction: '' };
|
|
170
|
+
}
|
|
171
|
+
if (result.exitCode === -1) {
|
|
172
|
+
const timeoutSecs = Math.round(testTimeoutMs / 1000);
|
|
173
|
+
return {
|
|
174
|
+
passed: false,
|
|
175
|
+
output: result.summary,
|
|
176
|
+
correction: `tests-passing blocked: test command timed out after ${timeoutSecs}s. Increase testTimeout in .taproot/settings.yaml if needed.`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
passed: false,
|
|
181
|
+
output: result.summary,
|
|
182
|
+
correction: 'tests-passing blocked: Fix failing tests and re-run taproot dod.',
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// Re-export for use in commithook staleness check
|
|
186
|
+
export { readResolutions };
|
|
187
|
+
//# sourceMappingURL=test-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-cache.js","sourceRoot":"","sources":["../../src/core/test-cache.ts"],"names":[],"mappings":"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"}
|
package/docs/agents.md
CHANGED
|
@@ -8,6 +8,7 @@ Taproot works with any AI assistant that can read files. Run `taproot init --age
|
|
|
8
8
|
|-------|-------------|---------|---------------------|
|
|
9
9
|
| Claude Code | **Tier 1** — fully supported | `taproot init --agent claude` | `.claude/commands/tr-*.md` — one file per slash command |
|
|
10
10
|
| Gemini CLI | **Tier 2** — implemented & tested | `taproot init --agent gemini` | `.gemini/commands/tr-*.toml` — one file per command |
|
|
11
|
+
| Aider | **Tier 2** — implemented & tested | `taproot init --agent aider` | `.aider.conf.yml` with `read:` entries + `CONVENTIONS.md` |
|
|
11
12
|
| Cursor | **Tier 3** — community supported | `taproot init --agent cursor` | `.cursor/rules/taproot.md` — project-wide rules |
|
|
12
13
|
| GitHub Copilot | **Tier 3** — community supported | `taproot init --agent copilot` | `.github/copilot-instructions.md` |
|
|
13
14
|
| Windsurf | **Tier 3** — community supported | `taproot init --agent windsurf` | `.windsurfrules` |
|
|
@@ -69,6 +70,16 @@ This refreshes all adapter files and skill definitions to the current version. R
|
|
|
69
70
|
|
|
70
71
|
---
|
|
71
72
|
|
|
73
|
+
## Aider
|
|
74
|
+
|
|
75
|
+
The Aider adapter installs `.aider.conf.yml` with `read:` entries so every Aider session automatically loads all taproot skill definitions and `CONVENTIONS.md` as context. No extra flags needed — run `aider` in the project directory and it picks up taproot context immediately.
|
|
76
|
+
|
|
77
|
+
Skills are invoked by natural language: *"implement the behaviour at taproot/my-intent/my-feature/"* rather than a slash command.
|
|
78
|
+
|
|
79
|
+
If `.aider.conf.yml` already exists, `taproot init` merges the `read:` entries without removing your existing settings (model, API key, etc.). If the file contains invalid YAML, the command stops with an error rather than overwriting it.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
72
83
|
## Non-Claude agents
|
|
73
84
|
|
|
74
85
|
For Cursor, Copilot, and Windsurf, the adapter installs a rules or instructions file. These give the agent context on the taproot hierarchy, the document formats, and the commit convention — enough to read and navigate the hierarchy, write conformant documents, and use the CLI commands correctly.
|
package/docs/cli.md
CHANGED
|
@@ -170,7 +170,7 @@ Surfaces unimplemented behaviours as work items, ordered by priority (intents wi
|
|
|
170
170
|
### `taproot dod`
|
|
171
171
|
|
|
172
172
|
```bash
|
|
173
|
-
taproot dod [impl-path] [--dry-run]
|
|
173
|
+
taproot dod [impl-path] [--dry-run] [--rerun-tests]
|
|
174
174
|
taproot dod <impl-path> --resolve <condition> --note "<text>" [--resolve <condition> --note "<text>" ...]
|
|
175
175
|
```
|
|
176
176
|
|
|
@@ -178,6 +178,8 @@ Runs all configured DoD conditions from `.taproot/settings.yaml` against the spe
|
|
|
178
178
|
|
|
179
179
|
Use `--resolve`/`--note` to record agent resolutions for agent-driven conditions (e.g. `document-current`, `check-if-affected`, `check-if-affected-by`). Multiple pairs can be supplied in a single invocation — conditions are paired with notes by position.
|
|
180
180
|
|
|
181
|
+
Use `--rerun-tests` to force re-execution of `testsCommand` regardless of any cached result. Requires `<impl-path>`.
|
|
182
|
+
|
|
181
183
|
See [Configuration](configuration.md) for how to define DoD conditions.
|
|
182
184
|
|
|
183
185
|
---
|
package/docs/configuration.md
CHANGED
|
@@ -64,7 +64,7 @@ The `definitionOfDone` list controls what `taproot dod` checks and what the pre-
|
|
|
64
64
|
|
|
65
65
|
| Form | What it does |
|
|
66
66
|
|------|-------------|
|
|
67
|
-
| `tests-passing` | Built-in: runs `npm test
|
|
67
|
+
| `tests-passing` | Built-in: runs `npm test`. When `testsCommand` is configured in `settings.yaml`, uses evidence-backed execution with a cache file — see [State Transition Guardrails](#state-transition-guardrails). |
|
|
68
68
|
| `linter-clean` | Built-in: runs `npm run lint`. Passes if exit code is 0. |
|
|
69
69
|
| `commit-conventions` | Built-in: runs `npm run check:commits`. Passes if exit code is 0. |
|
|
70
70
|
| `document-current: <description>` | Agent-verified: the agent checks whether the described documentation is current and applies updates if needed. |
|
|
@@ -106,6 +106,50 @@ Taproot's own `.taproot/settings.yaml` ships with several `check-if-affected-by`
|
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|
|
109
|
+
## Autonomous Execution
|
|
110
|
+
|
|
111
|
+
Setting `autonomous: true` in `settings.yaml` (or `TAPROOT_AUTONOMOUS=1` / `--autonomous` per invocation) puts all agent skills into non-interactive mode.
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
autonomous: true # all sessions in this repo run without confirmation prompts
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**What autonomous mode changes:**
|
|
118
|
+
- `/tr-implement` proceeds from plan to code without pausing for plan approval
|
|
119
|
+
- `/tr-commit` stages and commits without asking for confirmation when nothing is pre-staged
|
|
120
|
+
- DoD conditions are self-evaluated: resolvable conditions are recorded directly; unresolvable `check:` questions are marked `<!-- autonomous: pending-review -->` in `impl.md`
|
|
121
|
+
- Test failures or hook rejections are recorded in `impl.md` (impl marked `needs-rework`) and the agent stops — the developer returns to a clear failure report
|
|
122
|
+
|
|
123
|
+
**Three activation mechanisms (in order of scope):**
|
|
124
|
+
1. `autonomous: true` in `.taproot/settings.yaml` — repo-wide, all sessions
|
|
125
|
+
2. `TAPROOT_AUTONOMOUS=1` environment variable — per process invocation
|
|
126
|
+
3. `--autonomous` flag on a skill invocation (e.g. `/tr-implement path/ --autonomous`) — per skill
|
|
127
|
+
|
|
128
|
+
When none of these is set, confirmation prompts are shown as normal. Autonomous mode is never inferred from context.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## State Transition Guardrails
|
|
133
|
+
|
|
134
|
+
When `testsCommand` is set in `settings.yaml`, the `tests-passing` condition uses evidence-backed execution: it runs the command, caches the result in `.taproot/.test-results/`, and enforces freshness at commit time.
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
testsCommand: npm test # command to run for evidence-backed tests-passing
|
|
138
|
+
testResultMaxAge: 60 # minutes before a no-source-file cache is stale (default: 60)
|
|
139
|
+
testTimeout: 300 # seconds before testsCommand is killed (default: 300)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**How it works:**
|
|
143
|
+
- `taproot dod <impl-path>` runs `testsCommand`, streams output live, and writes `.taproot/.test-results/<intent>/<behaviour>/<impl>.json`
|
|
144
|
+
- On subsequent runs, the cached result is used if it is not stale (no tracked source files changed since the last run)
|
|
145
|
+
- `taproot dod <impl-path> --rerun-tests` forces re-execution regardless of cache
|
|
146
|
+
- `--resolve "tests-passing"` is rejected when `testsCommand` is configured — evidence is required, not agent assertion
|
|
147
|
+
- The pre-commit hook verifies a fresh passing result exists before allowing an implementation commit with a `complete` impl
|
|
148
|
+
|
|
149
|
+
**Add `.taproot/.test-results/` to `.gitignore`** — the cache is a local execution artifact, not a committed record.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
109
153
|
## Definition of Ready
|
|
110
154
|
|
|
111
155
|
The `definitionOfReady` list controls what the pre-commit hook checks when you make a declaration commit (committing `impl.md` without source files). All conditions must pass before the declaration commit is accepted.
|
package/docs/patterns.md
CHANGED
|
@@ -116,3 +116,46 @@ The agent reads the question text, reasons whether the answer is yes, no, or not
|
|
|
116
116
|
|---|---|
|
|
117
117
|
| `does this story introduce a cross-cutting concern that warrants a new check-if-affected-by or check-if-affected entry in .taproot/settings.yaml?` | Agent adds the entry to `.taproot/settings.yaml` |
|
|
118
118
|
| `does this story reveal a reusable pattern worth documenting in docs/patterns.md?` | Agent adds a pattern entry to `docs/patterns.md` |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Autonomous mode preamble (`## Autonomous mode` section in skills)
|
|
123
|
+
|
|
124
|
+
**Problem:** A skill has one or more confirmation prompts (plan approval, staging confirmation, DoD resolution prompts). You want the same skill to work in both interactive and non-interactive (CI, headless agent) contexts without maintaining two versions.
|
|
125
|
+
|
|
126
|
+
**Pattern:** Add an `## Autonomous mode` section at the top of the skill file (before `## Steps`) that tells the agent to check for autonomous mode activation and apply autonomous notes throughout the steps.
|
|
127
|
+
|
|
128
|
+
```markdown
|
|
129
|
+
## Autonomous mode
|
|
130
|
+
|
|
131
|
+
Before following any steps, check whether autonomous mode is active:
|
|
132
|
+
- `TAPROOT_AUTONOMOUS=1` is set in the environment, **or**
|
|
133
|
+
- `--autonomous` was passed as an argument to this skill invocation, **or**
|
|
134
|
+
- `.taproot/settings.yaml` contains `autonomous: true`
|
|
135
|
+
|
|
136
|
+
If any of these is true, **autonomous mode is active** — apply the autonomous notes at each step where they appear. If none is true, autonomous mode is **inactive** — show confirmation prompts as normal.
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Then at each confirmation step, add a conditional note:
|
|
140
|
+
|
|
141
|
+
```markdown
|
|
142
|
+
**Interactive mode:** ask "Should I proceed?" and wait for confirmation.
|
|
143
|
+
|
|
144
|
+
**Autonomous mode:** proceed directly without waiting for confirmation.
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**When to use it:**
|
|
148
|
+
- The skill has at least one confirmation prompt that would block unattended execution
|
|
149
|
+
- You want CI agents, headless runners, or `TAPROOT_AUTONOMOUS=1` users to be able to run the skill without interaction
|
|
150
|
+
- The skill already exists and works correctly in interactive mode — this is an additive change
|
|
151
|
+
|
|
152
|
+
**When NOT to use it:**
|
|
153
|
+
- The confirmation prompt exists to prevent destructive irreversible actions (e.g. deleting data, force-pushing) — in these cases, autonomous bypass is unsafe
|
|
154
|
+
- The skill is already fully automated (no prompts) — the preamble adds noise without value
|
|
155
|
+
|
|
156
|
+
**Taproot's built-in uses:**
|
|
157
|
+
|
|
158
|
+
| Skill | Prompt bypassed in autonomous mode |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `skills/implement.md` | Plan approval in step 4 |
|
|
161
|
+
| `skills/commit.md` | Staging confirmation in step 3 |
|
package/package.json
CHANGED
package/skills/backlog.md
CHANGED
|
@@ -33,12 +33,16 @@ Capture ideas, findings, and deferred work mid-session with a single command —
|
|
|
33
33
|
```
|
|
34
34
|
Non-standard lines (not matching `- [YYYY-MM-DD] <text>`) are silently skipped in the display but preserved in the file.
|
|
35
35
|
|
|
36
|
-
3. Offer: `D <n>` discard · `P <n>` promote · `A <n>` analyze · `done` finish
|
|
36
|
+
3. Offer: `D <n>` discard · `P <n>` promote to /tr-ineed · `A <n>` analyze · `done` finish
|
|
37
37
|
|
|
38
38
|
4. Accept commands one at a time:
|
|
39
39
|
- **`D <n>`** — remove item n from `.taproot/backlog.md`. Confirm: *"✓ Discarded #n"*. Redisplay the updated numbered list.
|
|
40
|
-
- **`P <n
|
|
41
|
-
- **`A <n
|
|
40
|
+
- **`P <n>` promote to /tr-ineed** — remove item n from `.taproot/backlog.md`. Invoke `/tr-ineed` with the item text. On return, redisplay the updated numbered list.
|
|
41
|
+
- **`A <n>` analyze** — produce a structured analysis of the item:
|
|
42
|
+
- A short description of what the item is or could be (2–4 sentences)
|
|
43
|
+
- A complexity signal: **simple** / **moderate** / **significant**
|
|
44
|
+
- An impact assessment: **minor addition** / **meaningful improvement** / **major capability**
|
|
45
|
+
Then ask: *"[P] Promote to /tr-ineed · [K] Keep · [D] Discard"*. After the choice, redisplay the updated numbered list.
|
|
42
46
|
- **`done`** — end triage. Items not acted on are kept implicitly.
|
|
43
47
|
|
|
44
48
|
5. After `done`: *"Triage complete — X discarded, Y promoted, Z kept."*
|
package/skills/bug.md
CHANGED
|
@@ -31,6 +31,19 @@ Diagnose a defect through structured root cause analysis (5-Why) and delegate to
|
|
|
31
31
|
- **External cause** — dependency, environment, or configuration outside the hierarchy
|
|
32
32
|
- If categories overlap, use this priority: **Spec gap > Implementation gap > Missing test**
|
|
33
33
|
|
|
34
|
+
4a. **Recurrence check.** Ask: *"Could this class of bug happen again — is there a missing gate or outdated guideline that would prevent it?"*
|
|
35
|
+
|
|
36
|
+
- **No (clearly one-off** — typo, isolated misconfiguration, external incident): note this and continue to step 5.
|
|
37
|
+
- **Yes**: propose prevention across one or more of:
|
|
38
|
+
- A new DoR or DoD condition to add to `.taproot/settings.yaml`
|
|
39
|
+
- An update to `docs/architecture.md`, `docs/security.md`, or `docs/patterns.md`
|
|
40
|
+
|
|
41
|
+
If a satisfactory measure is found: present it — e.g. *"I'll add `check-if-affected-by: <gate>` to `.taproot/settings.yaml`"* or *"I'll add to `docs/security.md`: `<constraint>`"* — and wait for actor confirmation.
|
|
42
|
+
- On **confirm**: apply the change, then continue to step 5.
|
|
43
|
+
- On **reject**: record the recurrence concern in the implicated impl.md `## Notes` and continue to step 5.
|
|
44
|
+
|
|
45
|
+
If no satisfactory measure can be identified: invoke `/tr-grill-me` seeded with *"How do we prevent `<root-cause>` from recurring?"* — incorporate the answer and apply it before continuing to step 5.
|
|
46
|
+
|
|
34
47
|
5. **Locate the implicated artifact.** Use reverse lookup:
|
|
35
48
|
- Scan all `impl.md` files in `taproot/` for `## Source Files` entries matching the files involved in the root cause
|
|
36
49
|
- If a match is found: that impl.md is implicated
|
package/skills/commit.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Skill: commit
|
|
2
2
|
|
|
3
|
+
## Autonomous mode
|
|
4
|
+
|
|
5
|
+
Before following any steps, check whether autonomous mode is active:
|
|
6
|
+
- `TAPROOT_AUTONOMOUS=1` is set in the environment, **or**
|
|
7
|
+
- `--autonomous` was passed as an argument to this skill invocation, **or**
|
|
8
|
+
- `.taproot/settings.yaml` contains `autonomous: true`
|
|
9
|
+
|
|
10
|
+
If any of these is true, **autonomous mode is active** — apply autonomous notes where they appear. If none is true, show confirmation prompts as normal.
|
|
11
|
+
|
|
3
12
|
## Description
|
|
4
13
|
|
|
5
14
|
Execute the full commit procedure: classify the commit type, run the appropriate gate proactively, resolve all conditions before staging, and commit. Handles implementation, declaration, requirement, and plain commits. Invoke this skill whenever you are about to commit, or when the user says "commit", "let's commit", "commit that", or similar.
|
|
@@ -20,7 +29,11 @@ Execute the full commit procedure: classify the commit type, run the appropriate
|
|
|
20
29
|
|
|
21
30
|
To identify impl.md ownership, run `grep -rl "<filename>" taproot/` for each candidate source file.
|
|
22
31
|
|
|
23
|
-
3. If nothing is staged yet, announce: "Nothing staged yet. Here's what's changed: [list].
|
|
32
|
+
3. If nothing is staged yet, announce: "Nothing staged yet. Here's what's changed: [list]."
|
|
33
|
+
|
|
34
|
+
**Interactive mode:** ask "Should I stage these and proceed with the commit?" and wait for confirmation before proceeding.
|
|
35
|
+
|
|
36
|
+
**Autonomous mode:** stage all relevant files and proceed directly without waiting for confirmation.
|
|
24
37
|
|
|
25
38
|
4. Read `.taproot/settings.yaml` to identify all configured `definitionOfDone` and `definitionOfReady` conditions. If the file does not exist or has no `definitionOfDone`/`definitionOfReady` sections, note: "No user-configured conditions — baseline hook checks only." and proceed to the appropriate sub-flow below.
|
|
26
39
|
|
package/skills/grill-me.md
CHANGED
|
@@ -46,6 +46,7 @@ Based on Matt Pocock's `grill-me` skill (MIT licensed, https://github.com/mattpo
|
|
|
46
46
|
**What's next?**
|
|
47
47
|
[A] `/tr-ineed "<clarified requirement>"` — route the sharpened requirement into the hierarchy
|
|
48
48
|
[B] `/tr-behaviour <path>/` — write the spec now that the design is clear
|
|
49
|
+
[C] `/tr-backlog <deferred question>` — capture an unresolved question for later without routing it now
|
|
49
50
|
|
|
50
51
|
## Output
|
|
51
52
|
|
package/skills/guide.md
CHANGED
|
@@ -105,6 +105,7 @@ ineed → intent → behaviour → implement → trace → status
|
|
|
105
105
|
**What's next?**
|
|
106
106
|
[A] `/tr-ineed` — capture your first (or next) requirement
|
|
107
107
|
[B] `/tr-status` — see the current project health at a glance
|
|
108
|
+
[C] `/tr-backlog` — triage captured ideas (only if `.taproot/backlog.md` is non-empty)
|
|
108
109
|
|
|
109
110
|
## Output
|
|
110
111
|
|
package/skills/implement.md
CHANGED
|
@@ -9,6 +9,15 @@ Implement a behaviour spec: write the code, write the tests, create the `impl.md
|
|
|
9
9
|
- `path` (required): Path to the behaviour folder containing `usecase.md` to implement.
|
|
10
10
|
- `name` (optional): Slug for the implementation folder (e.g., `rest-api`, `background-job`). If omitted, derive from the implementation approach chosen.
|
|
11
11
|
|
|
12
|
+
## Autonomous mode
|
|
13
|
+
|
|
14
|
+
Before following any steps, check whether autonomous mode is active:
|
|
15
|
+
- `TAPROOT_AUTONOMOUS=1` is set in the environment, **or**
|
|
16
|
+
- `--autonomous` was passed as an argument to this skill invocation, **or**
|
|
17
|
+
- `.taproot/settings.yaml` contains `autonomous: true`
|
|
18
|
+
|
|
19
|
+
If any of these is true, **autonomous mode is active** — apply the autonomous notes at each step where they appear. If none is true, autonomous mode is **inactive** — show confirmation prompts as normal.
|
|
20
|
+
|
|
12
21
|
## Steps
|
|
13
22
|
|
|
14
23
|
1. Read `<path>/usecase.md` thoroughly. Understand:
|
|
@@ -38,7 +47,9 @@ Implement a behaviour spec: write the code, write the tests, create the `impl.md
|
|
|
38
47
|
- Any design decisions that need to be made (with options and recommendation)
|
|
39
48
|
- The implementation folder slug and path
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
**Autonomous mode:** form the plan internally, record it in the `impl.md` Design Decisions section, and proceed directly to step 5 without pausing for approval.
|
|
51
|
+
|
|
52
|
+
**Interactive mode:** present the plan. Do not proceed to writing code until the user approves.
|
|
42
53
|
|
|
43
54
|
5. Create the implementation folder `<path>/<impl-slug>/` and write `impl.md`:
|
|
44
55
|
- **Behaviour**: relative path to `../usecase.md`
|
|
@@ -99,8 +110,15 @@ Implement a behaviour spec: write the code, write the tests, create the `impl.md
|
|
|
99
110
|
b. Write the tests — each test should be traceable to a specific UseCase step, postcondition, error condition, or alternate flow trigger. Name tests descriptively.
|
|
100
111
|
c. Verify the tests pass
|
|
101
112
|
|
|
113
|
+
**Autonomous mode — if tests fail:** record the full test output in `impl.md` under a `## Notes` entry headed `Autonomous execution — test failure`, set `**State:** needs-rework`, and stop. Do not attempt to fix tests autonomously without context from the developer.
|
|
114
|
+
|
|
102
115
|
8. Run `taproot dod <impl-path>` to evaluate the Definition of Done. For agent-driven conditions (`check-if-affected`, `document-current`): reason about each, apply any needed changes, then record your resolution with `taproot dod <impl-path> --resolve "<condition>" --note "<reasoning>"`. Re-run until all conditions pass. `taproot dod` marks `impl.md` state `complete` when all pass.
|
|
103
116
|
|
|
117
|
+
**Autonomous mode — DoD self-resolution:**
|
|
118
|
+
- For every `check-if-affected-by`, `check-if-affected`, `check:`, and `document-current` condition: reason through it by reading the spec and source, then record the resolution with `--resolve` and `--note` without prompting.
|
|
119
|
+
- For any `check:` condition where the answer cannot be determined from the code and spec alone: write a `<!-- autonomous: pending-review -->` comment in `## DoD Resolutions` alongside the unresolved condition entry, with the question text. Continue evaluating remaining conditions. After all conditions are processed, if any remain marked pending-review, set `**State:** in-progress` and commit — the developer will complete them on return.
|
|
120
|
+
- For `run:` conditions that exit non-zero: record the output in `impl.md`, mark `needs-rework`, and stop.
|
|
121
|
+
|
|
104
122
|
9. **Implementation commit** — commit source files and `impl.md` together:
|
|
105
123
|
|
|
106
124
|
Before staging:
|