@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,309 @@
|
|
|
1
|
+
import { existsSync, rmSync, readdirSync, readFileSync, writeFileSync, unlinkSync, mkdirSync, renameSync } from 'fs';
|
|
2
|
+
import { join, dirname, relative, resolve } from 'path';
|
|
3
|
+
import { buildConfigurationMd } from '../core/configuration.js';
|
|
4
|
+
import { generateAdapters } from '../adapters/index.js';
|
|
5
|
+
import { installSkills, installDocs, SKILL_FILES } from './init.js';
|
|
6
|
+
import { runOverview } from './overview.js';
|
|
7
|
+
import { DEFAULT_CONFIG, loadConfig } from '../core/config.js';
|
|
8
|
+
import { loadLanguagePack, supportedLanguages } from '../core/language.js';
|
|
9
|
+
import { walkHierarchy, flattenTree } from '../core/fs-walker.js';
|
|
10
|
+
const TAPROOT_START = '<!-- TAPROOT:START -->';
|
|
11
|
+
// Stale paths left behind by older taproot versions
|
|
12
|
+
const STALE_PATHS = [
|
|
13
|
+
'.claude/skills/taproot', // pre-tr- layout: skills were in a subdirectory
|
|
14
|
+
// tr- files that lived in skills/ before moving to commands/
|
|
15
|
+
// resolved dynamically for globbing — see removeStale()
|
|
16
|
+
];
|
|
17
|
+
function detectInstalledAgents(cwd) {
|
|
18
|
+
const installed = [];
|
|
19
|
+
// claude: tr-*.md files in .claude/commands/ (current), .claude/skills/ (old), or taproot/ subdir (oldest)
|
|
20
|
+
const claudeCommandsDir = join(cwd, '.claude', 'commands');
|
|
21
|
+
const claudeSkillsDir = join(cwd, '.claude', 'skills');
|
|
22
|
+
const oldClaudeSubdir = join(cwd, '.claude', 'skills', 'taproot');
|
|
23
|
+
if ((existsSync(claudeCommandsDir) && readdirSync(claudeCommandsDir).some(f => f.startsWith('tr-'))) ||
|
|
24
|
+
existsSync(oldClaudeSubdir) ||
|
|
25
|
+
(existsSync(claudeSkillsDir) && readdirSync(claudeSkillsDir).some(f => f.startsWith('tr-')))) {
|
|
26
|
+
installed.push('claude');
|
|
27
|
+
}
|
|
28
|
+
// cursor: .cursor/rules/taproot.md
|
|
29
|
+
if (existsSync(join(cwd, '.cursor', 'rules', 'taproot.md'))) {
|
|
30
|
+
installed.push('cursor');
|
|
31
|
+
}
|
|
32
|
+
// copilot: .github/copilot-instructions.md containing taproot section
|
|
33
|
+
const copilotPath = join(cwd, '.github', 'copilot-instructions.md');
|
|
34
|
+
if (existsSync(copilotPath) && readFileSync(copilotPath, 'utf-8').includes(TAPROOT_START)) {
|
|
35
|
+
installed.push('copilot');
|
|
36
|
+
}
|
|
37
|
+
// windsurf: .windsurfrules containing taproot section
|
|
38
|
+
const windsurfPath = join(cwd, '.windsurfrules');
|
|
39
|
+
if (existsSync(windsurfPath) && readFileSync(windsurfPath, 'utf-8').includes(TAPROOT_START)) {
|
|
40
|
+
installed.push('windsurf');
|
|
41
|
+
}
|
|
42
|
+
// generic: AGENTS.md containing taproot section
|
|
43
|
+
const agentsPath = join(cwd, 'AGENTS.md');
|
|
44
|
+
if (existsSync(agentsPath) && readFileSync(agentsPath, 'utf-8').includes(TAPROOT_START)) {
|
|
45
|
+
installed.push('generic');
|
|
46
|
+
}
|
|
47
|
+
return installed;
|
|
48
|
+
}
|
|
49
|
+
function removeStale(cwd) {
|
|
50
|
+
const messages = [];
|
|
51
|
+
// Remove old taproot/ subdirectory
|
|
52
|
+
const oldSubdir = join(cwd, '.claude', 'skills', 'taproot');
|
|
53
|
+
if (existsSync(oldSubdir)) {
|
|
54
|
+
rmSync(oldSubdir, { recursive: true, force: true });
|
|
55
|
+
messages.push(`removed .claude/skills/taproot`);
|
|
56
|
+
}
|
|
57
|
+
// Remove tr-*.md files that were placed in .claude/skills/ (before commands/ layout)
|
|
58
|
+
const claudeSkillsDir = join(cwd, '.claude', 'skills');
|
|
59
|
+
if (existsSync(claudeSkillsDir)) {
|
|
60
|
+
for (const f of readdirSync(claudeSkillsDir)) {
|
|
61
|
+
if (f.startsWith('tr-') && f.endsWith('.md')) {
|
|
62
|
+
unlinkSync(join(claudeSkillsDir, f));
|
|
63
|
+
messages.push(`removed .claude/skills/${f}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Migrate taproot/skills/ → .taproot/skills/
|
|
68
|
+
const oldSkillsDir = join(cwd, DEFAULT_CONFIG.root, 'skills');
|
|
69
|
+
const newSkillsDir = join(cwd, '.taproot', 'skills');
|
|
70
|
+
if (existsSync(oldSkillsDir) && !existsSync(newSkillsDir)) {
|
|
71
|
+
mkdirSync(join(cwd, '.taproot'), { recursive: true });
|
|
72
|
+
renameSync(oldSkillsDir, newSkillsDir);
|
|
73
|
+
messages.push(`migrated taproot/skills/ → .taproot/skills/`);
|
|
74
|
+
}
|
|
75
|
+
else if (existsSync(oldSkillsDir)) {
|
|
76
|
+
rmSync(oldSkillsDir, { recursive: true, force: true });
|
|
77
|
+
messages.push(`removed taproot/skills/ (already migrated to .taproot/skills/)`);
|
|
78
|
+
}
|
|
79
|
+
// Remove taproot/_brainstorms/
|
|
80
|
+
const brainsDir = join(cwd, DEFAULT_CONFIG.root, '_brainstorms');
|
|
81
|
+
if (existsSync(brainsDir)) {
|
|
82
|
+
rmSync(brainsDir, { recursive: true, force: true });
|
|
83
|
+
messages.push(`removed taproot/_brainstorms/`);
|
|
84
|
+
}
|
|
85
|
+
// Migrate old pre-commit hook content to taproot commithook
|
|
86
|
+
const hookPath = join(cwd, '.git', 'hooks', 'pre-commit');
|
|
87
|
+
if (existsSync(hookPath)) {
|
|
88
|
+
const hookContent = readFileSync(hookPath, 'utf-8');
|
|
89
|
+
if (hookContent.includes('validate-structure') || hookContent.includes('validate-format')) {
|
|
90
|
+
writeFileSync(hookPath, '#!/bin/sh\ntaproot commithook\n', { mode: 0o755 });
|
|
91
|
+
messages.push(`migrated .git/hooks/pre-commit → taproot commithook`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return messages;
|
|
95
|
+
}
|
|
96
|
+
function extractTitle(content, fallback) {
|
|
97
|
+
const m = content.match(/^# (?:[^:\n]+: )?(.+)$/m);
|
|
98
|
+
return m?.[1]?.trim() ?? fallback;
|
|
99
|
+
}
|
|
100
|
+
function upsertLinkSection(content, docPath, sectionTitle, childNodes, childDoc) {
|
|
101
|
+
const managedHeader = `## ${sectionTitle} <!-- taproot-managed -->`;
|
|
102
|
+
// Build desired links: rel path → title
|
|
103
|
+
const desiredLinks = [];
|
|
104
|
+
for (const child of childNodes) {
|
|
105
|
+
const childDocPath = join(child.absolutePath, childDoc);
|
|
106
|
+
if (!existsSync(childDocPath))
|
|
107
|
+
continue;
|
|
108
|
+
const rel = './' + relative(dirname(docPath), childDocPath).replace(/\\/g, '/');
|
|
109
|
+
const childContent = readFileSync(childDocPath, 'utf-8');
|
|
110
|
+
desiredLinks.push({ rel, title: extractTitle(childContent, child.name) });
|
|
111
|
+
}
|
|
112
|
+
const lines = content.split('\n');
|
|
113
|
+
// Find section start: any "## <Title>" line (with or without managed comment)
|
|
114
|
+
const sectionPattern = new RegExp(`^## ${sectionTitle}(\\s|$)`);
|
|
115
|
+
const sectionStartIdx = lines.findIndex(l => sectionPattern.test(l));
|
|
116
|
+
if (sectionStartIdx === -1) {
|
|
117
|
+
if (desiredLinks.length === 0)
|
|
118
|
+
return content;
|
|
119
|
+
// Insert before ## Status or append at end
|
|
120
|
+
const statusIdx = lines.findIndex(l => /^## Status(\s|$)/.test(l));
|
|
121
|
+
const newBlock = [managedHeader, ...desiredLinks.map(l => `- [${l.title}](${l.rel})`), ''];
|
|
122
|
+
if (statusIdx !== -1) {
|
|
123
|
+
lines.splice(statusIdx, 0, ...newBlock, '');
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
if (lines[lines.length - 1] !== '')
|
|
127
|
+
lines.push('');
|
|
128
|
+
lines.push(...newBlock);
|
|
129
|
+
}
|
|
130
|
+
return lines.join('\n');
|
|
131
|
+
}
|
|
132
|
+
// Find section end: next "## " heading or EOF
|
|
133
|
+
let sectionEndIdx = lines.length;
|
|
134
|
+
for (let i = sectionStartIdx + 1; i < lines.length; i++) {
|
|
135
|
+
if (/^## /.test(lines[i])) {
|
|
136
|
+
sectionEndIdx = i;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Process body lines: prune stale links, collect existing
|
|
141
|
+
const bodyLines = lines.slice(sectionStartIdx + 1, sectionEndIdx);
|
|
142
|
+
const existingRels = new Set();
|
|
143
|
+
const prunedBody = [];
|
|
144
|
+
for (const line of bodyLines) {
|
|
145
|
+
const linkMatch = line.match(/\[.*?\]\((.+?)\)/);
|
|
146
|
+
if (linkMatch) {
|
|
147
|
+
const rel = linkMatch[1];
|
|
148
|
+
const resolved = resolve(dirname(docPath), rel);
|
|
149
|
+
if (!existsSync(resolved))
|
|
150
|
+
continue; // prune stale
|
|
151
|
+
existingRels.add(rel);
|
|
152
|
+
}
|
|
153
|
+
prunedBody.push(line);
|
|
154
|
+
}
|
|
155
|
+
// Append missing links
|
|
156
|
+
for (const { rel, title } of desiredLinks) {
|
|
157
|
+
if (!existingRels.has(rel)) {
|
|
158
|
+
prunedBody.push(`- [${title}](${rel})`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Replace the section (update header to managed form, replace body)
|
|
162
|
+
lines.splice(sectionStartIdx, sectionEndIdx - sectionStartIdx, managedHeader, ...prunedBody);
|
|
163
|
+
return lines.join('\n');
|
|
164
|
+
}
|
|
165
|
+
export function refreshLinks(cwd, taprootDir) {
|
|
166
|
+
const messages = [];
|
|
167
|
+
if (!existsSync(taprootDir))
|
|
168
|
+
return messages;
|
|
169
|
+
const tree = walkHierarchy(taprootDir);
|
|
170
|
+
const nodes = flattenTree(tree).filter(n => n.marker === 'intent' || n.marker === 'behaviour');
|
|
171
|
+
for (const node of nodes) {
|
|
172
|
+
const markerFile = node.marker === 'intent' ? 'intent.md' : 'usecase.md';
|
|
173
|
+
const docPath = join(node.absolutePath, markerFile);
|
|
174
|
+
if (!existsSync(docPath))
|
|
175
|
+
continue;
|
|
176
|
+
const childMarker = node.marker === 'intent' ? 'behaviour' : 'impl';
|
|
177
|
+
const childDoc = childMarker === 'behaviour' ? 'usecase.md' : 'impl.md';
|
|
178
|
+
const sectionTitle = node.marker === 'intent' ? 'Behaviours' : 'Implementations';
|
|
179
|
+
const childNodes = node.children.filter(c => c.marker === childMarker);
|
|
180
|
+
const content = readFileSync(docPath, 'utf-8');
|
|
181
|
+
const updated = upsertLinkSection(content, docPath, sectionTitle, childNodes, childDoc);
|
|
182
|
+
if (updated !== content) {
|
|
183
|
+
writeFileSync(docPath, updated, 'utf-8');
|
|
184
|
+
messages.push(`updated ${relative(cwd, docPath)}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return messages;
|
|
188
|
+
}
|
|
189
|
+
export async function runUpdate(options) {
|
|
190
|
+
const cwd = options.cwd ?? process.cwd();
|
|
191
|
+
const messages = [];
|
|
192
|
+
// Validate language pack before modifying any files (AC-4)
|
|
193
|
+
const { config } = loadConfig(cwd);
|
|
194
|
+
let pack = null;
|
|
195
|
+
if (config.language) {
|
|
196
|
+
pack = loadLanguagePack(config.language);
|
|
197
|
+
if (!pack) {
|
|
198
|
+
messages.push(`error Unknown language pack '${config.language}'. ` +
|
|
199
|
+
`Supported: ${supportedLanguages().join(', ')}. ` +
|
|
200
|
+
`No files modified.`);
|
|
201
|
+
return messages;
|
|
202
|
+
}
|
|
203
|
+
messages.push(`language ${config.language} (${Object.keys(pack).length} tokens)`);
|
|
204
|
+
}
|
|
205
|
+
// Validate vocabulary overrides before modifying any files
|
|
206
|
+
const vocab = config.vocabulary ?? null;
|
|
207
|
+
if (vocab && Object.keys(vocab).length > 0) {
|
|
208
|
+
const emptyKeys = Object.entries(vocab)
|
|
209
|
+
.filter(([, v]) => v === '')
|
|
210
|
+
.map(([k]) => k);
|
|
211
|
+
if (emptyKeys.length > 0) {
|
|
212
|
+
for (const key of emptyKeys) {
|
|
213
|
+
messages.push(`error Vocabulary override '${key}' maps to an empty string — ` +
|
|
214
|
+
`this would silently delete the term from skill files. ` +
|
|
215
|
+
`Provide a non-empty replacement or remove the key.`);
|
|
216
|
+
}
|
|
217
|
+
messages.push('No files modified.');
|
|
218
|
+
return messages;
|
|
219
|
+
}
|
|
220
|
+
messages.push(`vocabulary ${Object.keys(vocab).length} overrides`);
|
|
221
|
+
}
|
|
222
|
+
const agents = detectInstalledAgents(cwd);
|
|
223
|
+
if (agents.length === 0) {
|
|
224
|
+
messages.push('No taproot agent adapters detected — nothing to update.');
|
|
225
|
+
messages.push('Run `taproot init --agent <name>` to install adapters.');
|
|
226
|
+
return Promise.resolve(messages);
|
|
227
|
+
}
|
|
228
|
+
messages.push(`Detected adapters: ${agents.join(', ')}`);
|
|
229
|
+
messages.push('');
|
|
230
|
+
// Remove stale paths from old versions
|
|
231
|
+
messages.push(...removeStale(cwd));
|
|
232
|
+
// Regenerate detected adapters
|
|
233
|
+
for (const agent of agents) {
|
|
234
|
+
const results = generateAdapters(agent, cwd);
|
|
235
|
+
for (const result of results) {
|
|
236
|
+
for (const file of result.files) {
|
|
237
|
+
const rel = file.path.replace(cwd + '/', '').replace(cwd + '\\', '');
|
|
238
|
+
const verb = file.status === 'created' ? 'created' : file.status === 'updated' ? 'updated' : 'exists ';
|
|
239
|
+
messages.push(`${verb} ${rel}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Refresh/install skills — always when claude adapter is present, otherwise only if already installed
|
|
244
|
+
const skillsDir = join(cwd, '.taproot', 'skills');
|
|
245
|
+
const hasInstalledSkills = existsSync(skillsDir) &&
|
|
246
|
+
SKILL_FILES.some(f => existsSync(join(skillsDir, f)));
|
|
247
|
+
if (agents.includes('claude') || hasInstalledSkills) {
|
|
248
|
+
messages.push('');
|
|
249
|
+
messages.push(...installSkills(skillsDir, true, pack, vocab));
|
|
250
|
+
messages.push(...installDocs(join(cwd, '.taproot', 'docs'), true));
|
|
251
|
+
}
|
|
252
|
+
// Install or refresh .taproot/CONFIGURATION.md (AC-6/AC-7 of update-adapters-and-skills)
|
|
253
|
+
const taprootConfigDir = join(cwd, '.taproot');
|
|
254
|
+
const configMdPath = join(taprootConfigDir, 'CONFIGURATION.md');
|
|
255
|
+
try {
|
|
256
|
+
mkdirSync(taprootConfigDir, { recursive: true });
|
|
257
|
+
const content = buildConfigurationMd();
|
|
258
|
+
const existed = existsSync(configMdPath);
|
|
259
|
+
writeFileSync(configMdPath, content, 'utf-8');
|
|
260
|
+
messages.push('');
|
|
261
|
+
messages.push(`${existed ? 'updated' : 'created'} .taproot/CONFIGURATION.md`);
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
messages.push(`warning Could not write .taproot/CONFIGURATION.md: ${err.message}`);
|
|
265
|
+
}
|
|
266
|
+
// Refresh cross-links (## Behaviours / ## Implementations sections)
|
|
267
|
+
const taprootDir = join(cwd, DEFAULT_CONFIG.root);
|
|
268
|
+
const linkMsgs = refreshLinks(cwd, taprootDir);
|
|
269
|
+
if (linkMsgs.length > 0) {
|
|
270
|
+
messages.push('');
|
|
271
|
+
messages.push(...linkMsgs);
|
|
272
|
+
}
|
|
273
|
+
// Regenerate OVERVIEW.md
|
|
274
|
+
const overviewMsgs = await runOverview({ taprootDir, cwd });
|
|
275
|
+
if (overviewMsgs.length > 0) {
|
|
276
|
+
messages.push('');
|
|
277
|
+
messages.push(...overviewMsgs);
|
|
278
|
+
}
|
|
279
|
+
// Install hook if --with-hooks and none exists
|
|
280
|
+
if (options.withHooks) {
|
|
281
|
+
const hookDir = join(cwd, '.git', 'hooks');
|
|
282
|
+
const hookPath = join(hookDir, 'pre-commit');
|
|
283
|
+
if (existsSync(join(cwd, '.git')) && !existsSync(hookPath)) {
|
|
284
|
+
mkdirSync(hookDir, { recursive: true });
|
|
285
|
+
writeFileSync(hookPath, '#!/bin/sh\ntaproot commithook\n', { mode: 0o755 });
|
|
286
|
+
messages.push(`created .git/hooks/pre-commit`);
|
|
287
|
+
}
|
|
288
|
+
else if (existsSync(hookPath)) {
|
|
289
|
+
messages.push(`exists .git/hooks/pre-commit`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
messages.push('');
|
|
293
|
+
messages.push('Update complete.');
|
|
294
|
+
return messages;
|
|
295
|
+
}
|
|
296
|
+
export function registerUpdate(program) {
|
|
297
|
+
program
|
|
298
|
+
.command('update')
|
|
299
|
+
.description('Regenerate agent adapters and refresh installed skills')
|
|
300
|
+
.option('--path <path>', 'Project directory to update', process.cwd())
|
|
301
|
+
.option('--with-hooks', 'Install pre-commit hook if not already present')
|
|
302
|
+
.action(async (options) => {
|
|
303
|
+
const msgs = await runUpdate({ cwd: options.path, withHooks: options.withHooks });
|
|
304
|
+
for (const msg of msgs) {
|
|
305
|
+
process.stdout.write(msg + '\n');
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACrH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAkB,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGlE,MAAM,aAAa,GAAG,wBAAwB,CAAC;AAE/C,oDAAoD;AACpD,MAAM,WAAW,GAAG;IAClB,wBAAwB,EAAE,gDAAgD;IAC1E,6DAA6D;IAC7D,wDAAwD;CACzD,CAAC;AAEF,SAAS,qBAAqB,CAAC,GAAW;IACxC,MAAM,SAAS,GAAgB,EAAE,CAAC;IAElC,2GAA2G;IAC3G,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAClE,IACE,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,WAAW,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAChG,UAAU,CAAC,eAAe,CAAC;QAC3B,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,WAAW,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAC5F,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,mCAAmC;IACnC,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QAC5D,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,sEAAsE;IACtE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,yBAAyB,CAAC,CAAC;IACpE,IAAI,UAAU,CAAC,WAAW,CAAC,IAAI,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1F,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC;IAED,sDAAsD;IACtD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC5F,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,gDAAgD;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1C,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACxF,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,mCAAmC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5D,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IACnD,CAAC;IAED,qFAAqF;IACrF,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7C,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;gBACrC,QAAQ,CAAC,IAAI,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1D,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,UAAU,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC/D,CAAC;SAAM,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,QAAQ,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;IACnF,CAAC;IAED,+BAA+B;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACjE,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAClD,CAAC;IAED,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAC1D,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpD,IAAI,WAAW,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC1F,aAAa,CAAC,QAAQ,EAAE,iCAAiC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5E,QAAQ,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,OAAe,EAAE,QAAgB;IACrD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,SAAS,iBAAiB,CACxB,OAAe,EACf,OAAe,EACf,YAAoB,EACpB,UAAwB,EACxB,QAAgB;IAEhB,MAAM,aAAa,GAAG,MAAM,YAAY,2BAA2B,CAAC;IAEpE,wCAAwC;IACxC,MAAM,YAAY,GAA0C,EAAE,CAAC;IAC/D,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACxD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,SAAS;QACxC,MAAM,GAAG,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChF,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACzD,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,8EAA8E;IAC9E,MAAM,cAAc,GAAG,IAAI,MAAM,CAAC,OAAO,YAAY,SAAS,CAAC,CAAC;IAChE,MAAM,eAAe,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,IAAI,eAAe,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3B,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC;QAC9C,2CAA2C;QAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,CAAC,aAAa,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3F,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACrB,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,8CAA8C;IAC9C,IAAI,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;IACjC,KAAK,IAAI,CAAC,GAAG,eAAe,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;YAC3B,aAAa,GAAG,CAAC,CAAC;YAClB,MAAM;QACR,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACjD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;YAChD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;gBAAE,SAAS,CAAC,cAAc;YACnD,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,uBAAuB;IACvB,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,YAAY,EAAE,CAAC;QAC1C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,aAAa,GAAG,eAAe,EAAE,aAAa,EAAE,GAAG,UAAU,CAAC,CAAC;IAC7F,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,UAAkB;IAC1D,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,QAAQ,CAAC;IAE7C,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;IAE/F,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC;QACzE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QACpD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,SAAS;QAEnC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;QACpE,MAAM,QAAQ,GAAG,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;QACxE,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAEjF,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;QAEvE,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;QAExF,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACzC,QAAQ,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAA8C;IAC5E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,2DAA2D;IAC3D,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,QAAQ,CAAC,IAAI,CACX,mCAAmC,MAAM,CAAC,QAAQ,KAAK;gBACvD,cAAc,kBAAkB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACjD,oBAAoB,CACrB,CAAC;YACF,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC;IACpF,CAAC;IAED,2DAA2D;IAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC;IACxC,IAAI,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;aACpC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;aAC3B,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CACX,iCAAiC,GAAG,8BAA8B;oBAClE,wDAAwD;oBACxD,oDAAoD,CACrD,CAAC;YACJ,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACpC,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,YAAY,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;QACzE,QAAQ,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAElB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAEnC,+BAA+B;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAChC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC;gBACrE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;gBACxG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAED,sGAAsG;IACtG,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAClD,MAAM,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC;QAC9C,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAExD,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QAC9D,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,yFAAyF;IACzF,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;IAChE,IAAI,CAAC;QACH,SAAS,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACzC,aAAa,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,6BAA6B,CAAC,CAAC;IACjF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CAAC,uDAAwD,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,oEAAoE;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC/C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,yBAAyB;IACzB,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5D,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;IACjC,CAAC;IAED,+CAA+C;IAC/C,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC7C,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,aAAa,CAAC,QAAQ,EAAE,iCAAiC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5E,QAAQ,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAClC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,wDAAwD,CAAC;SACrE,MAAM,CAAC,eAAe,EAAE,6BAA6B,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACrE,MAAM,CAAC,cAAc,EAAE,gDAAgD,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,OAA8C,EAAE,EAAE;QAC/D,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAClF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { Violation } from '../validators/types.js';
|
|
3
|
+
export declare function registerValidateFormat(program: Command): void;
|
|
4
|
+
export declare function runValidateFormat(options: {
|
|
5
|
+
path?: string;
|
|
6
|
+
fix?: boolean;
|
|
7
|
+
cwd?: string;
|
|
8
|
+
}): Promise<Violation[]>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { resolve, join } from 'path';
|
|
2
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import { loadConfig } from '../core/config.js';
|
|
4
|
+
import { loadLanguagePack, supportedLanguages } from '../core/language.js';
|
|
5
|
+
import { walkHierarchy, flattenTree } from '../core/fs-walker.js';
|
|
6
|
+
import { parseMarkdown } from '../core/markdown-parser.js';
|
|
7
|
+
import { validateFormat } from '../validators/format-rules.js';
|
|
8
|
+
import { renderViolations, exitCode } from '../core/reporter.js';
|
|
9
|
+
import { SECTION_PLACEHOLDERS } from '../templates/index.js';
|
|
10
|
+
const MARKER_FILE = {
|
|
11
|
+
intent: 'intent.md',
|
|
12
|
+
behaviour: 'usecase.md',
|
|
13
|
+
impl: 'impl.md',
|
|
14
|
+
};
|
|
15
|
+
export function registerValidateFormat(program) {
|
|
16
|
+
program
|
|
17
|
+
.command('validate-format')
|
|
18
|
+
.description('Validate marker file contents against their schemas')
|
|
19
|
+
.option('--path <path>', 'Root path to validate (overrides config)')
|
|
20
|
+
.option('--fix', 'Add missing section headers with placeholder content')
|
|
21
|
+
.action(async (options) => {
|
|
22
|
+
const violations = await runValidateFormat({
|
|
23
|
+
path: options.path,
|
|
24
|
+
fix: options.fix ?? false,
|
|
25
|
+
});
|
|
26
|
+
process.stdout.write(renderViolations(violations));
|
|
27
|
+
process.exit(exitCode(violations));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export async function runValidateFormat(options) {
|
|
31
|
+
const { config, configDir } = loadConfig(options.cwd);
|
|
32
|
+
const rootPath = options.path
|
|
33
|
+
? resolve(options.path)
|
|
34
|
+
: config.root.startsWith('/') ? config.root : resolve(configDir, config.root);
|
|
35
|
+
// Load language pack if configured
|
|
36
|
+
let pack = null;
|
|
37
|
+
if (config.language) {
|
|
38
|
+
pack = loadLanguagePack(config.language);
|
|
39
|
+
if (!pack) {
|
|
40
|
+
process.stderr.write(`Warning: Language pack '${config.language}' could not be loaded — falling back to English. ` +
|
|
41
|
+
`Supported: ${supportedLanguages().join(', ')}. Check your taproot installation.\n`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const tree = walkHierarchy(rootPath);
|
|
45
|
+
const nodes = flattenTree(tree).filter((n) => n.marker !== null);
|
|
46
|
+
const violations = [];
|
|
47
|
+
for (const node of nodes) {
|
|
48
|
+
const markerFile = MARKER_FILE[node.marker];
|
|
49
|
+
const filePath = join(node.absolutePath, markerFile);
|
|
50
|
+
let content;
|
|
51
|
+
try {
|
|
52
|
+
content = readFileSync(filePath, 'utf-8');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
violations.push({
|
|
56
|
+
type: 'error',
|
|
57
|
+
filePath,
|
|
58
|
+
code: 'UNREADABLE_FILE',
|
|
59
|
+
message: `Could not read file: ${filePath}`,
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const parsed = parseMarkdown(filePath, content);
|
|
64
|
+
const nodeViolations = validateFormat(parsed, node.marker, config, node, pack);
|
|
65
|
+
if (options.fix && nodeViolations.some(v => v.code === 'MISSING_SECTION')) {
|
|
66
|
+
const fixed = applyFix(content, parsed, node.marker);
|
|
67
|
+
writeFileSync(filePath, fixed, 'utf-8');
|
|
68
|
+
// Re-parse and re-validate after fix
|
|
69
|
+
const reparsed = parseMarkdown(filePath, fixed);
|
|
70
|
+
violations.push(...validateFormat(reparsed, node.marker, config, node));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
violations.push(...nodeViolations);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return violations;
|
|
77
|
+
}
|
|
78
|
+
function applyFix(content, parsed, markerType) {
|
|
79
|
+
const placeholders = SECTION_PLACEHOLDERS[markerType] ?? {};
|
|
80
|
+
const required = markerType === 'intent' ? ['stakeholders', 'goal', 'success criteria', 'status'] :
|
|
81
|
+
markerType === 'behaviour' ? ['actor', 'preconditions', 'main flow', 'postconditions', 'status'] :
|
|
82
|
+
['behaviour', 'commits', 'tests', 'status'];
|
|
83
|
+
const missing = required.filter(s => !parsed.sections.has(s));
|
|
84
|
+
if (missing.length === 0)
|
|
85
|
+
return content;
|
|
86
|
+
const additions = missing.map(section => {
|
|
87
|
+
const placeholder = placeholders[section] ?? '<placeholder>';
|
|
88
|
+
const heading = section.replace(/\b\w/g, c => c.toUpperCase());
|
|
89
|
+
return `\n## ${heading}\n${placeholder}\n`;
|
|
90
|
+
});
|
|
91
|
+
return content.trimEnd() + '\n' + additions.join('');
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=validate-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-format.js","sourceRoot":"","sources":["../../src/commands/validate-format.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 registerValidateStructure(program: Command): void;
|
|
4
|
+
export declare function runValidateStructure(options: {
|
|
5
|
+
path?: string;
|
|
6
|
+
strict?: boolean;
|
|
7
|
+
cwd?: string;
|
|
8
|
+
}): Promise<Violation[]>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { loadConfig } from '../core/config.js';
|
|
3
|
+
import { walkHierarchy } from '../core/fs-walker.js';
|
|
4
|
+
import { validateStructure } from '../validators/structure-rules.js';
|
|
5
|
+
import { renderViolations, exitCode } from '../core/reporter.js';
|
|
6
|
+
export function registerValidateStructure(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('validate-structure')
|
|
9
|
+
.description('Validate folder hierarchy nesting rules')
|
|
10
|
+
.option('--path <path>', 'Root path to validate (overrides config)')
|
|
11
|
+
.option('--strict', 'Also warn on empty folders and missing optional fields')
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
const violations = await runValidateStructure({
|
|
14
|
+
path: options.path,
|
|
15
|
+
strict: options.strict ?? false,
|
|
16
|
+
});
|
|
17
|
+
process.stdout.write(renderViolations(violations));
|
|
18
|
+
process.exit(exitCode(violations));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export async function runValidateStructure(options) {
|
|
22
|
+
const { config, configDir } = loadConfig(options.cwd);
|
|
23
|
+
const rootPath = options.path
|
|
24
|
+
? resolve(options.path)
|
|
25
|
+
: config.root.startsWith('/') ? config.root : resolve(configDir, config.root);
|
|
26
|
+
const tree = walkHierarchy(rootPath);
|
|
27
|
+
return validateStructure(tree, { strict: options.strict ?? false });
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=validate-structure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-structure.js","sourceRoot":"","sources":["../../src/commands/validate-structure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGjE,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO;SACJ,OAAO,CAAC,oBAAoB,CAAC;SAC7B,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,eAAe,EAAE,0CAA0C,CAAC;SACnE,MAAM,CAAC,UAAU,EAAE,wDAAwD,CAAC;SAC5E,MAAM,CAAC,KAAK,EAAE,OAA4C,EAAE,EAAE;QAC7D,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC;YAC5C,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;SAChC,CAAC,CAAC;QACH,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,oBAAoB,CAAC,OAI1C;IACC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI;QAC3B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;QACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAEhF,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,OAAO,iBAAiB,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { resolve, dirname, join } from 'path';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
export const DEFAULT_CONFIG = {
|
|
5
|
+
version: 1,
|
|
6
|
+
root: 'taproot/',
|
|
7
|
+
commitPattern: 'taproot\\(([^)]+)\\):',
|
|
8
|
+
commitTrailer: 'Taproot',
|
|
9
|
+
agents: ['claude', 'cursor', 'generic'],
|
|
10
|
+
validation: {
|
|
11
|
+
requireDates: true,
|
|
12
|
+
requireStatus: true,
|
|
13
|
+
allowedIntentStates: ['draft', 'active', 'achieved', 'deprecated'],
|
|
14
|
+
allowedBehaviourStates: ['proposed', 'specified', 'implemented', 'tested', 'deprecated', 'deferred'],
|
|
15
|
+
allowedImplStates: ['planned', 'in-progress', 'complete', 'needs-rework', 'deferred'],
|
|
16
|
+
},
|
|
17
|
+
hooks: {
|
|
18
|
+
preCommit: ['taproot validate-structure', 'taproot validate-format'],
|
|
19
|
+
},
|
|
20
|
+
ci: {
|
|
21
|
+
onPr: [
|
|
22
|
+
'taproot validate-structure',
|
|
23
|
+
'taproot validate-format',
|
|
24
|
+
'taproot check-orphans',
|
|
25
|
+
'taproot sync-check',
|
|
26
|
+
],
|
|
27
|
+
onMerge: [
|
|
28
|
+
'taproot link-commits',
|
|
29
|
+
'taproot coverage --format markdown >> pr-comment',
|
|
30
|
+
'taproot coverage --format context',
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
function findConfigFile(startDir) {
|
|
35
|
+
let current = resolve(startDir);
|
|
36
|
+
while (true) {
|
|
37
|
+
const candidate = join(current, '.taproot', 'settings.yaml');
|
|
38
|
+
if (existsSync(candidate))
|
|
39
|
+
return { configFile: candidate, projectRoot: current };
|
|
40
|
+
const parent = dirname(current);
|
|
41
|
+
if (parent === current)
|
|
42
|
+
return null;
|
|
43
|
+
current = parent;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function deepMerge(defaults, overrides) {
|
|
47
|
+
const result = { ...defaults };
|
|
48
|
+
for (const key of Object.keys(overrides)) {
|
|
49
|
+
const override = overrides[key];
|
|
50
|
+
const def = defaults[key];
|
|
51
|
+
if (override !== undefined && override !== null) {
|
|
52
|
+
if (typeof override === 'object' &&
|
|
53
|
+
!Array.isArray(override) &&
|
|
54
|
+
typeof def === 'object' &&
|
|
55
|
+
!Array.isArray(def) &&
|
|
56
|
+
def !== null) {
|
|
57
|
+
result[key] = deepMerge(def, override);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
result[key] = override;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
export function loadConfig(cwd = process.cwd()) {
|
|
67
|
+
const found = findConfigFile(cwd);
|
|
68
|
+
if (!found) {
|
|
69
|
+
return {
|
|
70
|
+
config: { ...DEFAULT_CONFIG, root: resolve(cwd, DEFAULT_CONFIG.root) },
|
|
71
|
+
configDir: cwd,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const { configFile, projectRoot } = found;
|
|
75
|
+
let raw;
|
|
76
|
+
try {
|
|
77
|
+
raw = yaml.load(readFileSync(configFile, 'utf-8'));
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
throw new Error(`Failed to parse ${configFile}: ${err.message}`);
|
|
81
|
+
}
|
|
82
|
+
const merged = deepMerge(DEFAULT_CONFIG, (raw ?? {}));
|
|
83
|
+
merged.root = resolve(projectRoot, merged.root);
|
|
84
|
+
return { config: merged, configDir: projectRoot };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|