@cristiancorreau/forge 2.12.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/assets/core/hooks/post-turn-check.js +129 -0
- package/assets/core/hooks/session-start.js +142 -0
- package/assets/manifest.json +1 -1
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +3 -2
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +16 -25
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/panel.d.ts.map +1 -1
- package/dist/commands/panel.js +88 -22
- package/dist/commands/panel.js.map +1 -1
- package/dist/lib/bun.d.ts +28 -0
- package/dist/lib/bun.d.ts.map +1 -0
- package/dist/lib/bun.js +92 -0
- package/dist/lib/bun.js.map +1 -0
- package/dist/lib/catalog-install.d.ts +62 -0
- package/dist/lib/catalog-install.d.ts.map +1 -0
- package/dist/lib/catalog-install.js +561 -0
- package/dist/lib/catalog-install.js.map +1 -0
- package/dist/tui/dashboard.js +1 -1
- package/dist/tui/dashboard.js.map +1 -1
- package/dist/tui/panel.d.ts.map +1 -1
- package/dist/tui/panel.js +163 -10
- package/dist/tui/panel.js.map +1 -1
- package/dist/ui/ascii.d.ts +38 -0
- package/dist/ui/ascii.d.ts.map +1 -0
- package/dist/ui/ascii.js +50 -0
- package/dist/ui/ascii.js.map +1 -0
- package/dist/ui/banner.d.ts +15 -4
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +22 -4
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/box.d.ts.map +1 -1
- package/dist/ui/box.js +6 -4
- package/dist/ui/box.js.map +1 -1
- package/dist/ui/header.d.ts.map +1 -1
- package/dist/ui/header.js +4 -3
- package/dist/ui/header.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install data layer for `forge panel` — unified catalog search + idempotent
|
|
3
|
+
* installers for skills, profiles and templates. See SPEC-034.
|
|
4
|
+
*
|
|
5
|
+
* Every function here is pure-ish: it reads/writes the filesystem and never
|
|
6
|
+
* touches a TTY or prints, so the OpenTUI panel, the @clack fallback and the
|
|
7
|
+
* test suite all share the same logic.
|
|
8
|
+
*
|
|
9
|
+
* CRITICAL: writes to project.yaml are SURGICAL (text-level) so the hand-
|
|
10
|
+
* maintained file keeps its comments and block-style formatting. We never
|
|
11
|
+
* js-yaml.dump the whole document.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, mkdirSync, copyFileSync, statSync, } from 'fs';
|
|
14
|
+
import { join } from 'path';
|
|
15
|
+
import { SKILLS } from './catalog.js';
|
|
16
|
+
import { findProjectYaml, loadProjectYaml } from './yaml.js';
|
|
17
|
+
import { listTemplates } from './panel-data.js';
|
|
18
|
+
// ─── project.yaml readers ────────────────────────────────────────────────────
|
|
19
|
+
/** Active skill ids from project.yaml (normalising leading slashes). [] on error. */
|
|
20
|
+
function activeSkillIds(projectRoot) {
|
|
21
|
+
const yamlPath = findProjectYaml(projectRoot);
|
|
22
|
+
if (!yamlPath)
|
|
23
|
+
return [];
|
|
24
|
+
try {
|
|
25
|
+
const cfg = loadProjectYaml(yamlPath);
|
|
26
|
+
const raw = Array.isArray(cfg.skills) ? cfg.skills : [];
|
|
27
|
+
return raw.map(s => String(s).replace(/^\//, ''));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Active profile names from project.yaml (agents.profiles). [] on error. */
|
|
34
|
+
function activeProfiles(projectRoot) {
|
|
35
|
+
const yamlPath = findProjectYaml(projectRoot);
|
|
36
|
+
if (!yamlPath)
|
|
37
|
+
return [];
|
|
38
|
+
try {
|
|
39
|
+
const cfg = loadProjectYaml(yamlPath);
|
|
40
|
+
const raw = cfg.agents?.profiles;
|
|
41
|
+
return Array.isArray(raw) ? raw.map(p => String(p)) : [];
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Profile names available in the forge assets tree (profiles/<name>/). */
|
|
48
|
+
export function listAvailableProfiles(forgeRoot) {
|
|
49
|
+
if (!forgeRoot)
|
|
50
|
+
return [];
|
|
51
|
+
const dir = join(forgeRoot, 'profiles');
|
|
52
|
+
if (!existsSync(dir))
|
|
53
|
+
return [];
|
|
54
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
55
|
+
.filter(e => e.isDirectory())
|
|
56
|
+
.map(e => e.name)
|
|
57
|
+
.sort();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Stable id for a template entry, used by installTemplate. Wiki templates all
|
|
61
|
+
* collapse to the single `wiki` install target; spec/mode/claude-md keep their
|
|
62
|
+
* file name (without extension) so each is addressable.
|
|
63
|
+
*/
|
|
64
|
+
export function templateInstallId(t) {
|
|
65
|
+
if (t.category === 'wiki')
|
|
66
|
+
return 'wiki';
|
|
67
|
+
return `${t.category}:${t.name}`;
|
|
68
|
+
}
|
|
69
|
+
/** Is a template (by its install id) already scaffolded in the project? */
|
|
70
|
+
function templateInstalled(projectRoot, id) {
|
|
71
|
+
if (id === 'wiki')
|
|
72
|
+
return existsSync(join(projectRoot, 'wiki', 'index.md'));
|
|
73
|
+
if (id === 'spec:spec-template.md') {
|
|
74
|
+
return existsSync(join(projectRoot, 'docs', 'specs', '_template.md'));
|
|
75
|
+
}
|
|
76
|
+
if (id.startsWith('claude-md:')) {
|
|
77
|
+
const name = id.slice('claude-md:'.length);
|
|
78
|
+
if (name === 'project.md')
|
|
79
|
+
return existsSync(join(projectRoot, 'CLAUDE.md'));
|
|
80
|
+
if (name === 'architecture.rules')
|
|
81
|
+
return existsSync(join(projectRoot, '.claude', 'architecture.rules'));
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
// mode templates are not project-local files → never "installed".
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
// ─── searchCatalog ───────────────────────────────────────────────────────────
|
|
88
|
+
const profileDescription = (name) => `Profile Tier 2 para el stack ${name} (agentes en .claude/agents/)`;
|
|
89
|
+
/**
|
|
90
|
+
* Unified, case-insensitive substring search across installable items: skills,
|
|
91
|
+
* profiles and templates. An empty query returns the whole catalog. Each item
|
|
92
|
+
* is marked `installed` against project.yaml and/or the scaffolded state on
|
|
93
|
+
* disk. Profiles and templates require a `forgeRoot`; with `forgeRoot === null`
|
|
94
|
+
* only skills are returned.
|
|
95
|
+
*/
|
|
96
|
+
export function searchCatalog(forgeRoot, projectRoot, query) {
|
|
97
|
+
const q = query.trim().toLowerCase();
|
|
98
|
+
const skillSet = new Set(activeSkillIds(projectRoot));
|
|
99
|
+
const profileSet = new Set(activeProfiles(projectRoot));
|
|
100
|
+
const items = [];
|
|
101
|
+
// Skills.
|
|
102
|
+
for (const s of SKILLS) {
|
|
103
|
+
items.push({
|
|
104
|
+
type: 'skill', id: s.id, label: s.command,
|
|
105
|
+
description: `[${s.category}] ${s.purpose}`,
|
|
106
|
+
installed: skillSet.has(s.id),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Profiles.
|
|
110
|
+
for (const name of listAvailableProfiles(forgeRoot)) {
|
|
111
|
+
items.push({
|
|
112
|
+
type: 'profile', id: name, label: name,
|
|
113
|
+
description: profileDescription(name),
|
|
114
|
+
installed: profileSet.has(name),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// Templates (wiki collapses to a single install target).
|
|
118
|
+
const seenTpl = new Set();
|
|
119
|
+
for (const t of listTemplates(forgeRoot)) {
|
|
120
|
+
const id = templateInstallId(t);
|
|
121
|
+
if (seenTpl.has(id))
|
|
122
|
+
continue;
|
|
123
|
+
seenTpl.add(id);
|
|
124
|
+
const label = id === 'wiki' ? 'wiki' : t.name;
|
|
125
|
+
const description = id === 'wiki'
|
|
126
|
+
? 'Estructura de wiki del proyecto (index, log, subdirs)'
|
|
127
|
+
: t.description;
|
|
128
|
+
items.push({
|
|
129
|
+
type: 'template', id, label, description,
|
|
130
|
+
installed: templateInstalled(projectRoot, id),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (!q)
|
|
134
|
+
return items;
|
|
135
|
+
return items.filter(it => it.id.toLowerCase().includes(q) ||
|
|
136
|
+
it.label.toLowerCase().includes(q) ||
|
|
137
|
+
it.type.toLowerCase().includes(q) ||
|
|
138
|
+
it.description.toLowerCase().includes(q));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Append `item` to a TOP-LEVEL block/flat list `key` in `content`, preserving
|
|
142
|
+
* comments and formatting. Handles three shapes:
|
|
143
|
+
* - block list: `skills:\n - a\n - b` → inserts ` - item` after the block
|
|
144
|
+
* - flat list: `skills: [a, b]` → rewrites to `[a, b, item]`
|
|
145
|
+
* - empty/value: `skills:` or missing → creates a block list
|
|
146
|
+
* If `item` is already present (block or flat), returns unchanged.
|
|
147
|
+
*/
|
|
148
|
+
function appendTopLevelListItem(content, key, item) {
|
|
149
|
+
const lines = content.split('\n');
|
|
150
|
+
const keyRe = new RegExp(`^${key}:(.*)$`);
|
|
151
|
+
let keyIdx = -1;
|
|
152
|
+
let inlineRest = '';
|
|
153
|
+
for (let i = 0; i < lines.length; i++) {
|
|
154
|
+
const m = lines[i].match(keyRe);
|
|
155
|
+
if (m) {
|
|
156
|
+
keyIdx = i;
|
|
157
|
+
inlineRest = m[1];
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Key missing → append a fresh block list at the end of the document.
|
|
162
|
+
if (keyIdx === -1) {
|
|
163
|
+
const trimmed = content.replace(/\n+$/, '');
|
|
164
|
+
const block = `${key}:\n - ${item}`;
|
|
165
|
+
return { changed: true, content: `${trimmed}\n\n${block}\n` };
|
|
166
|
+
}
|
|
167
|
+
const rest = inlineRest.trim();
|
|
168
|
+
// Flat list form: `key: [a, b]`.
|
|
169
|
+
const flat = rest.match(/^\[(.*)\]$/);
|
|
170
|
+
if (flat) {
|
|
171
|
+
const inner = flat[1].trim();
|
|
172
|
+
const current = inner.length
|
|
173
|
+
? inner.split(',').map(s => s.trim().replace(/^["']|["']$/g, '')).filter(Boolean)
|
|
174
|
+
: [];
|
|
175
|
+
if (current.includes(item))
|
|
176
|
+
return { changed: false, content };
|
|
177
|
+
current.push(item);
|
|
178
|
+
lines[keyIdx] = `${key}: [${current.join(', ')}]`;
|
|
179
|
+
return { changed: true, content: lines.join('\n') };
|
|
180
|
+
}
|
|
181
|
+
// Block list form (or empty value → becomes a block list). Find the extent of
|
|
182
|
+
// the block: contiguous following lines that are ` - ...` items (or blanks).
|
|
183
|
+
let lastItemIdx = keyIdx;
|
|
184
|
+
let indent = ' ';
|
|
185
|
+
let foundItem = false;
|
|
186
|
+
for (let i = keyIdx + 1; i < lines.length; i++) {
|
|
187
|
+
const line = lines[i];
|
|
188
|
+
const m = line.match(/^(\s+)-\s+(.*)$/);
|
|
189
|
+
if (m) {
|
|
190
|
+
foundItem = true;
|
|
191
|
+
indent = m[1];
|
|
192
|
+
lastItemIdx = i;
|
|
193
|
+
const existing = m[2].trim().replace(/^["']|["']$/g, '');
|
|
194
|
+
if (existing === item)
|
|
195
|
+
return { changed: false, content };
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
// Allow blank lines/comments that belong to the block to be skipped only
|
|
199
|
+
// before the first item; once items started, stop at the first non-item.
|
|
200
|
+
if (!foundItem && (line.trim() === '' || line.trim().startsWith('#')))
|
|
201
|
+
continue;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
// If the value was inline non-list (e.g. `key: something`), don't touch it —
|
|
205
|
+
// append a fresh block list at the end instead (safe fallback).
|
|
206
|
+
if (!foundItem && rest.length > 0) {
|
|
207
|
+
const trimmed = content.replace(/\n+$/, '');
|
|
208
|
+
return { changed: true, content: `${trimmed}\n\n${key}:\n - ${item}\n` };
|
|
209
|
+
}
|
|
210
|
+
lines.splice(lastItemIdx + 1, 0, `${indent}- ${item}`);
|
|
211
|
+
return { changed: true, content: lines.join('\n') };
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Append `name` to the `agents.profiles` block list, creating `agents:` and/or
|
|
215
|
+
* `profiles:` as needed while preserving the rest of the document. Returns
|
|
216
|
+
* unchanged if `name` is already present.
|
|
217
|
+
*/
|
|
218
|
+
function appendProfile(content, name) {
|
|
219
|
+
const lines = content.split('\n');
|
|
220
|
+
// Locate a top-level `agents:` mapping header (`agents:` optionally followed
|
|
221
|
+
// by a comment). An inline value like `agents: {}` is not a block we can edit.
|
|
222
|
+
let agentsIdx = -1;
|
|
223
|
+
for (let i = 0; i < lines.length; i++) {
|
|
224
|
+
if (/^agents:\s*(#.*)?$/.test(lines[i])) {
|
|
225
|
+
agentsIdx = i;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// No agents: block → append a fresh one.
|
|
230
|
+
if (agentsIdx === -1) {
|
|
231
|
+
const trimmed = content.replace(/\n+$/, '');
|
|
232
|
+
return { changed: true, content: `${trimmed}\n\nagents:\n profiles:\n - ${name}\n` };
|
|
233
|
+
}
|
|
234
|
+
// Find `profiles:` inside the agents block (indented child).
|
|
235
|
+
let profilesIdx = -1;
|
|
236
|
+
let agentsBlockEnd = lines.length;
|
|
237
|
+
for (let i = agentsIdx + 1; i < lines.length; i++) {
|
|
238
|
+
const line = lines[i];
|
|
239
|
+
// A non-indented, non-blank, non-comment line ends the agents block.
|
|
240
|
+
if (line.trim() !== '' && !line.startsWith(' ') && !line.startsWith('\t')) {
|
|
241
|
+
agentsBlockEnd = i;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
if (/^\s+profiles:\s*(\[.*\])?\s*(#.*)?$/.test(line) || /^\s+profiles:\s+\S/.test(line)) {
|
|
245
|
+
profilesIdx = i;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// profiles: missing → insert a `profiles:` child at the end of the agents block.
|
|
250
|
+
if (profilesIdx === -1) {
|
|
251
|
+
// Determine the child indent used inside agents (default 2 spaces).
|
|
252
|
+
let childIndent = ' ';
|
|
253
|
+
for (let i = agentsIdx + 1; i < agentsBlockEnd; i++) {
|
|
254
|
+
const m = lines[i].match(/^(\s+)\S/);
|
|
255
|
+
if (m) {
|
|
256
|
+
childIndent = m[1];
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const insertAt = agentsBlockEnd;
|
|
261
|
+
lines.splice(insertAt, 0, `${childIndent}profiles:`, `${childIndent} - ${name}`);
|
|
262
|
+
return { changed: true, content: lines.join('\n') };
|
|
263
|
+
}
|
|
264
|
+
// profiles: present — handle flat or block forms within the nested scope.
|
|
265
|
+
const profLine = lines[profilesIdx];
|
|
266
|
+
const inlineRest = profLine.replace(/^\s+profiles:/, '').trim();
|
|
267
|
+
const flat = inlineRest.match(/^\[(.*)\]$/);
|
|
268
|
+
if (flat) {
|
|
269
|
+
const inner = flat[1].trim();
|
|
270
|
+
const current = inner.length
|
|
271
|
+
? inner.split(',').map(s => s.trim().replace(/^["']|["']$/g, '')).filter(Boolean)
|
|
272
|
+
: [];
|
|
273
|
+
if (current.includes(name))
|
|
274
|
+
return { changed: false, content };
|
|
275
|
+
current.push(name);
|
|
276
|
+
const lead = profLine.match(/^(\s+)/)?.[1] ?? ' ';
|
|
277
|
+
lines[profilesIdx] = `${lead}profiles: [${current.join(', ')}]`;
|
|
278
|
+
return { changed: true, content: lines.join('\n') };
|
|
279
|
+
}
|
|
280
|
+
// Block list under profiles:.
|
|
281
|
+
let lastItemIdx = profilesIdx;
|
|
282
|
+
let itemIndent = null;
|
|
283
|
+
let foundItem = false;
|
|
284
|
+
for (let i = profilesIdx + 1; i < lines.length; i++) {
|
|
285
|
+
const line = lines[i];
|
|
286
|
+
const m = line.match(/^(\s+)-\s+(.*)$/);
|
|
287
|
+
if (m) {
|
|
288
|
+
foundItem = true;
|
|
289
|
+
itemIndent = m[1];
|
|
290
|
+
lastItemIdx = i;
|
|
291
|
+
const existing = m[2].trim().replace(/^["']|["']$/g, '');
|
|
292
|
+
if (existing === name)
|
|
293
|
+
return { changed: false, content };
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (!foundItem && (line.trim() === '' || line.trim().startsWith('#')))
|
|
297
|
+
continue;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
if (itemIndent === null) {
|
|
301
|
+
const lead = profLine.match(/^(\s+)/)?.[1] ?? ' ';
|
|
302
|
+
itemIndent = lead + ' ';
|
|
303
|
+
}
|
|
304
|
+
lines.splice(lastItemIdx + 1, 0, `${itemIndent}- ${name}`);
|
|
305
|
+
return { changed: true, content: lines.join('\n') };
|
|
306
|
+
}
|
|
307
|
+
/** Find or build the project.yaml path for a project root. */
|
|
308
|
+
function projectYamlPath(projectRoot) {
|
|
309
|
+
return findProjectYaml(projectRoot) ?? join(projectRoot, 'project.yaml');
|
|
310
|
+
}
|
|
311
|
+
// ─── File install helpers ────────────────────────────────────────────────────
|
|
312
|
+
function copyDir(src, dest) {
|
|
313
|
+
const out = [];
|
|
314
|
+
if (!existsSync(dest))
|
|
315
|
+
mkdirSync(dest, { recursive: true });
|
|
316
|
+
for (const entry of readdirSync(src)) {
|
|
317
|
+
const s = join(src, entry);
|
|
318
|
+
const d = join(dest, entry);
|
|
319
|
+
if (statSync(s).isDirectory()) {
|
|
320
|
+
out.push(...copyDir(s, d));
|
|
321
|
+
}
|
|
322
|
+
else if (!existsSync(d)) {
|
|
323
|
+
copyFileSync(s, d);
|
|
324
|
+
out.push(d);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return out;
|
|
328
|
+
}
|
|
329
|
+
const rel = (projectRoot, abs) => abs.startsWith(projectRoot + '/') ? abs.slice(projectRoot.length + 1) : abs;
|
|
330
|
+
// ─── installSkill ────────────────────────────────────────────────────────────
|
|
331
|
+
/**
|
|
332
|
+
* Activate a skill: add its id to project.yaml `skills` (dedupe, surgical edit)
|
|
333
|
+
* and copy its slash command into `.claude/commands/` when one is bundled
|
|
334
|
+
* (`adapters/claude-code/commands/<id>.md`). Idempotent.
|
|
335
|
+
*/
|
|
336
|
+
export function installSkill(projectRoot, forgeRoot, id) {
|
|
337
|
+
const known = SKILLS.some(s => s.id === id);
|
|
338
|
+
if (!known) {
|
|
339
|
+
return { ok: false, alreadyInstalled: false, message: `Skill desconocida: ${id}`, changed: [] };
|
|
340
|
+
}
|
|
341
|
+
const yamlPath = projectYamlPath(projectRoot);
|
|
342
|
+
const changed = [];
|
|
343
|
+
let alreadyInYaml = false;
|
|
344
|
+
if (existsSync(yamlPath)) {
|
|
345
|
+
const before = readFileSync(yamlPath, 'utf-8');
|
|
346
|
+
const edit = appendTopLevelListItem(before, 'skills', id);
|
|
347
|
+
if (edit.changed) {
|
|
348
|
+
writeFileSync(yamlPath, edit.content, 'utf-8');
|
|
349
|
+
changed.push(rel(projectRoot, yamlPath));
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
alreadyInYaml = true;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
// No project.yaml yet → create a minimal one with the skill.
|
|
357
|
+
writeFileSync(yamlPath, `project:\n name: "Project"\n mode: standard\n\nskills:\n - ${id}\n`, 'utf-8');
|
|
358
|
+
changed.push(rel(projectRoot, yamlPath));
|
|
359
|
+
}
|
|
360
|
+
// Copy the slash command if one is bundled for this id.
|
|
361
|
+
if (forgeRoot) {
|
|
362
|
+
const cmdSrc = join(forgeRoot, 'adapters', 'claude-code', 'commands', `${id}.md`);
|
|
363
|
+
if (existsSync(cmdSrc)) {
|
|
364
|
+
const cmdDir = join(projectRoot, '.claude', 'commands');
|
|
365
|
+
const cmdDest = join(cmdDir, `${id}.md`);
|
|
366
|
+
if (!existsSync(cmdDest)) {
|
|
367
|
+
mkdirSync(cmdDir, { recursive: true });
|
|
368
|
+
copyFileSync(cmdSrc, cmdDest);
|
|
369
|
+
changed.push(rel(projectRoot, cmdDest));
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
const alreadyInstalled = alreadyInYaml && changed.length === 0;
|
|
374
|
+
return {
|
|
375
|
+
ok: true,
|
|
376
|
+
alreadyInstalled,
|
|
377
|
+
message: alreadyInstalled ? `La skill ${id} ya estaba activa.` : `Skill ${id} activada.`,
|
|
378
|
+
changed,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
// ─── installProfile ──────────────────────────────────────────────────────────
|
|
382
|
+
/**
|
|
383
|
+
* Activate a profile: add its name to project.yaml `agents.profiles` (dedupe,
|
|
384
|
+
* surgical edit) and install the profile's agents into `.claude/agents/`.
|
|
385
|
+
* Idempotent.
|
|
386
|
+
*/
|
|
387
|
+
export function installProfile(projectRoot, forgeRoot, name) {
|
|
388
|
+
if (!forgeRoot) {
|
|
389
|
+
return { ok: false, alreadyInstalled: false, message: 'forge root no disponible para instalar el profile.', changed: [] };
|
|
390
|
+
}
|
|
391
|
+
const profileDir = join(forgeRoot, 'profiles', name);
|
|
392
|
+
if (!existsSync(profileDir)) {
|
|
393
|
+
return { ok: false, alreadyInstalled: false, message: `Profile desconocido: ${name}`, changed: [] };
|
|
394
|
+
}
|
|
395
|
+
const yamlPath = projectYamlPath(projectRoot);
|
|
396
|
+
const changed = [];
|
|
397
|
+
let alreadyInYaml = false;
|
|
398
|
+
if (existsSync(yamlPath)) {
|
|
399
|
+
const before = readFileSync(yamlPath, 'utf-8');
|
|
400
|
+
const edit = appendProfile(before, name);
|
|
401
|
+
if (edit.changed) {
|
|
402
|
+
writeFileSync(yamlPath, edit.content, 'utf-8');
|
|
403
|
+
changed.push(rel(projectRoot, yamlPath));
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
alreadyInYaml = true;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
writeFileSync(yamlPath, `project:\n name: "Project"\n mode: standard\n\nagents:\n profiles:\n - ${name}\n`, 'utf-8');
|
|
411
|
+
changed.push(rel(projectRoot, yamlPath));
|
|
412
|
+
}
|
|
413
|
+
// Install the profile's agent files into .claude/agents/.
|
|
414
|
+
const agentsSrc = join(profileDir, 'agents');
|
|
415
|
+
if (existsSync(agentsSrc)) {
|
|
416
|
+
const dest = join(projectRoot, '.claude', 'agents');
|
|
417
|
+
for (const f of copyDir(agentsSrc, dest))
|
|
418
|
+
changed.push(rel(projectRoot, f));
|
|
419
|
+
}
|
|
420
|
+
const alreadyInstalled = alreadyInYaml && changed.length === 0;
|
|
421
|
+
return {
|
|
422
|
+
ok: true,
|
|
423
|
+
alreadyInstalled,
|
|
424
|
+
message: alreadyInstalled ? `El profile ${name} ya estaba activo.` : `Profile ${name} activado.`,
|
|
425
|
+
changed,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
// ─── installTemplate ─────────────────────────────────────────────────────────
|
|
429
|
+
/**
|
|
430
|
+
* Scaffold a template into the project (idempotent):
|
|
431
|
+
* - `wiki` → full templated wiki structure
|
|
432
|
+
* - `spec:spec-template.md` → docs/specs/_template.md from the bundled spec template
|
|
433
|
+
* - `claude-md:project.md` → CLAUDE.md if missing
|
|
434
|
+
* - `claude-md:architecture.rules` → .claude/architecture.rules if missing
|
|
435
|
+
* - `mode:*` → project.yaml mode template into docs/ (reference copy)
|
|
436
|
+
*/
|
|
437
|
+
export function installTemplate(projectRoot, forgeRoot, id) {
|
|
438
|
+
if (!forgeRoot) {
|
|
439
|
+
return { ok: false, alreadyInstalled: false, message: 'forge root no disponible para instalar el template.', changed: [] };
|
|
440
|
+
}
|
|
441
|
+
const changed = [];
|
|
442
|
+
// Wiki — reuse the canonical scaffolder via dynamic import to avoid pulling
|
|
443
|
+
// the wiki command module into the panel data layer eagerly.
|
|
444
|
+
if (id === 'wiki') {
|
|
445
|
+
const existed = existsSync(join(projectRoot, 'wiki', 'index.md'));
|
|
446
|
+
scaffoldWiki(projectRoot, forgeRoot);
|
|
447
|
+
if (!existed)
|
|
448
|
+
changed.push('wiki/');
|
|
449
|
+
return {
|
|
450
|
+
ok: true, alreadyInstalled: existed,
|
|
451
|
+
message: existed ? 'El wiki ya estaba inicializado.' : 'Wiki inicializado.',
|
|
452
|
+
changed,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
if (id === 'spec:spec-template.md') {
|
|
456
|
+
const src = join(forgeRoot, 'core', 'templates', 'spec-template.md');
|
|
457
|
+
const destDir = join(projectRoot, 'docs', 'specs');
|
|
458
|
+
const dest = join(destDir, '_template.md');
|
|
459
|
+
if (existsSync(dest)) {
|
|
460
|
+
return { ok: true, alreadyInstalled: true, message: 'La plantilla de spec ya existía.', changed };
|
|
461
|
+
}
|
|
462
|
+
if (!existsSync(src)) {
|
|
463
|
+
return { ok: false, alreadyInstalled: false, message: 'No se encontró spec-template.md en el forge root.', changed };
|
|
464
|
+
}
|
|
465
|
+
mkdirSync(destDir, { recursive: true });
|
|
466
|
+
copyFileSync(src, dest);
|
|
467
|
+
changed.push('docs/specs/_template.md');
|
|
468
|
+
return { ok: true, alreadyInstalled: false, message: 'Plantilla de spec instalada en docs/specs/_template.md.', changed };
|
|
469
|
+
}
|
|
470
|
+
if (id.startsWith('claude-md:')) {
|
|
471
|
+
const name = id.slice('claude-md:'.length);
|
|
472
|
+
const src = join(forgeRoot, 'core', 'templates', 'claude-md', name);
|
|
473
|
+
if (!existsSync(src)) {
|
|
474
|
+
return { ok: false, alreadyInstalled: false, message: `No se encontró el template ${name}.`, changed };
|
|
475
|
+
}
|
|
476
|
+
if (name === 'architecture.rules') {
|
|
477
|
+
const destDir = join(projectRoot, '.claude');
|
|
478
|
+
const dest = join(destDir, 'architecture.rules');
|
|
479
|
+
if (existsSync(dest))
|
|
480
|
+
return { ok: true, alreadyInstalled: true, message: 'architecture.rules ya existía.', changed };
|
|
481
|
+
mkdirSync(destDir, { recursive: true });
|
|
482
|
+
copyFileSync(src, dest);
|
|
483
|
+
changed.push('.claude/architecture.rules');
|
|
484
|
+
return { ok: true, alreadyInstalled: false, message: 'architecture.rules instalado.', changed };
|
|
485
|
+
}
|
|
486
|
+
// project.md / global.md → reference copy under docs/.
|
|
487
|
+
const destDir = join(projectRoot, 'docs');
|
|
488
|
+
const dest = join(destDir, name);
|
|
489
|
+
if (existsSync(dest))
|
|
490
|
+
return { ok: true, alreadyInstalled: true, message: `${name} ya existía en docs/.`, changed };
|
|
491
|
+
mkdirSync(destDir, { recursive: true });
|
|
492
|
+
copyFileSync(src, dest);
|
|
493
|
+
changed.push(`docs/${name}`);
|
|
494
|
+
return { ok: true, alreadyInstalled: false, message: `${name} copiado a docs/.`, changed };
|
|
495
|
+
}
|
|
496
|
+
if (id.startsWith('mode:')) {
|
|
497
|
+
const name = id.slice('mode:'.length);
|
|
498
|
+
const src = join(forgeRoot, 'templates', 'modes', name);
|
|
499
|
+
if (!existsSync(src)) {
|
|
500
|
+
return { ok: false, alreadyInstalled: false, message: `No se encontró el mode template ${name}.`, changed };
|
|
501
|
+
}
|
|
502
|
+
// A mode template is a reference for project.yaml — copy under docs/ so it
|
|
503
|
+
// never clobbers the live project.yaml.
|
|
504
|
+
const destDir = join(projectRoot, 'docs', 'modes');
|
|
505
|
+
const dest = join(destDir, name);
|
|
506
|
+
if (existsSync(dest))
|
|
507
|
+
return { ok: true, alreadyInstalled: true, message: `El mode ${name} ya estaba copiado.`, changed };
|
|
508
|
+
mkdirSync(destDir, { recursive: true });
|
|
509
|
+
copyFileSync(src, dest);
|
|
510
|
+
changed.push(`docs/modes/${name}`);
|
|
511
|
+
return { ok: true, alreadyInstalled: false, message: `Mode template ${name} copiado a docs/modes/.`, changed };
|
|
512
|
+
}
|
|
513
|
+
return { ok: false, alreadyInstalled: false, message: `Template desconocido: ${id}`, changed };
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Minimal wiki scaffolder embedded here to keep the data layer free of the
|
|
517
|
+
* interactive wiki command module. Mirrors scaffoldWikiStructure: 5 subdirs,
|
|
518
|
+
* index.md/log.md and the per-subdir _template.md seeds, from the bundled
|
|
519
|
+
* templates with safe inline fallbacks. Idempotent (never overwrites).
|
|
520
|
+
*/
|
|
521
|
+
function scaffoldWiki(projectRoot, forgeRoot) {
|
|
522
|
+
const root = join(projectRoot, 'wiki');
|
|
523
|
+
const tplDir = join(forgeRoot, 'templates', 'wiki');
|
|
524
|
+
const SUBDIRS = ['raw', 'concepts', 'entities', 'sources', 'synthesis'];
|
|
525
|
+
const TEMPLATED = ['concepts', 'entities', 'sources', 'synthesis'];
|
|
526
|
+
const FALLBACK = {
|
|
527
|
+
'index.md': '# Wiki Index\n\n<!-- generado por forge -->\n',
|
|
528
|
+
'log.md': '# Wiki Log\n\n<!-- ingesta registrada aquí -->\n',
|
|
529
|
+
};
|
|
530
|
+
for (const sub of SUBDIRS)
|
|
531
|
+
mkdirSync(join(root, sub), { recursive: true });
|
|
532
|
+
for (const fname of ['index.md', 'log.md']) {
|
|
533
|
+
const dest = join(root, fname);
|
|
534
|
+
if (existsSync(dest))
|
|
535
|
+
continue;
|
|
536
|
+
const tpl = join(tplDir, fname);
|
|
537
|
+
if (existsSync(tpl))
|
|
538
|
+
copyFileSync(tpl, dest);
|
|
539
|
+
else
|
|
540
|
+
writeFileSync(dest, FALLBACK[fname], 'utf-8');
|
|
541
|
+
}
|
|
542
|
+
for (const sub of TEMPLATED) {
|
|
543
|
+
const dest = join(root, sub, '_template.md');
|
|
544
|
+
if (existsSync(dest))
|
|
545
|
+
continue;
|
|
546
|
+
const tpl = join(tplDir, sub, '_template.md');
|
|
547
|
+
if (existsSync(tpl))
|
|
548
|
+
copyFileSync(tpl, dest);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
// ─── Dispatcher ──────────────────────────────────────────────────────────────
|
|
552
|
+
/** Install any catalog item by type. Convenience wrapper for the UI layers. */
|
|
553
|
+
export function installItem(projectRoot, forgeRoot, item) {
|
|
554
|
+
switch (item.type) {
|
|
555
|
+
case 'skill': return installSkill(projectRoot, forgeRoot, item.id);
|
|
556
|
+
case 'profile': return installProfile(projectRoot, forgeRoot, item.id);
|
|
557
|
+
case 'template': return installTemplate(projectRoot, forgeRoot, item.id);
|
|
558
|
+
default: return { ok: false, alreadyInstalled: false, message: 'Tipo desconocido', changed: [] };
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
//# sourceMappingURL=catalog-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-install.js","sourceRoot":"","sources":["../../src/lib/catalog-install.ts"],"names":[],"mappings":"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"}
|
package/dist/tui/dashboard.js
CHANGED
|
@@ -163,7 +163,7 @@ function detectRuntimes() {
|
|
|
163
163
|
try {
|
|
164
164
|
const proc = globalThis.Bun.spawnSync(rt.cmd, { stdout: 'pipe', stderr: 'pipe' });
|
|
165
165
|
const out = (proc.stdout ? new TextDecoder().decode(proc.stdout) : '').trim();
|
|
166
|
-
result[rt.id] = { installed: proc.exitCode === 0, version: out.split(
|
|
166
|
+
result[rt.id] = { installed: proc.exitCode === 0, version: out.split(/\r?\n/)[0].slice(0, 20) };
|
|
167
167
|
}
|
|
168
168
|
catch {
|
|
169
169
|
result[rt.id] = { installed: false, version: '' };
|