argos-harness 0.2.0 → 0.2.1

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.
@@ -80,7 +80,7 @@ function isPlainObject(v) {
80
80
  if (!hasArgosShellFileMarker(content)) {
81
81
  findings.push({
82
82
  level: "info",
83
- message: `archivo ajeno en hooks/${id}.sh — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla.`
83
+ message: `archivo ajeno en hooks/${id}.sh — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla, o corre \`argos init --force\` para reemplazarlo (con backup).`
84
84
  });
85
85
  continue;
86
86
  }
@@ -319,7 +319,7 @@ function checkMotor(findings) {
319
319
  if (!hasArgosFileMarker(content)) {
320
320
  findings.push({
321
321
  level: "info",
322
- message: `archivo ajeno en ${label} — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla.`
322
+ message: `archivo ajeno en ${label} — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla, o corre \`argos init --force\` para reemplazarlo (con backup).`
323
323
  });
324
324
  }
325
325
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { existsSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport pc from \"picocolors\";\nimport { z } from \"zod\";\nimport { ArgosConfigSchema, hasConfig } from \"../lib/config.js\";\nimport {\n detectFramework,\n detectLibs,\n detectPackageManager,\n readPackageJson,\n} from \"../lib/detect.js\";\nimport { buildFichaContent, FICHA_BLOCK_ID } from \"../lib/ficha.js\";\nimport { getRemoteOriginUrl, isGitRepo, parseIdentityFromRemote } from \"../lib/git.js\";\nimport { listAgentIds, listSkillIds, MANAGED_BLOCK_IDS, resolveAssetsDir } from \"../lib/assets.js\";\nimport { listBlocks, listDanglingBlockIds } from \"../lib/markers.js\";\nimport { hasArgosFileMarker, hasArgosShellFileMarker } from \"../lib/managed-files.js\";\nimport { hasNaviorConfig } from \"../lib/navori-import.js\";\nimport { resolveClaudeDir } from \"../lib/paths.js\";\nimport { isArgosHookCommand } from \"../lib/settings-merge.js\";\nimport { readCliVersion } from \"../lib/version.js\";\nimport { loadRegistry, resolveWorkspaceForRepo } from \"../lib/workspaces.js\";\nimport { describeZodError } from \"../lib/zod-messages.js\";\nimport { NO_GATE_PLACEHOLDER } from \"./adopt.js\";\n\nexport type DoctorLevel = \"info\" | \"warning\" | \"error\";\n\nexport interface DoctorFinding {\n level: DoctorLevel;\n message: string;\n}\n\nexport interface DoctorOptions {\n cwd: string;\n}\n\nexport interface DoctorReport {\n findings: DoctorFinding[];\n exitCode: 0 | 1;\n}\n\n/**\n * Read a text file, guarding against fs failures (e.g. EACCES) that would\n * otherwise crash doctor's read-only audit. On failure, pushes an error\n * finding and falls back to `\"\"` so the rest of the audit can still run.\n */\nfunction readFileSafe(path: string, findings: DoctorFinding[], label: string): string {\n if (!existsSync(path)) return \"\";\n try {\n return readFileSync(path, \"utf-8\");\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer ${label} (${err instanceof Error ? err.message : String(err)}).`,\n });\n return \"\";\n }\n}\n\n/** Compare two semver-ish `x.y.z` strings. Returns <0, 0, or >0 like Array.sort comparators. */\nfunction compareVersions(a: string, b: string): number {\n const pa = a.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n const pb = b.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return 0;\n}\n\n/**\n * Ids (basenames under `<claudeDir>/hooks/`) of the 2 global hooks `argos\n * init` installs (see spec 0003 \"Hooks globales parametrizados\"). Mirrors\n * `HOOK_IDS` in commands/init.ts — kept as a local duplicate here since\n * doctor only reads the filesystem/version drift, it never installs, and the\n * two commands are intentionally not allowed to share private constants.\n */\nconst HOOK_IDS = [\"argos-guard-destructive\", \"argos-quality-gate\"] as const;\n\n/** Extract the version stamped by a shell-comment `# argos:file v=\"<version>\"` marker (see lib/managed-files.ts). */\nfunction extractShellMarkerVersion(content: string): string | null {\n return /^# argos:file v=\"([^\"]*)\"/m.exec(content)?.[1] ?? null;\n}\n\n/** Extract the script path from an Argos hook command string (`bash \"<scriptPath>\"`, see lib/settings-merge.ts). */\nfunction extractHookScriptPath(command: string): string | null {\n return /^bash \"(.+)\"$/.exec(command)?.[1] ?? null;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/**\n * Hooks (F2, motor scope): presence, ownership, and version drift of the 2\n * global hook scripts under `<claudeDir>/hooks/`. Same bidirectional-version\n * convention as the CLAUDE.md managed-blocks check in `checkMotor`.\n */\nfunction checkHookScripts(findings: DoctorFinding[], claudeDir: string, currentVersion: string): void {\n for (const id of HOOK_IDS) {\n const hookPath = join(claudeDir, \"hooks\", `${id}.sh`);\n if (!existsSync(hookPath)) {\n findings.push({ level: \"warning\", message: `Falta el hook hooks/${id}.sh. Corre argos init.` });\n continue;\n }\n\n const beforeCount = findings.length;\n const content = readFileSafe(hookPath, findings, `hooks/${id}.sh`);\n if (findings.length > beforeCount) continue; // read error already reported by readFileSafe\n\n if (!hasArgosShellFileMarker(content)) {\n findings.push({\n level: \"info\",\n message: `archivo ajeno en hooks/${id}.sh — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla.`,\n });\n continue;\n }\n\n const hookVersion = extractShellMarkerVersion(content);\n if (!hookVersion) continue;\n const cmp = compareVersions(hookVersion, currentVersion);\n if (cmp < 0) {\n findings.push({\n level: \"warning\",\n message: `hooks/${id}.sh está desactualizado (v${hookVersion} < v${currentVersion}). Corre argos init.`,\n });\n } else if (cmp > 0) {\n findings.push({\n level: \"warning\",\n message: `hooks/${id}.sh es más nuevo que el binario (v${hookVersion} > v${currentVersion}) — el binario es más viejo que el motor instalado — actualiza el paquete (npm i -g).`,\n });\n }\n }\n}\n\n/**\n * Hooks (F2, motor scope): `settings.json` PreToolUse entries — missing,\n * orphaned (the entry's script file is gone), or the file itself unreadable\n * as valid JSON. Guarded reads throughout: never throws, always degrades to\n * an error finding so the rest of doctor's audit still runs.\n */\nfunction checkHookSettings(findings: DoctorFinding[], claudeDir: string): void {\n const settingsPath = join(claudeDir, \"settings.json\");\n if (!existsSync(settingsPath)) {\n for (const id of HOOK_IDS) {\n findings.push({ level: \"warning\", message: `Falta la entrada del hook ${id} en settings.json. Corre argos init.` });\n }\n return;\n }\n\n let raw: string;\n try {\n raw = readFileSync(settingsPath, \"utf-8\");\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer settings.json (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n\n let settings: unknown;\n try {\n settings = raw.trim().length === 0 ? {} : JSON.parse(raw);\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `settings.json tiene JSON inválido (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n\n const foundScriptPaths = new Set<string>();\n const hooksRoot = isPlainObject(settings) ? settings.hooks : undefined;\n const preToolUse = isPlainObject(hooksRoot) ? hooksRoot.PreToolUse : undefined;\n if (Array.isArray(preToolUse)) {\n for (const bucket of preToolUse) {\n if (!isPlainObject(bucket) || !Array.isArray(bucket.hooks)) continue;\n for (const hook of bucket.hooks) {\n if (!isPlainObject(hook) || !isArgosHookCommand(hook.command)) continue;\n const scriptPath = extractHookScriptPath(hook.command);\n if (!scriptPath) continue;\n foundScriptPaths.add(scriptPath);\n // `existsSync` alone is true for directories too — a settings.json\n // entry pointing at a directory (e.g. a failed write that left a\n // stray directory in the script's place) would otherwise read as\n // \"present\" here and slip past the orphan check.\n let isRealFile = false;\n try {\n isRealFile = existsSync(scriptPath) && statSync(scriptPath).isFile();\n } catch {\n isRealFile = false;\n }\n if (!isRealFile) {\n findings.push({\n level: \"warning\",\n message: `settings.json referencia el hook huérfano ${scriptPath} (el script ya no existe). Corre argos init.`,\n });\n }\n }\n }\n }\n\n for (const id of HOOK_IDS) {\n const expectedPath = join(claudeDir, \"hooks\", `${id}.sh`);\n if (!foundScriptPaths.has(expectedPath)) {\n findings.push({ level: \"warning\", message: `Falta la entrada del hook ${id} en settings.json. Corre argos init.` });\n }\n }\n}\n\n/**\n * Voice activation (spec 0004 \"Activación de la voz\"): Argos's own\n * output-style asset is installed on disk (`output-styles/argos.md`, with\n * the argos:file marker) but `settings.json.outputStyle` isn't `\"Argos\"` —\n * the voice is present but not the one Claude Code will actually load.\n * Read-only, guarded against a missing/corrupt settings.json (never throws).\n */\nfunction checkOutputStyleVoice(findings: DoctorFinding[], claudeDir: string): void {\n const outputStylePath = join(claudeDir, \"output-styles\", \"argos.md\");\n if (!existsSync(outputStylePath)) return; // nothing installed — checkMotor's own full-file check already covers this\n if (!hasArgosFileMarker(readFileSafe(outputStylePath, findings, \"output-styles/argos.md\"))) return; // foreign, not ours to opine on\n\n const settingsPath = join(claudeDir, \"settings.json\");\n if (!existsSync(settingsPath)) {\n findings.push({ level: \"warning\", message: \"La voz de Argos está instalada pero no activa. Corre argos init.\" });\n return;\n }\n\n let settings: unknown;\n try {\n const raw = readFileSync(settingsPath, \"utf-8\");\n settings = raw.trim().length === 0 ? {} : JSON.parse(raw);\n } catch {\n return; // settings.json's own JSON validity is already reported by checkHookSettings\n }\n\n const outputStyle = isPlainObject(settings) ? settings.outputStyle : undefined;\n if (outputStyle !== \"Argos\") {\n findings.push({ level: \"warning\", message: \"La voz de Argos está instalada pero no activa. Corre argos init.\" });\n }\n}\n\n/**\n * Workspaces (F2, motor scope): `~/.argos/workspaces.json` registry entries\n * whose repo path no longer exists on disk (moved/deleted repo). Guarded\n * against a corrupt registry file — never throws.\n */\nfunction checkWorkspaceRegistryHealth(findings: DoctorFinding[]): void {\n let registry: ReturnType<typeof loadRegistry>;\n try {\n registry = loadRegistry();\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer workspaces.json (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n\n const stale: string[] = [];\n for (const [wsName, ws] of Object.entries(registry)) {\n for (const repo of ws.repos) {\n if (!existsSync(repo.path)) stale.push(`${wsName}/${repo.name} (${repo.path})`);\n }\n }\n if (stale.length > 0) {\n findings.push({\n level: \"warning\",\n message: `Hay repos registrados en workspaces con paths inexistentes: ${stale.join(\", \")}. Corre argos workspace link o editá el registro a mano.`,\n });\n }\n}\n\n/**\n * Flag dangling/unclosed managed-block markers (an open marker with no\n * matching close — crash residue or hand-edited corruption) as a warning.\n * Reuses `listDanglingBlockIds` (lib/markers.ts) — the same scanning logic\n * `remove`'s progress-guard relies on to avoid spinning forever on the same\n * corruption (see commands/remove.ts's processClaudeMd).\n */\nfunction checkDanglingMarkers(findings: DoctorFinding[], content: string, label: string): void {\n for (const id of listDanglingBlockIds(content)) {\n findings.push({\n level: \"warning\",\n message: `Marker argos huérfano sin cierre en ${label} (bloque \"${id}\"). Corre argos remove para limpiarlo, o editá el archivo a mano.`,\n });\n }\n}\n\nfunction checkMotor(findings: DoctorFinding[]): void {\n const claudeDir = resolveClaudeDir();\n const currentVersion = readCliVersion();\n const assetsDir = resolveAssetsDir();\n\n const claudeMdPath = join(claudeDir, \"CLAUDE.md\");\n const claudeMd = readFileSafe(claudeMdPath, findings, \"CLAUDE.md\");\n const blocks = listBlocks(claudeMd);\n\n checkDanglingMarkers(findings, claudeMd, \"CLAUDE.md\");\n\n for (const id of MANAGED_BLOCK_IDS) {\n const matching = blocks.filter((b) => b.id === id);\n if (matching.length > 1) {\n findings.push({\n level: \"warning\",\n message: `El bloque \"${id}\" está duplicado (${matching.length} veces) en CLAUDE.md. Corre argos init para sanearlo.`,\n });\n }\n\n const block = matching[0];\n if (!block) {\n findings.push({ level: \"error\", message: `Falta el bloque managed \"${id}\" en CLAUDE.md. Corre argos init.` });\n continue;\n }\n if (block.version) {\n const cmp = compareVersions(block.version, currentVersion);\n if (cmp < 0) {\n findings.push({\n level: \"warning\",\n message: `El bloque \"${id}\" está desactualizado (v${block.version} < v${currentVersion}). Corre argos init.`,\n });\n } else if (cmp > 0) {\n findings.push({\n level: \"warning\",\n message: `El bloque \"${id}\" es más nuevo que el binario (v${block.version} > v${currentVersion}) — el binario es más viejo que el motor instalado — actualiza el paquete (npm i -g).`,\n });\n }\n }\n }\n\n const fullFiles: string[][] = [\n [\"output-styles\", \"argos.md\"],\n ...listAgentIds(assetsDir).map((id) => [\"agents\", `${id}.md`]),\n ...listSkillIds(assetsDir).map((id) => [\"skills\", id, \"SKILL.md\"]),\n ];\n for (const relPath of fullFiles) {\n const dest = join(claudeDir, ...relPath);\n const label = join(...relPath);\n if (!existsSync(dest)) {\n findings.push({ level: \"error\", message: `Falta ${label} en el motor. Corre argos init.` });\n continue;\n }\n const content = readFileSync(dest, \"utf-8\");\n if (!hasArgosFileMarker(content)) {\n findings.push({\n level: \"info\",\n message: `archivo ajeno en ${label} — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla.`,\n });\n }\n }\n\n checkHookScripts(findings, claudeDir, currentVersion);\n checkHookSettings(findings, claudeDir);\n checkOutputStyleVoice(findings, claudeDir);\n checkWorkspaceRegistryHealth(findings);\n}\n\nfunction checkRepo(cwd: string, findings: DoctorFinding[]): void {\n if (!hasConfig(cwd)) return;\n\n const configPath = join(cwd, \"argos.config.json\");\n let config: z.infer<typeof ArgosConfigSchema> | undefined;\n try {\n const raw: unknown = JSON.parse(readFileSync(configPath, \"utf-8\"));\n config = ArgosConfigSchema.parse(raw);\n } catch (error) {\n for (const message of describeZodError(error)) {\n findings.push({ level: \"error\", message: `argos.config.json inválido — ${message}` });\n }\n return;\n }\n\n if (hasNaviorConfig(cwd)) {\n findings.push({\n level: \"info\",\n message: \"navori.config.json coexiste con argos.config.json (migración en curso).\",\n });\n }\n\n if (config.qualityGate.fast === NO_GATE_PLACEHOLDER) {\n findings.push({\n level: \"warning\",\n message: \"quality gate placeholder — configura scripts y corre argos adopt --refresh.\",\n });\n }\n\n // Ficha drift: does ./CLAUDE.md's ficha block match what adopt would write today?\n const claudeMdPath = join(cwd, \"CLAUDE.md\");\n const claudeMd = readFileSafe(claudeMdPath, findings, \"./CLAUDE.md\");\n checkDanglingMarkers(findings, claudeMd, \"./CLAUDE.md\");\n const fichaBlocks = listBlocks(claudeMd).filter((b) => b.id === FICHA_BLOCK_ID);\n if (fichaBlocks.length > 1) {\n findings.push({\n level: \"warning\",\n message: `La ficha está duplicada (${fichaBlocks.length} veces) en ./CLAUDE.md. Corre argos adopt --refresh para sanearla.`,\n });\n }\n const fichaBlock = fichaBlocks[0];\n if (!fichaBlock) {\n findings.push({ level: \"warning\", message: \"Falta la ficha en ./CLAUDE.md. Corre argos adopt --refresh.\" });\n } else {\n const expectedFicha = buildFichaContent(config);\n if (!claudeMd.includes(expectedFicha)) {\n findings.push({ level: \"warning\", message: \"La ficha de ./CLAUDE.md quedó vieja. Corre argos adopt --refresh.\" });\n }\n }\n\n // Stack drift: new relevant libs in package.json not yet recorded.\n const pkg = readPackageJson(cwd);\n if (pkg) {\n const recordedLibs = new Set(config.stack?.libs ?? []);\n const freshLibs = detectLibs(pkg);\n const newLibs = freshLibs.filter((lib) => !recordedLibs.has(lib));\n if (newLibs.length > 0) {\n findings.push({\n level: \"warning\",\n message: `Nuevas libs detectadas sin registrar (${newLibs.join(\", \")}). Corre argos adopt --refresh.`,\n });\n }\n\n const freshFramework = detectFramework(pkg);\n if (freshFramework && config.stack?.framework && freshFramework !== config.stack.framework) {\n findings.push({\n level: \"warning\",\n message: `El framework detectado (${freshFramework}) difiere del registrado (${config.stack.framework}). Corre argos adopt --refresh.`,\n });\n }\n\n const freshPackageManager = detectPackageManager(cwd);\n if (\n freshPackageManager &&\n config.stack?.packageManager &&\n freshPackageManager !== config.stack.packageManager\n ) {\n findings.push({\n level: \"warning\",\n message: `El package manager detectado (${freshPackageManager}) difiere del registrado (${config.stack.packageManager}). Corre argos adopt --refresh.`,\n });\n }\n }\n\n // Identity drift: current git remote vs the identity recorded in config.\n const remoteUrl = getRemoteOriginUrl(cwd);\n const freshIdentity = remoteUrl ? (parseIdentityFromRemote(remoteUrl) ?? undefined) : undefined;\n if (freshIdentity && config.identity && freshIdentity !== config.identity) {\n findings.push({\n level: \"warning\",\n message: `La identidad detectada (${freshIdentity}) difiere de la registrada (${config.identity}). Corre argos adopt --refresh.`,\n });\n }\n\n // Workspace linkage (F2): repo not registered, registered under a stale\n // path, or config.workspace pointing at a name absent from the registry.\n let registry: ReturnType<typeof loadRegistry>;\n try {\n registry = loadRegistry();\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer workspaces.json (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n const resolution = resolveWorkspaceForRepo(registry, {\n configWorkspace: config.workspace,\n remoteUrl,\n repoPath: cwd,\n });\n\n if (resolution.kind === \"unresolved\") {\n findings.push({\n level: \"info\",\n message: \"El repo no está vinculado a ningún workspace. Corre argos workspace link.\",\n });\n } else if (resolution.kind === \"resolved\") {\n const workspace = registry[resolution.name];\n if (!workspace) {\n findings.push({\n level: \"warning\",\n message: `argos.config.json referencia el workspace '${resolution.name}', que no existe en el registro. Corre argos workspace link ${resolution.name}.`,\n });\n } else {\n const entry = workspace.repos.find((r) => r.name === config.name);\n if (!entry) {\n findings.push({\n level: \"info\",\n message: \"El repo no está vinculado a ningún workspace. Corre argos workspace link.\",\n });\n } else {\n let realCwd: string | undefined;\n try {\n realCwd = realpathSync(resolve(cwd));\n } catch {\n realCwd = undefined;\n }\n if (realCwd && entry.path !== realCwd) {\n findings.push({\n level: \"warning\",\n message: `El repo está registrado en el workspace '${resolution.name}' con un path distinto (${entry.path} vs ${realCwd}). Corre argos workspace link para actualizarlo.`,\n });\n }\n }\n }\n }\n}\n\n/**\n * Core, testable implementation of `argos doctor`: a read-only audit of the\n * global engine and (when cwd is a git repo) the repo's argos.config.json +\n * ficha. Never writes anything.\n */\nexport function runDoctor(options: DoctorOptions): DoctorReport {\n const findings: DoctorFinding[] = [];\n\n checkMotor(findings);\n if (isGitRepo(options.cwd)) {\n checkRepo(options.cwd, findings);\n }\n\n const exitCode = findings.some((f) => f.level !== \"info\") ? 1 : 0;\n return { findings, exitCode };\n}\n\nexport const doctorCommand = defineCommand({\n meta: {\n name: \"doctor\",\n description: \"Report drift between the engine, the repo config, and its ficha.\",\n },\n run() {\n const report = runDoctor({ cwd: process.cwd() });\n\n if (report.findings.length === 0) {\n console.log(\"Todo al día.\");\n process.exit(0);\n }\n\n for (const finding of report.findings) {\n const padded = finding.level.padEnd(10);\n const label = finding.level === \"error\" ? pc.red(padded) : finding.level === \"warning\" ? pc.yellow(padded) : pc.dim(padded);\n console.log(`${label} ${finding.message}`);\n }\n\n process.exit(report.exitCode);\n },\n});\n"],"names":["defineCommand","existsSync","readFileSync","realpathSync","statSync","join","resolve","pc","ArgosConfigSchema","hasConfig","detectFramework","detectLibs","detectPackageManager","readPackageJson","buildFichaContent","FICHA_BLOCK_ID","getRemoteOriginUrl","isGitRepo","parseIdentityFromRemote","listAgentIds","listSkillIds","MANAGED_BLOCK_IDS","resolveAssetsDir","listBlocks","listDanglingBlockIds","hasArgosFileMarker","hasArgosShellFileMarker","hasNaviorConfig","resolveClaudeDir","isArgosHookCommand","readCliVersion","loadRegistry","resolveWorkspaceForRepo","describeZodError","NO_GATE_PLACEHOLDER","readFileSafe","path","findings","label","err","push","level","message","Error","String","compareVersions","a","b","pa","split","map","n","Number","parseInt","pb","i","Math","max","length","diff","HOOK_IDS","extractShellMarkerVersion","content","exec","extractHookScriptPath","command","isPlainObject","v","Array","isArray","checkHookScripts","claudeDir","currentVersion","id","hookPath","beforeCount","hookVersion","cmp","checkHookSettings","settingsPath","raw","settings","trim","JSON","parse","foundScriptPaths","Set","hooksRoot","hooks","undefined","preToolUse","PreToolUse","bucket","hook","scriptPath","add","isRealFile","isFile","expectedPath","has","checkOutputStyleVoice","outputStylePath","outputStyle","checkWorkspaceRegistryHealth","registry","stale","wsName","ws","Object","entries","repo","repos","name","checkDanglingMarkers","checkMotor","assetsDir","claudeMdPath","claudeMd","blocks","matching","filter","block","version","fullFiles","relPath","dest","checkRepo","cwd","configPath","config","error","qualityGate","fast","fichaBlocks","fichaBlock","expectedFicha","includes","pkg","recordedLibs","stack","libs","freshLibs","newLibs","lib","freshFramework","framework","freshPackageManager","packageManager","remoteUrl","freshIdentity","identity","resolution","configWorkspace","workspace","repoPath","kind","entry","find","r","realCwd","runDoctor","options","exitCode","some","f","doctorCommand","meta","description","run","report","process","console","log","exit","finding","padded","padEnd","red","yellow","dim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { existsSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport pc from \"picocolors\";\nimport { z } from \"zod\";\nimport { ArgosConfigSchema, hasConfig } from \"../lib/config.js\";\nimport {\n detectFramework,\n detectLibs,\n detectPackageManager,\n readPackageJson,\n} from \"../lib/detect.js\";\nimport { buildFichaContent, FICHA_BLOCK_ID } from \"../lib/ficha.js\";\nimport { getRemoteOriginUrl, isGitRepo, parseIdentityFromRemote } from \"../lib/git.js\";\nimport { listAgentIds, listSkillIds, MANAGED_BLOCK_IDS, resolveAssetsDir } from \"../lib/assets.js\";\nimport { listBlocks, listDanglingBlockIds } from \"../lib/markers.js\";\nimport { hasArgosFileMarker, hasArgosShellFileMarker } from \"../lib/managed-files.js\";\nimport { hasNaviorConfig } from \"../lib/navori-import.js\";\nimport { resolveClaudeDir } from \"../lib/paths.js\";\nimport { isArgosHookCommand } from \"../lib/settings-merge.js\";\nimport { readCliVersion } from \"../lib/version.js\";\nimport { loadRegistry, resolveWorkspaceForRepo } from \"../lib/workspaces.js\";\nimport { describeZodError } from \"../lib/zod-messages.js\";\nimport { NO_GATE_PLACEHOLDER } from \"./adopt.js\";\n\nexport type DoctorLevel = \"info\" | \"warning\" | \"error\";\n\nexport interface DoctorFinding {\n level: DoctorLevel;\n message: string;\n}\n\nexport interface DoctorOptions {\n cwd: string;\n}\n\nexport interface DoctorReport {\n findings: DoctorFinding[];\n exitCode: 0 | 1;\n}\n\n/**\n * Read a text file, guarding against fs failures (e.g. EACCES) that would\n * otherwise crash doctor's read-only audit. On failure, pushes an error\n * finding and falls back to `\"\"` so the rest of the audit can still run.\n */\nfunction readFileSafe(path: string, findings: DoctorFinding[], label: string): string {\n if (!existsSync(path)) return \"\";\n try {\n return readFileSync(path, \"utf-8\");\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer ${label} (${err instanceof Error ? err.message : String(err)}).`,\n });\n return \"\";\n }\n}\n\n/** Compare two semver-ish `x.y.z` strings. Returns <0, 0, or >0 like Array.sort comparators. */\nfunction compareVersions(a: string, b: string): number {\n const pa = a.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n const pb = b.split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return 0;\n}\n\n/**\n * Ids (basenames under `<claudeDir>/hooks/`) of the 2 global hooks `argos\n * init` installs (see spec 0003 \"Hooks globales parametrizados\"). Mirrors\n * `HOOK_IDS` in commands/init.ts — kept as a local duplicate here since\n * doctor only reads the filesystem/version drift, it never installs, and the\n * two commands are intentionally not allowed to share private constants.\n */\nconst HOOK_IDS = [\"argos-guard-destructive\", \"argos-quality-gate\"] as const;\n\n/** Extract the version stamped by a shell-comment `# argos:file v=\"<version>\"` marker (see lib/managed-files.ts). */\nfunction extractShellMarkerVersion(content: string): string | null {\n return /^# argos:file v=\"([^\"]*)\"/m.exec(content)?.[1] ?? null;\n}\n\n/** Extract the script path from an Argos hook command string (`bash \"<scriptPath>\"`, see lib/settings-merge.ts). */\nfunction extractHookScriptPath(command: string): string | null {\n return /^bash \"(.+)\"$/.exec(command)?.[1] ?? null;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/**\n * Hooks (F2, motor scope): presence, ownership, and version drift of the 2\n * global hook scripts under `<claudeDir>/hooks/`. Same bidirectional-version\n * convention as the CLAUDE.md managed-blocks check in `checkMotor`.\n */\nfunction checkHookScripts(findings: DoctorFinding[], claudeDir: string, currentVersion: string): void {\n for (const id of HOOK_IDS) {\n const hookPath = join(claudeDir, \"hooks\", `${id}.sh`);\n if (!existsSync(hookPath)) {\n findings.push({ level: \"warning\", message: `Falta el hook hooks/${id}.sh. Corre argos init.` });\n continue;\n }\n\n const beforeCount = findings.length;\n const content = readFileSafe(hookPath, findings, `hooks/${id}.sh`);\n if (findings.length > beforeCount) continue; // read error already reported by readFileSafe\n\n if (!hasArgosShellFileMarker(content)) {\n findings.push({\n level: \"info\",\n message: `archivo ajeno en hooks/${id}.sh — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla, o corre \\`argos init --force\\` para reemplazarlo (con backup).`,\n });\n continue;\n }\n\n const hookVersion = extractShellMarkerVersion(content);\n if (!hookVersion) continue;\n const cmp = compareVersions(hookVersion, currentVersion);\n if (cmp < 0) {\n findings.push({\n level: \"warning\",\n message: `hooks/${id}.sh está desactualizado (v${hookVersion} < v${currentVersion}). Corre argos init.`,\n });\n } else if (cmp > 0) {\n findings.push({\n level: \"warning\",\n message: `hooks/${id}.sh es más nuevo que el binario (v${hookVersion} > v${currentVersion}) — el binario es más viejo que el motor instalado — actualiza el paquete (npm i -g).`,\n });\n }\n }\n}\n\n/**\n * Hooks (F2, motor scope): `settings.json` PreToolUse entries — missing,\n * orphaned (the entry's script file is gone), or the file itself unreadable\n * as valid JSON. Guarded reads throughout: never throws, always degrades to\n * an error finding so the rest of doctor's audit still runs.\n */\nfunction checkHookSettings(findings: DoctorFinding[], claudeDir: string): void {\n const settingsPath = join(claudeDir, \"settings.json\");\n if (!existsSync(settingsPath)) {\n for (const id of HOOK_IDS) {\n findings.push({ level: \"warning\", message: `Falta la entrada del hook ${id} en settings.json. Corre argos init.` });\n }\n return;\n }\n\n let raw: string;\n try {\n raw = readFileSync(settingsPath, \"utf-8\");\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer settings.json (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n\n let settings: unknown;\n try {\n settings = raw.trim().length === 0 ? {} : JSON.parse(raw);\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `settings.json tiene JSON inválido (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n\n const foundScriptPaths = new Set<string>();\n const hooksRoot = isPlainObject(settings) ? settings.hooks : undefined;\n const preToolUse = isPlainObject(hooksRoot) ? hooksRoot.PreToolUse : undefined;\n if (Array.isArray(preToolUse)) {\n for (const bucket of preToolUse) {\n if (!isPlainObject(bucket) || !Array.isArray(bucket.hooks)) continue;\n for (const hook of bucket.hooks) {\n if (!isPlainObject(hook) || !isArgosHookCommand(hook.command)) continue;\n const scriptPath = extractHookScriptPath(hook.command);\n if (!scriptPath) continue;\n foundScriptPaths.add(scriptPath);\n // `existsSync` alone is true for directories too — a settings.json\n // entry pointing at a directory (e.g. a failed write that left a\n // stray directory in the script's place) would otherwise read as\n // \"present\" here and slip past the orphan check.\n let isRealFile = false;\n try {\n isRealFile = existsSync(scriptPath) && statSync(scriptPath).isFile();\n } catch {\n isRealFile = false;\n }\n if (!isRealFile) {\n findings.push({\n level: \"warning\",\n message: `settings.json referencia el hook huérfano ${scriptPath} (el script ya no existe). Corre argos init.`,\n });\n }\n }\n }\n }\n\n for (const id of HOOK_IDS) {\n const expectedPath = join(claudeDir, \"hooks\", `${id}.sh`);\n if (!foundScriptPaths.has(expectedPath)) {\n findings.push({ level: \"warning\", message: `Falta la entrada del hook ${id} en settings.json. Corre argos init.` });\n }\n }\n}\n\n/**\n * Voice activation (spec 0004 \"Activación de la voz\"): Argos's own\n * output-style asset is installed on disk (`output-styles/argos.md`, with\n * the argos:file marker) but `settings.json.outputStyle` isn't `\"Argos\"` —\n * the voice is present but not the one Claude Code will actually load.\n * Read-only, guarded against a missing/corrupt settings.json (never throws).\n */\nfunction checkOutputStyleVoice(findings: DoctorFinding[], claudeDir: string): void {\n const outputStylePath = join(claudeDir, \"output-styles\", \"argos.md\");\n if (!existsSync(outputStylePath)) return; // nothing installed — checkMotor's own full-file check already covers this\n if (!hasArgosFileMarker(readFileSafe(outputStylePath, findings, \"output-styles/argos.md\"))) return; // foreign, not ours to opine on\n\n const settingsPath = join(claudeDir, \"settings.json\");\n if (!existsSync(settingsPath)) {\n findings.push({ level: \"warning\", message: \"La voz de Argos está instalada pero no activa. Corre argos init.\" });\n return;\n }\n\n let settings: unknown;\n try {\n const raw = readFileSync(settingsPath, \"utf-8\");\n settings = raw.trim().length === 0 ? {} : JSON.parse(raw);\n } catch {\n return; // settings.json's own JSON validity is already reported by checkHookSettings\n }\n\n const outputStyle = isPlainObject(settings) ? settings.outputStyle : undefined;\n if (outputStyle !== \"Argos\") {\n findings.push({ level: \"warning\", message: \"La voz de Argos está instalada pero no activa. Corre argos init.\" });\n }\n}\n\n/**\n * Workspaces (F2, motor scope): `~/.argos/workspaces.json` registry entries\n * whose repo path no longer exists on disk (moved/deleted repo). Guarded\n * against a corrupt registry file — never throws.\n */\nfunction checkWorkspaceRegistryHealth(findings: DoctorFinding[]): void {\n let registry: ReturnType<typeof loadRegistry>;\n try {\n registry = loadRegistry();\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer workspaces.json (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n\n const stale: string[] = [];\n for (const [wsName, ws] of Object.entries(registry)) {\n for (const repo of ws.repos) {\n if (!existsSync(repo.path)) stale.push(`${wsName}/${repo.name} (${repo.path})`);\n }\n }\n if (stale.length > 0) {\n findings.push({\n level: \"warning\",\n message: `Hay repos registrados en workspaces con paths inexistentes: ${stale.join(\", \")}. Corre argos workspace link o editá el registro a mano.`,\n });\n }\n}\n\n/**\n * Flag dangling/unclosed managed-block markers (an open marker with no\n * matching close — crash residue or hand-edited corruption) as a warning.\n * Reuses `listDanglingBlockIds` (lib/markers.ts) — the same scanning logic\n * `remove`'s progress-guard relies on to avoid spinning forever on the same\n * corruption (see commands/remove.ts's processClaudeMd).\n */\nfunction checkDanglingMarkers(findings: DoctorFinding[], content: string, label: string): void {\n for (const id of listDanglingBlockIds(content)) {\n findings.push({\n level: \"warning\",\n message: `Marker argos huérfano sin cierre en ${label} (bloque \"${id}\"). Corre argos remove para limpiarlo, o editá el archivo a mano.`,\n });\n }\n}\n\nfunction checkMotor(findings: DoctorFinding[]): void {\n const claudeDir = resolveClaudeDir();\n const currentVersion = readCliVersion();\n const assetsDir = resolveAssetsDir();\n\n const claudeMdPath = join(claudeDir, \"CLAUDE.md\");\n const claudeMd = readFileSafe(claudeMdPath, findings, \"CLAUDE.md\");\n const blocks = listBlocks(claudeMd);\n\n checkDanglingMarkers(findings, claudeMd, \"CLAUDE.md\");\n\n for (const id of MANAGED_BLOCK_IDS) {\n const matching = blocks.filter((b) => b.id === id);\n if (matching.length > 1) {\n findings.push({\n level: \"warning\",\n message: `El bloque \"${id}\" está duplicado (${matching.length} veces) en CLAUDE.md. Corre argos init para sanearlo.`,\n });\n }\n\n const block = matching[0];\n if (!block) {\n findings.push({ level: \"error\", message: `Falta el bloque managed \"${id}\" en CLAUDE.md. Corre argos init.` });\n continue;\n }\n if (block.version) {\n const cmp = compareVersions(block.version, currentVersion);\n if (cmp < 0) {\n findings.push({\n level: \"warning\",\n message: `El bloque \"${id}\" está desactualizado (v${block.version} < v${currentVersion}). Corre argos init.`,\n });\n } else if (cmp > 0) {\n findings.push({\n level: \"warning\",\n message: `El bloque \"${id}\" es más nuevo que el binario (v${block.version} > v${currentVersion}) — el binario es más viejo que el motor instalado — actualiza el paquete (npm i -g).`,\n });\n }\n }\n }\n\n const fullFiles: string[][] = [\n [\"output-styles\", \"argos.md\"],\n ...listAgentIds(assetsDir).map((id) => [\"agents\", `${id}.md`]),\n ...listSkillIds(assetsDir).map((id) => [\"skills\", id, \"SKILL.md\"]),\n ];\n for (const relPath of fullFiles) {\n const dest = join(claudeDir, ...relPath);\n const label = join(...relPath);\n if (!existsSync(dest)) {\n findings.push({ level: \"error\", message: `Falta ${label} en el motor. Corre argos init.` });\n continue;\n }\n const content = readFileSync(dest, \"utf-8\");\n if (!hasArgosFileMarker(content)) {\n findings.push({\n level: \"info\",\n message: `archivo ajeno en ${label} — hay versión del motor disponible pero está bloqueada; muévelo o bórralo y corre argos init para instalarla, o corre \\`argos init --force\\` para reemplazarlo (con backup).`,\n });\n }\n }\n\n checkHookScripts(findings, claudeDir, currentVersion);\n checkHookSettings(findings, claudeDir);\n checkOutputStyleVoice(findings, claudeDir);\n checkWorkspaceRegistryHealth(findings);\n}\n\nfunction checkRepo(cwd: string, findings: DoctorFinding[]): void {\n if (!hasConfig(cwd)) return;\n\n const configPath = join(cwd, \"argos.config.json\");\n let config: z.infer<typeof ArgosConfigSchema> | undefined;\n try {\n const raw: unknown = JSON.parse(readFileSync(configPath, \"utf-8\"));\n config = ArgosConfigSchema.parse(raw);\n } catch (error) {\n for (const message of describeZodError(error)) {\n findings.push({ level: \"error\", message: `argos.config.json inválido — ${message}` });\n }\n return;\n }\n\n if (hasNaviorConfig(cwd)) {\n findings.push({\n level: \"info\",\n message: \"navori.config.json coexiste con argos.config.json (migración en curso).\",\n });\n }\n\n if (config.qualityGate.fast === NO_GATE_PLACEHOLDER) {\n findings.push({\n level: \"warning\",\n message: \"quality gate placeholder — configura scripts y corre argos adopt --refresh.\",\n });\n }\n\n // Ficha drift: does ./CLAUDE.md's ficha block match what adopt would write today?\n const claudeMdPath = join(cwd, \"CLAUDE.md\");\n const claudeMd = readFileSafe(claudeMdPath, findings, \"./CLAUDE.md\");\n checkDanglingMarkers(findings, claudeMd, \"./CLAUDE.md\");\n const fichaBlocks = listBlocks(claudeMd).filter((b) => b.id === FICHA_BLOCK_ID);\n if (fichaBlocks.length > 1) {\n findings.push({\n level: \"warning\",\n message: `La ficha está duplicada (${fichaBlocks.length} veces) en ./CLAUDE.md. Corre argos adopt --refresh para sanearla.`,\n });\n }\n const fichaBlock = fichaBlocks[0];\n if (!fichaBlock) {\n findings.push({ level: \"warning\", message: \"Falta la ficha en ./CLAUDE.md. Corre argos adopt --refresh.\" });\n } else {\n const expectedFicha = buildFichaContent(config);\n if (!claudeMd.includes(expectedFicha)) {\n findings.push({ level: \"warning\", message: \"La ficha de ./CLAUDE.md quedó vieja. Corre argos adopt --refresh.\" });\n }\n }\n\n // Stack drift: new relevant libs in package.json not yet recorded.\n const pkg = readPackageJson(cwd);\n if (pkg) {\n const recordedLibs = new Set(config.stack?.libs ?? []);\n const freshLibs = detectLibs(pkg);\n const newLibs = freshLibs.filter((lib) => !recordedLibs.has(lib));\n if (newLibs.length > 0) {\n findings.push({\n level: \"warning\",\n message: `Nuevas libs detectadas sin registrar (${newLibs.join(\", \")}). Corre argos adopt --refresh.`,\n });\n }\n\n const freshFramework = detectFramework(pkg);\n if (freshFramework && config.stack?.framework && freshFramework !== config.stack.framework) {\n findings.push({\n level: \"warning\",\n message: `El framework detectado (${freshFramework}) difiere del registrado (${config.stack.framework}). Corre argos adopt --refresh.`,\n });\n }\n\n const freshPackageManager = detectPackageManager(cwd);\n if (\n freshPackageManager &&\n config.stack?.packageManager &&\n freshPackageManager !== config.stack.packageManager\n ) {\n findings.push({\n level: \"warning\",\n message: `El package manager detectado (${freshPackageManager}) difiere del registrado (${config.stack.packageManager}). Corre argos adopt --refresh.`,\n });\n }\n }\n\n // Identity drift: current git remote vs the identity recorded in config.\n const remoteUrl = getRemoteOriginUrl(cwd);\n const freshIdentity = remoteUrl ? (parseIdentityFromRemote(remoteUrl) ?? undefined) : undefined;\n if (freshIdentity && config.identity && freshIdentity !== config.identity) {\n findings.push({\n level: \"warning\",\n message: `La identidad detectada (${freshIdentity}) difiere de la registrada (${config.identity}). Corre argos adopt --refresh.`,\n });\n }\n\n // Workspace linkage (F2): repo not registered, registered under a stale\n // path, or config.workspace pointing at a name absent from the registry.\n let registry: ReturnType<typeof loadRegistry>;\n try {\n registry = loadRegistry();\n } catch (err) {\n findings.push({\n level: \"error\",\n message: `No se pudo leer workspaces.json (${err instanceof Error ? err.message : String(err)}).`,\n });\n return;\n }\n const resolution = resolveWorkspaceForRepo(registry, {\n configWorkspace: config.workspace,\n remoteUrl,\n repoPath: cwd,\n });\n\n if (resolution.kind === \"unresolved\") {\n findings.push({\n level: \"info\",\n message: \"El repo no está vinculado a ningún workspace. Corre argos workspace link.\",\n });\n } else if (resolution.kind === \"resolved\") {\n const workspace = registry[resolution.name];\n if (!workspace) {\n findings.push({\n level: \"warning\",\n message: `argos.config.json referencia el workspace '${resolution.name}', que no existe en el registro. Corre argos workspace link ${resolution.name}.`,\n });\n } else {\n const entry = workspace.repos.find((r) => r.name === config.name);\n if (!entry) {\n findings.push({\n level: \"info\",\n message: \"El repo no está vinculado a ningún workspace. Corre argos workspace link.\",\n });\n } else {\n let realCwd: string | undefined;\n try {\n realCwd = realpathSync(resolve(cwd));\n } catch {\n realCwd = undefined;\n }\n if (realCwd && entry.path !== realCwd) {\n findings.push({\n level: \"warning\",\n message: `El repo está registrado en el workspace '${resolution.name}' con un path distinto (${entry.path} vs ${realCwd}). Corre argos workspace link para actualizarlo.`,\n });\n }\n }\n }\n }\n}\n\n/**\n * Core, testable implementation of `argos doctor`: a read-only audit of the\n * global engine and (when cwd is a git repo) the repo's argos.config.json +\n * ficha. Never writes anything.\n */\nexport function runDoctor(options: DoctorOptions): DoctorReport {\n const findings: DoctorFinding[] = [];\n\n checkMotor(findings);\n if (isGitRepo(options.cwd)) {\n checkRepo(options.cwd, findings);\n }\n\n const exitCode = findings.some((f) => f.level !== \"info\") ? 1 : 0;\n return { findings, exitCode };\n}\n\nexport const doctorCommand = defineCommand({\n meta: {\n name: \"doctor\",\n description: \"Report drift between the engine, the repo config, and its ficha.\",\n },\n run() {\n const report = runDoctor({ cwd: process.cwd() });\n\n if (report.findings.length === 0) {\n console.log(\"Todo al día.\");\n process.exit(0);\n }\n\n for (const finding of report.findings) {\n const padded = finding.level.padEnd(10);\n const label = finding.level === \"error\" ? pc.red(padded) : finding.level === \"warning\" ? pc.yellow(padded) : pc.dim(padded);\n console.log(`${label} ${finding.message}`);\n }\n\n process.exit(report.exitCode);\n },\n});\n"],"names":["defineCommand","existsSync","readFileSync","realpathSync","statSync","join","resolve","pc","ArgosConfigSchema","hasConfig","detectFramework","detectLibs","detectPackageManager","readPackageJson","buildFichaContent","FICHA_BLOCK_ID","getRemoteOriginUrl","isGitRepo","parseIdentityFromRemote","listAgentIds","listSkillIds","MANAGED_BLOCK_IDS","resolveAssetsDir","listBlocks","listDanglingBlockIds","hasArgosFileMarker","hasArgosShellFileMarker","hasNaviorConfig","resolveClaudeDir","isArgosHookCommand","readCliVersion","loadRegistry","resolveWorkspaceForRepo","describeZodError","NO_GATE_PLACEHOLDER","readFileSafe","path","findings","label","err","push","level","message","Error","String","compareVersions","a","b","pa","split","map","n","Number","parseInt","pb","i","Math","max","length","diff","HOOK_IDS","extractShellMarkerVersion","content","exec","extractHookScriptPath","command","isPlainObject","v","Array","isArray","checkHookScripts","claudeDir","currentVersion","id","hookPath","beforeCount","hookVersion","cmp","checkHookSettings","settingsPath","raw","settings","trim","JSON","parse","foundScriptPaths","Set","hooksRoot","hooks","undefined","preToolUse","PreToolUse","bucket","hook","scriptPath","add","isRealFile","isFile","expectedPath","has","checkOutputStyleVoice","outputStylePath","outputStyle","checkWorkspaceRegistryHealth","registry","stale","wsName","ws","Object","entries","repo","repos","name","checkDanglingMarkers","checkMotor","assetsDir","claudeMdPath","claudeMd","blocks","matching","filter","block","version","fullFiles","relPath","dest","checkRepo","cwd","configPath","config","error","qualityGate","fast","fichaBlocks","fichaBlock","expectedFicha","includes","pkg","recordedLibs","stack","libs","freshLibs","newLibs","lib","freshFramework","framework","freshPackageManager","packageManager","remoteUrl","freshIdentity","identity","resolution","configWorkspace","workspace","repoPath","kind","entry","find","r","realCwd","runDoctor","options","exitCode","some","f","doctorCommand","meta","description","run","report","process","console","log","exit","finding","padded","padEnd","red","yellow","dim"],"mappings":"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"}
@@ -24,6 +24,19 @@ export interface InitOptions {
24
24
  * takeover prompt.
25
25
  */
26
26
  takeoverNavoriVoice?: boolean;
27
+ /**
28
+ * `argos init --force`: full-file motor assets (skills incl. every
29
+ * manifest subfile, agents, output-styles, hooks) that exist on disk
30
+ * WITHOUT an `argos:file` ownership marker — normally left untouched,
31
+ * reported `skipped-foreign` — get overwritten with the motor version
32
+ * instead, reported `overwritten-foreign`. The marker lands with the
33
+ * write, so a later (non-forced) `init` treats them as owned from then on.
34
+ * Does NOT cross into CLAUDE.md prose (managed-block injection stays
35
+ * own-blocks-only) or foreign `settings.json` entries (surgical merge is
36
+ * unchanged) — force only ever replaces whole files at motor paths.
37
+ * Default `false`.
38
+ */
39
+ force?: boolean;
27
40
  }
28
41
  export interface InitReport {
29
42
  rows: InitRow[];
@@ -66,5 +79,10 @@ export declare const initCommand: import("citty").CommandDef<{
66
79
  readonly default: false;
67
80
  readonly description: "Fuerza modo no interactivo aunque haya una TTY real (defaults + flags, sin wizard).";
68
81
  };
82
+ readonly force: {
83
+ readonly type: "boolean";
84
+ readonly default: false;
85
+ readonly description: "Sobrescribe con la versión del motor los archivos ajenos (sin marker argos) en agents/skills/output-styles/hooks. No toca prosa ajena de CLAUDE.md ni entradas ajenas de settings.json.";
86
+ };
69
87
  }>;
70
88
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,yBAAyB,CAAC;AAQjC,OAAO,EAAgC,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAqBjF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oFAAoF;IACpF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAqDD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,WAAgB,GAAG,UAAU,CA2L7D;AAED,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,sEAAsE;IACtE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAgCD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,UAAU,CAAC,CAsFlG;AAED,eAAO,MAAM,WAAW;;;;;;;;;;;;EA8CtB,CAAC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,KAAK,UAAU,EAKhB,MAAM,yBAAyB,CAAC;AAQjC,OAAO,EAAgC,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAqBjF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oFAAoF;IACpF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA8ED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,WAAgB,GAAG,UAAU,CAqM7D;AAED,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,sEAAsE;IACtE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAiFD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,UAAU,CAAC,CA4GlG;AAED,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;EA0DtB,CAAC"}
@@ -6,7 +6,7 @@ import { listAgentIds, listSkillFiles, listSkillIds, MANAGED_BLOCK_IDS, readAsse
6
6
  import { writeFileAtomic } from "../lib/atomic-write.js";
7
7
  import { createBackup } from "../lib/backup.js";
8
8
  import { injectBlock, listBlocks } from "../lib/markers.js";
9
- import { hasArgosFileMarker, writeManagedFile, writeManagedShellFile } from "../lib/managed-files.js";
9
+ import { hasArgosFileMarker, hasArgosShellFileMarker, writeManagedFile, writeManagedShellFile } from "../lib/managed-files.js";
10
10
  import { resolveArgosHome, resolveClaudeDir } from "../lib/paths.js";
11
11
  import { applyOutputStylePolicy, isNavoriOutputStyle, mergeHooksIntoSettings } from "../lib/settings-merge.js";
12
12
  import { isInteractive, clackPrompter } from "../lib/prompter.js";
@@ -33,6 +33,7 @@ const STATUS_COUNT_ORDER = [
33
33
  "updated",
34
34
  "unchanged",
35
35
  "skipped-foreign",
36
+ "overwritten-foreign",
36
37
  "error"
37
38
  ];
38
39
  function summarize(rows) {
@@ -41,6 +42,7 @@ function summarize(rows) {
41
42
  updated: 0,
42
43
  unchanged: 0,
43
44
  "skipped-foreign": 0,
45
+ "overwritten-foreign": 0,
44
46
  error: 0
45
47
  };
46
48
  for (const row of rows)counts[row.status]++;
@@ -71,6 +73,23 @@ function errorMessage(err) {
71
73
  writeFileAtomic(destPath, sourceContent);
72
74
  return "updated";
73
75
  }
76
+ /**
77
+ * `--force` counterpart to `writePlainFile`, used only for a supporting file
78
+ * (e.g. `references/core.md`) that lives under a skill directory whose
79
+ * `SKILL.md` was just detected as foreign (no `argos:file` marker). These
80
+ * plain subfiles never carry a marker of their own — the whole skill
81
+ * directory's ownership is decided once from `SKILL.md` (see the skills loop
82
+ * below) — so this always overwrites unconditionally: `overwritten-foreign`
83
+ * when something was already there to replace, `created` when the motor
84
+ * ships a subfile the foreign directory never had.
85
+ */ function writeForcedPlainFile(destPath, sourceContent) {
86
+ const existed = existsSync(destPath);
87
+ if (!existed) mkdirSync(dirname(destPath), {
88
+ recursive: true
89
+ });
90
+ writeFileAtomic(destPath, sourceContent);
91
+ return existed ? "overwritten-foreign" : "created";
92
+ }
74
93
  /** Inject one managed CLAUDE.md block, reporting created/updated/unchanged. */ function injectAndReport(claudeMd, id, version, content) {
75
94
  const hadBlock = listBlocks(claudeMd).some((b)=>b.id === id);
76
95
  const after = injectBlock(claudeMd, id, version, content);
@@ -89,6 +108,7 @@ function errorMessage(err) {
89
108
  const language = options.language ?? "es";
90
109
  const installAgents = options.installAgents ?? true;
91
110
  const installHooks = options.installHooks ?? true;
111
+ const force = options.force ?? false;
92
112
  const version = readCliVersion();
93
113
  const claudeDir = resolveClaudeDir();
94
114
  const assetsDir = resolveAssetsDir();
@@ -168,7 +188,9 @@ function errorMessage(err) {
168
188
  const source = readAsset(assetsDir, ...relPath);
169
189
  const dest = join(claudeDir, ...relPath);
170
190
  try {
171
- const status = writeManagedFile(dest, source, version);
191
+ const status = writeManagedFile(dest, source, version, {
192
+ force
193
+ });
172
194
  rows.push({
173
195
  path: join(...relPath),
174
196
  status
@@ -188,14 +210,18 @@ function errorMessage(err) {
188
210
  // file the skill ships.
189
211
  // - SKILL.md present WITHOUT the marker (foreign/user-modified) → skip
190
212
  // every file under that skill dir, untouched — same policy as a single
191
- // foreign full-file asset above, extended to the whole directory.
213
+ // foreign full-file asset above, extended to the whole directory. Under
214
+ // `--force`, every file in that directory is overwritten instead
215
+ // (`overwritten-foreign`) — SKILL.md gets its marker stamped via
216
+ // `writeManagedFile`'s own `force` path, and each plain subfile is
217
+ // force-written via `writeForcedPlainFile` (see its own doc comment).
192
218
  for (const skillId of listSkillIds(assetsDir)){
193
219
  const skillMdDest = join(claudeDir, "skills", skillId, "SKILL.md");
194
220
  const isForeignSkill = existsSync(skillMdDest) && !hasArgosFileMarker(readFileSync(skillMdDest, "utf-8"));
195
221
  for (const relFile of listSkillFiles(assetsDir, skillId)){
196
222
  const relParts = relFile.split("/");
197
223
  const relPath = join("skills", skillId, ...relParts);
198
- if (isForeignSkill) {
224
+ if (isForeignSkill && !force) {
199
225
  rows.push({
200
226
  path: relPath,
201
227
  status: "skipped-foreign"
@@ -205,7 +231,9 @@ function errorMessage(err) {
205
231
  const source = readAsset(assetsDir, "skills", skillId, ...relParts);
206
232
  const dest = join(claudeDir, "skills", skillId, ...relParts);
207
233
  try {
208
- const status = relFile === "SKILL.md" ? writeManagedFile(dest, source, version) : writePlainFile(dest, source);
234
+ const status = relFile === "SKILL.md" ? writeManagedFile(dest, source, version, {
235
+ force
236
+ }) : isForeignSkill ? writeForcedPlainFile(dest, source) : writePlainFile(dest, source);
209
237
  rows.push({
210
238
  path: relPath,
211
239
  status
@@ -241,7 +269,9 @@ function errorMessage(err) {
241
269
  const source = readAsset(assetsDir, ...relPath);
242
270
  const dest = join(claudeDir, ...relPath);
243
271
  try {
244
- const status = writeManagedShellFile(dest, source, version);
272
+ const status = writeManagedShellFile(dest, source, version, {
273
+ force
274
+ });
245
275
  rows.push({
246
276
  path: join(...relPath),
247
277
  status
@@ -373,6 +403,50 @@ function errorMessage(err) {
373
403
  return undefined;
374
404
  }
375
405
  }
406
+ /**
407
+ * Read-only `--force` pre-flight: counts how many on-disk paths at motor
408
+ * paths (output-style, agents, skills incl. every manifest subfile, hooks)
409
+ * are foreign (no `argos:file`/shell marker) and would therefore be
410
+ * overwritten by a forced `runInit`. Used only by the interactive wizard to
411
+ * size its confirm prompt — the actual overwrite decision and write happen
412
+ * inside `runInit` itself, independently, so this can never drift into
413
+ * writing anything. Mirrors the same directory-ownership rule `runInit`'s
414
+ * own skills loop uses (SKILL.md's marker decides the whole directory), and
415
+ * — like `doctor.ts`'s own read-only checks — intentionally duplicates that
416
+ * iteration shape rather than sharing private state with the writer.
417
+ */ function countForceOverwrites(claudeDir, assetsDir, installAgents, installHooks) {
418
+ let count = 0;
419
+ const fullFiles = [
420
+ [
421
+ "output-styles",
422
+ "argos.md"
423
+ ],
424
+ ...installAgents ? listAgentIds(assetsDir).map((id)=>[
425
+ "agents",
426
+ `${id}.md`
427
+ ]) : []
428
+ ];
429
+ for (const relPath of fullFiles){
430
+ const dest = join(claudeDir, ...relPath);
431
+ if (existsSync(dest) && !hasArgosFileMarker(readFileSync(dest, "utf-8"))) count++;
432
+ }
433
+ for (const skillId of listSkillIds(assetsDir)){
434
+ const skillMdDest = join(claudeDir, "skills", skillId, "SKILL.md");
435
+ const isForeignSkill = existsSync(skillMdDest) && !hasArgosFileMarker(readFileSync(skillMdDest, "utf-8"));
436
+ if (!isForeignSkill) continue;
437
+ for (const relFile of listSkillFiles(assetsDir, skillId)){
438
+ const dest = join(claudeDir, "skills", skillId, ...relFile.split("/"));
439
+ if (existsSync(dest)) count++;
440
+ }
441
+ }
442
+ if (installHooks) {
443
+ for (const id of HOOK_IDS){
444
+ const dest = join(claudeDir, "hooks", `${id}.sh`);
445
+ if (existsSync(dest) && !hasArgosShellFileMarker(readFileSync(dest, "utf-8"))) count++;
446
+ }
447
+ }
448
+ return count;
449
+ }
376
450
  /**
377
451
  * Interactive layer over `runInit` (spec 0004 F5 "argos init"). A pure
378
452
  * additive wrapper — the core `runInit` never changes behavior or contract.
@@ -424,6 +498,26 @@ function errorMessage(err) {
424
498
  return cancelledInitReport();
425
499
  }
426
500
  const claudeDir = resolveClaudeDir();
501
+ // `--force` pre-flight (see `InitOptions.force`'s doc comment): flag-driven,
502
+ // not itself a wizard question. When active, count how many on-disk paths
503
+ // are foreign and about to be overwritten (read-only — see
504
+ // `countForceOverwrites`) and, only if that count is > 0, require an
505
+ // explicit confirm before proceeding. Zero foreign paths means force has
506
+ // nothing to do this run, so no extra prompt.
507
+ const force = options.force ?? false;
508
+ if (force) {
509
+ const foreignCount = countForceOverwrites(claudeDir, resolveAssetsDir(), installAgents, installHooks);
510
+ if (foreignCount > 0) {
511
+ const confirmForce = await prompter.confirm({
512
+ message: `${foreignCount} archivos ajenos serán sobrescritos por versiones del motor — backup previo en ~/.argos/backups. ¿Continuar?`,
513
+ initialValue: false
514
+ });
515
+ if (prompter.isCancel(confirmForce) || !confirmForce) {
516
+ prompter.cancel("argos init cancelado — no se tocó nada.");
517
+ return cancelledInitReport();
518
+ }
519
+ }
520
+ }
427
521
  // Voice activation (spec 0004): if the current settings.json.outputStyle
428
522
  // matches the predecessor harness's voice, ask before taking it over —
429
523
  // this peek is read-only and never writes; the actual takeover only
@@ -461,7 +555,8 @@ function errorMessage(err) {
461
555
  language,
462
556
  installAgents,
463
557
  installHooks,
464
- takeoverNavoriVoice
558
+ takeoverNavoriVoice,
559
+ force
465
560
  });
466
561
  prompter.outro(report.summary);
467
562
  return report;
@@ -485,18 +580,26 @@ export const initCommand = defineCommand({
485
580
  type: "boolean",
486
581
  default: false,
487
582
  description: "Fuerza modo no interactivo aunque haya una TTY real (defaults + flags, sin wizard)."
583
+ },
584
+ force: {
585
+ type: "boolean",
586
+ default: false,
587
+ description: "Sobrescribe con la versión del motor los archivos ajenos (sin marker argos) en agents/skills/output-styles/hooks. No toca prosa ajena de CLAUDE.md ni entradas ajenas de settings.json."
488
588
  }
489
589
  },
490
590
  async run ({ args }) {
491
591
  const report = await runInitInteractive({
492
592
  language: args.language,
493
- yes: Boolean(args.yes)
593
+ yes: Boolean(args.yes),
594
+ force: Boolean(args.force)
494
595
  });
495
596
  const colorize = (status)=>{
496
597
  const padded = status.padEnd(18);
497
598
  switch(status){
498
599
  case "skipped-foreign":
499
600
  return pc.yellow(padded);
601
+ case "overwritten-foreign":
602
+ return pc.magenta(padded);
500
603
  case "created":
501
604
  return pc.green(padded);
502
605
  case "updated":
@@ -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 {\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
+ {"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 hasArgosShellFileMarker,\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 * `argos init --force`: full-file motor assets (skills incl. every\n * manifest subfile, agents, output-styles, hooks) that exist on disk\n * WITHOUT an `argos:file` ownership marker — normally left untouched,\n * reported `skipped-foreign` — get overwritten with the motor version\n * instead, reported `overwritten-foreign`. The marker lands with the\n * write, so a later (non-forced) `init` treats them as owned from then on.\n * Does NOT cross into CLAUDE.md prose (managed-block injection stays\n * own-blocks-only) or foreign `settings.json` entries (surgical merge is\n * unchanged) — force only ever replaces whole files at motor paths.\n * Default `false`.\n */\n force?: 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[] = [\n \"created\",\n \"updated\",\n \"unchanged\",\n \"skipped-foreign\",\n \"overwritten-foreign\",\n \"error\",\n];\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 \"overwritten-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/**\n * `--force` counterpart to `writePlainFile`, used only for a supporting file\n * (e.g. `references/core.md`) that lives under a skill directory whose\n * `SKILL.md` was just detected as foreign (no `argos:file` marker). These\n * plain subfiles never carry a marker of their own — the whole skill\n * directory's ownership is decided once from `SKILL.md` (see the skills loop\n * below) — so this always overwrites unconditionally: `overwritten-foreign`\n * when something was already there to replace, `created` when the motor\n * ships a subfile the foreign directory never had.\n */\nfunction writeForcedPlainFile(destPath: string, sourceContent: string): FileStatus {\n const existed = existsSync(destPath);\n if (!existed) mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, sourceContent);\n return existed ? \"overwritten-foreign\" : \"created\";\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 force = options.force ?? false;\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, { force });\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. Under\n // `--force`, every file in that directory is overwritten instead\n // (`overwritten-foreign`) — SKILL.md gets its marker stamped via\n // `writeManagedFile`'s own `force` path, and each plain subfile is\n // force-written via `writeForcedPlainFile` (see its own doc comment).\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 && !force) {\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 =\n relFile === \"SKILL.md\"\n ? writeManagedFile(dest, source, version, { force })\n : isForeignSkill\n ? writeForcedPlainFile(dest, source)\n : 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, { force });\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 * Read-only `--force` pre-flight: counts how many on-disk paths at motor\n * paths (output-style, agents, skills incl. every manifest subfile, hooks)\n * are foreign (no `argos:file`/shell marker) and would therefore be\n * overwritten by a forced `runInit`. Used only by the interactive wizard to\n * size its confirm prompt — the actual overwrite decision and write happen\n * inside `runInit` itself, independently, so this can never drift into\n * writing anything. Mirrors the same directory-ownership rule `runInit`'s\n * own skills loop uses (SKILL.md's marker decides the whole directory), and\n * — like `doctor.ts`'s own read-only checks — intentionally duplicates that\n * iteration shape rather than sharing private state with the writer.\n */\nfunction countForceOverwrites(\n claudeDir: string,\n assetsDir: string,\n installAgents: boolean,\n installHooks: boolean,\n): number {\n let count = 0;\n\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 dest = join(claudeDir, ...relPath);\n if (existsSync(dest) && !hasArgosFileMarker(readFileSync(dest, \"utf-8\"))) count++;\n }\n\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 if (!isForeignSkill) continue;\n for (const relFile of listSkillFiles(assetsDir, skillId)) {\n const dest = join(claudeDir, \"skills\", skillId, ...relFile.split(\"/\"));\n if (existsSync(dest)) count++;\n }\n }\n\n if (installHooks) {\n for (const id of HOOK_IDS) {\n const dest = join(claudeDir, \"hooks\", `${id}.sh`);\n if (existsSync(dest) && !hasArgosShellFileMarker(readFileSync(dest, \"utf-8\"))) count++;\n }\n }\n\n return count;\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 // `--force` pre-flight (see `InitOptions.force`'s doc comment): flag-driven,\n // not itself a wizard question. When active, count how many on-disk paths\n // are foreign and about to be overwritten (read-only — see\n // `countForceOverwrites`) and, only if that count is > 0, require an\n // explicit confirm before proceeding. Zero foreign paths means force has\n // nothing to do this run, so no extra prompt.\n const force = options.force ?? false;\n if (force) {\n const foreignCount = countForceOverwrites(claudeDir, resolveAssetsDir(), installAgents, installHooks);\n if (foreignCount > 0) {\n const confirmForce = await prompter.confirm({\n message: `${foreignCount} archivos ajenos serán sobrescritos por versiones del motor — backup previo en ~/.argos/backups. ¿Continuar?`,\n initialValue: false,\n });\n if (prompter.isCancel(confirmForce) || !confirmForce) {\n prompter.cancel(\"argos init cancelado — no se tocó nada.\");\n return cancelledInitReport();\n }\n }\n }\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 force,\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 force: {\n type: \"boolean\",\n default: false,\n description:\n \"Sobrescribe con la versión del motor los archivos ajenos (sin marker argos) en agents/skills/output-styles/hooks. No toca prosa ajena de CLAUDE.md ni entradas ajenas de settings.json.\",\n },\n },\n async run({ args }) {\n const report = await runInitInteractive({\n language: args.language as \"es\" | \"en\",\n yes: Boolean(args.yes),\n force: Boolean(args.force),\n });\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 \"overwritten-foreign\":\n return pc.magenta(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","hasArgosShellFileMarker","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","writeForcedPlainFile","existed","injectAndReport","claudeMd","id","version","content","hadBlock","some","b","after","runInit","options","language","installAgents","installHooks","force","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","countForceOverwrites","count","runInitInteractive","yes","prompter","intro","select","value","label","initialValue","isCancel","cancel","confirm","foreignCount","confirmForce","currentOutputStyle","takeover","note","proceed","report","outro","initCommand","meta","name","description","args","type","default","run","Boolean","colorize","padded","padEnd","yellow","magenta","green","cyan","red","dim","suffix","console","log","process","exit"],"mappings":"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"}
@@ -8,15 +8,27 @@ export declare function hasArgosFileMarker(content: string): boolean;
8
8
  * Falls back to prefixing the marker when there is no frontmatter.
9
9
  */
10
10
  export declare function withFileMarker(content: string, version: string): string;
11
- export type FileStatus = "created" | "updated" | "unchanged" | "skipped-foreign";
11
+ export type FileStatus = "created" | "updated" | "unchanged" | "skipped-foreign" | "overwritten-foreign";
12
+ export interface WriteManagedFileOptions {
13
+ /**
14
+ * `argos init --force`: when the destination exists WITHOUT the
15
+ * ownership marker (foreign), overwrite it with the motor version instead
16
+ * of skipping it. The marker lands with this write, so a subsequent
17
+ * (non-forced) run treats the file as owned from then on. Default `false`
18
+ * — the pre-existing skip-foreign behavior.
19
+ */
20
+ force?: boolean;
21
+ }
12
22
  /**
13
23
  * Write a full-file Argos-owned asset (agent, skill, output-style) to
14
24
  * `destPath`, honoring the ownership marker policy:
15
25
  * - absent → write it (created)
16
26
  * - present with the argos:file marker → overwrite (updated/unchanged)
17
- * - present without the marker (foreign) → never touch it (skipped-foreign)
27
+ * - present without the marker (foreign) → never touch it (skipped-foreign),
28
+ * unless `options.force` is set, in which case it's overwritten
29
+ * (overwritten-foreign) and stamped with the marker.
18
30
  */
19
- export declare function writeManagedFile(destPath: string, sourceContent: string, version: string): FileStatus;
31
+ export declare function writeManagedFile(destPath: string, sourceContent: string, version: string, options?: WriteManagedFileOptions): FileStatus;
20
32
  /** True when `content` carries a shell-comment `# argos:file` ownership marker (any version). */
21
33
  export declare function hasArgosShellFileMarker(content: string): boolean;
22
34
  /**
@@ -29,7 +41,9 @@ export declare function hasArgosShellFileMarker(content: string): boolean;
29
41
  * the result executable (0o755). Same ownership policy as `writeManagedFile`:
30
42
  * - absent → write it (created)
31
43
  * - present with the shell marker → overwrite (updated/unchanged)
32
- * - present without the marker (foreign) → never touch it (skipped-foreign)
44
+ * - present without the marker (foreign) → never touch it (skipped-foreign),
45
+ * unless `options.force` is set, in which case it's overwritten
46
+ * (overwritten-foreign) and stamped with the marker.
33
47
  */
34
- export declare function writeManagedShellFile(destPath: string, sourceContent: string, version: string): FileStatus;
48
+ export declare function writeManagedShellFile(destPath: string, sourceContent: string, version: string, options?: WriteManagedFileOptions): FileStatus;
35
49
  //# sourceMappingURL=managed-files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/lib/managed-files.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAM7D,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAOvE;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,iBAAiB,CAAC;AAEjF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAerG;AAED,iGAAiG;AACjG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CA6B1G"}
1
+ {"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/lib/managed-files.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAM7D,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAOvE;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,iBAAiB,GAAG,qBAAqB,CAAC;AAEzG,MAAM,WAAW,uBAAuB;IACtC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,uBAA4B,GACpC,UAAU,CAmBZ;AAED,iGAAiG;AACjG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,uBAA4B,GACpC,UAAU,CAiCZ"}
@@ -35,8 +35,10 @@ function fileMarker(version) {
35
35
  * `destPath`, honoring the ownership marker policy:
36
36
  * - absent → write it (created)
37
37
  * - present with the argos:file marker → overwrite (updated/unchanged)
38
- * - present without the marker (foreign) → never touch it (skipped-foreign)
39
- */ export function writeManagedFile(destPath, sourceContent, version) {
38
+ * - present without the marker (foreign) → never touch it (skipped-foreign),
39
+ * unless `options.force` is set, in which case it's overwritten
40
+ * (overwritten-foreign) and stamped with the marker.
41
+ */ export function writeManagedFile(destPath, sourceContent, version, options = {}) {
40
42
  const finalContent = withFileMarker(sourceContent, version);
41
43
  if (!existsSync(destPath)) {
42
44
  mkdirSync(dirname(destPath), {
@@ -46,7 +48,11 @@ function fileMarker(version) {
46
48
  return "created";
47
49
  }
48
50
  const current = readFileSync(destPath, "utf-8");
49
- if (!hasArgosFileMarker(current)) return "skipped-foreign";
51
+ if (!hasArgosFileMarker(current)) {
52
+ if (!options.force) return "skipped-foreign";
53
+ writeFileAtomic(destPath, finalContent);
54
+ return "overwritten-foreign";
55
+ }
50
56
  if (current === finalContent) return "unchanged";
51
57
  writeFileAtomic(destPath, finalContent);
52
58
  return "updated";
@@ -64,8 +70,10 @@ function fileMarker(version) {
64
70
  * the result executable (0o755). Same ownership policy as `writeManagedFile`:
65
71
  * - absent → write it (created)
66
72
  * - present with the shell marker → overwrite (updated/unchanged)
67
- * - present without the marker (foreign) → never touch it (skipped-foreign)
68
- */ export function writeManagedShellFile(destPath, sourceContent, version) {
73
+ * - present without the marker (foreign) → never touch it (skipped-foreign),
74
+ * unless `options.force` is set, in which case it's overwritten
75
+ * (overwritten-foreign) and stamped with the marker.
76
+ */ export function writeManagedShellFile(destPath, sourceContent, version, options = {}) {
69
77
  const finalContent = sourceContent.replaceAll(SHELL_VERSION_PLACEHOLDER, version);
70
78
  if (!existsSync(destPath)) {
71
79
  mkdirSync(dirname(destPath), {
@@ -75,7 +83,11 @@ function fileMarker(version) {
75
83
  return "created";
76
84
  }
77
85
  const current = readFileSync(destPath, "utf-8");
78
- if (!hasArgosShellFileMarker(current)) return "skipped-foreign";
86
+ if (!hasArgosShellFileMarker(current)) {
87
+ if (!options.force) return "skipped-foreign";
88
+ writeFileAtomic(destPath, finalContent, 0o755);
89
+ return "overwritten-foreign";
90
+ }
79
91
  if (current === finalContent) {
80
92
  // Re-assert the executable bit even when content is unchanged, in case
81
93
  // it drifted (e.g. a user ran `chmod -x` on it by hand). Best-effort:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/managed-files.ts"],"sourcesContent":["import { chmodSync, existsSync, mkdirSync, readFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { writeFileAtomic } from \"./atomic-write.js\";\n\nconst MARKER_PREFIX = '<!-- argos:file v=\"';\nconst FRONTMATTER_RE = /^---\\n[\\s\\S]*?\\n---\\n/;\n\n// Shell assets (hooks) can't carry the HTML-comment marker above (`.sh` has\n// no such syntax) or YAML frontmatter, so they get their own shell-comment\n// marker form: `# argos:file v=\"<version>\"`, hardcoded as the literal first\n// line after the shebang in the asset source (see assets/hooks/*.sh) with a\n// `SHELL_VERSION_PLACEHOLDER` token in place of the version — stamped with\n// the real version at install time by `writeManagedShellFile`.\nconst SHELL_MARKER_PREFIX = '# argos:file v=\"';\nexport const SHELL_VERSION_PLACEHOLDER = \"__ARGOS_VERSION__\";\n\nfunction fileMarker(version: string): string {\n return `${MARKER_PREFIX}${version}\" -->`;\n}\n\n/** True when `content` carries an `argos:file` ownership marker (any version). */\nexport function hasArgosFileMarker(content: string): boolean {\n return content.includes(MARKER_PREFIX);\n}\n\n/**\n * Insert the `argos:file` marker immediately after the leading YAML\n * frontmatter block, so the frontmatter stays the very first thing in the\n * file (required by tools that parse it, e.g. Claude Code agents/skills).\n * Falls back to prefixing the marker when there is no frontmatter.\n */\nexport function withFileMarker(content: string, version: string): string {\n const marker = fileMarker(version);\n const fmMatch = FRONTMATTER_RE.exec(content);\n if (!fmMatch) return `${marker}\\n\\n${content}`;\n const frontmatter = fmMatch[0];\n const rest = content.slice(frontmatter.length);\n return `${frontmatter}${marker}\\n${rest}`;\n}\n\nexport type FileStatus = \"created\" | \"updated\" | \"unchanged\" | \"skipped-foreign\";\n\n/**\n * Write a full-file Argos-owned asset (agent, skill, output-style) to\n * `destPath`, honoring the ownership marker policy:\n * - absent → write it (created)\n * - present with the argos:file marker → overwrite (updated/unchanged)\n * - present without the marker (foreign) → never touch it (skipped-foreign)\n */\nexport function writeManagedFile(destPath: string, sourceContent: string, version: string): FileStatus {\n const finalContent = withFileMarker(sourceContent, version);\n\n if (!existsSync(destPath)) {\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, finalContent);\n return \"created\";\n }\n\n const current = readFileSync(destPath, \"utf-8\");\n if (!hasArgosFileMarker(current)) return \"skipped-foreign\";\n if (current === finalContent) return \"unchanged\";\n\n writeFileAtomic(destPath, finalContent);\n return \"updated\";\n}\n\n/** True when `content` carries a shell-comment `# argos:file` ownership marker (any version). */\nexport function hasArgosShellFileMarker(content: string): boolean {\n return content.includes(SHELL_MARKER_PREFIX);\n}\n\n/**\n * Write a full-file Argos-owned shell script (a hook) to `destPath`.\n * `sourceContent` must already contain the literal\n * `# argos:file v=\"__ARGOS_VERSION__\"` marker line as the first line after\n * the shebang (see assets/hooks/*.sh) — this stamps it with the real\n * `version` (simple placeholder replace, no structural splicing needed since\n * the marker line is already in the right place in the source) and chmods\n * the result executable (0o755). Same ownership policy as `writeManagedFile`:\n * - absent → write it (created)\n * - present with the shell marker → overwrite (updated/unchanged)\n * - present without the marker (foreign) → never touch it (skipped-foreign)\n */\nexport function writeManagedShellFile(destPath: string, sourceContent: string, version: string): FileStatus {\n const finalContent = sourceContent.replaceAll(SHELL_VERSION_PLACEHOLDER, version);\n\n if (!existsSync(destPath)) {\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, finalContent, 0o755);\n return \"created\";\n }\n\n const current = readFileSync(destPath, \"utf-8\");\n if (!hasArgosShellFileMarker(current)) return \"skipped-foreign\";\n\n if (current === finalContent) {\n // Re-assert the executable bit even when content is unchanged, in case\n // it drifted (e.g. a user ran `chmod -x` on it by hand). Best-effort:\n // hooks are invoked as `bash \"<path>\"` (see lib/settings-merge.ts), so\n // the executable bit is inert for Claude Code's own purposes — a chmod\n // failure here (e.g. EPERM on an unusual filesystem) shouldn't fail the\n // whole `argos init` run over a cosmetic permission bit.\n try {\n chmodSync(destPath, 0o755);\n } catch {\n // Swallowed on purpose — see comment above.\n }\n return \"unchanged\";\n }\n\n writeFileAtomic(destPath, finalContent, 0o755);\n return \"updated\";\n}\n"],"names":["chmodSync","existsSync","mkdirSync","readFileSync","dirname","writeFileAtomic","MARKER_PREFIX","FRONTMATTER_RE","SHELL_MARKER_PREFIX","SHELL_VERSION_PLACEHOLDER","fileMarker","version","hasArgosFileMarker","content","includes","withFileMarker","marker","fmMatch","exec","frontmatter","rest","slice","length","writeManagedFile","destPath","sourceContent","finalContent","recursive","current","hasArgosShellFileMarker","writeManagedShellFile","replaceAll"],"mappings":"AAAA,SAASA,SAAS,EAAEC,UAAU,EAAEC,SAAS,EAAEC,YAAY,QAAQ,UAAU;AACzE,SAASC,OAAO,QAAQ,YAAY;AACpC,SAASC,eAAe,QAAQ,oBAAoB;AAEpD,MAAMC,gBAAgB;AACtB,MAAMC,iBAAiB;AAEvB,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,+DAA+D;AAC/D,MAAMC,sBAAsB;AAC5B,OAAO,MAAMC,4BAA4B,oBAAoB;AAE7D,SAASC,WAAWC,OAAe;IACjC,OAAO,GAAGL,gBAAgBK,QAAQ,KAAK,CAAC;AAC1C;AAEA,gFAAgF,GAChF,OAAO,SAASC,mBAAmBC,OAAe;IAChD,OAAOA,QAAQC,QAAQ,CAACR;AAC1B;AAEA;;;;;CAKC,GACD,OAAO,SAASS,eAAeF,OAAe,EAAEF,OAAe;IAC7D,MAAMK,SAASN,WAAWC;IAC1B,MAAMM,UAAUV,eAAeW,IAAI,CAACL;IACpC,IAAI,CAACI,SAAS,OAAO,GAAGD,OAAO,IAAI,EAAEH,SAAS;IAC9C,MAAMM,cAAcF,OAAO,CAAC,EAAE;IAC9B,MAAMG,OAAOP,QAAQQ,KAAK,CAACF,YAAYG,MAAM;IAC7C,OAAO,GAAGH,cAAcH,OAAO,EAAE,EAAEI,MAAM;AAC3C;AAIA;;;;;;CAMC,GACD,OAAO,SAASG,iBAAiBC,QAAgB,EAAEC,aAAqB,EAAEd,OAAe;IACvF,MAAMe,eAAeX,eAAeU,eAAed;IAEnD,IAAI,CAACV,WAAWuB,WAAW;QACzBtB,UAAUE,QAAQoB,WAAW;YAAEG,WAAW;QAAK;QAC/CtB,gBAAgBmB,UAAUE;QAC1B,OAAO;IACT;IAEA,MAAME,UAAUzB,aAAaqB,UAAU;IACvC,IAAI,CAACZ,mBAAmBgB,UAAU,OAAO;IACzC,IAAIA,YAAYF,cAAc,OAAO;IAErCrB,gBAAgBmB,UAAUE;IAC1B,OAAO;AACT;AAEA,+FAA+F,GAC/F,OAAO,SAASG,wBAAwBhB,OAAe;IACrD,OAAOA,QAAQC,QAAQ,CAACN;AAC1B;AAEA;;;;;;;;;;;CAWC,GACD,OAAO,SAASsB,sBAAsBN,QAAgB,EAAEC,aAAqB,EAAEd,OAAe;IAC5F,MAAMe,eAAeD,cAAcM,UAAU,CAACtB,2BAA2BE;IAEzE,IAAI,CAACV,WAAWuB,WAAW;QACzBtB,UAAUE,QAAQoB,WAAW;YAAEG,WAAW;QAAK;QAC/CtB,gBAAgBmB,UAAUE,cAAc;QACxC,OAAO;IACT;IAEA,MAAME,UAAUzB,aAAaqB,UAAU;IACvC,IAAI,CAACK,wBAAwBD,UAAU,OAAO;IAE9C,IAAIA,YAAYF,cAAc;QAC5B,uEAAuE;QACvE,sEAAsE;QACtE,uEAAuE;QACvE,uEAAuE;QACvE,wEAAwE;QACxE,yDAAyD;QACzD,IAAI;YACF1B,UAAUwB,UAAU;QACtB,EAAE,OAAM;QACN,4CAA4C;QAC9C;QACA,OAAO;IACT;IAEAnB,gBAAgBmB,UAAUE,cAAc;IACxC,OAAO;AACT"}
1
+ {"version":3,"sources":["../../src/lib/managed-files.ts"],"sourcesContent":["import { chmodSync, existsSync, mkdirSync, readFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { writeFileAtomic } from \"./atomic-write.js\";\n\nconst MARKER_PREFIX = '<!-- argos:file v=\"';\nconst FRONTMATTER_RE = /^---\\n[\\s\\S]*?\\n---\\n/;\n\n// Shell assets (hooks) can't carry the HTML-comment marker above (`.sh` has\n// no such syntax) or YAML frontmatter, so they get their own shell-comment\n// marker form: `# argos:file v=\"<version>\"`, hardcoded as the literal first\n// line after the shebang in the asset source (see assets/hooks/*.sh) with a\n// `SHELL_VERSION_PLACEHOLDER` token in place of the version — stamped with\n// the real version at install time by `writeManagedShellFile`.\nconst SHELL_MARKER_PREFIX = '# argos:file v=\"';\nexport const SHELL_VERSION_PLACEHOLDER = \"__ARGOS_VERSION__\";\n\nfunction fileMarker(version: string): string {\n return `${MARKER_PREFIX}${version}\" -->`;\n}\n\n/** True when `content` carries an `argos:file` ownership marker (any version). */\nexport function hasArgosFileMarker(content: string): boolean {\n return content.includes(MARKER_PREFIX);\n}\n\n/**\n * Insert the `argos:file` marker immediately after the leading YAML\n * frontmatter block, so the frontmatter stays the very first thing in the\n * file (required by tools that parse it, e.g. Claude Code agents/skills).\n * Falls back to prefixing the marker when there is no frontmatter.\n */\nexport function withFileMarker(content: string, version: string): string {\n const marker = fileMarker(version);\n const fmMatch = FRONTMATTER_RE.exec(content);\n if (!fmMatch) return `${marker}\\n\\n${content}`;\n const frontmatter = fmMatch[0];\n const rest = content.slice(frontmatter.length);\n return `${frontmatter}${marker}\\n${rest}`;\n}\n\nexport type FileStatus = \"created\" | \"updated\" | \"unchanged\" | \"skipped-foreign\" | \"overwritten-foreign\";\n\nexport interface WriteManagedFileOptions {\n /**\n * `argos init --force`: when the destination exists WITHOUT the\n * ownership marker (foreign), overwrite it with the motor version instead\n * of skipping it. The marker lands with this write, so a subsequent\n * (non-forced) run treats the file as owned from then on. Default `false`\n * — the pre-existing skip-foreign behavior.\n */\n force?: boolean;\n}\n\n/**\n * Write a full-file Argos-owned asset (agent, skill, output-style) to\n * `destPath`, honoring the ownership marker policy:\n * - absent → write it (created)\n * - present with the argos:file marker → overwrite (updated/unchanged)\n * - present without the marker (foreign) → never touch it (skipped-foreign),\n * unless `options.force` is set, in which case it's overwritten\n * (overwritten-foreign) and stamped with the marker.\n */\nexport function writeManagedFile(\n destPath: string,\n sourceContent: string,\n version: string,\n options: WriteManagedFileOptions = {},\n): FileStatus {\n const finalContent = withFileMarker(sourceContent, version);\n\n if (!existsSync(destPath)) {\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, finalContent);\n return \"created\";\n }\n\n const current = readFileSync(destPath, \"utf-8\");\n if (!hasArgosFileMarker(current)) {\n if (!options.force) return \"skipped-foreign\";\n writeFileAtomic(destPath, finalContent);\n return \"overwritten-foreign\";\n }\n if (current === finalContent) return \"unchanged\";\n\n writeFileAtomic(destPath, finalContent);\n return \"updated\";\n}\n\n/** True when `content` carries a shell-comment `# argos:file` ownership marker (any version). */\nexport function hasArgosShellFileMarker(content: string): boolean {\n return content.includes(SHELL_MARKER_PREFIX);\n}\n\n/**\n * Write a full-file Argos-owned shell script (a hook) to `destPath`.\n * `sourceContent` must already contain the literal\n * `# argos:file v=\"__ARGOS_VERSION__\"` marker line as the first line after\n * the shebang (see assets/hooks/*.sh) — this stamps it with the real\n * `version` (simple placeholder replace, no structural splicing needed since\n * the marker line is already in the right place in the source) and chmods\n * the result executable (0o755). Same ownership policy as `writeManagedFile`:\n * - absent → write it (created)\n * - present with the shell marker → overwrite (updated/unchanged)\n * - present without the marker (foreign) → never touch it (skipped-foreign),\n * unless `options.force` is set, in which case it's overwritten\n * (overwritten-foreign) and stamped with the marker.\n */\nexport function writeManagedShellFile(\n destPath: string,\n sourceContent: string,\n version: string,\n options: WriteManagedFileOptions = {},\n): FileStatus {\n const finalContent = sourceContent.replaceAll(SHELL_VERSION_PLACEHOLDER, version);\n\n if (!existsSync(destPath)) {\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, finalContent, 0o755);\n return \"created\";\n }\n\n const current = readFileSync(destPath, \"utf-8\");\n if (!hasArgosShellFileMarker(current)) {\n if (!options.force) return \"skipped-foreign\";\n writeFileAtomic(destPath, finalContent, 0o755);\n return \"overwritten-foreign\";\n }\n\n if (current === finalContent) {\n // Re-assert the executable bit even when content is unchanged, in case\n // it drifted (e.g. a user ran `chmod -x` on it by hand). Best-effort:\n // hooks are invoked as `bash \"<path>\"` (see lib/settings-merge.ts), so\n // the executable bit is inert for Claude Code's own purposes — a chmod\n // failure here (e.g. EPERM on an unusual filesystem) shouldn't fail the\n // whole `argos init` run over a cosmetic permission bit.\n try {\n chmodSync(destPath, 0o755);\n } catch {\n // Swallowed on purpose — see comment above.\n }\n return \"unchanged\";\n }\n\n writeFileAtomic(destPath, finalContent, 0o755);\n return \"updated\";\n}\n"],"names":["chmodSync","existsSync","mkdirSync","readFileSync","dirname","writeFileAtomic","MARKER_PREFIX","FRONTMATTER_RE","SHELL_MARKER_PREFIX","SHELL_VERSION_PLACEHOLDER","fileMarker","version","hasArgosFileMarker","content","includes","withFileMarker","marker","fmMatch","exec","frontmatter","rest","slice","length","writeManagedFile","destPath","sourceContent","options","finalContent","recursive","current","force","hasArgosShellFileMarker","writeManagedShellFile","replaceAll"],"mappings":"AAAA,SAASA,SAAS,EAAEC,UAAU,EAAEC,SAAS,EAAEC,YAAY,QAAQ,UAAU;AACzE,SAASC,OAAO,QAAQ,YAAY;AACpC,SAASC,eAAe,QAAQ,oBAAoB;AAEpD,MAAMC,gBAAgB;AACtB,MAAMC,iBAAiB;AAEvB,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,+DAA+D;AAC/D,MAAMC,sBAAsB;AAC5B,OAAO,MAAMC,4BAA4B,oBAAoB;AAE7D,SAASC,WAAWC,OAAe;IACjC,OAAO,GAAGL,gBAAgBK,QAAQ,KAAK,CAAC;AAC1C;AAEA,gFAAgF,GAChF,OAAO,SAASC,mBAAmBC,OAAe;IAChD,OAAOA,QAAQC,QAAQ,CAACR;AAC1B;AAEA;;;;;CAKC,GACD,OAAO,SAASS,eAAeF,OAAe,EAAEF,OAAe;IAC7D,MAAMK,SAASN,WAAWC;IAC1B,MAAMM,UAAUV,eAAeW,IAAI,CAACL;IACpC,IAAI,CAACI,SAAS,OAAO,GAAGD,OAAO,IAAI,EAAEH,SAAS;IAC9C,MAAMM,cAAcF,OAAO,CAAC,EAAE;IAC9B,MAAMG,OAAOP,QAAQQ,KAAK,CAACF,YAAYG,MAAM;IAC7C,OAAO,GAAGH,cAAcH,OAAO,EAAE,EAAEI,MAAM;AAC3C;AAeA;;;;;;;;CAQC,GACD,OAAO,SAASG,iBACdC,QAAgB,EAChBC,aAAqB,EACrBd,OAAe,EACfe,UAAmC,CAAC,CAAC;IAErC,MAAMC,eAAeZ,eAAeU,eAAed;IAEnD,IAAI,CAACV,WAAWuB,WAAW;QACzBtB,UAAUE,QAAQoB,WAAW;YAAEI,WAAW;QAAK;QAC/CvB,gBAAgBmB,UAAUG;QAC1B,OAAO;IACT;IAEA,MAAME,UAAU1B,aAAaqB,UAAU;IACvC,IAAI,CAACZ,mBAAmBiB,UAAU;QAChC,IAAI,CAACH,QAAQI,KAAK,EAAE,OAAO;QAC3BzB,gBAAgBmB,UAAUG;QAC1B,OAAO;IACT;IACA,IAAIE,YAAYF,cAAc,OAAO;IAErCtB,gBAAgBmB,UAAUG;IAC1B,OAAO;AACT;AAEA,+FAA+F,GAC/F,OAAO,SAASI,wBAAwBlB,OAAe;IACrD,OAAOA,QAAQC,QAAQ,CAACN;AAC1B;AAEA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASwB,sBACdR,QAAgB,EAChBC,aAAqB,EACrBd,OAAe,EACfe,UAAmC,CAAC,CAAC;IAErC,MAAMC,eAAeF,cAAcQ,UAAU,CAACxB,2BAA2BE;IAEzE,IAAI,CAACV,WAAWuB,WAAW;QACzBtB,UAAUE,QAAQoB,WAAW;YAAEI,WAAW;QAAK;QAC/CvB,gBAAgBmB,UAAUG,cAAc;QACxC,OAAO;IACT;IAEA,MAAME,UAAU1B,aAAaqB,UAAU;IACvC,IAAI,CAACO,wBAAwBF,UAAU;QACrC,IAAI,CAACH,QAAQI,KAAK,EAAE,OAAO;QAC3BzB,gBAAgBmB,UAAUG,cAAc;QACxC,OAAO;IACT;IAEA,IAAIE,YAAYF,cAAc;QAC5B,uEAAuE;QACvE,sEAAsE;QACtE,uEAAuE;QACvE,uEAAuE;QACvE,wEAAwE;QACxE,yDAAyD;QACzD,IAAI;YACF3B,UAAUwB,UAAU;QACtB,EAAE,OAAM;QACN,4CAA4C;QAC9C;QACA,OAAO;IACT;IAEAnB,gBAAgBmB,UAAUG,cAAc;IACxC,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argos-harness",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "Argos — global-first CLI harness for setting up and managing Claude Code across your projects",
6
6
  "license": "MIT",