@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,378 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync, readdirSync, readFileSync } from 'fs';
|
|
2
|
+
import { resolve, join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import yaml from 'js-yaml';
|
|
5
|
+
import { DEFAULT_CONFIG } from '../core/config.js';
|
|
6
|
+
import { substituteTokens, applyVocabulary, getStructuralKeys } from '../core/language.js';
|
|
7
|
+
import { intentTemplate, behaviourTemplate, implTemplate } from '../templates/index.js';
|
|
8
|
+
import { generateAdapters, ALL_AGENTS, AGENT_TIERS, getTierLabel } from '../adapters/index.js';
|
|
9
|
+
import checkbox from '@inquirer/checkbox';
|
|
10
|
+
import confirm from '@inquirer/confirm';
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
// Bundled skills directory — two levels up from src/commands/ → package root → skills/
|
|
13
|
+
const BUNDLED_SKILLS_DIR = resolve(__dirname, '..', '..', 'skills');
|
|
14
|
+
// Bundled docs directory — two levels up from src/commands/ → package root → docs/
|
|
15
|
+
const BUNDLED_DOCS_DIR = resolve(__dirname, '..', '..', 'docs');
|
|
16
|
+
export const SKILL_FILES = [
|
|
17
|
+
'analyse-change.md',
|
|
18
|
+
'review.md',
|
|
19
|
+
'review-all.md',
|
|
20
|
+
'grill-me.md',
|
|
21
|
+
'intent.md',
|
|
22
|
+
'behaviour.md',
|
|
23
|
+
'implement.md',
|
|
24
|
+
'trace.md',
|
|
25
|
+
'status.md',
|
|
26
|
+
'refine.md',
|
|
27
|
+
'promote.md',
|
|
28
|
+
'decompose.md',
|
|
29
|
+
'plan.md',
|
|
30
|
+
'guide.md',
|
|
31
|
+
'discover.md',
|
|
32
|
+
'ineed.md',
|
|
33
|
+
'research.md',
|
|
34
|
+
'sweep.md',
|
|
35
|
+
'commit.md',
|
|
36
|
+
'bug.md',
|
|
37
|
+
];
|
|
38
|
+
export function registerInit(program) {
|
|
39
|
+
program
|
|
40
|
+
.command('init')
|
|
41
|
+
.description('Initialize Taproot in the current project')
|
|
42
|
+
.option('--with-hooks', 'Install git pre-commit hooks')
|
|
43
|
+
.option('--with-ci <provider>', 'Generate CI workflow (github|gitlab)')
|
|
44
|
+
.option('--with-skills', 'Install canonical skill definitions into taproot/skills/')
|
|
45
|
+
.option('--agent <name>', `Generate agent adapter (${[...ALL_AGENTS, 'all'].join('|')})`)
|
|
46
|
+
.option('--path <path>', 'Directory to initialize in', process.cwd())
|
|
47
|
+
.action(async (options) => {
|
|
48
|
+
let agent = options.agent;
|
|
49
|
+
if (!agent) {
|
|
50
|
+
const AGENT_BASE_LABELS = {
|
|
51
|
+
claude: 'Claude Code',
|
|
52
|
+
cursor: 'Cursor',
|
|
53
|
+
copilot: 'GitHub Copilot',
|
|
54
|
+
windsurf: 'Windsurf',
|
|
55
|
+
gemini: 'Gemini CLI',
|
|
56
|
+
generic: 'Generic (any AI agent)',
|
|
57
|
+
};
|
|
58
|
+
const selected = await checkbox({
|
|
59
|
+
message: 'Which agent adapter(s) would you like to generate?',
|
|
60
|
+
choices: ALL_AGENTS.map((a) => ({
|
|
61
|
+
name: `${AGENT_BASE_LABELS[a]} (${getTierLabel(a)})`,
|
|
62
|
+
value: a,
|
|
63
|
+
})),
|
|
64
|
+
});
|
|
65
|
+
if (selected.length === ALL_AGENTS.length) {
|
|
66
|
+
agent = 'all';
|
|
67
|
+
}
|
|
68
|
+
else if (selected.length > 0) {
|
|
69
|
+
agent = selected;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let withHooks = options.withHooks;
|
|
73
|
+
if (!withHooks) {
|
|
74
|
+
withHooks = await confirm({
|
|
75
|
+
message: 'Install the pre-commit hook? (Strongly recommended — prevents implementation commits without traceability and requirement commits without quality checks)',
|
|
76
|
+
default: true,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const created = runInit({
|
|
80
|
+
cwd: options.path,
|
|
81
|
+
withHooks,
|
|
82
|
+
withCi: options.withCi,
|
|
83
|
+
withSkills: options.withSkills,
|
|
84
|
+
agent,
|
|
85
|
+
});
|
|
86
|
+
for (const msg of created) {
|
|
87
|
+
process.stdout.write(msg + '\n');
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export function runInit(options) {
|
|
92
|
+
const cwd = options.cwd ?? process.cwd();
|
|
93
|
+
const messages = [];
|
|
94
|
+
if (!existsSync(join(cwd, '.git'))) {
|
|
95
|
+
throw new Error('No git repository found. Run `git init` first, then re-run `taproot init`.');
|
|
96
|
+
}
|
|
97
|
+
const configPath = join(cwd, '.taproot', 'settings.yaml');
|
|
98
|
+
const taprootDir = resolve(cwd, DEFAULT_CONFIG.root);
|
|
99
|
+
const skillsDir = join(cwd, '.taproot', 'skills');
|
|
100
|
+
// Create taproot/ directory
|
|
101
|
+
if (!existsSync(taprootDir)) {
|
|
102
|
+
mkdirSync(taprootDir, { recursive: true });
|
|
103
|
+
messages.push(`created ${DEFAULT_CONFIG.root}`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
messages.push(`exists ${DEFAULT_CONFIG.root}`);
|
|
107
|
+
}
|
|
108
|
+
// Ensure .taproot/ directory exists
|
|
109
|
+
mkdirSync(join(cwd, '.taproot'), { recursive: true });
|
|
110
|
+
// Write .taproot/settings.yaml
|
|
111
|
+
if (!existsSync(configPath)) {
|
|
112
|
+
const configForYaml = {
|
|
113
|
+
version: DEFAULT_CONFIG.version,
|
|
114
|
+
root: DEFAULT_CONFIG.root,
|
|
115
|
+
commit_pattern: DEFAULT_CONFIG.commitPattern,
|
|
116
|
+
commit_trailer: DEFAULT_CONFIG.commitTrailer,
|
|
117
|
+
agents: DEFAULT_CONFIG.agents,
|
|
118
|
+
validation: {
|
|
119
|
+
require_dates: DEFAULT_CONFIG.validation.requireDates,
|
|
120
|
+
require_status: DEFAULT_CONFIG.validation.requireStatus,
|
|
121
|
+
allowed_intent_states: DEFAULT_CONFIG.validation.allowedIntentStates,
|
|
122
|
+
allowed_behaviour_states: DEFAULT_CONFIG.validation.allowedBehaviourStates,
|
|
123
|
+
allowed_impl_states: DEFAULT_CONFIG.validation.allowedImplStates,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
writeFileSync(configPath, yaml.dump(configForYaml));
|
|
127
|
+
messages.push('created .taproot/settings.yaml');
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
messages.push('exists .taproot/settings.yaml');
|
|
131
|
+
}
|
|
132
|
+
// Write CONVENTIONS.md
|
|
133
|
+
const conventionsPath = join(taprootDir, 'CONVENTIONS.md');
|
|
134
|
+
if (!existsSync(conventionsPath)) {
|
|
135
|
+
writeFileSync(conventionsPath, buildConventionsDoc());
|
|
136
|
+
messages.push(`created ${DEFAULT_CONFIG.root}CONVENTIONS.md`);
|
|
137
|
+
}
|
|
138
|
+
// Install skill definitions — always enabled when an adapter that references .taproot/skills/ is requested
|
|
139
|
+
const agentList = options.agent === 'all'
|
|
140
|
+
? ALL_AGENTS
|
|
141
|
+
: Array.isArray(options.agent)
|
|
142
|
+
? options.agent
|
|
143
|
+
: options.agent
|
|
144
|
+
? [options.agent]
|
|
145
|
+
: [];
|
|
146
|
+
const needsSkills = options.withSkills || agentList.includes('claude') || agentList.includes('gemini');
|
|
147
|
+
if (needsSkills) {
|
|
148
|
+
messages.push(...installSkills(skillsDir));
|
|
149
|
+
messages.push(...installDocs(join(cwd, '.taproot', 'docs')));
|
|
150
|
+
}
|
|
151
|
+
// Git pre-commit hook
|
|
152
|
+
if (options.withHooks) {
|
|
153
|
+
const hookDir = join(cwd, '.git', 'hooks');
|
|
154
|
+
const hookPath = join(hookDir, 'pre-commit');
|
|
155
|
+
if (existsSync(join(cwd, '.git')) && !existsSync(hookPath)) {
|
|
156
|
+
mkdirSync(hookDir, { recursive: true });
|
|
157
|
+
writeFileSync(hookPath, '#!/bin/sh\ntaproot commithook\n', { mode: 0o755 });
|
|
158
|
+
messages.push('created .git/hooks/pre-commit');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (options.withHooks === false) {
|
|
162
|
+
messages.push('skipped .git/hooks/pre-commit — run `taproot init --with-hooks` to add it later');
|
|
163
|
+
}
|
|
164
|
+
// Agent adapters
|
|
165
|
+
if (options.agent) {
|
|
166
|
+
const results = generateAdapters(options.agent, cwd);
|
|
167
|
+
for (const result of results) {
|
|
168
|
+
for (const file of result.files) {
|
|
169
|
+
const rel = file.path.replace(cwd + '/', '').replace(cwd + '\\', '');
|
|
170
|
+
const verb = file.status === 'created' ? 'created' : file.status === 'updated' ? 'updated' : 'exists ';
|
|
171
|
+
messages.push(`${verb} ${rel}`);
|
|
172
|
+
}
|
|
173
|
+
const tier = AGENT_TIERS[result.agent];
|
|
174
|
+
messages.push(` ${getTierLabel(result.agent)}`);
|
|
175
|
+
if (tier === 3) {
|
|
176
|
+
messages.push(` Community-supported: adapter generated but not officially validated end-to-end. Feedback and fixes welcome.`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// CI workflow
|
|
181
|
+
if (options.withCi === 'github') {
|
|
182
|
+
const workflowDir = join(cwd, '.github', 'workflows');
|
|
183
|
+
const workflowPath = join(workflowDir, 'taproot.yml');
|
|
184
|
+
if (!existsSync(workflowPath)) {
|
|
185
|
+
mkdirSync(workflowDir, { recursive: true });
|
|
186
|
+
writeFileSync(workflowPath, buildGithubWorkflow());
|
|
187
|
+
messages.push('created .github/workflows/taproot.yml');
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
messages.push('exists .github/workflows/taproot.yml');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (options.withCi === 'gitlab') {
|
|
194
|
+
const ciPath = join(cwd, '.gitlab-ci.yml');
|
|
195
|
+
if (!existsSync(ciPath)) {
|
|
196
|
+
writeFileSync(ciPath, buildGitlabCi());
|
|
197
|
+
messages.push('created .gitlab-ci.yml');
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// Append taproot job if not already present
|
|
201
|
+
const existing = readFileSync(ciPath, 'utf-8');
|
|
202
|
+
if (!existing.includes('taproot-validate')) {
|
|
203
|
+
writeFileSync(ciPath, existing.trimEnd() + '\n\n' + buildGitlabCiJob());
|
|
204
|
+
messages.push('updated .gitlab-ci.yml (appended taproot-validate job)');
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
messages.push('exists .gitlab-ci.yml');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
messages.push('');
|
|
212
|
+
messages.push('Taproot initialized. Run `taproot validate-structure` to verify.');
|
|
213
|
+
return messages;
|
|
214
|
+
}
|
|
215
|
+
export function installSkills(targetSkillsDir, force = false, pack, vocab) {
|
|
216
|
+
const messages = [];
|
|
217
|
+
if (!existsSync(BUNDLED_SKILLS_DIR)) {
|
|
218
|
+
messages.push(`warning Skills directory not found at ${BUNDLED_SKILLS_DIR} — skipping`);
|
|
219
|
+
return messages;
|
|
220
|
+
}
|
|
221
|
+
mkdirSync(targetSkillsDir, { recursive: true });
|
|
222
|
+
for (const filename of SKILL_FILES) {
|
|
223
|
+
const src = join(BUNDLED_SKILLS_DIR, filename);
|
|
224
|
+
const dest = join(targetSkillsDir, filename);
|
|
225
|
+
if (!existsSync(src)) {
|
|
226
|
+
messages.push(`warning Skill file not found: ${filename}`);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
let content = readFileSync(src, 'utf-8');
|
|
230
|
+
if (pack) {
|
|
231
|
+
content = substituteTokens(content, pack);
|
|
232
|
+
}
|
|
233
|
+
if (vocab && Object.keys(vocab).length > 0) {
|
|
234
|
+
const structuralKeys = getStructuralKeys(pack ?? null);
|
|
235
|
+
const { result, warnings } = applyVocabulary(content, vocab, structuralKeys);
|
|
236
|
+
content = result;
|
|
237
|
+
for (const w of warnings) {
|
|
238
|
+
messages.push(`warning ${w}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (!existsSync(dest)) {
|
|
242
|
+
writeFileSync(dest, content);
|
|
243
|
+
messages.push(`created .taproot/skills/${filename}`);
|
|
244
|
+
}
|
|
245
|
+
else if (force) {
|
|
246
|
+
writeFileSync(dest, content);
|
|
247
|
+
messages.push(`updated .taproot/skills/${filename}`);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
messages.push(`exists .taproot/skills/${filename}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return messages;
|
|
254
|
+
}
|
|
255
|
+
export function installDocs(targetDocsDir, force = false) {
|
|
256
|
+
const messages = [];
|
|
257
|
+
if (!existsSync(BUNDLED_DOCS_DIR)) {
|
|
258
|
+
messages.push(`warning Docs directory not found at ${BUNDLED_DOCS_DIR} — skipping`);
|
|
259
|
+
return messages;
|
|
260
|
+
}
|
|
261
|
+
mkdirSync(targetDocsDir, { recursive: true });
|
|
262
|
+
for (const filename of readdirSync(BUNDLED_DOCS_DIR).filter(f => f.endsWith('.md'))) {
|
|
263
|
+
const src = join(BUNDLED_DOCS_DIR, filename);
|
|
264
|
+
const dest = join(targetDocsDir, filename);
|
|
265
|
+
const content = readFileSync(src, 'utf-8');
|
|
266
|
+
if (!existsSync(dest)) {
|
|
267
|
+
writeFileSync(dest, content);
|
|
268
|
+
messages.push(`created .taproot/docs/${filename}`);
|
|
269
|
+
}
|
|
270
|
+
else if (force) {
|
|
271
|
+
writeFileSync(dest, content);
|
|
272
|
+
messages.push(`updated .taproot/docs/${filename}`);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
messages.push(`exists .taproot/docs/${filename}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return messages;
|
|
279
|
+
}
|
|
280
|
+
function buildConventionsDoc() {
|
|
281
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
282
|
+
return `# Taproot Conventions
|
|
283
|
+
|
|
284
|
+
Auto-generated reference for document formats and commit conventions.
|
|
285
|
+
|
|
286
|
+
## Document Formats
|
|
287
|
+
|
|
288
|
+
### intent.md — Business Intent
|
|
289
|
+
|
|
290
|
+
\`\`\`markdown
|
|
291
|
+
${intentTemplate(date)}\`\`\`
|
|
292
|
+
|
|
293
|
+
### usecase.md — Behaviour (UseCase)
|
|
294
|
+
|
|
295
|
+
\`\`\`markdown
|
|
296
|
+
${behaviourTemplate(date)}\`\`\`
|
|
297
|
+
|
|
298
|
+
### impl.md — Implementation
|
|
299
|
+
|
|
300
|
+
\`\`\`markdown
|
|
301
|
+
${implTemplate(date)}\`\`\`
|
|
302
|
+
|
|
303
|
+
## Folder Naming
|
|
304
|
+
|
|
305
|
+
- Lowercase kebab-case: \`^[a-z0-9]+(-[a-z0-9]+)*\$\`
|
|
306
|
+
- Each folder is exactly one type (intent, behaviour, or implementation)
|
|
307
|
+
- Identified by its marker file: \`intent.md\`, \`usecase.md\`, or \`impl.md\`
|
|
308
|
+
|
|
309
|
+
## Commit Convention
|
|
310
|
+
|
|
311
|
+
Link commits to implementations using the conventional tag format:
|
|
312
|
+
|
|
313
|
+
\`\`\`
|
|
314
|
+
taproot(<intent>/<behaviour>/<impl>): <message>
|
|
315
|
+
\`\`\`
|
|
316
|
+
|
|
317
|
+
Or use a commit trailer:
|
|
318
|
+
|
|
319
|
+
\`\`\`
|
|
320
|
+
Taproot: <intent>/<behaviour>/<impl>
|
|
321
|
+
\`\`\`
|
|
322
|
+
|
|
323
|
+
## Folder Structure
|
|
324
|
+
|
|
325
|
+
\`\`\`
|
|
326
|
+
taproot/
|
|
327
|
+
├── <intent-slug>/
|
|
328
|
+
│ ├── intent.md
|
|
329
|
+
│ └── <behaviour-slug>/
|
|
330
|
+
│ ├── usecase.md
|
|
331
|
+
│ └── <implementation-slug>/
|
|
332
|
+
│ └── impl.md
|
|
333
|
+
\`\`\`
|
|
334
|
+
`;
|
|
335
|
+
}
|
|
336
|
+
function buildGithubWorkflow() {
|
|
337
|
+
return `name: Taproot Validation
|
|
338
|
+
|
|
339
|
+
on:
|
|
340
|
+
pull_request:
|
|
341
|
+
push:
|
|
342
|
+
branches: [main, master]
|
|
343
|
+
|
|
344
|
+
jobs:
|
|
345
|
+
validate:
|
|
346
|
+
runs-on: ubuntu-latest
|
|
347
|
+
steps:
|
|
348
|
+
- uses: actions/checkout@v4
|
|
349
|
+
- uses: actions/setup-node@v4
|
|
350
|
+
with:
|
|
351
|
+
node-version: '20'
|
|
352
|
+
- run: npm install -g taproot
|
|
353
|
+
- run: taproot validate-structure
|
|
354
|
+
- run: taproot validate-format
|
|
355
|
+
- run: taproot check-orphans
|
|
356
|
+
`;
|
|
357
|
+
}
|
|
358
|
+
function buildGitlabCiJob() {
|
|
359
|
+
return `taproot-validate:
|
|
360
|
+
stage: test
|
|
361
|
+
image: node:20-alpine
|
|
362
|
+
script:
|
|
363
|
+
- npm install -g taproot
|
|
364
|
+
- taproot validate-structure
|
|
365
|
+
- taproot validate-format
|
|
366
|
+
- taproot check-orphans
|
|
367
|
+
rules:
|
|
368
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
369
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH`;
|
|
370
|
+
}
|
|
371
|
+
function buildGitlabCi() {
|
|
372
|
+
return `stages:
|
|
373
|
+
- test
|
|
374
|
+
|
|
375
|
+
${buildGitlabCiJob()}
|
|
376
|
+
`;
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
export interface LinkResult {
|
|
3
|
+
implPath: string;
|
|
4
|
+
addedHashes: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function registerLinkCommits(program: Command): void;
|
|
7
|
+
export declare function runLinkCommits(options: {
|
|
8
|
+
since?: string;
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
path?: string;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
}): Promise<LinkResult[]>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join, relative, 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 { gitLog, extractTaprootPath, isGitRepo, getRepoRoot } from '../core/git.js';
|
|
8
|
+
export function registerLinkCommits(program) {
|
|
9
|
+
program
|
|
10
|
+
.command('link-commits')
|
|
11
|
+
.description('Update impl.md files with commit references from git history')
|
|
12
|
+
.option('--since <date|hash>', 'Only scan commits after this date or hash')
|
|
13
|
+
.option('--dry-run', 'Preview changes without writing')
|
|
14
|
+
.option('--path <path>', 'Root path (overrides config)')
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
const results = await runLinkCommits({
|
|
17
|
+
since: options.since,
|
|
18
|
+
dryRun: options.dryRun ?? false,
|
|
19
|
+
path: options.path,
|
|
20
|
+
});
|
|
21
|
+
if (results.length === 0) {
|
|
22
|
+
process.stdout.write('No new commits to link.\n');
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
for (const r of results) {
|
|
26
|
+
const verb = options.dryRun ? 'would add' : 'added';
|
|
27
|
+
process.stdout.write(`${r.implPath}: ${verb} ${r.addedHashes.join(', ')}\n`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export async function runLinkCommits(options) {
|
|
33
|
+
const { config, configDir } = loadConfig(options.cwd);
|
|
34
|
+
const rootPath = options.path ? resolve(options.path) : config.root;
|
|
35
|
+
const cwd = options.cwd ?? process.cwd();
|
|
36
|
+
if (!isGitRepo(cwd)) {
|
|
37
|
+
throw new Error('Not inside a git repository. link-commits requires git.');
|
|
38
|
+
}
|
|
39
|
+
const repoRoot = getRepoRoot(cwd) ?? cwd;
|
|
40
|
+
// Build map: taproot-relative path → impl node
|
|
41
|
+
const tree = walkHierarchy(rootPath);
|
|
42
|
+
const implNodes = flattenTree(tree).filter((n) => n.marker === 'impl');
|
|
43
|
+
// Read existing commits for each impl
|
|
44
|
+
const implIndex = new Map();
|
|
45
|
+
for (const node of implNodes) {
|
|
46
|
+
const filePath = join(node.absolutePath, 'impl.md');
|
|
47
|
+
try {
|
|
48
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
49
|
+
const doc = parseMarkdown(filePath, content);
|
|
50
|
+
const data = parseImplData(doc);
|
|
51
|
+
// Index by relative path from repo root (normalized, no trailing slash)
|
|
52
|
+
const relFromRoot = relative(repoRoot, node.absolutePath).replace(/\\/g, '/');
|
|
53
|
+
implIndex.set(relFromRoot, { node, existingHashes: new Set(data.commits) });
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// skip unreadable impl.md
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Also index by relative path from taproot root for flexible matching
|
|
60
|
+
const implIndexFromTaproot = new Map(); // taproot-relative → repoRoot-relative
|
|
61
|
+
for (const node of implNodes) {
|
|
62
|
+
const relFromTaproot = node.relativePath.replace(/\\/g, '/');
|
|
63
|
+
const relFromRoot = relative(repoRoot, node.absolutePath).replace(/\\/g, '/');
|
|
64
|
+
implIndexFromTaproot.set(relFromTaproot, relFromRoot);
|
|
65
|
+
}
|
|
66
|
+
// Scan git log
|
|
67
|
+
const commits = gitLog({ since: options.since, cwd: repoRoot });
|
|
68
|
+
// Collect new commits per impl
|
|
69
|
+
const pendingAdditions = new Map(); // repoRoot-relative → new hashes
|
|
70
|
+
for (const commit of commits) {
|
|
71
|
+
const taprootPath = extractTaprootPath(commit, config.commitPattern, config.commitTrailer);
|
|
72
|
+
if (!taprootPath)
|
|
73
|
+
continue;
|
|
74
|
+
// Try matching as repoRoot-relative path first, then taproot-relative
|
|
75
|
+
let key = taprootPath;
|
|
76
|
+
if (!implIndex.has(key)) {
|
|
77
|
+
const mapped = implIndexFromTaproot.get(key);
|
|
78
|
+
if (mapped)
|
|
79
|
+
key = mapped;
|
|
80
|
+
}
|
|
81
|
+
const entry = implIndex.get(key);
|
|
82
|
+
if (!entry)
|
|
83
|
+
continue;
|
|
84
|
+
if (entry.existingHashes.has(commit.hash) || entry.existingHashes.has(commit.hash.slice(0, 7)))
|
|
85
|
+
continue;
|
|
86
|
+
const list = pendingAdditions.get(key) ?? [];
|
|
87
|
+
list.push(commit.hash);
|
|
88
|
+
pendingAdditions.set(key, list);
|
|
89
|
+
}
|
|
90
|
+
const results = [];
|
|
91
|
+
for (const [key, hashes] of pendingAdditions) {
|
|
92
|
+
const entry = implIndex.get(key);
|
|
93
|
+
if (!entry)
|
|
94
|
+
continue;
|
|
95
|
+
const filePath = join(entry.node.absolutePath, 'impl.md');
|
|
96
|
+
results.push({ implPath: filePath, addedHashes: hashes });
|
|
97
|
+
if (!options.dryRun) {
|
|
98
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
99
|
+
const updated = appendCommitsToImplMd(content, hashes);
|
|
100
|
+
writeFileSync(filePath, updated, 'utf-8');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return results;
|
|
104
|
+
}
|
|
105
|
+
function appendCommitsToImplMd(content, hashes) {
|
|
106
|
+
const lines = content.split('\n');
|
|
107
|
+
const commitsHeading = lines.findIndex(l => /^##\s+Commits\s*$/.test(l));
|
|
108
|
+
if (commitsHeading === -1) {
|
|
109
|
+
// Append Commits section at end
|
|
110
|
+
const additions = hashes.map(h => `- \`${h}\` — (auto-linked by taproot link-commits)`);
|
|
111
|
+
return content.trimEnd() + '\n\n## Commits\n' + additions.join('\n') + '\n';
|
|
112
|
+
}
|
|
113
|
+
// Find last non-empty line in the Commits section (before next ## or EOF)
|
|
114
|
+
let insertAt = commitsHeading + 1;
|
|
115
|
+
for (let i = commitsHeading + 1; i < lines.length; i++) {
|
|
116
|
+
const line = lines[i] ?? '';
|
|
117
|
+
if (/^##\s/.test(line))
|
|
118
|
+
break;
|
|
119
|
+
if (line.trim())
|
|
120
|
+
insertAt = i + 1;
|
|
121
|
+
}
|
|
122
|
+
const newLines = hashes.map(h => `- \`${h}\` — (auto-linked by taproot link-commits)`);
|
|
123
|
+
lines.splice(insertAt, 0, ...newLines);
|
|
124
|
+
return lines.join('\n');
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=link-commits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-commits.js","sourceRoot":"","sources":["../../src/commands/link-commits.ts"],"names":[],"mappings":"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"}
|