argos-harness 0.1.0 → 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/assets/hooks/argos-guard-destructive.sh +1 -1
- package/assets/managed/disciplina-skills.md +11 -0
- package/assets/managed/formato-respuesta.md +2 -2
- package/assets/managed/identidad.md +7 -7
- package/assets/managed/operaciones-seguras.md +6 -6
- package/assets/output-styles/argos.md +12 -12
- package/dist/commands/adopt.d.ts +41 -1
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +243 -6
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +36 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +38 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +222 -59
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/remove.d.ts +24 -0
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +94 -4
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/workspace.d.ts +32 -0
- package/dist/commands/workspace.d.ts.map +1 -1
- package/dist/commands/workspace.js +97 -3
- package/dist/commands/workspace.js.map +1 -1
- package/dist/lib/assets.d.ts +5 -3
- package/dist/lib/assets.d.ts.map +1 -1
- package/dist/lib/assets.js +5 -2
- package/dist/lib/assets.js.map +1 -1
- package/dist/lib/prompter.d.ts +63 -0
- package/dist/lib/prompter.d.ts.map +1 -0
- package/dist/lib/prompter.js +30 -0
- package/dist/lib/prompter.js.map +1 -0
- package/dist/lib/settings-merge.d.ts +78 -0
- package/dist/lib/settings-merge.d.ts.map +1 -1
- package/dist/lib/settings-merge.js +204 -0
- package/dist/lib/settings-merge.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -8,7 +8,8 @@ import { createBackup } from "../lib/backup.js";
|
|
|
8
8
|
import { injectBlock, listBlocks } from "../lib/markers.js";
|
|
9
9
|
import { hasArgosFileMarker, writeManagedFile, writeManagedShellFile } from "../lib/managed-files.js";
|
|
10
10
|
import { resolveArgosHome, resolveClaudeDir } from "../lib/paths.js";
|
|
11
|
-
import { mergeHooksIntoSettings } from "../lib/settings-merge.js";
|
|
11
|
+
import { applyOutputStylePolicy, isNavoriOutputStyle, mergeHooksIntoSettings } from "../lib/settings-merge.js";
|
|
12
|
+
import { isInteractive, clackPrompter } from "../lib/prompter.js";
|
|
12
13
|
import { readCliVersion } from "../lib/version.js";
|
|
13
14
|
/**
|
|
14
15
|
* Ids (basenames under assets/hooks/) of the 2 global hooks argos init
|
|
@@ -86,6 +87,8 @@ function errorMessage(err) {
|
|
|
86
87
|
* filesystem — no process.exit, no console output.
|
|
87
88
|
*/ export function runInit(options = {}) {
|
|
88
89
|
const language = options.language ?? "es";
|
|
90
|
+
const installAgents = options.installAgents ?? true;
|
|
91
|
+
const installHooks = options.installHooks ?? true;
|
|
89
92
|
const version = readCliVersion();
|
|
90
93
|
const claudeDir = resolveClaudeDir();
|
|
91
94
|
const assetsDir = resolveAssetsDir();
|
|
@@ -117,7 +120,7 @@ function errorMessage(err) {
|
|
|
117
120
|
exitCode: 1
|
|
118
121
|
};
|
|
119
122
|
}
|
|
120
|
-
// 1. CLAUDE.md —
|
|
123
|
+
// 1. CLAUDE.md — MANAGED_BLOCK_IDS.length managed blocks, in order.
|
|
121
124
|
const claudeMdPath = join(claudeDir, "CLAUDE.md");
|
|
122
125
|
let claudeMd = existsSync(claudeMdPath) ? readFileSync(claudeMdPath, "utf-8") : "";
|
|
123
126
|
const blockResults = [];
|
|
@@ -147,16 +150,19 @@ function errorMessage(err) {
|
|
|
147
150
|
detail
|
|
148
151
|
});
|
|
149
152
|
}
|
|
150
|
-
// 2. Full-file assets: output-style, agents
|
|
153
|
+
// 2. Full-file assets: output-style always, agents gated by the
|
|
154
|
+
// `installAgents` toggle (default true; the wizard's "agentes sí/no"
|
|
155
|
+
// step — spec 0004). Skills below are NEVER gated: they load on-demand
|
|
156
|
+
// and trimming the set breaks the arsenal.
|
|
151
157
|
const fullFiles = [
|
|
152
158
|
[
|
|
153
159
|
"output-styles",
|
|
154
160
|
"argos.md"
|
|
155
161
|
],
|
|
156
|
-
...listAgentIds(assetsDir).map((id)=>[
|
|
162
|
+
...installAgents ? listAgentIds(assetsDir).map((id)=>[
|
|
157
163
|
"agents",
|
|
158
164
|
`${id}.md`
|
|
159
|
-
])
|
|
165
|
+
]) : []
|
|
160
166
|
];
|
|
161
167
|
for (const relPath of fullFiles){
|
|
162
168
|
const source = readAsset(assetsDir, ...relPath);
|
|
@@ -219,62 +225,90 @@ function errorMessage(err) {
|
|
|
219
225
|
// write threw must NEVER get a settings.json entry (see 2c below): a
|
|
220
226
|
// dangling PreToolUse entry pointing at a script that isn't there hard-
|
|
221
227
|
// blocks every subsequent Bash call.
|
|
228
|
+
//
|
|
229
|
+
// Gated by the `installHooks` toggle (default true; the wizard's "hooks
|
|
230
|
+
// sí/no" step — spec 0004): when disabled, this run neither writes nor
|
|
231
|
+
// touches any pre-existing hook script/settings.json entry — a full
|
|
232
|
+
// uninstall of previously-installed hooks is `argos remove`'s job, not a
|
|
233
|
+
// side effect of toggling this flag off on a later `init` run.
|
|
222
234
|
const hookWriteFailed = new Map();
|
|
223
|
-
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
if (installHooks) {
|
|
236
|
+
for (const id of HOOK_IDS){
|
|
237
|
+
const relPath = [
|
|
238
|
+
"hooks",
|
|
239
|
+
`${id}.sh`
|
|
240
|
+
];
|
|
241
|
+
const source = readAsset(assetsDir, ...relPath);
|
|
242
|
+
const dest = join(claudeDir, ...relPath);
|
|
243
|
+
try {
|
|
244
|
+
const status = writeManagedShellFile(dest, source, version);
|
|
245
|
+
rows.push({
|
|
246
|
+
path: join(...relPath),
|
|
247
|
+
status
|
|
248
|
+
});
|
|
249
|
+
hookWriteFailed.set(id, false);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
rows.push({
|
|
252
|
+
path: join(...relPath),
|
|
253
|
+
status: "error",
|
|
254
|
+
detail: errorMessage(err)
|
|
255
|
+
});
|
|
256
|
+
hookWriteFailed.set(id, true);
|
|
257
|
+
}
|
|
244
258
|
}
|
|
259
|
+
// 2c. settings.json — surgical merge of the 2 PreToolUse hook entries.
|
|
260
|
+
// Only writes/updates entries whose command targets one of the 2 scripts
|
|
261
|
+
// above; every other key and hook in the user's settings.json is left
|
|
262
|
+
// untouched (see lib/settings-merge.ts). Only hooks whose script write
|
|
263
|
+
// actually succeeded get an entry built for them at all.
|
|
264
|
+
const settingsPath = join(claudeDir, "settings.json");
|
|
265
|
+
const allHookSpecs = {
|
|
266
|
+
"argos-guard-destructive": {
|
|
267
|
+
scriptPath: join(claudeDir, "hooks", "argos-guard-destructive.sh"),
|
|
268
|
+
matcher: "Bash",
|
|
269
|
+
timeout: 10,
|
|
270
|
+
statusMessage: "argos: guard-destructive"
|
|
271
|
+
},
|
|
272
|
+
"argos-quality-gate": {
|
|
273
|
+
scriptPath: join(claudeDir, "hooks", "argos-quality-gate.sh"),
|
|
274
|
+
matcher: "Bash",
|
|
275
|
+
timeout: QUALITY_GATE_OUTER_TIMEOUT_SECONDS,
|
|
276
|
+
statusMessage: "argos: quality-gate"
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
const hookSpecs = HOOK_IDS.filter((id)=>!hookWriteFailed.get(id)).map((id)=>allHookSpecs[id]);
|
|
280
|
+
// Any hook whose write just failed also gets its (possibly pre-existing,
|
|
281
|
+
// from an earlier successful run) settings.json entry stripped out — a
|
|
282
|
+
// script that's gone or broken must never be left with a live entry.
|
|
283
|
+
const failedScriptPaths = HOOK_IDS.filter((id)=>hookWriteFailed.get(id)).map((id)=>allHookSpecs[id].scriptPath);
|
|
284
|
+
const mergeResult = mergeHooksIntoSettings(settingsPath, hookSpecs, {
|
|
285
|
+
removeScriptPaths: failedScriptPaths
|
|
286
|
+
});
|
|
287
|
+
rows.push({
|
|
288
|
+
path: "settings.json",
|
|
289
|
+
status: mergeResult.status,
|
|
290
|
+
detail: mergeResult.detail
|
|
291
|
+
});
|
|
245
292
|
}
|
|
246
|
-
//
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
timeout: 10,
|
|
257
|
-
statusMessage: "argos: guard-destructive"
|
|
258
|
-
},
|
|
259
|
-
"argos-quality-gate": {
|
|
260
|
-
scriptPath: join(claudeDir, "hooks", "argos-quality-gate.sh"),
|
|
261
|
-
matcher: "Bash",
|
|
262
|
-
timeout: QUALITY_GATE_OUTER_TIMEOUT_SECONDS,
|
|
263
|
-
statusMessage: "argos: quality-gate"
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
const hookSpecs = HOOK_IDS.filter((id)=>!hookWriteFailed.get(id)).map((id)=>allHookSpecs[id]);
|
|
267
|
-
// Any hook whose write just failed also gets its (possibly pre-existing,
|
|
268
|
-
// from an earlier successful run) settings.json entry stripped out — a
|
|
269
|
-
// script that's gone or broken must never be left with a live entry.
|
|
270
|
-
const failedScriptPaths = HOOK_IDS.filter((id)=>hookWriteFailed.get(id)).map((id)=>allHookSpecs[id].scriptPath);
|
|
271
|
-
const mergeResult = mergeHooksIntoSettings(settingsPath, hookSpecs, {
|
|
272
|
-
removeScriptPaths: failedScriptPaths
|
|
293
|
+
// 2d. Voice activation (spec 0004 "Activación de la voz"):
|
|
294
|
+
// settings.json.outputStyle. Absent → set to "Argos". Matching the
|
|
295
|
+
// predecessor harness's voice (navori) → takeover per
|
|
296
|
+
// `takeoverNavoriVoice` (default true, i.e. unconditional replace under
|
|
297
|
+
// --yes/no-TTY; the interactive wizard passes `false` when the user
|
|
298
|
+
// declines). Any other value → never touched. Reported separately from
|
|
299
|
+
// the hooks settings.json row above so a takeover/foreign-voice detail is
|
|
300
|
+
// never conflated with the hooks merge outcome.
|
|
301
|
+
const outputStyleResult = applyOutputStylePolicy(join(claudeDir, "settings.json"), {
|
|
302
|
+
takeoverNavori: options.takeoverNavoriVoice ?? true
|
|
273
303
|
});
|
|
304
|
+
// "untouched" (a foreign non-navori voice, or a declined navori takeover)
|
|
305
|
+
// maps to the same "skipped-foreign" row status used elsewhere for
|
|
306
|
+
// "found something not ours, left it byte-identical".
|
|
307
|
+
const outputStyleRowStatus = outputStyleResult.status === "untouched" ? "skipped-foreign" : outputStyleResult.status;
|
|
274
308
|
rows.push({
|
|
275
|
-
path: "settings.json",
|
|
276
|
-
status:
|
|
277
|
-
detail:
|
|
309
|
+
path: "settings.json#outputStyle",
|
|
310
|
+
status: outputStyleRowStatus,
|
|
311
|
+
detail: outputStyleResult.detail
|
|
278
312
|
});
|
|
279
313
|
// 3. ~/.argos/global.json
|
|
280
314
|
const argosHome = resolveArgosHome();
|
|
@@ -309,6 +343,129 @@ function errorMessage(err) {
|
|
|
309
343
|
backupPath
|
|
310
344
|
};
|
|
311
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* A cancelled wizard's report: identical shape to a run that touched
|
|
348
|
+
* nothing. `exitCode: 1` — a cancel is neither a successful write nor
|
|
349
|
+
* silently indistinguishable from one by exit code alone (matches
|
|
350
|
+
* `runWorkspaceLinkInteractive`'s convention for its own cancel paths).
|
|
351
|
+
*/ function cancelledInitReport() {
|
|
352
|
+
return {
|
|
353
|
+
rows: [],
|
|
354
|
+
summary: "argos init: cancelado — no se tocó nada.",
|
|
355
|
+
exitCode: 1
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Read-only peek at `settings.json.outputStyle`, used only to decide whether
|
|
360
|
+
* the interactive wizard needs to ask about a navori takeover. Never throws,
|
|
361
|
+
* never writes — any missing file, unreadable file, or invalid JSON just
|
|
362
|
+
* reads as "no value" (`undefined`), which is safely a non-match for
|
|
363
|
+
* `isNavoriOutputStyle`. The actual write happens inside `runInit` via
|
|
364
|
+
* `applyOutputStylePolicy`, which re-does this read itself under its own
|
|
365
|
+
* mtime-guarded contract.
|
|
366
|
+
*/ function peekOutputStyleValue(settingsPath) {
|
|
367
|
+
if (!existsSync(settingsPath)) return undefined;
|
|
368
|
+
try {
|
|
369
|
+
const parsed = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
370
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return undefined;
|
|
371
|
+
return parsed.outputStyle;
|
|
372
|
+
} catch {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Interactive layer over `runInit` (spec 0004 F5 "argos init"). A pure
|
|
378
|
+
* additive wrapper — the core `runInit` never changes behavior or contract.
|
|
379
|
+
* Without a real TTY, or with `--yes`, this delegates to `runInit(options)`
|
|
380
|
+
* unchanged: no prompt library call is ever reached on that path. With a
|
|
381
|
+
* TTY, it runs a 3-step wizard (language, agents/hooks toggles, summary +
|
|
382
|
+
* final confirm) before calling `runInit` with the gathered choices;
|
|
383
|
+
* cancelling at any step touches nothing and returns a no-op report.
|
|
384
|
+
*/ export async function runInitInteractive(options = {}) {
|
|
385
|
+
if (!isInteractive({
|
|
386
|
+
yes: options.yes
|
|
387
|
+
})) {
|
|
388
|
+
return runInit(options);
|
|
389
|
+
}
|
|
390
|
+
const prompter = options.prompter ?? clackPrompter;
|
|
391
|
+
prompter.intro("argos init — instalación interactiva del motor");
|
|
392
|
+
const language = await prompter.select({
|
|
393
|
+
message: "Idioma del motor",
|
|
394
|
+
options: [
|
|
395
|
+
{
|
|
396
|
+
value: "es",
|
|
397
|
+
label: "es — español"
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
value: "en",
|
|
401
|
+
label: "en — English"
|
|
402
|
+
}
|
|
403
|
+
],
|
|
404
|
+
initialValue: options.language ?? "es"
|
|
405
|
+
});
|
|
406
|
+
if (prompter.isCancel(language)) {
|
|
407
|
+
prompter.cancel("argos init cancelado — no se tocó nada.");
|
|
408
|
+
return cancelledInitReport();
|
|
409
|
+
}
|
|
410
|
+
const installAgents = await prompter.confirm({
|
|
411
|
+
message: "¿Instalar los agentes del motor (agents/)?",
|
|
412
|
+
initialValue: options.installAgents ?? true
|
|
413
|
+
});
|
|
414
|
+
if (prompter.isCancel(installAgents)) {
|
|
415
|
+
prompter.cancel("argos init cancelado — no se tocó nada.");
|
|
416
|
+
return cancelledInitReport();
|
|
417
|
+
}
|
|
418
|
+
const installHooks = await prompter.confirm({
|
|
419
|
+
message: "¿Instalar los hooks globales (guard-destructive + quality-gate)?",
|
|
420
|
+
initialValue: options.installHooks ?? true
|
|
421
|
+
});
|
|
422
|
+
if (prompter.isCancel(installHooks)) {
|
|
423
|
+
prompter.cancel("argos init cancelado — no se tocó nada.");
|
|
424
|
+
return cancelledInitReport();
|
|
425
|
+
}
|
|
426
|
+
const claudeDir = resolveClaudeDir();
|
|
427
|
+
// Voice activation (spec 0004): if the current settings.json.outputStyle
|
|
428
|
+
// matches the predecessor harness's voice, ask before taking it over —
|
|
429
|
+
// this peek is read-only and never writes; the actual takeover only
|
|
430
|
+
// happens inside runInit below, once the user has confirmed everything.
|
|
431
|
+
let takeoverNavoriVoice = options.takeoverNavoriVoice ?? true;
|
|
432
|
+
const currentOutputStyle = peekOutputStyleValue(join(claudeDir, "settings.json"));
|
|
433
|
+
if (isNavoriOutputStyle(currentOutputStyle)) {
|
|
434
|
+
const takeover = await prompter.confirm({
|
|
435
|
+
message: `settings.json.outputStyle apunta a la voz del harness predecesor ('${String(currentOutputStyle)}') — ¿reemplazarla por Argos?`,
|
|
436
|
+
initialValue: true
|
|
437
|
+
});
|
|
438
|
+
if (prompter.isCancel(takeover)) {
|
|
439
|
+
prompter.cancel("argos init cancelado — no se tocó nada.");
|
|
440
|
+
return cancelledInitReport();
|
|
441
|
+
}
|
|
442
|
+
takeoverNavoriVoice = takeover;
|
|
443
|
+
}
|
|
444
|
+
prompter.note([
|
|
445
|
+
`idioma: ${language}`,
|
|
446
|
+
`agentes: ${installAgents ? "sí" : "no"}`,
|
|
447
|
+
"hooks: " + (installHooks ? "sí" : "no"),
|
|
448
|
+
"skills: sí (siempre — cargan on-demand)",
|
|
449
|
+
`destino: ${claudeDir}`,
|
|
450
|
+
"se hace un backup antes de escribir nada"
|
|
451
|
+
].join("\n"), "Resumen");
|
|
452
|
+
const proceed = await prompter.confirm({
|
|
453
|
+
message: "¿Proceder a escribir estos cambios?",
|
|
454
|
+
initialValue: true
|
|
455
|
+
});
|
|
456
|
+
if (prompter.isCancel(proceed) || !proceed) {
|
|
457
|
+
prompter.cancel("argos init cancelado — no se tocó nada.");
|
|
458
|
+
return cancelledInitReport();
|
|
459
|
+
}
|
|
460
|
+
const report = runInit({
|
|
461
|
+
language,
|
|
462
|
+
installAgents,
|
|
463
|
+
installHooks,
|
|
464
|
+
takeoverNavoriVoice
|
|
465
|
+
});
|
|
466
|
+
prompter.outro(report.summary);
|
|
467
|
+
return report;
|
|
468
|
+
}
|
|
312
469
|
export const initCommand = defineCommand({
|
|
313
470
|
meta: {
|
|
314
471
|
name: "init",
|
|
@@ -323,11 +480,17 @@ export const initCommand = defineCommand({
|
|
|
323
480
|
],
|
|
324
481
|
default: "es",
|
|
325
482
|
description: "Idioma del motor (global.json)."
|
|
483
|
+
},
|
|
484
|
+
yes: {
|
|
485
|
+
type: "boolean",
|
|
486
|
+
default: false,
|
|
487
|
+
description: "Fuerza modo no interactivo aunque haya una TTY real (defaults + flags, sin wizard)."
|
|
326
488
|
}
|
|
327
489
|
},
|
|
328
|
-
run ({ args }) {
|
|
329
|
-
const report =
|
|
330
|
-
language: args.language
|
|
490
|
+
async run ({ args }) {
|
|
491
|
+
const report = await runInitInteractive({
|
|
492
|
+
language: args.language,
|
|
493
|
+
yes: Boolean(args.yes)
|
|
331
494
|
});
|
|
332
495
|
const colorize = (status)=>{
|
|
333
496
|
const padded = status.padEnd(18);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport pc from \"picocolors\";\nimport {\n listAgentIds,\n listSkillFiles,\n listSkillIds,\n MANAGED_BLOCK_IDS,\n readAsset,\n resolveAssetsDir,\n} from \"../lib/assets.js\";\nimport { writeFileAtomic } from \"../lib/atomic-write.js\";\nimport { createBackup } from \"../lib/backup.js\";\nimport { injectBlock, listBlocks } from \"../lib/markers.js\";\nimport {\n type FileStatus,\n hasArgosFileMarker,\n writeManagedFile,\n writeManagedShellFile,\n} from \"../lib/managed-files.js\";\nimport { resolveArgosHome, resolveClaudeDir } from \"../lib/paths.js\";\nimport { type ArgosHookSpec, mergeHooksIntoSettings } from \"../lib/settings-merge.js\";\nimport { readCliVersion } from \"../lib/version.js\";\n\n/**\n * Ids (basenames under assets/hooks/) of the 2 global hooks argos init\n * installs. See spec 0003 \"Hooks globales parametrizados\".\n */\nconst HOOK_IDS = [\"argos-guard-destructive\", \"argos-quality-gate\"] as const;\n\n/**\n * Outer Claude Code hook timeout (seconds) for argos-quality-gate.sh. Fixed\n * rather than derived from $ARGOS_GATE_TIMEOUT_MS: that env var is read\n * inside the hook at COMMIT time (whatever env the Claude Code session has),\n * not at `argos init` time, so there's nothing meaningful to read here. 600s\n * comfortably covers the hook's own default inner bound (300s) with 2x\n * headroom; a repo whose gate legitimately needs longer than ~590s needs to\n * bump this constant (and rerun `argos init`) alongside its own\n * $ARGOS_GATE_TIMEOUT_MS — not automated in v1.\n */\nconst QUALITY_GATE_OUTER_TIMEOUT_SECONDS = 600;\n\nexport type InitRowStatus = FileStatus | \"error\";\n\nexport interface InitRow {\n path: string;\n status: InitRowStatus;\n detail?: string;\n}\n\nexport interface InitOptions {\n language?: \"es\" | \"en\";\n}\n\nexport interface InitReport {\n rows: InitRow[];\n summary: string;\n exitCode: 0 | 1;\n backupPath?: string;\n}\n\nconst STATUS_COUNT_ORDER: InitRowStatus[] = [\"created\", \"updated\", \"unchanged\", \"skipped-foreign\", \"error\"];\n\nfunction summarize(rows: InitRow[]): string {\n const counts: Record<InitRowStatus, number> = {\n created: 0,\n updated: 0,\n unchanged: 0,\n \"skipped-foreign\": 0,\n error: 0,\n };\n for (const row of rows) counts[row.status]++;\n\n const parts = STATUS_COUNT_ORDER.filter((s) => counts[s] > 0).map((s) => `${counts[s]} ${s}`);\n return `argos init: ${parts.join(\", \")}.`;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Write a plain (unmarked) supporting file belonging to an already\n * ownership-checked skill directory — e.g. `references/core.md`,\n * `phases/0-product.md`. Unlike `writeManagedFile`, this never carries or\n * checks the `argos:file` marker itself: ownership for the whole skill\n * directory is decided once, up front, from its `SKILL.md` (see the skills\n * loop in `runInit`), so per-file marker bookkeeping here would be\n * redundant. Reports the same created/updated/unchanged statuses.\n */\nfunction writePlainFile(destPath: string, sourceContent: string): FileStatus {\n if (!existsSync(destPath)) {\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, sourceContent);\n return \"created\";\n }\n\n const current = readFileSync(destPath, \"utf-8\");\n if (current === sourceContent) return \"unchanged\";\n\n writeFileAtomic(destPath, sourceContent);\n return \"updated\";\n}\n\n/** Inject one managed CLAUDE.md block, reporting created/updated/unchanged. */\nfunction injectAndReport(claudeMd: string, id: string, version: string, content: string) {\n const hadBlock = listBlocks(claudeMd).some((b) => b.id === id);\n const after = injectBlock(claudeMd, id, version, content);\n const status: FileStatus = after === claudeMd ? \"unchanged\" : hadBlock ? \"updated\" : \"created\";\n return { claudeMd: after, status };\n}\n\n/**\n * Core, testable implementation of `argos init`: installs the Argos engine\n * (CLAUDE.md managed blocks + agents/skills/output-style full files +\n * `~/.argos/global.json`) into `resolveClaudeDir()`. Pure function of the\n * filesystem — no process.exit, no console output.\n */\nexport function runInit(options: InitOptions = {}): InitReport {\n const language = options.language ?? \"es\";\n const version = readCliVersion();\n const claudeDir = resolveClaudeDir();\n const assetsDir = resolveAssetsDir();\n const rows: InitRow[] = [];\n\n // Backup everything Argos is about to touch, before any write happens. A\n // failed backup means we have no safety net for what's about to be\n // mutated, so it aborts the whole run right here — every subsequent\n // mutation step is skipped, nothing gets touched.\n let backupPath: string | undefined;\n try {\n backupPath = createBackup(claudeDir, [\"CLAUDE.md\", \"agents\", \"skills\", \"output-styles\", \"hooks\", \"settings.json\"]);\n } catch (err) {\n const detail = errorMessage(err);\n rows.push({ path: \"backup\", status: \"error\", detail });\n return { rows, summary: `backup falló — no se tocó nada (${detail}).`, exitCode: 1 };\n }\n\n // 1. CLAUDE.md — 5 managed blocks, in order.\n const claudeMdPath = join(claudeDir, \"CLAUDE.md\");\n let claudeMd = existsSync(claudeMdPath) ? readFileSync(claudeMdPath, \"utf-8\") : \"\";\n const blockResults: { id: string; status: FileStatus }[] = [];\n for (const id of MANAGED_BLOCK_IDS) {\n const content = readAsset(assetsDir, \"managed\", `${id}.md`).replace(/\\n$/, \"\");\n const result = injectAndReport(claudeMd, id, version, content);\n claudeMd = result.claudeMd;\n blockResults.push({ id, status: result.status });\n }\n try {\n mkdirSync(claudeDir, { recursive: true });\n writeFileAtomic(claudeMdPath, claudeMd);\n for (const b of blockResults) rows.push({ path: `CLAUDE.md#${b.id}`, status: b.status });\n } catch (err) {\n const detail = errorMessage(err);\n for (const id of MANAGED_BLOCK_IDS) rows.push({ path: `CLAUDE.md#${id}`, status: \"error\", detail });\n }\n\n // 2. Full-file assets: output-style, agents.\n const fullFiles: string[][] = [\n [\"output-styles\", \"argos.md\"],\n ...listAgentIds(assetsDir).map((id) => [\"agents\", `${id}.md`]),\n ];\n for (const relPath of fullFiles) {\n const source = readAsset(assetsDir, ...relPath);\n const dest = join(claudeDir, ...relPath);\n try {\n const status = writeManagedFile(dest, source, version);\n rows.push({ path: join(...relPath), status });\n } catch (err) {\n rows.push({ path: join(...relPath), status: \"error\", detail: errorMessage(err) });\n }\n }\n\n // 2a. Skills: each skill directory (SKILL.md plus any `references/`,\n // `phases/`, `assets/`, etc. it ships) is installed as a single unit.\n // Ownership sentinel is SKILL.md's `argos:file` marker:\n // - SKILL.md absent, or present WITH the marker → install/update every\n // file the skill ships.\n // - SKILL.md present WITHOUT the marker (foreign/user-modified) → skip\n // every file under that skill dir, untouched — same policy as a single\n // foreign full-file asset above, extended to the whole directory.\n for (const skillId of listSkillIds(assetsDir)) {\n const skillMdDest = join(claudeDir, \"skills\", skillId, \"SKILL.md\");\n const isForeignSkill = existsSync(skillMdDest) && !hasArgosFileMarker(readFileSync(skillMdDest, \"utf-8\"));\n\n for (const relFile of listSkillFiles(assetsDir, skillId)) {\n const relParts = relFile.split(\"/\");\n const relPath = join(\"skills\", skillId, ...relParts);\n\n if (isForeignSkill) {\n rows.push({ path: relPath, status: \"skipped-foreign\" });\n continue;\n }\n\n const source = readAsset(assetsDir, \"skills\", skillId, ...relParts);\n const dest = join(claudeDir, \"skills\", skillId, ...relParts);\n try {\n const status = relFile === \"SKILL.md\" ? writeManagedFile(dest, source, version) : writePlainFile(dest, source);\n rows.push({ path: relPath, status });\n } catch (err) {\n rows.push({ path: relPath, status: \"error\", detail: errorMessage(err) });\n }\n }\n }\n\n // 2b. Global hooks: full-file shell assets, own shell-comment marker,\n // chmod +x. Same skipped-foreign policy as the full-file assets above.\n // Track which hooks actually landed on disk successfully — a hook whose\n // write threw must NEVER get a settings.json entry (see 2c below): a\n // dangling PreToolUse entry pointing at a script that isn't there hard-\n // blocks every subsequent Bash call.\n const hookWriteFailed = new Map<(typeof HOOK_IDS)[number], boolean>();\n for (const id of HOOK_IDS) {\n const relPath = [\"hooks\", `${id}.sh`];\n const source = readAsset(assetsDir, ...relPath);\n const dest = join(claudeDir, ...relPath);\n try {\n const status = writeManagedShellFile(dest, source, version);\n rows.push({ path: join(...relPath), status });\n hookWriteFailed.set(id, false);\n } catch (err) {\n rows.push({ path: join(...relPath), status: \"error\", detail: errorMessage(err) });\n hookWriteFailed.set(id, true);\n }\n }\n\n // 2c. settings.json — surgical merge of the 2 PreToolUse hook entries.\n // Only writes/updates entries whose command targets one of the 2 scripts\n // above; every other key and hook in the user's settings.json is left\n // untouched (see lib/settings-merge.ts). Only hooks whose script write\n // actually succeeded get an entry built for them at all.\n const settingsPath = join(claudeDir, \"settings.json\");\n const allHookSpecs: Record<(typeof HOOK_IDS)[number], ArgosHookSpec> = {\n \"argos-guard-destructive\": {\n scriptPath: join(claudeDir, \"hooks\", \"argos-guard-destructive.sh\"),\n matcher: \"Bash\",\n timeout: 10,\n statusMessage: \"argos: guard-destructive\",\n },\n \"argos-quality-gate\": {\n scriptPath: join(claudeDir, \"hooks\", \"argos-quality-gate.sh\"),\n matcher: \"Bash\",\n timeout: QUALITY_GATE_OUTER_TIMEOUT_SECONDS,\n statusMessage: \"argos: quality-gate\",\n },\n };\n const hookSpecs: ArgosHookSpec[] = HOOK_IDS.filter((id) => !hookWriteFailed.get(id)).map((id) => allHookSpecs[id]);\n // Any hook whose write just failed also gets its (possibly pre-existing,\n // from an earlier successful run) settings.json entry stripped out — a\n // script that's gone or broken must never be left with a live entry.\n const failedScriptPaths = HOOK_IDS.filter((id) => hookWriteFailed.get(id)).map((id) => allHookSpecs[id].scriptPath);\n const mergeResult = mergeHooksIntoSettings(settingsPath, hookSpecs, { removeScriptPaths: failedScriptPaths });\n rows.push({ path: \"settings.json\", status: mergeResult.status, detail: mergeResult.detail });\n\n // 3. ~/.argos/global.json\n const argosHome = resolveArgosHome();\n const globalJsonPath = join(argosHome, \"global.json\");\n const globalJsonContent = `${JSON.stringify({ version, language }, null, 2)}\\n`;\n try {\n const globalJsonExisted = existsSync(globalJsonPath);\n const globalJsonStatus: FileStatus = !globalJsonExisted\n ? \"created\"\n : readFileSync(globalJsonPath, \"utf-8\") === globalJsonContent\n ? \"unchanged\"\n : \"updated\";\n mkdirSync(argosHome, { recursive: true });\n writeFileSync(globalJsonPath, globalJsonContent, \"utf-8\");\n rows.push({ path: \"global.json\", status: globalJsonStatus });\n } catch (err) {\n rows.push({ path: \"global.json\", status: \"error\", detail: errorMessage(err) });\n }\n\n const exitCode: 0 | 1 = rows.some((r) => r.status === \"error\") ? 1 : 0;\n return { rows, summary: summarize(rows), exitCode, backupPath };\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: \"init\",\n description: \"Install the Argos engine into the global Claude Code home.\",\n },\n args: {\n language: {\n type: \"enum\",\n options: [\"es\", \"en\"],\n default: \"es\",\n description: \"Idioma del motor (global.json).\",\n },\n },\n run({ args }) {\n const report = runInit({ language: args.language as \"es\" | \"en\" });\n\n const colorize = (status: InitRowStatus): string => {\n const padded = status.padEnd(18);\n switch (status) {\n case \"skipped-foreign\":\n return pc.yellow(padded);\n case \"created\":\n return pc.green(padded);\n case \"updated\":\n return pc.cyan(padded);\n case \"error\":\n return pc.red(padded);\n default:\n return pc.dim(padded);\n }\n };\n for (const row of report.rows) {\n const suffix = row.detail ? ` (${row.detail})` : \"\";\n console.log(`${colorize(row.status)} ${row.path}${suffix}`);\n }\n console.log(\"\");\n console.log(report.summary);\n if (report.backupPath) console.log(`backup en ${report.backupPath}`);\n\n process.exit(report.exitCode);\n },\n});\n"],"names":["defineCommand","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","pc","listAgentIds","listSkillFiles","listSkillIds","MANAGED_BLOCK_IDS","readAsset","resolveAssetsDir","writeFileAtomic","createBackup","injectBlock","listBlocks","hasArgosFileMarker","writeManagedFile","writeManagedShellFile","resolveArgosHome","resolveClaudeDir","mergeHooksIntoSettings","readCliVersion","HOOK_IDS","QUALITY_GATE_OUTER_TIMEOUT_SECONDS","STATUS_COUNT_ORDER","summarize","rows","counts","created","updated","unchanged","error","row","status","parts","filter","s","map","errorMessage","err","Error","message","String","writePlainFile","destPath","sourceContent","recursive","current","injectAndReport","claudeMd","id","version","content","hadBlock","some","b","after","runInit","options","language","claudeDir","assetsDir","backupPath","detail","push","path","summary","exitCode","claudeMdPath","blockResults","replace","result","fullFiles","relPath","source","dest","skillId","skillMdDest","isForeignSkill","relFile","relParts","split","hookWriteFailed","Map","set","settingsPath","allHookSpecs","scriptPath","matcher","timeout","statusMessage","hookSpecs","get","failedScriptPaths","mergeResult","removeScriptPaths","argosHome","globalJsonPath","globalJsonContent","JSON","stringify","globalJsonExisted","globalJsonStatus","r","initCommand","meta","name","description","args","type","default","run","report","colorize","padded","padEnd","yellow","green","cyan","red","dim","suffix","console","log","process","exit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport pc from \"picocolors\";\nimport {\n listAgentIds,\n listSkillFiles,\n listSkillIds,\n MANAGED_BLOCK_IDS,\n readAsset,\n resolveAssetsDir,\n} from \"../lib/assets.js\";\nimport { writeFileAtomic } from \"../lib/atomic-write.js\";\nimport { createBackup } from \"../lib/backup.js\";\nimport { injectBlock, listBlocks } from \"../lib/markers.js\";\nimport {\n type FileStatus,\n hasArgosFileMarker,\n writeManagedFile,\n writeManagedShellFile,\n} from \"../lib/managed-files.js\";\nimport { resolveArgosHome, resolveClaudeDir } from \"../lib/paths.js\";\nimport {\n type ArgosHookSpec,\n applyOutputStylePolicy,\n isNavoriOutputStyle,\n mergeHooksIntoSettings,\n} from \"../lib/settings-merge.js\";\nimport { isInteractive, clackPrompter, type Prompter } from \"../lib/prompter.js\";\nimport { readCliVersion } from \"../lib/version.js\";\n\n/**\n * Ids (basenames under assets/hooks/) of the 2 global hooks argos init\n * installs. See spec 0003 \"Hooks globales parametrizados\".\n */\nconst HOOK_IDS = [\"argos-guard-destructive\", \"argos-quality-gate\"] as const;\n\n/**\n * Outer Claude Code hook timeout (seconds) for argos-quality-gate.sh. Fixed\n * rather than derived from $ARGOS_GATE_TIMEOUT_MS: that env var is read\n * inside the hook at COMMIT time (whatever env the Claude Code session has),\n * not at `argos init` time, so there's nothing meaningful to read here. 600s\n * comfortably covers the hook's own default inner bound (300s) with 2x\n * headroom; a repo whose gate legitimately needs longer than ~590s needs to\n * bump this constant (and rerun `argos init`) alongside its own\n * $ARGOS_GATE_TIMEOUT_MS — not automated in v1.\n */\nconst QUALITY_GATE_OUTER_TIMEOUT_SECONDS = 600;\n\nexport type InitRowStatus = FileStatus | \"error\";\n\nexport interface InitRow {\n path: string;\n status: InitRowStatus;\n detail?: string;\n}\n\nexport interface InitOptions {\n language?: \"es\" | \"en\";\n /**\n * Install the agent full-file assets under `agents/`. Default `true`.\n * Skills are NEVER gated by an option (spec 0004: they load on-demand and\n * trimming them breaks the arsenal), only agents and hooks are.\n */\n installAgents?: boolean;\n /** Install the 2 global hooks (scripts + settings.json entries). Default `true`. */\n installHooks?: boolean;\n /**\n * Whether to take over `settings.json.outputStyle` when it currently\n * points at the predecessor harness's voice (`navori`). Default `true`\n * (unconditional replace — the `--yes`/no-TTY behavior from spec 0004);\n * the interactive wizard passes `false` when the user declines the\n * takeover prompt.\n */\n takeoverNavoriVoice?: boolean;\n}\n\nexport interface InitReport {\n rows: InitRow[];\n summary: string;\n exitCode: 0 | 1;\n backupPath?: string;\n}\n\nconst STATUS_COUNT_ORDER: InitRowStatus[] = [\"created\", \"updated\", \"unchanged\", \"skipped-foreign\", \"error\"];\n\nfunction summarize(rows: InitRow[]): string {\n const counts: Record<InitRowStatus, number> = {\n created: 0,\n updated: 0,\n unchanged: 0,\n \"skipped-foreign\": 0,\n error: 0,\n };\n for (const row of rows) counts[row.status]++;\n\n const parts = STATUS_COUNT_ORDER.filter((s) => counts[s] > 0).map((s) => `${counts[s]} ${s}`);\n return `argos init: ${parts.join(\", \")}.`;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Write a plain (unmarked) supporting file belonging to an already\n * ownership-checked skill directory — e.g. `references/core.md`,\n * `phases/0-product.md`. Unlike `writeManagedFile`, this never carries or\n * checks the `argos:file` marker itself: ownership for the whole skill\n * directory is decided once, up front, from its `SKILL.md` (see the skills\n * loop in `runInit`), so per-file marker bookkeeping here would be\n * redundant. Reports the same created/updated/unchanged statuses.\n */\nfunction writePlainFile(destPath: string, sourceContent: string): FileStatus {\n if (!existsSync(destPath)) {\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, sourceContent);\n return \"created\";\n }\n\n const current = readFileSync(destPath, \"utf-8\");\n if (current === sourceContent) return \"unchanged\";\n\n writeFileAtomic(destPath, sourceContent);\n return \"updated\";\n}\n\n/** Inject one managed CLAUDE.md block, reporting created/updated/unchanged. */\nfunction injectAndReport(claudeMd: string, id: string, version: string, content: string) {\n const hadBlock = listBlocks(claudeMd).some((b) => b.id === id);\n const after = injectBlock(claudeMd, id, version, content);\n const status: FileStatus = after === claudeMd ? \"unchanged\" : hadBlock ? \"updated\" : \"created\";\n return { claudeMd: after, status };\n}\n\n/**\n * Core, testable implementation of `argos init`: installs the Argos engine\n * (CLAUDE.md managed blocks + agents/skills/output-style full files +\n * `~/.argos/global.json`) into `resolveClaudeDir()`. Pure function of the\n * filesystem — no process.exit, no console output.\n */\nexport function runInit(options: InitOptions = {}): InitReport {\n const language = options.language ?? \"es\";\n const installAgents = options.installAgents ?? true;\n const installHooks = options.installHooks ?? true;\n const version = readCliVersion();\n const claudeDir = resolveClaudeDir();\n const assetsDir = resolveAssetsDir();\n const rows: InitRow[] = [];\n\n // Backup everything Argos is about to touch, before any write happens. A\n // failed backup means we have no safety net for what's about to be\n // mutated, so it aborts the whole run right here — every subsequent\n // mutation step is skipped, nothing gets touched.\n let backupPath: string | undefined;\n try {\n backupPath = createBackup(claudeDir, [\"CLAUDE.md\", \"agents\", \"skills\", \"output-styles\", \"hooks\", \"settings.json\"]);\n } catch (err) {\n const detail = errorMessage(err);\n rows.push({ path: \"backup\", status: \"error\", detail });\n return { rows, summary: `backup falló — no se tocó nada (${detail}).`, exitCode: 1 };\n }\n\n // 1. CLAUDE.md — MANAGED_BLOCK_IDS.length managed blocks, in order.\n const claudeMdPath = join(claudeDir, \"CLAUDE.md\");\n let claudeMd = existsSync(claudeMdPath) ? readFileSync(claudeMdPath, \"utf-8\") : \"\";\n const blockResults: { id: string; status: FileStatus }[] = [];\n for (const id of MANAGED_BLOCK_IDS) {\n const content = readAsset(assetsDir, \"managed\", `${id}.md`).replace(/\\n$/, \"\");\n const result = injectAndReport(claudeMd, id, version, content);\n claudeMd = result.claudeMd;\n blockResults.push({ id, status: result.status });\n }\n try {\n mkdirSync(claudeDir, { recursive: true });\n writeFileAtomic(claudeMdPath, claudeMd);\n for (const b of blockResults) rows.push({ path: `CLAUDE.md#${b.id}`, status: b.status });\n } catch (err) {\n const detail = errorMessage(err);\n for (const id of MANAGED_BLOCK_IDS) rows.push({ path: `CLAUDE.md#${id}`, status: \"error\", detail });\n }\n\n // 2. Full-file assets: output-style always, agents gated by the\n // `installAgents` toggle (default true; the wizard's \"agentes sí/no\"\n // step — spec 0004). Skills below are NEVER gated: they load on-demand\n // and trimming the set breaks the arsenal.\n const fullFiles: string[][] = [\n [\"output-styles\", \"argos.md\"],\n ...(installAgents ? listAgentIds(assetsDir).map((id) => [\"agents\", `${id}.md`]) : []),\n ];\n for (const relPath of fullFiles) {\n const source = readAsset(assetsDir, ...relPath);\n const dest = join(claudeDir, ...relPath);\n try {\n const status = writeManagedFile(dest, source, version);\n rows.push({ path: join(...relPath), status });\n } catch (err) {\n rows.push({ path: join(...relPath), status: \"error\", detail: errorMessage(err) });\n }\n }\n\n // 2a. Skills: each skill directory (SKILL.md plus any `references/`,\n // `phases/`, `assets/`, etc. it ships) is installed as a single unit.\n // Ownership sentinel is SKILL.md's `argos:file` marker:\n // - SKILL.md absent, or present WITH the marker → install/update every\n // file the skill ships.\n // - SKILL.md present WITHOUT the marker (foreign/user-modified) → skip\n // every file under that skill dir, untouched — same policy as a single\n // foreign full-file asset above, extended to the whole directory.\n for (const skillId of listSkillIds(assetsDir)) {\n const skillMdDest = join(claudeDir, \"skills\", skillId, \"SKILL.md\");\n const isForeignSkill = existsSync(skillMdDest) && !hasArgosFileMarker(readFileSync(skillMdDest, \"utf-8\"));\n\n for (const relFile of listSkillFiles(assetsDir, skillId)) {\n const relParts = relFile.split(\"/\");\n const relPath = join(\"skills\", skillId, ...relParts);\n\n if (isForeignSkill) {\n rows.push({ path: relPath, status: \"skipped-foreign\" });\n continue;\n }\n\n const source = readAsset(assetsDir, \"skills\", skillId, ...relParts);\n const dest = join(claudeDir, \"skills\", skillId, ...relParts);\n try {\n const status = relFile === \"SKILL.md\" ? writeManagedFile(dest, source, version) : writePlainFile(dest, source);\n rows.push({ path: relPath, status });\n } catch (err) {\n rows.push({ path: relPath, status: \"error\", detail: errorMessage(err) });\n }\n }\n }\n\n // 2b. Global hooks: full-file shell assets, own shell-comment marker,\n // chmod +x. Same skipped-foreign policy as the full-file assets above.\n // Track which hooks actually landed on disk successfully — a hook whose\n // write threw must NEVER get a settings.json entry (see 2c below): a\n // dangling PreToolUse entry pointing at a script that isn't there hard-\n // blocks every subsequent Bash call.\n //\n // Gated by the `installHooks` toggle (default true; the wizard's \"hooks\n // sí/no\" step — spec 0004): when disabled, this run neither writes nor\n // touches any pre-existing hook script/settings.json entry — a full\n // uninstall of previously-installed hooks is `argos remove`'s job, not a\n // side effect of toggling this flag off on a later `init` run.\n const hookWriteFailed = new Map<(typeof HOOK_IDS)[number], boolean>();\n if (installHooks) {\n for (const id of HOOK_IDS) {\n const relPath = [\"hooks\", `${id}.sh`];\n const source = readAsset(assetsDir, ...relPath);\n const dest = join(claudeDir, ...relPath);\n try {\n const status = writeManagedShellFile(dest, source, version);\n rows.push({ path: join(...relPath), status });\n hookWriteFailed.set(id, false);\n } catch (err) {\n rows.push({ path: join(...relPath), status: \"error\", detail: errorMessage(err) });\n hookWriteFailed.set(id, true);\n }\n }\n\n // 2c. settings.json — surgical merge of the 2 PreToolUse hook entries.\n // Only writes/updates entries whose command targets one of the 2 scripts\n // above; every other key and hook in the user's settings.json is left\n // untouched (see lib/settings-merge.ts). Only hooks whose script write\n // actually succeeded get an entry built for them at all.\n const settingsPath = join(claudeDir, \"settings.json\");\n const allHookSpecs: Record<(typeof HOOK_IDS)[number], ArgosHookSpec> = {\n \"argos-guard-destructive\": {\n scriptPath: join(claudeDir, \"hooks\", \"argos-guard-destructive.sh\"),\n matcher: \"Bash\",\n timeout: 10,\n statusMessage: \"argos: guard-destructive\",\n },\n \"argos-quality-gate\": {\n scriptPath: join(claudeDir, \"hooks\", \"argos-quality-gate.sh\"),\n matcher: \"Bash\",\n timeout: QUALITY_GATE_OUTER_TIMEOUT_SECONDS,\n statusMessage: \"argos: quality-gate\",\n },\n };\n const hookSpecs: ArgosHookSpec[] = HOOK_IDS.filter((id) => !hookWriteFailed.get(id)).map((id) => allHookSpecs[id]);\n // Any hook whose write just failed also gets its (possibly pre-existing,\n // from an earlier successful run) settings.json entry stripped out — a\n // script that's gone or broken must never be left with a live entry.\n const failedScriptPaths = HOOK_IDS.filter((id) => hookWriteFailed.get(id)).map((id) => allHookSpecs[id].scriptPath);\n const mergeResult = mergeHooksIntoSettings(settingsPath, hookSpecs, { removeScriptPaths: failedScriptPaths });\n rows.push({ path: \"settings.json\", status: mergeResult.status, detail: mergeResult.detail });\n }\n\n // 2d. Voice activation (spec 0004 \"Activación de la voz\"):\n // settings.json.outputStyle. Absent → set to \"Argos\". Matching the\n // predecessor harness's voice (navori) → takeover per\n // `takeoverNavoriVoice` (default true, i.e. unconditional replace under\n // --yes/no-TTY; the interactive wizard passes `false` when the user\n // declines). Any other value → never touched. Reported separately from\n // the hooks settings.json row above so a takeover/foreign-voice detail is\n // never conflated with the hooks merge outcome.\n const outputStyleResult = applyOutputStylePolicy(join(claudeDir, \"settings.json\"), {\n takeoverNavori: options.takeoverNavoriVoice ?? true,\n });\n // \"untouched\" (a foreign non-navori voice, or a declined navori takeover)\n // maps to the same \"skipped-foreign\" row status used elsewhere for\n // \"found something not ours, left it byte-identical\".\n const outputStyleRowStatus: InitRowStatus =\n outputStyleResult.status === \"untouched\" ? \"skipped-foreign\" : outputStyleResult.status;\n rows.push({ path: \"settings.json#outputStyle\", status: outputStyleRowStatus, detail: outputStyleResult.detail });\n\n // 3. ~/.argos/global.json\n const argosHome = resolveArgosHome();\n const globalJsonPath = join(argosHome, \"global.json\");\n const globalJsonContent = `${JSON.stringify({ version, language }, null, 2)}\\n`;\n try {\n const globalJsonExisted = existsSync(globalJsonPath);\n const globalJsonStatus: FileStatus = !globalJsonExisted\n ? \"created\"\n : readFileSync(globalJsonPath, \"utf-8\") === globalJsonContent\n ? \"unchanged\"\n : \"updated\";\n mkdirSync(argosHome, { recursive: true });\n writeFileSync(globalJsonPath, globalJsonContent, \"utf-8\");\n rows.push({ path: \"global.json\", status: globalJsonStatus });\n } catch (err) {\n rows.push({ path: \"global.json\", status: \"error\", detail: errorMessage(err) });\n }\n\n const exitCode: 0 | 1 = rows.some((r) => r.status === \"error\") ? 1 : 0;\n return { rows, summary: summarize(rows), exitCode, backupPath };\n}\n\nexport interface InitInteractiveOptions extends InitOptions {\n /** `--yes`: forces non-interactive behavior even under a real TTY. */\n yes?: boolean;\n /** Injectable for tests; defaults to the real `@clack/prompts`-backed prompter. */\n prompter?: Prompter;\n}\n\n/**\n * A cancelled wizard's report: identical shape to a run that touched\n * nothing. `exitCode: 1` — a cancel is neither a successful write nor\n * silently indistinguishable from one by exit code alone (matches\n * `runWorkspaceLinkInteractive`'s convention for its own cancel paths).\n */\nfunction cancelledInitReport(): InitReport {\n return { rows: [], summary: \"argos init: cancelado — no se tocó nada.\", exitCode: 1 };\n}\n\n/**\n * Read-only peek at `settings.json.outputStyle`, used only to decide whether\n * the interactive wizard needs to ask about a navori takeover. Never throws,\n * never writes — any missing file, unreadable file, or invalid JSON just\n * reads as \"no value\" (`undefined`), which is safely a non-match for\n * `isNavoriOutputStyle`. The actual write happens inside `runInit` via\n * `applyOutputStylePolicy`, which re-does this read itself under its own\n * mtime-guarded contract.\n */\nfunction peekOutputStyleValue(settingsPath: string): unknown {\n if (!existsSync(settingsPath)) return undefined;\n try {\n const parsed: unknown = JSON.parse(readFileSync(settingsPath, \"utf-8\"));\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return undefined;\n return (parsed as Record<string, unknown>).outputStyle;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Interactive layer over `runInit` (spec 0004 F5 \"argos init\"). A pure\n * additive wrapper — the core `runInit` never changes behavior or contract.\n * Without a real TTY, or with `--yes`, this delegates to `runInit(options)`\n * unchanged: no prompt library call is ever reached on that path. With a\n * TTY, it runs a 3-step wizard (language, agents/hooks toggles, summary +\n * final confirm) before calling `runInit` with the gathered choices;\n * cancelling at any step touches nothing and returns a no-op report.\n */\nexport async function runInitInteractive(options: InitInteractiveOptions = {}): Promise<InitReport> {\n if (!isInteractive({ yes: options.yes })) {\n return runInit(options);\n }\n\n const prompter = options.prompter ?? clackPrompter;\n\n prompter.intro(\"argos init — instalación interactiva del motor\");\n\n const language = await prompter.select<\"es\" | \"en\">({\n message: \"Idioma del motor\",\n options: [\n { value: \"es\", label: \"es — español\" },\n { value: \"en\", label: \"en — English\" },\n ],\n initialValue: options.language ?? \"es\",\n });\n if (prompter.isCancel(language)) {\n prompter.cancel(\"argos init cancelado — no se tocó nada.\");\n return cancelledInitReport();\n }\n\n const installAgents = await prompter.confirm({\n message: \"¿Instalar los agentes del motor (agents/)?\",\n initialValue: options.installAgents ?? true,\n });\n if (prompter.isCancel(installAgents)) {\n prompter.cancel(\"argos init cancelado — no se tocó nada.\");\n return cancelledInitReport();\n }\n\n const installHooks = await prompter.confirm({\n message: \"¿Instalar los hooks globales (guard-destructive + quality-gate)?\",\n initialValue: options.installHooks ?? true,\n });\n if (prompter.isCancel(installHooks)) {\n prompter.cancel(\"argos init cancelado — no se tocó nada.\");\n return cancelledInitReport();\n }\n\n const claudeDir = resolveClaudeDir();\n\n // Voice activation (spec 0004): if the current settings.json.outputStyle\n // matches the predecessor harness's voice, ask before taking it over —\n // this peek is read-only and never writes; the actual takeover only\n // happens inside runInit below, once the user has confirmed everything.\n let takeoverNavoriVoice = options.takeoverNavoriVoice ?? true;\n const currentOutputStyle = peekOutputStyleValue(join(claudeDir, \"settings.json\"));\n if (isNavoriOutputStyle(currentOutputStyle)) {\n const takeover = await prompter.confirm({\n message: `settings.json.outputStyle apunta a la voz del harness predecesor ('${String(currentOutputStyle)}') — ¿reemplazarla por Argos?`,\n initialValue: true,\n });\n if (prompter.isCancel(takeover)) {\n prompter.cancel(\"argos init cancelado — no se tocó nada.\");\n return cancelledInitReport();\n }\n takeoverNavoriVoice = takeover;\n }\n\n prompter.note(\n [\n `idioma: ${language}`,\n `agentes: ${installAgents ? \"sí\" : \"no\"}`,\n \"hooks: \" + (installHooks ? \"sí\" : \"no\"),\n \"skills: sí (siempre — cargan on-demand)\",\n `destino: ${claudeDir}`,\n \"se hace un backup antes de escribir nada\",\n ].join(\"\\n\"),\n \"Resumen\",\n );\n\n const proceed = await prompter.confirm({ message: \"¿Proceder a escribir estos cambios?\", initialValue: true });\n if (prompter.isCancel(proceed) || !proceed) {\n prompter.cancel(\"argos init cancelado — no se tocó nada.\");\n return cancelledInitReport();\n }\n\n const report = runInit({\n language,\n installAgents,\n installHooks,\n takeoverNavoriVoice,\n });\n prompter.outro(report.summary);\n return report;\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: \"init\",\n description: \"Install the Argos engine into the global Claude Code home.\",\n },\n args: {\n language: {\n type: \"enum\",\n options: [\"es\", \"en\"],\n default: \"es\",\n description: \"Idioma del motor (global.json).\",\n },\n yes: {\n type: \"boolean\",\n default: false,\n description: \"Fuerza modo no interactivo aunque haya una TTY real (defaults + flags, sin wizard).\",\n },\n },\n async run({ args }) {\n const report = await runInitInteractive({ language: args.language as \"es\" | \"en\", yes: Boolean(args.yes) });\n\n const colorize = (status: InitRowStatus): string => {\n const padded = status.padEnd(18);\n switch (status) {\n case \"skipped-foreign\":\n return pc.yellow(padded);\n case \"created\":\n return pc.green(padded);\n case \"updated\":\n return pc.cyan(padded);\n case \"error\":\n return pc.red(padded);\n default:\n return pc.dim(padded);\n }\n };\n for (const row of report.rows) {\n const suffix = row.detail ? ` (${row.detail})` : \"\";\n console.log(`${colorize(row.status)} ${row.path}${suffix}`);\n }\n console.log(\"\");\n console.log(report.summary);\n if (report.backupPath) console.log(`backup en ${report.backupPath}`);\n\n process.exit(report.exitCode);\n },\n});\n"],"names":["defineCommand","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","pc","listAgentIds","listSkillFiles","listSkillIds","MANAGED_BLOCK_IDS","readAsset","resolveAssetsDir","writeFileAtomic","createBackup","injectBlock","listBlocks","hasArgosFileMarker","writeManagedFile","writeManagedShellFile","resolveArgosHome","resolveClaudeDir","applyOutputStylePolicy","isNavoriOutputStyle","mergeHooksIntoSettings","isInteractive","clackPrompter","readCliVersion","HOOK_IDS","QUALITY_GATE_OUTER_TIMEOUT_SECONDS","STATUS_COUNT_ORDER","summarize","rows","counts","created","updated","unchanged","error","row","status","parts","filter","s","map","errorMessage","err","Error","message","String","writePlainFile","destPath","sourceContent","recursive","current","injectAndReport","claudeMd","id","version","content","hadBlock","some","b","after","runInit","options","language","installAgents","installHooks","claudeDir","assetsDir","backupPath","detail","push","path","summary","exitCode","claudeMdPath","blockResults","replace","result","fullFiles","relPath","source","dest","skillId","skillMdDest","isForeignSkill","relFile","relParts","split","hookWriteFailed","Map","set","settingsPath","allHookSpecs","scriptPath","matcher","timeout","statusMessage","hookSpecs","get","failedScriptPaths","mergeResult","removeScriptPaths","outputStyleResult","takeoverNavori","takeoverNavoriVoice","outputStyleRowStatus","argosHome","globalJsonPath","globalJsonContent","JSON","stringify","globalJsonExisted","globalJsonStatus","r","cancelledInitReport","peekOutputStyleValue","undefined","parsed","parse","Array","isArray","outputStyle","runInitInteractive","yes","prompter","intro","select","value","label","initialValue","isCancel","cancel","confirm","currentOutputStyle","takeover","note","proceed","report","outro","initCommand","meta","name","description","args","type","default","run","Boolean","colorize","padded","padEnd","yellow","green","cyan","red","dim","suffix","console","log","process","exit"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Prompter } from "../lib/prompter.js";
|
|
1
2
|
/**
|
|
2
3
|
* Uninstaller for `argos init`: the mirror image of `runInit` (see
|
|
3
4
|
* commands/init.ts). Removes only what Argos itself owns — a managed
|
|
@@ -47,6 +48,24 @@ export interface RemoveReport {
|
|
|
47
48
|
* (kept by default) — backups are removed last and always warned about.
|
|
48
49
|
*/
|
|
49
50
|
export declare function runRemove(options?: RemoveOptions): RemoveReport;
|
|
51
|
+
export interface RemoveInteractiveOptions extends RemoveOptions {
|
|
52
|
+
/** `--yes`: forces non-interactive behavior even under a real TTY. */
|
|
53
|
+
yes?: boolean;
|
|
54
|
+
/** Injectable for tests; defaults to the real `@clack/prompts`-backed prompter. */
|
|
55
|
+
prompter?: Prompter;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Interactive layer over `runRemove` (spec 0004 F5 "argos remove"). A pure
|
|
59
|
+
* additive wrapper — the core `runRemove` never changes behavior or
|
|
60
|
+
* contract. Without a real TTY, with `--yes`, or for a plain preview
|
|
61
|
+
* (`apply: false`, the default) this delegates to `runRemove(options)`
|
|
62
|
+
* unchanged — no prompt library call is ever reached on those paths. With a
|
|
63
|
+
* TTY AND `apply: true`, requires the operator to type the exact target
|
|
64
|
+
* directory (`resolveClaudeDir()`) before proceeding; `purge: true` on top
|
|
65
|
+
* of that requires a SECOND, separate confirmation mentioning backups.
|
|
66
|
+
* Either confirmation failing/cancelling aborts with zero writes.
|
|
67
|
+
*/
|
|
68
|
+
export declare function runRemoveInteractive(options?: RemoveInteractiveOptions): Promise<RemoveReport>;
|
|
50
69
|
export declare const removeCommand: import("citty").CommandDef<{
|
|
51
70
|
readonly apply: {
|
|
52
71
|
readonly type: "boolean";
|
|
@@ -58,5 +77,10 @@ export declare const removeCommand: import("citty").CommandDef<{
|
|
|
58
77
|
readonly default: false;
|
|
59
78
|
readonly description: "Also remove ~/.argos data (registry, global.json, backups). Irreversible.";
|
|
60
79
|
};
|
|
80
|
+
readonly yes: {
|
|
81
|
+
readonly type: "boolean";
|
|
82
|
+
readonly default: false;
|
|
83
|
+
readonly description: "Fuerza modo no interactivo aunque haya una TTY real (salta las confirmaciones tipadas).";
|
|
84
|
+
};
|
|
61
85
|
}>;
|
|
62
86
|
//# sourceMappingURL=remove.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAUA,OAAO,EAAgC,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGjF;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,cAAc,GAAG,iBAAiB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5G,MAAM,MAAM,iBAAiB,GACzB,iBAAiB,GACjB,aAAa,GACb,aAAa,GACb,oBAAoB,GACpB,YAAY,GACZ,kBAAkB,GAClB,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4FAA4F;IAC5F,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA2RD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,aAAkB,GAAG,YAAY,CAiFnE;AAED,MAAM,WAAW,wBAAyB,SAAQ,aAAa;IAC7D,sEAAsE;IACtE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAiBD;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,YAAY,CAAC,CAkCxG;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;EAuDxB,CAAC"}
|