@cristiancorreau/forge 2.16.0 → 2.17.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 +7 -0
- package/assets/manifest.json +1 -1
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts +2 -0
- package/dist/commands/adopt.d.ts.map +1 -0
- package/dist/commands/adopt.js +259 -0
- package/dist/commands/adopt.js.map +1 -0
- package/dist/commands/init.d.ts +40 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +48 -40
- package/dist/commands/init.js.map +1 -1
- package/dist/lib/project-analysis.d.ts +52 -0
- package/dist/lib/project-analysis.d.ts.map +1 -0
- package/dist/lib/project-analysis.js +361 -0
- package/dist/lib/project-analysis.js.map +1 -0
- package/dist/lib/wiki-autogen.d.ts +31 -0
- package/dist/lib/wiki-autogen.d.ts.map +1 -0
- package/dist/lib/wiki-autogen.js +596 -0
- package/dist/lib/wiki-autogen.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ Versioning: [Semantic Versioning](https://semver.org/lang/es/)
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [2.17.0] — 2026-06-04
|
|
11
|
+
|
|
12
|
+
### Agregado
|
|
13
|
+
- **`forge adopt [path]` — onboarding de forge en un repo existente (brownfield).** Lee y analiza un codebase ya existente (sin LLM), genera el `project.yaml` desde lo que detecta (stack vía `detect.ts` con lenguaje por lado, `project.type`, ORM, testing, monorepo, docker), instala la config de forge reusando los installers de `forge init` (agentes por modo, hooks, slash commands, CLAUDE.md, settings.json, architecture.rules, manifest `.forge`) sin pisar archivos existentes salvo `--force`, y **auto-genera el wiki del proyecto** con HECHOS determinísticos: `concepts/arquitectura.md` y `concepts/stack.md` (del mapa de directorios + stack), `entities/` (proyecto + cada framework/herramienta detectada), `sources/` (resumen de README + manifest), `synthesis/overview.md` (resumen factual + nota "Pendiente: compilación semántica con /wiki-ingest") y `raw/` con copias inmutables del README + manifest. El wiki generado pasa `forge wiki lint` (sin links rotos ni huérfanos). La capa SEMÁNTICA (lógica de negocio, decisiones) sigue siendo trabajo del skill `/wiki-ingest`, que `adopt` apunta como próximo paso. Flags: `--yes` (no-interactivo por defecto), `--no-wiki`, `--runtime`, `--mode`, `--force`, `--dry-run`. Módulos puros y testeados: `lib/project-analysis.ts` y `lib/wiki-autogen.ts` (SPEC-038).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
10
17
|
## [2.16.0] — 2026-06-04
|
|
11
18
|
|
|
12
19
|
### Agregado
|
package/assets/manifest.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { init } from './commands/init.js';
|
|
3
|
+
import { adopt } from './commands/adopt.js';
|
|
3
4
|
import { audit } from './commands/audit.js';
|
|
4
5
|
import { generate } from './commands/generate.js';
|
|
5
6
|
import { validate } from './commands/validate.js';
|
|
@@ -21,6 +22,7 @@ Usage: forge <command> [options]
|
|
|
21
22
|
Setup
|
|
22
23
|
panel Open the interactive panel (config, monitor, skills, hooks, templates)
|
|
23
24
|
init Initialize forge in a project (wizard + post-install dashboard)
|
|
25
|
+
adopt Onboard forge into an EXISTING codebase (analyze + auto-wiki)
|
|
24
26
|
generate Generate runtime config files from project.yaml
|
|
25
27
|
migrate Migrate project.yaml from the v1 schema to v2 (--dry-run, --backup)
|
|
26
28
|
scaffold Scaffold a new agent: Tier 2 profile, or Tier 3 domain agent (--tier 3)
|
|
@@ -48,6 +50,7 @@ Run forge <command> --help for command-specific options.
|
|
|
48
50
|
|
|
49
51
|
Examples:
|
|
50
52
|
npx @cristiancorreau/forge init
|
|
53
|
+
npx @cristiancorreau/forge adopt ./my-existing-repo --yes
|
|
51
54
|
npx @cristiancorreau/forge panel
|
|
52
55
|
npx @cristiancorreau/forge skills
|
|
53
56
|
npx @cristiancorreau/forge migrate --dry-run
|
|
@@ -60,6 +63,9 @@ switch (cmd) {
|
|
|
60
63
|
case 'init':
|
|
61
64
|
exitCode = await init(rest);
|
|
62
65
|
break;
|
|
66
|
+
case 'adopt':
|
|
67
|
+
exitCode = await adopt(rest);
|
|
68
|
+
break;
|
|
63
69
|
case 'audit':
|
|
64
70
|
exitCode = await audit(rest);
|
|
65
71
|
break;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,IAAI,GAAG,UAAU,OAAO
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"AAwLA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+G3D"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `forge adopt [path]` — onboard forge into an EXISTING codebase (brownfield).
|
|
3
|
+
*
|
|
4
|
+
* Unlike `forge init` (greenfield wizard), adopt READS the target project, infers
|
|
5
|
+
* its configuration by static analysis, and materializes everything non-
|
|
6
|
+
* interactively: project.yaml + the forge config (.claude/, CLAUDE.md, settings,
|
|
7
|
+
* architecture.rules, manifest) + an auto-generated FACTUAL wiki.
|
|
8
|
+
*
|
|
9
|
+
* The wiki it seeds is deterministic facts only (stack, structure, dependencies,
|
|
10
|
+
* scripts, README summary). The deep SEMANTIC compilation stays the job of the
|
|
11
|
+
* /wiki-ingest skill, which adopt points to as the explicit next step.
|
|
12
|
+
*
|
|
13
|
+
* It reuses init's exported installers so the installed config is identical to
|
|
14
|
+
* `forge init`, and never clobbers existing files unless --force.
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, mkdirSync, writeFileSync, statSync } from 'fs';
|
|
17
|
+
import { join, resolve } from 'path';
|
|
18
|
+
import { resolveForgeRoot } from '../lib/paths.js';
|
|
19
|
+
import { generateClaudeMd } from '../lib/generators/claude-code.js';
|
|
20
|
+
import { generateAgentsMd } from '../lib/generators/opencode.js';
|
|
21
|
+
import { generateCodexAgentsMd } from '../lib/generators/codex.js';
|
|
22
|
+
import { scaffoldWikiStructure } from './wiki.js';
|
|
23
|
+
import { analyzeProject, slugify } from '../lib/project-analysis.js';
|
|
24
|
+
import { generateWiki } from '../lib/wiki-autogen.js';
|
|
25
|
+
import { languageLabel, deriveProjectLanguage, hasBackend, hasFrontend } from '../lib/wizard-flow.js';
|
|
26
|
+
import { VERSION } from '../version.js';
|
|
27
|
+
import { defaultAgentsForMode, installCoreAgents, installHooks, installCommands, writeSettingsJson, installSpecScaffold, saveInstallManifest, write, buildProjectYaml, } from './init.js';
|
|
28
|
+
import { bold, dim, green, cyan, gray, yellow, icons } from '../ui/colors.js';
|
|
29
|
+
import { box } from '../ui/box.js';
|
|
30
|
+
const HELP = `Usage: forge adopt [path] [options]
|
|
31
|
+
|
|
32
|
+
Onboard forge into an EXISTING codebase. Analyzes the project, generates
|
|
33
|
+
project.yaml from what it detects, installs the forge config, and seeds the
|
|
34
|
+
project wiki with FACTUAL knowledge (stack, structure, dependencies, scripts,
|
|
35
|
+
README). Non-interactive by default.
|
|
36
|
+
|
|
37
|
+
Arguments:
|
|
38
|
+
path Target project directory (default: current directory)
|
|
39
|
+
|
|
40
|
+
Options:
|
|
41
|
+
--yes Non-interactive (default — no prompts)
|
|
42
|
+
--no-wiki Skip the auto-generated wiki
|
|
43
|
+
--runtime <name> Runtime: claude-code (default), opencode, codex
|
|
44
|
+
--mode <mode> Mode: startup, standard (default), enterprise
|
|
45
|
+
--force Overwrite existing files instead of preserving them
|
|
46
|
+
--dry-run Analyze + print the plan; write nothing
|
|
47
|
+
-h, --help Show this help
|
|
48
|
+
|
|
49
|
+
The wiki adopt seeds is deterministic FACTS. The deep semantic compilation
|
|
50
|
+
(business logic, decisions) is the job of /wiki-ingest — adopt prints it as the
|
|
51
|
+
next step.
|
|
52
|
+
`;
|
|
53
|
+
function flagValue(args, flag) {
|
|
54
|
+
const i = args.indexOf(flag);
|
|
55
|
+
return i !== -1 ? (args[i + 1] ?? null) : null;
|
|
56
|
+
}
|
|
57
|
+
function parseOptions(args) {
|
|
58
|
+
// First non-flag arg (not a flag value) is the target path.
|
|
59
|
+
const flagsWithValue = new Set(['--runtime', '--mode']);
|
|
60
|
+
let target = process.cwd();
|
|
61
|
+
for (let i = 0; i < args.length; i++) {
|
|
62
|
+
const arg = args[i];
|
|
63
|
+
if (arg.startsWith('-')) {
|
|
64
|
+
if (flagsWithValue.has(arg))
|
|
65
|
+
i++; // skip its value
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
target = resolve(arg);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
const modeRaw = flagValue(args, '--mode');
|
|
72
|
+
const mode = modeRaw === 'startup' || modeRaw === 'enterprise' ? modeRaw : 'standard';
|
|
73
|
+
return {
|
|
74
|
+
target,
|
|
75
|
+
runtime: flagValue(args, '--runtime') ?? 'claude-code',
|
|
76
|
+
mode,
|
|
77
|
+
wiki: !args.includes('--no-wiki'),
|
|
78
|
+
force: args.includes('--force'),
|
|
79
|
+
dryRun: args.includes('--dry-run'),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** Map a ProjectAnalysis to a WizardResult so buildProjectYaml can render YAML. */
|
|
83
|
+
function analysisToWizardResult(a, opts) {
|
|
84
|
+
const s = a.stack;
|
|
85
|
+
// Per-side language falls back to the base detected language when no framework
|
|
86
|
+
// was matched on that side (e.g. a Python backend whose framework isn't in
|
|
87
|
+
// detect.ts still has a Python backend language, not the TS default).
|
|
88
|
+
const backendLanguage = s.backendLanguage
|
|
89
|
+
?? (hasBackend(a.type) ? (s.language ?? undefined) : undefined)
|
|
90
|
+
?? undefined;
|
|
91
|
+
const frontendLanguage = s.frontendLanguage
|
|
92
|
+
?? (hasFrontend(a.type) ? 'typescript' : undefined)
|
|
93
|
+
?? undefined;
|
|
94
|
+
const language = deriveProjectLanguage({ type: a.type, backendLanguage, frontendLanguage });
|
|
95
|
+
// Auto-detect profiles from the detected frameworks (mirrors the wizard).
|
|
96
|
+
const PROFILE_MAP = {
|
|
97
|
+
hono: 'hono-drizzle', nextjs: 'nextjs-admin', astro: 'astro',
|
|
98
|
+
fastapi: 'fastapi', rails: 'rails', laravel: 'laravel',
|
|
99
|
+
};
|
|
100
|
+
const profiles = [];
|
|
101
|
+
for (const key of [s.backend, s.frontend]) {
|
|
102
|
+
if (key && PROFILE_MAP[key])
|
|
103
|
+
profiles.push(PROFILE_MAP[key]);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
name: a.name,
|
|
107
|
+
slug: slugify(a.name),
|
|
108
|
+
description: a.description || '',
|
|
109
|
+
language,
|
|
110
|
+
type: a.type,
|
|
111
|
+
backendLanguage,
|
|
112
|
+
frontendLanguage,
|
|
113
|
+
mode: opts.mode,
|
|
114
|
+
backend: s.backend ?? undefined,
|
|
115
|
+
frontend: s.frontend ?? undefined,
|
|
116
|
+
database: s.database ?? undefined,
|
|
117
|
+
orm: s.orm ?? undefined,
|
|
118
|
+
packageManager: s.packageManager ?? undefined,
|
|
119
|
+
testing: s.testing,
|
|
120
|
+
profiles: [...new Set(profiles)],
|
|
121
|
+
skills: ['wiki-ingest', 'wiki-query', 'wiki-lint'],
|
|
122
|
+
runtime: opts.runtime,
|
|
123
|
+
detected: true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** Build the in-memory ProjectYaml config (matches init's config shape). */
|
|
127
|
+
function buildConfig(result) {
|
|
128
|
+
return {
|
|
129
|
+
project: {
|
|
130
|
+
name: result.name, slug: result.slug, description: result.description,
|
|
131
|
+
language: result.language, type: result.type, mode: result.mode, status: 'active',
|
|
132
|
+
},
|
|
133
|
+
stack: {
|
|
134
|
+
backend: result.backend, backend_language: result.backendLanguage,
|
|
135
|
+
frontend: result.frontend, frontend_language: result.frontendLanguage,
|
|
136
|
+
database: result.database, orm: result.orm,
|
|
137
|
+
package_manager: result.packageManager, testing: result.testing,
|
|
138
|
+
},
|
|
139
|
+
agents: { active: defaultAgentsForMode(result.mode), compliance: [], specialized: [], profiles: result.profiles },
|
|
140
|
+
runtimes: { active: [result.runtime] },
|
|
141
|
+
skills: result.skills,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function printDetectedSummary(a) {
|
|
145
|
+
const s = a.stack;
|
|
146
|
+
const lines = [];
|
|
147
|
+
lines.push(`${bold('Proyecto')}: ${a.name}${a.description ? gray(` — ${a.description}`) : ''}`);
|
|
148
|
+
lines.push(`${bold('Tipo')}: ${a.type} ${bold('Lenguaje')}: ${a.stack.language ? languageLabel(a.stack.language) : '—'} ${bold('Ecosistema')}: ${a.ecosystem}`);
|
|
149
|
+
if (s.backend)
|
|
150
|
+
lines.push(`${bold('Backend')}: ${s.backend}${s.backendLanguage ? ` (${s.backendLanguage})` : ''}`);
|
|
151
|
+
if (s.frontend)
|
|
152
|
+
lines.push(`${bold('Frontend')}: ${s.frontend}${s.frontendLanguage ? ` (${s.frontendLanguage})` : ''}`);
|
|
153
|
+
if (s.database || s.orm)
|
|
154
|
+
lines.push(`${bold('Datos')}: ${[s.database, s.orm].filter(Boolean).join(' + ') || '—'}`);
|
|
155
|
+
if (s.testing.length)
|
|
156
|
+
lines.push(`${bold('Testing')}: ${s.testing.join(', ')}`);
|
|
157
|
+
if (s.packageManager)
|
|
158
|
+
lines.push(`${bold('Package manager')}: ${s.packageManager}`);
|
|
159
|
+
lines.push(`${bold('Directorios')}: ${a.directories.slice(0, 6).map(d => `${d.name}/ (${d.fileCount})`).join(' ') || '—'}`);
|
|
160
|
+
if (a.entrypoints.length)
|
|
161
|
+
lines.push(`${bold('Entrypoints')}: ${a.entrypoints.slice(0, 4).join(', ')}`);
|
|
162
|
+
if (a.git.remote)
|
|
163
|
+
lines.push(`${bold('Git')}: ${a.git.remote}${a.git.branch ? ` @ ${a.git.branch}` : ''}`);
|
|
164
|
+
console.log('\n' + box(cyan('Proyecto detectado'), lines));
|
|
165
|
+
}
|
|
166
|
+
export async function adopt(args) {
|
|
167
|
+
if (args.includes('-h') || args.includes('--help')) {
|
|
168
|
+
process.stdout.write(HELP);
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
const opts = parseOptions(args);
|
|
172
|
+
console.log(cyan(bold('forge adopt')) + dim(` ${opts.target}`) + '\n');
|
|
173
|
+
if (!existsSync(opts.target) || !statSync(opts.target).isDirectory()) {
|
|
174
|
+
console.error(` ${icons.error} El target no existe o no es un directorio: ${opts.target}\n`);
|
|
175
|
+
return 1;
|
|
176
|
+
}
|
|
177
|
+
// 1. Analyze the existing project (never throws).
|
|
178
|
+
const analysis = analyzeProject(opts.target);
|
|
179
|
+
printDetectedSummary(analysis);
|
|
180
|
+
const result = analysisToWizardResult(analysis, opts);
|
|
181
|
+
const config = buildConfig(result);
|
|
182
|
+
// --- dry-run: print the plan, write nothing ---
|
|
183
|
+
if (opts.dryRun) {
|
|
184
|
+
const plan = [
|
|
185
|
+
`project.yaml ${gray('(generado del análisis)')}`,
|
|
186
|
+
...(opts.runtime === 'claude-code' ? [
|
|
187
|
+
`.claude/agents/ ${gray(`${config.agents?.active?.length ?? 0} agents (${opts.mode})`)}`,
|
|
188
|
+
'.claude/hooks/ ' + gray('guardrails'),
|
|
189
|
+
'.claude/commands/ ' + gray('slash commands'),
|
|
190
|
+
'CLAUDE.md ' + gray('generado'),
|
|
191
|
+
'.claude/settings.json ' + gray('permisos + hooks'),
|
|
192
|
+
'.claude/architecture.rules + docs/specs/',
|
|
193
|
+
'.forge/manifest.json',
|
|
194
|
+
] : [`${opts.runtime}: AGENTS.md ${gray('generado')}`]),
|
|
195
|
+
...(opts.wiki ? [`wiki/ ${gray('poblado (hechos) — semántica vía /wiki-ingest')}`] : []),
|
|
196
|
+
];
|
|
197
|
+
console.log('\n' + box(yellow('Plan (--dry-run, no escribe nada)'), plan));
|
|
198
|
+
console.log(dim('\n Ejecutá sin --dry-run para aplicar.\n'));
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
// 2. Write project.yaml (preserve existing unless --force).
|
|
202
|
+
const projectYamlPath = join(opts.target, 'project.yaml');
|
|
203
|
+
const created = [];
|
|
204
|
+
if (!existsSync(projectYamlPath) || opts.force) {
|
|
205
|
+
writeFileSync(projectYamlPath, buildProjectYaml(result, []), 'utf-8');
|
|
206
|
+
created.push('project.yaml');
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
console.log(dim(' project.yaml ya existe — se conserva (usá --force para sobrescribir).'));
|
|
210
|
+
}
|
|
211
|
+
// 3. Install the forge config, reusing init's exported installers.
|
|
212
|
+
const forgeRoot = resolveForgeRoot();
|
|
213
|
+
if (opts.runtime === 'claude-code') {
|
|
214
|
+
const claudeDir = join(opts.target, '.claude');
|
|
215
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
216
|
+
const activeAgents = config.agents?.active ?? [];
|
|
217
|
+
const profiles = config.agents?.profiles ?? [];
|
|
218
|
+
installCoreAgents(forgeRoot, join(claudeDir, 'agents'), activeAgents, profiles, opts.force);
|
|
219
|
+
installHooks(forgeRoot, join(claudeDir, 'hooks'), opts.mode, opts.force);
|
|
220
|
+
installCommands(forgeRoot, join(claudeDir, 'commands'), opts.force);
|
|
221
|
+
write(join(opts.target, 'CLAUDE.md'), generateClaudeMd(config), opts.force);
|
|
222
|
+
writeSettingsJson(join(claudeDir, 'settings.json'), config.project.language ?? 'typescript', opts.mode, opts.force);
|
|
223
|
+
installSpecScaffold(forgeRoot, opts.target, claudeDir, config);
|
|
224
|
+
saveInstallManifest(opts.target, claudeDir, opts.runtime, activeAgents, [], VERSION);
|
|
225
|
+
created.push('.claude/ (agents, hooks, commands, settings.json, architecture.rules)', 'CLAUDE.md', 'docs/specs/', '.forge/manifest.json');
|
|
226
|
+
}
|
|
227
|
+
else if (opts.runtime === 'opencode') {
|
|
228
|
+
mkdirSync(join(opts.target, '.opencode'), { recursive: true });
|
|
229
|
+
write(join(opts.target, 'AGENTS.md'), generateAgentsMd(config), opts.force);
|
|
230
|
+
created.push('AGENTS.md');
|
|
231
|
+
}
|
|
232
|
+
else if (opts.runtime === 'codex') {
|
|
233
|
+
write(join(opts.target, 'AGENTS.md'), generateCodexAgentsMd(config), opts.force);
|
|
234
|
+
created.push('AGENTS.md');
|
|
235
|
+
}
|
|
236
|
+
// 4. Auto-generate the wiki (factual) unless --no-wiki.
|
|
237
|
+
let wikiResult = null;
|
|
238
|
+
if (opts.wiki) {
|
|
239
|
+
scaffoldWikiStructure(opts.target, false);
|
|
240
|
+
wikiResult = generateWiki(analysis);
|
|
241
|
+
created.push(`wiki/ (${wikiResult.pages.length} páginas, ${wikiResult.rawSources.length} fuentes en raw/)`);
|
|
242
|
+
}
|
|
243
|
+
// 5. Summary + next steps.
|
|
244
|
+
console.log('\n' + box(green(`forge adoptado — ${opts.runtime}`), created.map(c => `${icons.ok} ${c}`)));
|
|
245
|
+
const rawList = wikiResult?.rawSources.length
|
|
246
|
+
? wikiResult.rawSources.map(r => `wiki/raw/${r}`)
|
|
247
|
+
: [];
|
|
248
|
+
const nextSteps = [];
|
|
249
|
+
if (opts.wiki) {
|
|
250
|
+
nextSteps.push(`${cyan('/wiki-ingest')} ${dim('— compilá la capa semántica desde las fuentes:')}`, ...rawList.map(r => ` ${dim(r)}`));
|
|
251
|
+
}
|
|
252
|
+
nextSteps.push(`${cyan('forge audit')} ${dim('— verificá el proyecto contra el estándar forge')}`, `${cyan('forge panel')} ${dim('— panel interactivo (config, monitor, skills)')}`);
|
|
253
|
+
console.log('\n' + bold(' Próximos pasos:'));
|
|
254
|
+
for (const step of nextSteps)
|
|
255
|
+
console.log(` ${step}`);
|
|
256
|
+
console.log('');
|
|
257
|
+
return 0;
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=adopt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,4 +1,43 @@
|
|
|
1
1
|
import { runWizard } from '../lib/wizard.js';
|
|
2
|
-
|
|
2
|
+
import type { ProjectYaml } from '../lib/yaml.js';
|
|
3
|
+
export declare function write(path: string, content: string, force: boolean): void;
|
|
4
|
+
/**
|
|
5
|
+
* Auto-detecta agentes Tier 3 existentes: escanea .claude/agents/*.md en `root`
|
|
6
|
+
* y devuelve los nombres cuyo frontmatter declara `tier: 3`. Sirve para poblar
|
|
7
|
+
* agents.specialized en project.yaml durante `forge init`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function detectTier3Agents(root: string): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Lista los archivos instalados en `<claudeDir>/<subdir>` (p. ej. hooks/ o
|
|
12
|
+
* commands/) como rutas RELATIVAS a `projectRoot`, usando separadores `/` para
|
|
13
|
+
* que el manifest sea estable entre plataformas. Devuelve [] si el dir no existe.
|
|
14
|
+
* Recorre subdirectorios (los slash commands pueden estar anidados).
|
|
15
|
+
*/
|
|
16
|
+
export declare function listInstalledRelativeFiles(claudeDir: string, subdir: string, projectRoot: string): string[];
|
|
17
|
+
export declare function buildProjectYaml(result: Awaited<ReturnType<typeof runWizard>> | null, specialized?: string[]): string;
|
|
18
|
+
export declare function defaultAgentsForMode(mode: string): string[];
|
|
19
|
+
export declare function installCoreAgents(forgeRoot: string, destDir: string, activeAgents: string[], profiles: string[], force: boolean): void;
|
|
20
|
+
export declare function installHooks(forgeRoot: string, destDir: string, mode: string, force: boolean): void;
|
|
21
|
+
/**
|
|
22
|
+
* Escribe `.claude/settings.json`. Si el archivo ya existe (y es JSON válido),
|
|
23
|
+
* mezcla preservando keys externas (`env`, etc.) y permisos previos. Si no
|
|
24
|
+
* existe o no se puede parsear, escribe los settings generados tal cual.
|
|
25
|
+
* Respeta `force`: con `force=false` no toca un archivo existente.
|
|
26
|
+
*/
|
|
27
|
+
export declare function writeSettingsJson(path: string, language: string, mode: string, force: boolean): void;
|
|
28
|
+
export declare function installCommands(forgeRoot: string, destDir: string, force: boolean): void;
|
|
29
|
+
/**
|
|
30
|
+
* Scaffolds docs/specs/ (+ _template.md), docs/daily-notes/ and the
|
|
31
|
+
* .claude/architecture.rules file. Idempotent: never overwrites the spec
|
|
32
|
+
* template or architecture.rules once they exist. Shared by `forge init` and
|
|
33
|
+
* `forge adopt` so both lay down the same SDD scaffold.
|
|
34
|
+
*/
|
|
35
|
+
export declare function installSpecScaffold(forgeRoot: string, projectRoot: string, claudeDir: string, config: ProjectYaml): void;
|
|
36
|
+
/**
|
|
37
|
+
* Builds and saves the .forge/manifest.json for a claude-code install: tracks
|
|
38
|
+
* CLAUDE.md, settings.json, architecture.rules, all agents (active + compliance
|
|
39
|
+
* + specialized) and the installed hooks/commands. Shared by init and adopt.
|
|
40
|
+
*/
|
|
41
|
+
export declare function saveInstallManifest(projectRoot: string, claudeDir: string, runtime: string, allAgents: string[], specializedAgents: string[], forgeVersion: string): void;
|
|
3
42
|
export declare function init(args: string[]): Promise<number>;
|
|
4
43
|
//# sourceMappingURL=init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AA2C7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA4BlD,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGzE;AAiBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmBxD;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAa3G;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,GAAG,IAAI,EAAE,WAAW,GAAE,MAAM,EAAO,GAAG,MAAM,CAwDzH;AAYD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAI3D;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAsBtI;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAqBnG;AAiED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAiBpG;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAKxF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAaxH;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EACvD,SAAS,EAAE,MAAM,EAAE,EAAE,iBAAiB,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GACrE,IAAI,CAYN;AAmBD,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwN1D"}
|
package/dist/commands/init.js
CHANGED
|
@@ -61,7 +61,7 @@ Options:
|
|
|
61
61
|
// ---------------------------------------------------------------------------
|
|
62
62
|
// Helpers
|
|
63
63
|
// ---------------------------------------------------------------------------
|
|
64
|
-
function write(path, content, force) {
|
|
64
|
+
export function write(path, content, force) {
|
|
65
65
|
if (existsSync(path) && !force)
|
|
66
66
|
return;
|
|
67
67
|
writeFileSync(path, content, 'utf-8');
|
|
@@ -88,7 +88,7 @@ function copyDir(src, dest, force) {
|
|
|
88
88
|
* y devuelve los nombres cuyo frontmatter declara `tier: 3`. Sirve para poblar
|
|
89
89
|
* agents.specialized en project.yaml durante `forge init`.
|
|
90
90
|
*/
|
|
91
|
-
function detectTier3Agents(root) {
|
|
91
|
+
export function detectTier3Agents(root) {
|
|
92
92
|
const agentsDir = join(root, '.claude', 'agents');
|
|
93
93
|
if (!existsSync(agentsDir))
|
|
94
94
|
return [];
|
|
@@ -118,7 +118,7 @@ function detectTier3Agents(root) {
|
|
|
118
118
|
* que el manifest sea estable entre plataformas. Devuelve [] si el dir no existe.
|
|
119
119
|
* Recorre subdirectorios (los slash commands pueden estar anidados).
|
|
120
120
|
*/
|
|
121
|
-
function listInstalledRelativeFiles(claudeDir, subdir, projectRoot) {
|
|
121
|
+
export function listInstalledRelativeFiles(claudeDir, subdir, projectRoot) {
|
|
122
122
|
const baseDir = join(claudeDir, subdir);
|
|
123
123
|
if (!existsSync(baseDir))
|
|
124
124
|
return [];
|
|
@@ -204,14 +204,14 @@ function getAgentTech(agent) {
|
|
|
204
204
|
};
|
|
205
205
|
return map[agent] ?? 'specialized';
|
|
206
206
|
}
|
|
207
|
-
function defaultAgentsForMode(mode) {
|
|
207
|
+
export function defaultAgentsForMode(mode) {
|
|
208
208
|
if (mode === 'startup')
|
|
209
209
|
return ['orchestrator', 'backend-engineer', 'frontend-engineer'];
|
|
210
210
|
if (mode === 'enterprise')
|
|
211
211
|
return ['orchestrator', 'backend-engineer', 'frontend-engineer', 'test-engineer', 'docs-writer', 'compliance-reviewer', 'security-auditor'];
|
|
212
212
|
return ['orchestrator', 'backend-engineer', 'frontend-engineer', 'test-engineer', 'docs-writer'];
|
|
213
213
|
}
|
|
214
|
-
function installCoreAgents(forgeRoot, destDir, activeAgents, profiles, force) {
|
|
214
|
+
export function installCoreAgents(forgeRoot, destDir, activeAgents, profiles, force) {
|
|
215
215
|
mkdirSync(destDir, { recursive: true });
|
|
216
216
|
// Tier 2: profile agents first
|
|
217
217
|
for (const profile of profiles) {
|
|
@@ -232,7 +232,7 @@ function installCoreAgents(forgeRoot, destDir, activeAgents, profiles, force) {
|
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
|
-
function installHooks(forgeRoot, destDir, mode, force) {
|
|
235
|
+
export function installHooks(forgeRoot, destDir, mode, force) {
|
|
236
236
|
mkdirSync(destDir, { recursive: true });
|
|
237
237
|
const hooksDir = join(forgeRoot, 'core', 'hooks');
|
|
238
238
|
if (!existsSync(hooksDir))
|
|
@@ -318,7 +318,7 @@ function mergeSettings(generated, existing) {
|
|
|
318
318
|
* existe o no se puede parsear, escribe los settings generados tal cual.
|
|
319
319
|
* Respeta `force`: con `force=false` no toca un archivo existente.
|
|
320
320
|
*/
|
|
321
|
-
function writeSettingsJson(path, language, mode, force) {
|
|
321
|
+
export function writeSettingsJson(path, language, mode, force) {
|
|
322
322
|
const generated = buildSettings(language, mode);
|
|
323
323
|
if (existsSync(path)) {
|
|
324
324
|
if (!force)
|
|
@@ -338,13 +338,51 @@ function writeSettingsJson(path, language, mode, force) {
|
|
|
338
338
|
}
|
|
339
339
|
writeFileSync(path, JSON.stringify(generated, null, 2), 'utf-8');
|
|
340
340
|
}
|
|
341
|
-
function installCommands(forgeRoot, destDir, force) {
|
|
341
|
+
export function installCommands(forgeRoot, destDir, force) {
|
|
342
342
|
mkdirSync(destDir, { recursive: true });
|
|
343
343
|
const commandsDir = join(forgeRoot, 'adapters', 'claude-code', 'commands');
|
|
344
344
|
if (!existsSync(commandsDir))
|
|
345
345
|
return;
|
|
346
346
|
copyDir(commandsDir, destDir, force);
|
|
347
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Scaffolds docs/specs/ (+ _template.md), docs/daily-notes/ and the
|
|
350
|
+
* .claude/architecture.rules file. Idempotent: never overwrites the spec
|
|
351
|
+
* template or architecture.rules once they exist. Shared by `forge init` and
|
|
352
|
+
* `forge adopt` so both lay down the same SDD scaffold.
|
|
353
|
+
*/
|
|
354
|
+
export function installSpecScaffold(forgeRoot, projectRoot, claudeDir, config) {
|
|
355
|
+
mkdirSync(join(projectRoot, 'docs', 'specs'), { recursive: true });
|
|
356
|
+
mkdirSync(join(projectRoot, 'docs', 'daily-notes'), { recursive: true });
|
|
357
|
+
const specTemplateSrc = join(forgeRoot, 'core', 'templates', 'spec-template.md');
|
|
358
|
+
if (existsSync(specTemplateSrc)) {
|
|
359
|
+
copyFile(specTemplateSrc, join(projectRoot, 'docs', 'specs', '_template.md'), false);
|
|
360
|
+
}
|
|
361
|
+
const archRulesTemplate = join(forgeRoot, 'core', 'templates', 'claude-md', 'architecture.rules');
|
|
362
|
+
const archRulesDest = join(claudeDir, 'architecture.rules');
|
|
363
|
+
if (existsSync(archRulesTemplate) && !existsSync(archRulesDest)) {
|
|
364
|
+
const content = readFileSync(archRulesTemplate, 'utf-8').replace('<NOMBRE_PROYECTO>', config.project.name ?? 'Mi Proyecto');
|
|
365
|
+
writeFileSync(archRulesDest, content, 'utf-8');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Builds and saves the .forge/manifest.json for a claude-code install: tracks
|
|
370
|
+
* CLAUDE.md, settings.json, architecture.rules, all agents (active + compliance
|
|
371
|
+
* + specialized) and the installed hooks/commands. Shared by init and adopt.
|
|
372
|
+
*/
|
|
373
|
+
export function saveInstallManifest(projectRoot, claudeDir, runtime, allAgents, specializedAgents, forgeVersion) {
|
|
374
|
+
const installedFiles = [
|
|
375
|
+
'CLAUDE.md', '.claude/settings.json', '.claude/architecture.rules',
|
|
376
|
+
...allAgents.map(a => `.claude/agents/${a}.md`),
|
|
377
|
+
...specializedAgents.map(a => `.claude/agents/${a}.md`),
|
|
378
|
+
...listInstalledRelativeFiles(claudeDir, 'hooks', projectRoot),
|
|
379
|
+
...listInstalledRelativeFiles(claudeDir, 'commands', projectRoot),
|
|
380
|
+
];
|
|
381
|
+
const seen = new Set();
|
|
382
|
+
const uniqueFiles = installedFiles.filter(f => (seen.has(f) ? false : seen.add(f)));
|
|
383
|
+
const ts = new Date().toISOString();
|
|
384
|
+
saveManifest(projectRoot, buildManifest(runtime, uniqueFiles, projectRoot, forgeVersion, ts));
|
|
385
|
+
}
|
|
348
386
|
function installKiro(forgeRoot, projectRoot, config, force) {
|
|
349
387
|
const kiroDir = join(projectRoot, '.kiro', 'steering');
|
|
350
388
|
const hooksDir = join(projectRoot, '.kiro', 'hooks');
|
|
@@ -503,20 +541,7 @@ export async function init(args) {
|
|
|
503
541
|
{
|
|
504
542
|
title: 'docs/specs/ + architecture.rules',
|
|
505
543
|
tech: 'scaffold',
|
|
506
|
-
task: () =>
|
|
507
|
-
mkdirSync(join(projectRoot, 'docs', 'specs'), { recursive: true });
|
|
508
|
-
mkdirSync(join(projectRoot, 'docs', 'daily-notes'), { recursive: true });
|
|
509
|
-
const specTemplateSrc = join(forgeRoot, 'core', 'templates', 'spec-template.md');
|
|
510
|
-
if (existsSync(specTemplateSrc)) {
|
|
511
|
-
copyFile(specTemplateSrc, join(projectRoot, 'docs', 'specs', '_template.md'), false);
|
|
512
|
-
}
|
|
513
|
-
const archRulesTemplate = join(forgeRoot, 'core', 'templates', 'claude-md', 'architecture.rules');
|
|
514
|
-
const archRulesDest = join(claudeDir, 'architecture.rules');
|
|
515
|
-
if (existsSync(archRulesTemplate) && !existsSync(archRulesDest)) {
|
|
516
|
-
const content = readFileSync(archRulesTemplate, 'utf-8').replace('<NOMBRE_PROYECTO>', config.project.name ?? 'Mi Proyecto');
|
|
517
|
-
writeFileSync(archRulesDest, content, 'utf-8');
|
|
518
|
-
}
|
|
519
|
-
},
|
|
544
|
+
task: () => installSpecScaffold(forgeRoot, projectRoot, claudeDir, config),
|
|
520
545
|
},
|
|
521
546
|
// Knowledge base — only for projects that activate a wiki-* skill. Other
|
|
522
547
|
// projects don't get a wiki/ dir forced on them.
|
|
@@ -528,24 +553,7 @@ export async function init(args) {
|
|
|
528
553
|
{
|
|
529
554
|
title: '.forge/manifest.json',
|
|
530
555
|
tech: 'sha256 tracking',
|
|
531
|
-
task: () =>
|
|
532
|
-
const specializedAgents = config.agents?.specialized ?? [];
|
|
533
|
-
const installedFiles = [
|
|
534
|
-
'CLAUDE.md', '.claude/settings.json', '.claude/architecture.rules',
|
|
535
|
-
// Tier 1 (active) + compliance agents.
|
|
536
|
-
...allAgents.map(a => `.claude/agents/${a}.md`),
|
|
537
|
-
// Tier 3 (specialized) agents — must not be dropped from the manifest.
|
|
538
|
-
...specializedAgents.map(a => `.claude/agents/${a}.md`),
|
|
539
|
-
// Installed guardrail hooks and slash commands (if present on disk).
|
|
540
|
-
...listInstalledRelativeFiles(claudeDir, 'hooks', projectRoot),
|
|
541
|
-
...listInstalledRelativeFiles(claudeDir, 'commands', projectRoot),
|
|
542
|
-
];
|
|
543
|
-
// De-dup while preserving order (an agent could appear in both lists).
|
|
544
|
-
const seen = new Set();
|
|
545
|
-
const uniqueFiles = installedFiles.filter(f => (seen.has(f) ? false : seen.add(f)));
|
|
546
|
-
const ts = new Date().toISOString();
|
|
547
|
-
saveManifest(projectRoot, buildManifest(runtime, uniqueFiles, projectRoot, VERSION, ts));
|
|
548
|
-
},
|
|
556
|
+
task: () => saveInstallManifest(projectRoot, claudeDir, runtime, allAgents, config.agents?.specialized ?? [], VERSION),
|
|
549
557
|
},
|
|
550
558
|
]);
|
|
551
559
|
}
|