@imix-js/taproot 0.2.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/README.md +88 -0
- package/dist/adapters/index.d.ts +20 -0
- package/dist/adapters/index.js +452 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +40 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/acceptance-check.d.ts +26 -0
- package/dist/commands/acceptance-check.js +213 -0
- package/dist/commands/acceptance-check.js.map +1 -0
- package/dist/commands/check-orphans.d.ts +8 -0
- package/dist/commands/check-orphans.js +157 -0
- package/dist/commands/check-orphans.js.map +1 -0
- package/dist/commands/commithook.d.ts +15 -0
- package/dist/commands/commithook.js +389 -0
- package/dist/commands/commithook.js.map +1 -0
- package/dist/commands/coverage.d.ts +41 -0
- package/dist/commands/coverage.js +390 -0
- package/dist/commands/coverage.js.map +1 -0
- package/dist/commands/dod.d.ts +13 -0
- package/dist/commands/dod.js +141 -0
- package/dist/commands/dod.js.map +1 -0
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.js +378 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/link-commits.d.ts +12 -0
- package/dist/commands/link-commits.js +126 -0
- package/dist/commands/link-commits.js.map +1 -0
- package/dist/commands/overview.d.ts +6 -0
- package/dist/commands/overview.js +192 -0
- package/dist/commands/overview.js.map +1 -0
- package/dist/commands/plan.d.ts +23 -0
- package/dist/commands/plan.js +167 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/sync-check.d.ts +8 -0
- package/dist/commands/sync-check.js +118 -0
- package/dist/commands/sync-check.js.map +1 -0
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.js +309 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate-format.d.ts +8 -0
- package/dist/commands/validate-format.js +93 -0
- package/dist/commands/validate-format.js.map +1 -0
- package/dist/commands/validate-structure.d.ts +8 -0
- package/dist/commands/validate-structure.js +29 -0
- package/dist/commands/validate-structure.js.map +1 -0
- package/dist/core/config.d.ts +6 -0
- package/dist/core/config.js +86 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/configuration.d.ts +7 -0
- package/dist/core/configuration.js +112 -0
- package/dist/core/configuration.js.map +1 -0
- package/dist/core/dod-runner.d.ts +20 -0
- package/dist/core/dod-runner.js +233 -0
- package/dist/core/dod-runner.js.map +1 -0
- package/dist/core/dor-runner.d.ts +18 -0
- package/dist/core/dor-runner.js +156 -0
- package/dist/core/dor-runner.js.map +1 -0
- package/dist/core/fs-walker.d.ts +5 -0
- package/dist/core/fs-walker.js +74 -0
- package/dist/core/fs-walker.js.map +1 -0
- package/dist/core/git.d.ts +24 -0
- package/dist/core/git.js +76 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/impl-reader.d.ts +8 -0
- package/dist/core/impl-reader.js +39 -0
- package/dist/core/impl-reader.js.map +1 -0
- package/dist/core/language.d.ts +39 -0
- package/dist/core/language.js +159 -0
- package/dist/core/language.js.map +1 -0
- package/dist/core/markdown-parser.d.ts +3 -0
- package/dist/core/markdown-parser.js +37 -0
- package/dist/core/markdown-parser.js.map +1 -0
- package/dist/core/reporter.d.ts +3 -0
- package/dist/core/reporter.js +33 -0
- package/dist/core/reporter.js.map +1 -0
- package/dist/templates/index.d.ts +4 -0
- package/dist/templates/index.js +126 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/validators/format-rules.d.ts +10 -0
- package/dist/validators/format-rules.js +238 -0
- package/dist/validators/format-rules.js.map +1 -0
- package/dist/validators/structure-rules.d.ts +10 -0
- package/dist/validators/structure-rules.js +94 -0
- package/dist/validators/structure-rules.js.map +1 -0
- package/dist/validators/types.d.ts +68 -0
- package/dist/validators/types.js +2 -0
- package/dist/validators/types.js.map +1 -0
- package/docs/agents.md +88 -0
- package/docs/architecture.md +53 -0
- package/docs/cli.md +226 -0
- package/docs/concepts.md +268 -0
- package/docs/configuration.md +255 -0
- package/docs/demo.svg +111 -0
- package/docs/patterns.md +118 -0
- package/docs/security.md +95 -0
- package/docs/workflows.md +151 -0
- package/languages/de.json +20 -0
- package/languages/en.json +20 -0
- package/languages/es.json +20 -0
- package/languages/fr.json +20 -0
- package/languages/ja.json +20 -0
- package/languages/pt.json +20 -0
- package/package.json +54 -0
- package/skills/analyse-change.md +101 -0
- package/skills/behaviour.md +179 -0
- package/skills/bug.md +70 -0
- package/skills/commit.md +99 -0
- package/skills/decompose.md +101 -0
- package/skills/discover.md +392 -0
- package/skills/grill-me.md +65 -0
- package/skills/guide.md +118 -0
- package/skills/implement.md +149 -0
- package/skills/ineed.md +147 -0
- package/skills/intent.md +104 -0
- package/skills/plan.md +63 -0
- package/skills/promote.md +69 -0
- package/skills/refine.md +78 -0
- package/skills/research.md +122 -0
- package/skills/review-all.md +92 -0
- package/skills/review.md +80 -0
- package/skills/status.md +103 -0
- package/skills/sweep.md +89 -0
- package/skills/trace.md +151 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
import { loadConfig } from '../core/config.js';
|
|
4
|
+
import { walkHierarchy } from '../core/fs-walker.js';
|
|
5
|
+
import { parseMarkdown } from '../core/markdown-parser.js';
|
|
6
|
+
import { parseImplData } from '../core/impl-reader.js';
|
|
7
|
+
// ─── Extraction helpers ───────────────────────────────────────────────────────
|
|
8
|
+
function readSection(filePath, section) {
|
|
9
|
+
try {
|
|
10
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
11
|
+
const doc = parseMarkdown(filePath, content);
|
|
12
|
+
return doc.sections.get(section)?.rawBody.trim() ?? '';
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function readState(filePath) {
|
|
19
|
+
try {
|
|
20
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
21
|
+
const doc = parseMarkdown(filePath, content);
|
|
22
|
+
const status = doc.sections.get('status');
|
|
23
|
+
const match = /\*\*State:\*\*\s*(\S+)/.exec(status?.rawBody ?? '');
|
|
24
|
+
return match?.[1]?.trim() ?? 'unknown';
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return 'unknown';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function buildImpl(node) {
|
|
31
|
+
const filePath = join(node.absolutePath, 'impl.md');
|
|
32
|
+
const state = readState(filePath);
|
|
33
|
+
let commitCount = 0;
|
|
34
|
+
let testCount = 0;
|
|
35
|
+
try {
|
|
36
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
37
|
+
const doc = parseMarkdown(filePath, content);
|
|
38
|
+
const data = parseImplData(doc);
|
|
39
|
+
commitCount = data.commits.length;
|
|
40
|
+
testCount = data.testFiles.length;
|
|
41
|
+
}
|
|
42
|
+
catch { /* use defaults */ }
|
|
43
|
+
return { name: node.name, path: `./${node.relativePath}/impl.md`, state, commitCount, testCount };
|
|
44
|
+
}
|
|
45
|
+
function buildBehaviour(node) {
|
|
46
|
+
const filePath = join(node.absolutePath, 'usecase.md');
|
|
47
|
+
const state = readState(filePath);
|
|
48
|
+
const actorRaw = readSection(filePath, 'actor');
|
|
49
|
+
const actor = actorRaw.replace(/<[^>]+>/g, '').split('\n')[0]?.trim() ?? '';
|
|
50
|
+
const implementations = [];
|
|
51
|
+
const subBehaviours = [];
|
|
52
|
+
for (const child of node.children) {
|
|
53
|
+
if (child.marker === 'impl')
|
|
54
|
+
implementations.push(buildImpl(child));
|
|
55
|
+
else if (child.marker === 'behaviour')
|
|
56
|
+
subBehaviours.push(buildBehaviour(child));
|
|
57
|
+
}
|
|
58
|
+
return { name: node.name, path: `./${node.relativePath}/usecase.md`, actor, state, implementations, subBehaviours };
|
|
59
|
+
}
|
|
60
|
+
function buildIntent(node) {
|
|
61
|
+
const filePath = join(node.absolutePath, 'intent.md');
|
|
62
|
+
const state = readState(filePath);
|
|
63
|
+
const goalRaw = readSection(filePath, 'goal');
|
|
64
|
+
// Strip template placeholders, take first sentence
|
|
65
|
+
const goal = goalRaw.replace(/<[^>]+>/g, '').split(/\.\s+/)[0]?.trim() ?? '';
|
|
66
|
+
const behaviours = [];
|
|
67
|
+
for (const child of node.children) {
|
|
68
|
+
if (child.marker === 'behaviour')
|
|
69
|
+
behaviours.push(buildBehaviour(child));
|
|
70
|
+
}
|
|
71
|
+
return { name: node.name, path: `./${node.relativePath}/intent.md`, goal, state, behaviours };
|
|
72
|
+
}
|
|
73
|
+
// ─── Formatters ───────────────────────────────────────────────────────────────
|
|
74
|
+
function implCounts(b) {
|
|
75
|
+
let total = b.implementations.length;
|
|
76
|
+
let complete = b.implementations.filter(i => i.state === 'complete').length;
|
|
77
|
+
for (const sub of b.subBehaviours) {
|
|
78
|
+
const c = implCounts(sub);
|
|
79
|
+
total += c.total;
|
|
80
|
+
complete += c.complete;
|
|
81
|
+
}
|
|
82
|
+
return { total, complete };
|
|
83
|
+
}
|
|
84
|
+
function renderBehaviour(b, indent) {
|
|
85
|
+
const lines = [];
|
|
86
|
+
const actor = b.actor ? ` — Actor: ${b.actor}` : '';
|
|
87
|
+
lines.push(`${indent}- **[${b.name}](${b.path})** \`[${b.state}]\`${actor}`);
|
|
88
|
+
for (const impl of b.implementations) {
|
|
89
|
+
const tests = impl.testCount > 0
|
|
90
|
+
? `, ${impl.testCount} test${impl.testCount !== 1 ? 's' : ''}`
|
|
91
|
+
: ' ⚠ no tests';
|
|
92
|
+
lines.push(`${indent} - [${impl.name}](${impl.path}) \`[${impl.state}]\` (${impl.commitCount} commit${impl.commitCount !== 1 ? 's' : ''}${tests})`);
|
|
93
|
+
}
|
|
94
|
+
for (const sub of b.subBehaviours) {
|
|
95
|
+
lines.push(...renderBehaviour(sub, indent + ' '));
|
|
96
|
+
}
|
|
97
|
+
return lines;
|
|
98
|
+
}
|
|
99
|
+
function formatOverview(intents) {
|
|
100
|
+
const now = new Date().toISOString().slice(0, 10);
|
|
101
|
+
const lines = [];
|
|
102
|
+
lines.push('# Project Overview');
|
|
103
|
+
lines.push('');
|
|
104
|
+
lines.push('<!-- Auto-generated by `taproot overview` — do not edit manually -->');
|
|
105
|
+
lines.push(`<!-- Last updated: ${now} -->`);
|
|
106
|
+
lines.push('');
|
|
107
|
+
lines.push('Compact summary for AI agents. Read this before diving into individual taproot documents.');
|
|
108
|
+
lines.push('');
|
|
109
|
+
if (intents.length === 0) {
|
|
110
|
+
lines.push('_No intents defined yet. Run `/tr-intent` to create one._');
|
|
111
|
+
lines.push('');
|
|
112
|
+
return lines.join('\n');
|
|
113
|
+
}
|
|
114
|
+
let totalBehaviours = 0;
|
|
115
|
+
let totalImpls = 0;
|
|
116
|
+
let totalComplete = 0;
|
|
117
|
+
for (const intent of intents) {
|
|
118
|
+
lines.push(`## [${intent.name}](${intent.path}) \`[${intent.state}]\``);
|
|
119
|
+
lines.push('');
|
|
120
|
+
if (intent.goal) {
|
|
121
|
+
lines.push(`**Goal:** ${intent.goal}`);
|
|
122
|
+
lines.push('');
|
|
123
|
+
}
|
|
124
|
+
if (intent.behaviours.length === 0) {
|
|
125
|
+
lines.push('_No behaviours yet._');
|
|
126
|
+
lines.push('');
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
for (const b of intent.behaviours) {
|
|
130
|
+
lines.push(...renderBehaviour(b, ''));
|
|
131
|
+
const c = implCounts(b);
|
|
132
|
+
totalBehaviours++;
|
|
133
|
+
totalImpls += c.total;
|
|
134
|
+
totalComplete += c.complete;
|
|
135
|
+
// count sub-behaviours toward totals
|
|
136
|
+
const countSubs = (sub) => {
|
|
137
|
+
totalBehaviours++;
|
|
138
|
+
for (const s of sub.subBehaviours)
|
|
139
|
+
countSubs(s);
|
|
140
|
+
};
|
|
141
|
+
for (const sub of b.subBehaviours)
|
|
142
|
+
countSubs(sub);
|
|
143
|
+
}
|
|
144
|
+
lines.push('');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
lines.push('---');
|
|
148
|
+
lines.push(`${intents.length} intent${intents.length !== 1 ? 's' : ''} · ` +
|
|
149
|
+
`${totalBehaviours} behaviour${totalBehaviours !== 1 ? 's' : ''} · ` +
|
|
150
|
+
`${totalImpls} implementation${totalImpls !== 1 ? 's' : ''} · ` +
|
|
151
|
+
`${totalComplete}/${totalImpls} complete`);
|
|
152
|
+
lines.push('');
|
|
153
|
+
return lines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
156
|
+
export async function runOverview(options) {
|
|
157
|
+
const { taprootDir } = options;
|
|
158
|
+
if (!existsSync(taprootDir))
|
|
159
|
+
return [];
|
|
160
|
+
const tree = walkHierarchy(taprootDir);
|
|
161
|
+
const intents = tree.children
|
|
162
|
+
.filter(c => c.marker === 'intent')
|
|
163
|
+
.map(buildIntent);
|
|
164
|
+
if (intents.length === 0)
|
|
165
|
+
return [];
|
|
166
|
+
const content = formatOverview(intents);
|
|
167
|
+
const outputPath = join(taprootDir, 'OVERVIEW.md');
|
|
168
|
+
writeFileSync(outputPath, content, 'utf-8');
|
|
169
|
+
const rel = options.cwd
|
|
170
|
+
? outputPath.replace(options.cwd + '/', '').replace(options.cwd + '\\', '')
|
|
171
|
+
: outputPath;
|
|
172
|
+
return [`updated ${rel}`];
|
|
173
|
+
}
|
|
174
|
+
export function registerOverview(program) {
|
|
175
|
+
program
|
|
176
|
+
.command('overview')
|
|
177
|
+
.description('Generate OVERVIEW.md — compact project summary for AI context')
|
|
178
|
+
.option('--path <path>', 'Taproot root directory (overrides config)')
|
|
179
|
+
.action(async (options) => {
|
|
180
|
+
const { config } = loadConfig();
|
|
181
|
+
const taprootDir = options.path ? resolve(options.path) : config.root;
|
|
182
|
+
const msgs = await runOverview({ taprootDir });
|
|
183
|
+
if (msgs.length === 0) {
|
|
184
|
+
process.stdout.write('No intents found — nothing to summarize.\n');
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
for (const msg of msgs)
|
|
188
|
+
process.stdout.write(msg + '\n');
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=overview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overview.js","sourceRoot":"","sources":["../../src/commands/overview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
export type Classification = 'afk' | 'hitl';
|
|
3
|
+
export type PlanFormat = 'tree' | 'json';
|
|
4
|
+
export interface PlanCandidate {
|
|
5
|
+
behaviourPath: string;
|
|
6
|
+
behaviourName: string;
|
|
7
|
+
intentName: string;
|
|
8
|
+
intentGoal: string;
|
|
9
|
+
specState: string;
|
|
10
|
+
classification: Classification;
|
|
11
|
+
classificationReason: string;
|
|
12
|
+
inProgressImpls: number;
|
|
13
|
+
}
|
|
14
|
+
export interface PlanReport {
|
|
15
|
+
candidates: PlanCandidate[];
|
|
16
|
+
allImplemented: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function runPlan(options: {
|
|
19
|
+
path?: string;
|
|
20
|
+
cwd?: string;
|
|
21
|
+
}): Promise<PlanReport>;
|
|
22
|
+
export declare function formatPlan(report: PlanReport, format: PlanFormat): string;
|
|
23
|
+
export declare function registerPlan(program: Command): void;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
import { loadConfig } from '../core/config.js';
|
|
4
|
+
import { walkHierarchy } from '../core/fs-walker.js';
|
|
5
|
+
import { parseMarkdown } from '../core/markdown-parser.js';
|
|
6
|
+
// ─── State reading ────────────────────────────────────────────────────────────
|
|
7
|
+
function readState(filePath) {
|
|
8
|
+
try {
|
|
9
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
10
|
+
const doc = parseMarkdown(filePath, content);
|
|
11
|
+
const match = /\*\*State:\*\*\s*(\S+)/.exec(doc.sections.get('status')?.rawBody ?? '');
|
|
12
|
+
return match?.[1]?.trim() ?? 'unknown';
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return 'unknown';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function readGoal(intentPath) {
|
|
19
|
+
try {
|
|
20
|
+
const content = readFileSync(intentPath, 'utf-8');
|
|
21
|
+
const doc = parseMarkdown(intentPath, content);
|
|
22
|
+
const goalBody = doc.sections.get('goal')?.rawBody ?? '';
|
|
23
|
+
return goalBody.replace(/<[^>]+>/g, '').split(/\.\s+/)[0]?.trim() ?? '';
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// ─── Classification ───────────────────────────────────────────────────────────
|
|
30
|
+
function classify(specState, hasInProgressImpls) {
|
|
31
|
+
if (specState === 'specified') {
|
|
32
|
+
return { classification: 'afk', reason: 'spec is complete and unambiguous' };
|
|
33
|
+
}
|
|
34
|
+
if (specState === 'implemented' && hasInProgressImpls) {
|
|
35
|
+
return { classification: 'afk', reason: 'spec is done; existing implementation is in-progress' };
|
|
36
|
+
}
|
|
37
|
+
if (specState === 'proposed') {
|
|
38
|
+
return { classification: 'hitl', reason: 'spec is only proposed — needs human review before implementing' };
|
|
39
|
+
}
|
|
40
|
+
return { classification: 'hitl', reason: `spec state "${specState}" — review before implementing` };
|
|
41
|
+
}
|
|
42
|
+
// ─── Hierarchy walk ───────────────────────────────────────────────────────────
|
|
43
|
+
function collectCandidates(node, intentName, intentGoal) {
|
|
44
|
+
const candidates = [];
|
|
45
|
+
if (node.marker === 'intent') {
|
|
46
|
+
const intentPath = join(node.absolutePath, 'intent.md');
|
|
47
|
+
const name = node.name;
|
|
48
|
+
const goal = readGoal(intentPath);
|
|
49
|
+
for (const child of node.children) {
|
|
50
|
+
candidates.push(...collectCandidates(child, name, goal));
|
|
51
|
+
}
|
|
52
|
+
return candidates;
|
|
53
|
+
}
|
|
54
|
+
if (node.marker === 'behaviour') {
|
|
55
|
+
const implChildren = node.children.filter(c => c.marker === 'impl');
|
|
56
|
+
const subBehaviours = node.children.filter(c => c.marker === 'behaviour');
|
|
57
|
+
// Recurse into sub-behaviours
|
|
58
|
+
for (const sub of subBehaviours) {
|
|
59
|
+
candidates.push(...collectCandidates(sub, intentName, intentGoal));
|
|
60
|
+
}
|
|
61
|
+
const specState = readState(join(node.absolutePath, 'usecase.md'));
|
|
62
|
+
// Skip deferred behaviours entirely
|
|
63
|
+
if (specState === 'deferred')
|
|
64
|
+
return candidates;
|
|
65
|
+
// Check impl status — exclude deferred impls from completion accounting
|
|
66
|
+
const activeImplStates = implChildren
|
|
67
|
+
.map(c => readState(join(c.absolutePath, 'impl.md')))
|
|
68
|
+
.filter(s => s !== 'deferred');
|
|
69
|
+
const allComplete = activeImplStates.length > 0 && activeImplStates.every(s => s === 'complete');
|
|
70
|
+
const inProgressCount = activeImplStates.filter(s => s === 'in-progress').length;
|
|
71
|
+
// Skip if fully implemented
|
|
72
|
+
if (allComplete)
|
|
73
|
+
return candidates;
|
|
74
|
+
const { classification, reason } = classify(specState, inProgressCount > 0);
|
|
75
|
+
candidates.push({
|
|
76
|
+
behaviourPath: node.relativePath,
|
|
77
|
+
behaviourName: node.name,
|
|
78
|
+
intentName,
|
|
79
|
+
intentGoal,
|
|
80
|
+
specState,
|
|
81
|
+
classification,
|
|
82
|
+
classificationReason: reason,
|
|
83
|
+
inProgressImpls: inProgressCount,
|
|
84
|
+
});
|
|
85
|
+
return candidates;
|
|
86
|
+
}
|
|
87
|
+
// Root or unknown node — recurse
|
|
88
|
+
for (const child of node.children) {
|
|
89
|
+
candidates.push(...collectCandidates(child, intentName, intentGoal));
|
|
90
|
+
}
|
|
91
|
+
return candidates;
|
|
92
|
+
}
|
|
93
|
+
// ─── Core logic ───────────────────────────────────────────────────────────────
|
|
94
|
+
export async function runPlan(options) {
|
|
95
|
+
const { config } = loadConfig(options.cwd);
|
|
96
|
+
const rootPath = options.path ? resolve(options.path) : config.root;
|
|
97
|
+
const tree = walkHierarchy(rootPath);
|
|
98
|
+
const candidates = collectCandidates(tree, '', '');
|
|
99
|
+
// Sort: AFK before HITL, then alphabetically by path
|
|
100
|
+
candidates.sort((a, b) => {
|
|
101
|
+
if (a.classification !== b.classification) {
|
|
102
|
+
return a.classification === 'afk' ? -1 : 1;
|
|
103
|
+
}
|
|
104
|
+
return a.behaviourPath.localeCompare(b.behaviourPath);
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
candidates,
|
|
108
|
+
allImplemented: candidates.length === 0,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// ─── Formatters ───────────────────────────────────────────────────────────────
|
|
112
|
+
export function formatPlan(report, format) {
|
|
113
|
+
if (format === 'json') {
|
|
114
|
+
return JSON.stringify(report, null, 2) + '\n';
|
|
115
|
+
}
|
|
116
|
+
return formatTree(report);
|
|
117
|
+
}
|
|
118
|
+
function formatTree(report) {
|
|
119
|
+
const lines = [];
|
|
120
|
+
if (report.allImplemented) {
|
|
121
|
+
lines.push('All behaviours are implemented. Consider running `taproot check-orphans` or `/tr-review-all`.');
|
|
122
|
+
lines.push('');
|
|
123
|
+
return lines.join('\n');
|
|
124
|
+
}
|
|
125
|
+
const afk = report.candidates.filter(c => c.classification === 'afk');
|
|
126
|
+
const hitl = report.candidates.filter(c => c.classification === 'hitl');
|
|
127
|
+
if (afk.length > 0) {
|
|
128
|
+
lines.push('AFK — ready to implement:');
|
|
129
|
+
for (const c of afk) {
|
|
130
|
+
lines.push(` ${c.behaviourPath} [${c.specState}]`);
|
|
131
|
+
if (c.intentGoal)
|
|
132
|
+
lines.push(` Intent: ${c.intentGoal}`);
|
|
133
|
+
if (c.inProgressImpls > 0)
|
|
134
|
+
lines.push(` (${c.inProgressImpls} impl${c.inProgressImpls > 1 ? 's' : ''} in progress)`);
|
|
135
|
+
lines.push(` ▸ /tr-implement ${c.behaviourPath}/`);
|
|
136
|
+
}
|
|
137
|
+
lines.push('');
|
|
138
|
+
}
|
|
139
|
+
if (hitl.length > 0) {
|
|
140
|
+
lines.push('HITL — needs human input first:');
|
|
141
|
+
for (const c of hitl) {
|
|
142
|
+
lines.push(` ${c.behaviourPath} [${c.specState}]`);
|
|
143
|
+
if (c.intentGoal)
|
|
144
|
+
lines.push(` Intent: ${c.intentGoal}`);
|
|
145
|
+
lines.push(` Reason: ${c.classificationReason}`);
|
|
146
|
+
lines.push(` ▸ /tr-behaviour ${c.behaviourPath}/usecase.md`);
|
|
147
|
+
}
|
|
148
|
+
lines.push('');
|
|
149
|
+
}
|
|
150
|
+
const total = report.candidates.length;
|
|
151
|
+
lines.push(`${total} candidate${total !== 1 ? 's' : ''} (${afk.length} AFK, ${hitl.length} HITL)`);
|
|
152
|
+
lines.push('');
|
|
153
|
+
return lines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
// ─── CLI registration ─────────────────────────────────────────────────────────
|
|
156
|
+
export function registerPlan(program) {
|
|
157
|
+
program
|
|
158
|
+
.command('plan')
|
|
159
|
+
.description('Show next implementable behaviours, classified as AFK or HITL')
|
|
160
|
+
.option('--path <path>', 'Root path (overrides config)')
|
|
161
|
+
.option('--format <format>', 'Output format: tree, json', 'tree')
|
|
162
|
+
.action(async (options) => {
|
|
163
|
+
const report = await runPlan({ path: options.path });
|
|
164
|
+
process.stdout.write(formatPlan(report, (options.format ?? 'tree')));
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Violation } from '../validators/types.js';
|
|
3
|
+
export declare function registerSyncCheck(program: Command): void;
|
|
4
|
+
export declare function runSyncCheck(options: {
|
|
5
|
+
path?: string;
|
|
6
|
+
since?: string;
|
|
7
|
+
cwd?: string;
|
|
8
|
+
}): Promise<Violation[]>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
import { loadConfig } from '../core/config.js';
|
|
4
|
+
import { walkHierarchy, flattenTree } from '../core/fs-walker.js';
|
|
5
|
+
import { parseMarkdown } from '../core/markdown-parser.js';
|
|
6
|
+
import { parseImplData } from '../core/impl-reader.js';
|
|
7
|
+
import { fileLastCommitDate, fileMtime, isGitRepo, getRepoRoot } from '../core/git.js';
|
|
8
|
+
import { renderViolations, exitCode } from '../core/reporter.js';
|
|
9
|
+
export function registerSyncCheck(program) {
|
|
10
|
+
program
|
|
11
|
+
.command('sync-check')
|
|
12
|
+
.description('Detect potential staleness between specs and code')
|
|
13
|
+
.option('--path <path>', 'Root path (overrides config)')
|
|
14
|
+
.option('--since <date>', 'Only consider changes after this date')
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
const violations = await runSyncCheck({ path: options.path, since: options.since });
|
|
17
|
+
process.stdout.write(renderViolations(violations));
|
|
18
|
+
process.exit(exitCode(violations));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export async function runSyncCheck(options) {
|
|
22
|
+
const { config } = loadConfig(options.cwd);
|
|
23
|
+
const rootPath = options.path ? resolve(options.path) : config.root;
|
|
24
|
+
const cwd = options.cwd ?? process.cwd();
|
|
25
|
+
const repoRoot = isGitRepo(cwd) ? (getRepoRoot(cwd) ?? cwd) : null;
|
|
26
|
+
const tree = walkHierarchy(rootPath);
|
|
27
|
+
const nodes = flattenTree(tree);
|
|
28
|
+
const violations = [];
|
|
29
|
+
for (const node of nodes) {
|
|
30
|
+
if (node.marker === 'impl') {
|
|
31
|
+
violations.push(...checkImplStaleness(node, repoRoot));
|
|
32
|
+
}
|
|
33
|
+
if (node.marker === 'behaviour') {
|
|
34
|
+
violations.push(...checkBehaviourSpecDrift(node, repoRoot));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return violations;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* If source files or test files in an impl.md changed more recently
|
|
41
|
+
* than the impl.md itself, the implementation record may be stale.
|
|
42
|
+
*/
|
|
43
|
+
function checkImplStaleness(node, repoRoot) {
|
|
44
|
+
const filePath = join(node.absolutePath, 'impl.md');
|
|
45
|
+
let content;
|
|
46
|
+
try {
|
|
47
|
+
content = readFileSync(filePath, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
const doc = parseMarkdown(filePath, content);
|
|
53
|
+
const data = parseImplData(doc);
|
|
54
|
+
const violations = [];
|
|
55
|
+
// Get the last commit date for impl.md itself
|
|
56
|
+
const implCommitDate = repoRoot ? fileLastCommitDate(filePath, repoRoot) : null;
|
|
57
|
+
const implMtime = fileMtime(filePath);
|
|
58
|
+
const implDate = implCommitDate ?? implMtime;
|
|
59
|
+
if (!implDate)
|
|
60
|
+
return [];
|
|
61
|
+
const allTrackedFiles = [...data.sourceFiles, ...data.testFiles];
|
|
62
|
+
for (const trackedFile of allTrackedFiles) {
|
|
63
|
+
const resolved = repoRoot ? resolve(repoRoot, trackedFile) : null;
|
|
64
|
+
if (!resolved || !existsSync(resolved))
|
|
65
|
+
continue;
|
|
66
|
+
// Check if file was committed more recently than impl.md
|
|
67
|
+
const fileCommitDate = repoRoot ? fileLastCommitDate(resolved, repoRoot) : null;
|
|
68
|
+
const fileDate = fileCommitDate ?? fileMtime(resolved);
|
|
69
|
+
if (!fileDate)
|
|
70
|
+
continue;
|
|
71
|
+
if (fileDate > implDate) {
|
|
72
|
+
violations.push({
|
|
73
|
+
type: 'warning',
|
|
74
|
+
filePath,
|
|
75
|
+
code: 'IMPL_STALE',
|
|
76
|
+
message: `Source file "${trackedFile}" was modified after impl.md — implementation record may be stale`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return violations;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* If a usecase.md was edited after its child impl.md files, the
|
|
84
|
+
* implementations may not reflect the latest spec.
|
|
85
|
+
*/
|
|
86
|
+
function checkBehaviourSpecDrift(node, repoRoot) {
|
|
87
|
+
const usecasePath = join(node.absolutePath, 'usecase.md');
|
|
88
|
+
if (!existsSync(usecasePath))
|
|
89
|
+
return [];
|
|
90
|
+
const usecaseCommitDate = repoRoot ? fileLastCommitDate(usecasePath, repoRoot) : null;
|
|
91
|
+
const usecaseMtime = fileMtime(usecasePath);
|
|
92
|
+
const usecaseDate = usecaseCommitDate ?? usecaseMtime;
|
|
93
|
+
if (!usecaseDate)
|
|
94
|
+
return [];
|
|
95
|
+
const violations = [];
|
|
96
|
+
for (const child of node.children) {
|
|
97
|
+
if (child.marker !== 'impl')
|
|
98
|
+
continue;
|
|
99
|
+
const implPath = join(child.absolutePath, 'impl.md');
|
|
100
|
+
if (!existsSync(implPath))
|
|
101
|
+
continue;
|
|
102
|
+
const implCommitDate = repoRoot ? fileLastCommitDate(implPath, repoRoot) : null;
|
|
103
|
+
const implMtime = fileMtime(implPath);
|
|
104
|
+
const implDate = implCommitDate ?? implMtime;
|
|
105
|
+
if (!implDate)
|
|
106
|
+
continue;
|
|
107
|
+
if (usecaseDate > implDate) {
|
|
108
|
+
violations.push({
|
|
109
|
+
type: 'warning',
|
|
110
|
+
filePath: implPath,
|
|
111
|
+
code: 'SPEC_UPDATED',
|
|
112
|
+
message: `usecase.md was updated after impl.md — review implementation against current spec`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return violations;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=sync-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-check.js","sourceRoot":"","sources":["../../src/commands/sync-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGjE,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,eAAe,EAAE,8BAA8B,CAAC;SACvD,MAAM,CAAC,gBAAgB,EAAE,uCAAuC,CAAC;SACjE,MAAM,CAAC,KAAK,EAAE,OAA0C,EAAE,EAAE;QAC3D,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACpF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAIlC;IACC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IACpE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEzC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEnE,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,UAAU,GAAgB,EAAE,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,UAAU,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAChC,UAAU,CAAC,IAAI,CAAC,GAAG,uBAAuB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,IAAgB,EAAE,QAAuB;IACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACpD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,UAAU,GAAgB,EAAE,CAAC;IAEnC,8CAA8C;IAC9C,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChF,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,cAAc,IAAI,SAAS,CAAC;IAE7C,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEzB,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAEjE,KAAK,MAAM,WAAW,IAAI,eAAe,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClE,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEjD,yDAAyD;QACzD,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChF,MAAM,QAAQ,GAAG,cAAc,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;YACxB,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,SAAS;gBACf,QAAQ;gBACR,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,gBAAgB,WAAW,mEAAmE;aACxG,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,uBAAuB,CAAC,IAAgB,EAAE,QAAuB;IACxE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,CAAC;IAExC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACtF,MAAM,YAAY,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,iBAAiB,IAAI,YAAY,CAAC;IAEtD,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAE5B,MAAM,UAAU,GAAgB,EAAE,CAAC;IAEnC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;YAAE,SAAS;QAEtC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACrD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS;QAEpC,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChF,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,cAAc,IAAI,SAAS,CAAC;QAC7C,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,IAAI,WAAW,GAAG,QAAQ,EAAE,CAAC;YAC3B,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,QAAQ;gBAClB,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,mFAAmF;aAC7F,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
export declare function refreshLinks(cwd: string, taprootDir: string): string[];
|
|
3
|
+
export declare function runUpdate(options: {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
withHooks?: boolean;
|
|
6
|
+
}): Promise<string[]>;
|
|
7
|
+
export declare function registerUpdate(program: Command): void;
|