argos-harness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/assets/agents/auditor.md +140 -0
  4. package/assets/agents/commit-pr-pilot.md +154 -0
  5. package/assets/agents/explorer.md +93 -0
  6. package/assets/agents/implementer.md +117 -0
  7. package/assets/agents/leader.md +149 -0
  8. package/assets/agents/researcher.md +89 -0
  9. package/assets/agents/review-readability.md +87 -0
  10. package/assets/agents/review-reliability.md +100 -0
  11. package/assets/agents/review-resilience.md +87 -0
  12. package/assets/agents/review-risk.md +87 -0
  13. package/assets/agents/reviewer.md +167 -0
  14. package/assets/agents/ticket-audit.md +129 -0
  15. package/assets/hooks/argos-guard-destructive.sh +127 -0
  16. package/assets/hooks/argos-quality-gate.sh +129 -0
  17. package/assets/managed/aterrizaje.md +24 -0
  18. package/assets/managed/formato-respuesta.md +21 -0
  19. package/assets/managed/identidad.md +48 -0
  20. package/assets/managed/operaciones-seguras.md +14 -0
  21. package/assets/managed/orquestacion.md +169 -0
  22. package/assets/output-styles/argos.md +71 -0
  23. package/assets/skills/ai-sdk-5/SKILL.md +230 -0
  24. package/assets/skills/angular/SKILL.md +19 -0
  25. package/assets/skills/angular/references/architecture.md +137 -0
  26. package/assets/skills/angular/references/core.md +197 -0
  27. package/assets/skills/angular/references/forms.md +115 -0
  28. package/assets/skills/angular/references/performance.md +124 -0
  29. package/assets/skills/apollo-client/SKILL.md +61 -0
  30. package/assets/skills/app-blueprint/SKILL.md +45 -0
  31. package/assets/skills/app-blueprint/assets/module-template.md +48 -0
  32. package/assets/skills/app-blueprint/assets/system-template.md +38 -0
  33. package/assets/skills/app-blueprint/references/workflow.md +101 -0
  34. package/assets/skills/app-builder/SKILL.md +43 -0
  35. package/assets/skills/app-builder/phases/0-product.md +58 -0
  36. package/assets/skills/app-builder/phases/1-scaffold.md +33 -0
  37. package/assets/skills/app-builder/phases/10-store.md +40 -0
  38. package/assets/skills/app-builder/phases/2-data.md +34 -0
  39. package/assets/skills/app-builder/phases/3-domain.md +33 -0
  40. package/assets/skills/app-builder/phases/4-ui-nav.md +32 -0
  41. package/assets/skills/app-builder/phases/5-identity.md +30 -0
  42. package/assets/skills/app-builder/phases/6-polish.md +34 -0
  43. package/assets/skills/app-builder/phases/7-brand.md +31 -0
  44. package/assets/skills/app-builder/phases/8-web.md +30 -0
  45. package/assets/skills/app-builder/phases/9-docs.md +31 -0
  46. package/assets/skills/app-ia/SKILL.md +54 -0
  47. package/assets/skills/astro/SKILL.md +39 -0
  48. package/assets/skills/axios/SKILL.md +61 -0
  49. package/assets/skills/branch-pr/SKILL.md +200 -0
  50. package/assets/skills/bullmq/SKILL.md +55 -0
  51. package/assets/skills/chained-pr/SKILL.md +48 -0
  52. package/assets/skills/chained-pr/references/chaining-details.md +99 -0
  53. package/assets/skills/cognitive-doc-design/SKILL.md +81 -0
  54. package/assets/skills/comment-writer/SKILL.md +74 -0
  55. package/assets/skills/dashboard-ia/SKILL.md +54 -0
  56. package/assets/skills/django-drf/SKILL.md +180 -0
  57. package/assets/skills/go-testing/SKILL.md +47 -0
  58. package/assets/skills/go-testing/references/examples.md +89 -0
  59. package/assets/skills/issue-creation/SKILL.md +223 -0
  60. package/assets/skills/jira-epic/SKILL.md +306 -0
  61. package/assets/skills/jira-task/SKILL.md +382 -0
  62. package/assets/skills/judgment-day/SKILL.md +52 -0
  63. package/assets/skills/judgment-day/references/prompts-and-formats.md +98 -0
  64. package/assets/skills/lightsail-deploy/SKILL.md +44 -0
  65. package/assets/skills/lightsail-deploy/references/runbook.md +102 -0
  66. package/assets/skills/loop-back-debug/SKILL.md +102 -0
  67. package/assets/skills/mantine-form/SKILL.md +57 -0
  68. package/assets/skills/mongoose/SKILL.md +66 -0
  69. package/assets/skills/nextjs-15/SKILL.md +144 -0
  70. package/assets/skills/not-boring-mobile/SKILL.md +43 -0
  71. package/assets/skills/not-boring-mobile/references/not-boring-playbook.md +65 -0
  72. package/assets/skills/playwright/SKILL.md +315 -0
  73. package/assets/skills/pr-comments/SKILL.md +93 -0
  74. package/assets/skills/pr-create/SKILL.md +64 -0
  75. package/assets/skills/promo-video/SKILL.md +52 -0
  76. package/assets/skills/promo-video/assets/package.template.json +22 -0
  77. package/assets/skills/promo-video/assets/promo.template.tsx +469 -0
  78. package/assets/skills/promo-video/assets/theme.template.ts +27 -0
  79. package/assets/skills/promo-video/references/pipeline.md +119 -0
  80. package/assets/skills/promo-video-web/SKILL.md +51 -0
  81. package/assets/skills/promo-video-web/assets/browser-promo.template.tsx +385 -0
  82. package/assets/skills/promo-video-web/assets/capture.template.ts +70 -0
  83. package/assets/skills/promo-video-web/assets/package.template.json +26 -0
  84. package/assets/skills/promo-video-web/references/pipeline.md +84 -0
  85. package/assets/skills/pytest/SKILL.md +180 -0
  86. package/assets/skills/react-19/SKILL.md +118 -0
  87. package/assets/skills/react-hook-form/SKILL.md +59 -0
  88. package/assets/skills/react-router/SKILL.md +60 -0
  89. package/assets/skills/redux-toolkit/SKILL.md +60 -0
  90. package/assets/skills/review-diff/SKILL.md +101 -0
  91. package/assets/skills/ship-docs/SKILL.md +45 -0
  92. package/assets/skills/ship-docs/references/ship-docs-playbook.md +31 -0
  93. package/assets/skills/skill-creator/SKILL.md +97 -0
  94. package/assets/skills/skill-creator/assets/SKILL-TEMPLATE.md +68 -0
  95. package/assets/skills/skill-creator/references/skill-style-guide.md +79 -0
  96. package/assets/skills/skill-improver/SKILL.md +50 -0
  97. package/assets/skills/skill-improver/references/skill-style-guide.md +79 -0
  98. package/assets/skills/socketio/SKILL.md +58 -0
  99. package/assets/skills/spec-bootstrap/SKILL.md +62 -0
  100. package/assets/skills/store-ship/SKILL.md +52 -0
  101. package/assets/skills/store-ship/assets/android-supply.template.md +22 -0
  102. package/assets/skills/store-ship/assets/eas.template.json +32 -0
  103. package/assets/skills/store-ship/assets/maestro-flow.template.yaml +27 -0
  104. package/assets/skills/store-ship/assets/store.config.template.json +28 -0
  105. package/assets/skills/store-ship/references/pipeline.md +198 -0
  106. package/assets/skills/stripe/SKILL.md +83 -0
  107. package/assets/skills/tailwind-4/SKILL.md +193 -0
  108. package/assets/skills/tamagui/SKILL.md +60 -0
  109. package/assets/skills/tanstack-query/SKILL.md +58 -0
  110. package/assets/skills/ticket-intake/SKILL.md +55 -0
  111. package/assets/skills/typescript/SKILL.md +134 -0
  112. package/assets/skills/verify-before-done/SKILL.md +111 -0
  113. package/assets/skills/webapp-rebuilder/SKILL.md +48 -0
  114. package/assets/skills/webapp-rebuilder/assets/charter-template.md +46 -0
  115. package/assets/skills/webapp-rebuilder/references/workflow.md +47 -0
  116. package/assets/skills/winston-logging/SKILL.md +61 -0
  117. package/assets/skills/work-unit-commits/SKILL.md +84 -0
  118. package/assets/skills/zod-4/SKILL.md +210 -0
  119. package/assets/skills/zustand-5/SKILL.md +216 -0
  120. package/bin/argos.js +6 -0
  121. package/dist/commands/adopt.d.ts +35 -0
  122. package/dist/commands/adopt.d.ts.map +1 -0
  123. package/dist/commands/adopt.js +347 -0
  124. package/dist/commands/adopt.js.map +1 -0
  125. package/dist/commands/doctor.d.ts +20 -0
  126. package/dist/commands/doctor.d.ts.map +1 -0
  127. package/dist/commands/doctor.js +478 -0
  128. package/dist/commands/doctor.js.map +1 -0
  129. package/dist/commands/init.d.ts +32 -0
  130. package/dist/commands/init.d.ts.map +1 -0
  131. package/dist/commands/init.js +358 -0
  132. package/dist/commands/init.js.map +1 -0
  133. package/dist/commands/remove.d.ts +62 -0
  134. package/dist/commands/remove.d.ts.map +1 -0
  135. package/dist/commands/remove.js +487 -0
  136. package/dist/commands/remove.js.map +1 -0
  137. package/dist/commands/workspace.d.ts +73 -0
  138. package/dist/commands/workspace.d.ts.map +1 -0
  139. package/dist/commands/workspace.js +354 -0
  140. package/dist/commands/workspace.js.map +1 -0
  141. package/dist/index.d.ts +2 -0
  142. package/dist/index.d.ts.map +1 -0
  143. package/dist/index.js +24 -0
  144. package/dist/index.js.map +1 -0
  145. package/dist/lib/assets.d.ts +29 -0
  146. package/dist/lib/assets.d.ts.map +1 -0
  147. package/dist/lib/assets.js +57 -0
  148. package/dist/lib/assets.js.map +1 -0
  149. package/dist/lib/atomic-write.d.ts +17 -0
  150. package/dist/lib/atomic-write.d.ts.map +1 -0
  151. package/dist/lib/atomic-write.js +41 -0
  152. package/dist/lib/atomic-write.js.map +1 -0
  153. package/dist/lib/backup.d.ts +11 -0
  154. package/dist/lib/backup.d.ts.map +1 -0
  155. package/dist/lib/backup.js +42 -0
  156. package/dist/lib/backup.js.map +1 -0
  157. package/dist/lib/config.d.ts +36 -0
  158. package/dist/lib/config.d.ts.map +1 -0
  159. package/dist/lib/config.js +52 -0
  160. package/dist/lib/config.js.map +1 -0
  161. package/dist/lib/detect.d.ts +58 -0
  162. package/dist/lib/detect.d.ts.map +1 -0
  163. package/dist/lib/detect.js +330 -0
  164. package/dist/lib/detect.js.map +1 -0
  165. package/dist/lib/ficha.d.ts +10 -0
  166. package/dist/lib/ficha.d.ts.map +1 -0
  167. package/dist/lib/ficha.js +38 -0
  168. package/dist/lib/ficha.js.map +1 -0
  169. package/dist/lib/git.d.ts +27 -0
  170. package/dist/lib/git.d.ts.map +1 -0
  171. package/dist/lib/git.js +79 -0
  172. package/dist/lib/git.js.map +1 -0
  173. package/dist/lib/managed-files.d.ts +35 -0
  174. package/dist/lib/managed-files.d.ts.map +1 -0
  175. package/dist/lib/managed-files.js +97 -0
  176. package/dist/lib/managed-files.js.map +1 -0
  177. package/dist/lib/markers.d.ts +64 -0
  178. package/dist/lib/markers.d.ts.map +1 -0
  179. package/dist/lib/markers.js +157 -0
  180. package/dist/lib/markers.js.map +1 -0
  181. package/dist/lib/navori-import.d.ts +42 -0
  182. package/dist/lib/navori-import.d.ts.map +1 -0
  183. package/dist/lib/navori-import.js +65 -0
  184. package/dist/lib/navori-import.js.map +1 -0
  185. package/dist/lib/openclaw-agents.d.ts +53 -0
  186. package/dist/lib/openclaw-agents.d.ts.map +1 -0
  187. package/dist/lib/openclaw-agents.js +118 -0
  188. package/dist/lib/openclaw-agents.js.map +1 -0
  189. package/dist/lib/package-root.d.ts +11 -0
  190. package/dist/lib/package-root.d.ts.map +1 -0
  191. package/dist/lib/package-root.js +23 -0
  192. package/dist/lib/package-root.js.map +1 -0
  193. package/dist/lib/paths.d.ts +11 -0
  194. package/dist/lib/paths.d.ts.map +1 -0
  195. package/dist/lib/paths.js +16 -0
  196. package/dist/lib/paths.js.map +1 -0
  197. package/dist/lib/settings-merge.d.ts +125 -0
  198. package/dist/lib/settings-merge.d.ts.map +1 -0
  199. package/dist/lib/settings-merge.js +373 -0
  200. package/dist/lib/settings-merge.js.map +1 -0
  201. package/dist/lib/version.d.ts +3 -0
  202. package/dist/lib/version.d.ts.map +1 -0
  203. package/dist/lib/version.js +13 -0
  204. package/dist/lib/version.js.map +1 -0
  205. package/dist/lib/which.d.ts +8 -0
  206. package/dist/lib/which.d.ts.map +1 -0
  207. package/dist/lib/which.js +30 -0
  208. package/dist/lib/which.js.map +1 -0
  209. package/dist/lib/workspaces.d.ts +133 -0
  210. package/dist/lib/workspaces.d.ts.map +1 -0
  211. package/dist/lib/workspaces.js +241 -0
  212. package/dist/lib/workspaces.js.map +1 -0
  213. package/dist/lib/zod-messages.d.ts +4 -0
  214. package/dist/lib/zod-messages.d.ts.map +1 -0
  215. package/dist/lib/zod-messages.js +28 -0
  216. package/dist/lib/zod-messages.js.map +1 -0
  217. package/package.json +44 -0
@@ -0,0 +1,478 @@
1
+ import { defineCommand } from "citty";
2
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
3
+ import { join, resolve } from "node:path";
4
+ import pc from "picocolors";
5
+ import { ArgosConfigSchema, hasConfig } from "../lib/config.js";
6
+ import { detectFramework, detectLibs, detectPackageManager, readPackageJson } from "../lib/detect.js";
7
+ import { buildFichaContent, FICHA_BLOCK_ID } from "../lib/ficha.js";
8
+ import { getRemoteOriginUrl, isGitRepo, parseIdentityFromRemote } from "../lib/git.js";
9
+ import { listAgentIds, listSkillIds, MANAGED_BLOCK_IDS, resolveAssetsDir } from "../lib/assets.js";
10
+ import { listBlocks, listDanglingBlockIds } from "../lib/markers.js";
11
+ import { hasArgosFileMarker, hasArgosShellFileMarker } from "../lib/managed-files.js";
12
+ import { hasNaviorConfig } from "../lib/navori-import.js";
13
+ import { resolveClaudeDir } from "../lib/paths.js";
14
+ import { isArgosHookCommand } from "../lib/settings-merge.js";
15
+ import { readCliVersion } from "../lib/version.js";
16
+ import { loadRegistry, resolveWorkspaceForRepo } from "../lib/workspaces.js";
17
+ import { describeZodError } from "../lib/zod-messages.js";
18
+ import { NO_GATE_PLACEHOLDER } from "./adopt.js";
19
+ /**
20
+ * Read a text file, guarding against fs failures (e.g. EACCES) that would
21
+ * otherwise crash doctor's read-only audit. On failure, pushes an error
22
+ * finding and falls back to `""` so the rest of the audit can still run.
23
+ */ function readFileSafe(path, findings, label) {
24
+ if (!existsSync(path)) return "";
25
+ try {
26
+ return readFileSync(path, "utf-8");
27
+ } catch (err) {
28
+ findings.push({
29
+ level: "error",
30
+ message: `No se pudo leer ${label} (${err instanceof Error ? err.message : String(err)}).`
31
+ });
32
+ return "";
33
+ }
34
+ }
35
+ /** Compare two semver-ish `x.y.z` strings. Returns <0, 0, or >0 like Array.sort comparators. */ function compareVersions(a, b) {
36
+ const pa = a.split(".").map((n)=>Number.parseInt(n, 10) || 0);
37
+ const pb = b.split(".").map((n)=>Number.parseInt(n, 10) || 0);
38
+ for(let i = 0; i < Math.max(pa.length, pb.length); i++){
39
+ const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
40
+ if (diff !== 0) return diff;
41
+ }
42
+ return 0;
43
+ }
44
+ /**
45
+ * Ids (basenames under `<claudeDir>/hooks/`) of the 2 global hooks `argos
46
+ * init` installs (see spec 0003 "Hooks globales parametrizados"). Mirrors
47
+ * `HOOK_IDS` in commands/init.ts — kept as a local duplicate here since
48
+ * doctor only reads the filesystem/version drift, it never installs, and the
49
+ * two commands are intentionally not allowed to share private constants.
50
+ */ const HOOK_IDS = [
51
+ "argos-guard-destructive",
52
+ "argos-quality-gate"
53
+ ];
54
+ /** Extract the version stamped by a shell-comment `# argos:file v="<version>"` marker (see lib/managed-files.ts). */ function extractShellMarkerVersion(content) {
55
+ return /^# argos:file v="([^"]*)"/m.exec(content)?.[1] ?? null;
56
+ }
57
+ /** Extract the script path from an Argos hook command string (`bash "<scriptPath>"`, see lib/settings-merge.ts). */ function extractHookScriptPath(command) {
58
+ return /^bash "(.+)"$/.exec(command)?.[1] ?? null;
59
+ }
60
+ function isPlainObject(v) {
61
+ return typeof v === "object" && v !== null && !Array.isArray(v);
62
+ }
63
+ /**
64
+ * Hooks (F2, motor scope): presence, ownership, and version drift of the 2
65
+ * global hook scripts under `<claudeDir>/hooks/`. Same bidirectional-version
66
+ * convention as the CLAUDE.md managed-blocks check in `checkMotor`.
67
+ */ function checkHookScripts(findings, claudeDir, currentVersion) {
68
+ for (const id of HOOK_IDS){
69
+ const hookPath = join(claudeDir, "hooks", `${id}.sh`);
70
+ if (!existsSync(hookPath)) {
71
+ findings.push({
72
+ level: "warning",
73
+ message: `Falta el hook hooks/${id}.sh. Corre argos init.`
74
+ });
75
+ continue;
76
+ }
77
+ const beforeCount = findings.length;
78
+ const content = readFileSafe(hookPath, findings, `hooks/${id}.sh`);
79
+ if (findings.length > beforeCount) continue; // read error already reported by readFileSafe
80
+ if (!hasArgosShellFileMarker(content)) {
81
+ findings.push({
82
+ level: "info",
83
+ message: `hooks/${id}.sh existe pero es ajeno (sin marker argos:file).`
84
+ });
85
+ continue;
86
+ }
87
+ const hookVersion = extractShellMarkerVersion(content);
88
+ if (!hookVersion) continue;
89
+ const cmp = compareVersions(hookVersion, currentVersion);
90
+ if (cmp < 0) {
91
+ findings.push({
92
+ level: "warning",
93
+ message: `hooks/${id}.sh está desactualizado (v${hookVersion} < v${currentVersion}). Corre argos init.`
94
+ });
95
+ } else if (cmp > 0) {
96
+ findings.push({
97
+ level: "warning",
98
+ 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).`
99
+ });
100
+ }
101
+ }
102
+ }
103
+ /**
104
+ * Hooks (F2, motor scope): `settings.json` PreToolUse entries — missing,
105
+ * orphaned (the entry's script file is gone), or the file itself unreadable
106
+ * as valid JSON. Guarded reads throughout: never throws, always degrades to
107
+ * an error finding so the rest of doctor's audit still runs.
108
+ */ function checkHookSettings(findings, claudeDir) {
109
+ const settingsPath = join(claudeDir, "settings.json");
110
+ if (!existsSync(settingsPath)) {
111
+ for (const id of HOOK_IDS){
112
+ findings.push({
113
+ level: "warning",
114
+ message: `Falta la entrada del hook ${id} en settings.json. Corre argos init.`
115
+ });
116
+ }
117
+ return;
118
+ }
119
+ let raw;
120
+ try {
121
+ raw = readFileSync(settingsPath, "utf-8");
122
+ } catch (err) {
123
+ findings.push({
124
+ level: "error",
125
+ message: `No se pudo leer settings.json (${err instanceof Error ? err.message : String(err)}).`
126
+ });
127
+ return;
128
+ }
129
+ let settings;
130
+ try {
131
+ settings = raw.trim().length === 0 ? {} : JSON.parse(raw);
132
+ } catch (err) {
133
+ findings.push({
134
+ level: "error",
135
+ message: `settings.json tiene JSON inválido (${err instanceof Error ? err.message : String(err)}).`
136
+ });
137
+ return;
138
+ }
139
+ const foundScriptPaths = new Set();
140
+ const hooksRoot = isPlainObject(settings) ? settings.hooks : undefined;
141
+ const preToolUse = isPlainObject(hooksRoot) ? hooksRoot.PreToolUse : undefined;
142
+ if (Array.isArray(preToolUse)) {
143
+ for (const bucket of preToolUse){
144
+ if (!isPlainObject(bucket) || !Array.isArray(bucket.hooks)) continue;
145
+ for (const hook of bucket.hooks){
146
+ if (!isPlainObject(hook) || !isArgosHookCommand(hook.command)) continue;
147
+ const scriptPath = extractHookScriptPath(hook.command);
148
+ if (!scriptPath) continue;
149
+ foundScriptPaths.add(scriptPath);
150
+ // `existsSync` alone is true for directories too — a settings.json
151
+ // entry pointing at a directory (e.g. a failed write that left a
152
+ // stray directory in the script's place) would otherwise read as
153
+ // "present" here and slip past the orphan check.
154
+ let isRealFile = false;
155
+ try {
156
+ isRealFile = existsSync(scriptPath) && statSync(scriptPath).isFile();
157
+ } catch {
158
+ isRealFile = false;
159
+ }
160
+ if (!isRealFile) {
161
+ findings.push({
162
+ level: "warning",
163
+ message: `settings.json referencia el hook huérfano ${scriptPath} (el script ya no existe). Corre argos init.`
164
+ });
165
+ }
166
+ }
167
+ }
168
+ }
169
+ for (const id of HOOK_IDS){
170
+ const expectedPath = join(claudeDir, "hooks", `${id}.sh`);
171
+ if (!foundScriptPaths.has(expectedPath)) {
172
+ findings.push({
173
+ level: "warning",
174
+ message: `Falta la entrada del hook ${id} en settings.json. Corre argos init.`
175
+ });
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * Workspaces (F2, motor scope): `~/.argos/workspaces.json` registry entries
181
+ * whose repo path no longer exists on disk (moved/deleted repo). Guarded
182
+ * against a corrupt registry file — never throws.
183
+ */ function checkWorkspaceRegistryHealth(findings) {
184
+ let registry;
185
+ try {
186
+ registry = loadRegistry();
187
+ } catch (err) {
188
+ findings.push({
189
+ level: "error",
190
+ message: `No se pudo leer workspaces.json (${err instanceof Error ? err.message : String(err)}).`
191
+ });
192
+ return;
193
+ }
194
+ const stale = [];
195
+ for (const [wsName, ws] of Object.entries(registry)){
196
+ for (const repo of ws.repos){
197
+ if (!existsSync(repo.path)) stale.push(`${wsName}/${repo.name} (${repo.path})`);
198
+ }
199
+ }
200
+ if (stale.length > 0) {
201
+ findings.push({
202
+ level: "warning",
203
+ message: `Hay repos registrados en workspaces con paths inexistentes: ${stale.join(", ")}. Corre argos workspace link o editá el registro a mano.`
204
+ });
205
+ }
206
+ }
207
+ /**
208
+ * Flag dangling/unclosed managed-block markers (an open marker with no
209
+ * matching close — crash residue or hand-edited corruption) as a warning.
210
+ * Reuses `listDanglingBlockIds` (lib/markers.ts) — the same scanning logic
211
+ * `remove`'s progress-guard relies on to avoid spinning forever on the same
212
+ * corruption (see commands/remove.ts's processClaudeMd).
213
+ */ function checkDanglingMarkers(findings, content, label) {
214
+ for (const id of listDanglingBlockIds(content)){
215
+ findings.push({
216
+ level: "warning",
217
+ message: `Marker argos huérfano sin cierre en ${label} (bloque "${id}"). Corre argos remove para limpiarlo, o editá el archivo a mano.`
218
+ });
219
+ }
220
+ }
221
+ function checkMotor(findings) {
222
+ const claudeDir = resolveClaudeDir();
223
+ const currentVersion = readCliVersion();
224
+ const assetsDir = resolveAssetsDir();
225
+ const claudeMdPath = join(claudeDir, "CLAUDE.md");
226
+ const claudeMd = readFileSafe(claudeMdPath, findings, "CLAUDE.md");
227
+ const blocks = listBlocks(claudeMd);
228
+ checkDanglingMarkers(findings, claudeMd, "CLAUDE.md");
229
+ for (const id of MANAGED_BLOCK_IDS){
230
+ const matching = blocks.filter((b)=>b.id === id);
231
+ if (matching.length > 1) {
232
+ findings.push({
233
+ level: "warning",
234
+ message: `El bloque "${id}" está duplicado (${matching.length} veces) en CLAUDE.md. Corre argos init para sanearlo.`
235
+ });
236
+ }
237
+ const block = matching[0];
238
+ if (!block) {
239
+ findings.push({
240
+ level: "error",
241
+ message: `Falta el bloque managed "${id}" en CLAUDE.md. Corre argos init.`
242
+ });
243
+ continue;
244
+ }
245
+ if (block.version) {
246
+ const cmp = compareVersions(block.version, currentVersion);
247
+ if (cmp < 0) {
248
+ findings.push({
249
+ level: "warning",
250
+ message: `El bloque "${id}" está desactualizado (v${block.version} < v${currentVersion}). Corre argos init.`
251
+ });
252
+ } else if (cmp > 0) {
253
+ findings.push({
254
+ level: "warning",
255
+ 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).`
256
+ });
257
+ }
258
+ }
259
+ }
260
+ const fullFiles = [
261
+ [
262
+ "output-styles",
263
+ "argos.md"
264
+ ],
265
+ ...listAgentIds(assetsDir).map((id)=>[
266
+ "agents",
267
+ `${id}.md`
268
+ ]),
269
+ ...listSkillIds(assetsDir).map((id)=>[
270
+ "skills",
271
+ id,
272
+ "SKILL.md"
273
+ ])
274
+ ];
275
+ for (const relPath of fullFiles){
276
+ const dest = join(claudeDir, ...relPath);
277
+ const label = join(...relPath);
278
+ if (!existsSync(dest)) {
279
+ findings.push({
280
+ level: "error",
281
+ message: `Falta ${label} en el motor. Corre argos init.`
282
+ });
283
+ continue;
284
+ }
285
+ const content = readFileSync(dest, "utf-8");
286
+ if (!hasArgosFileMarker(content)) {
287
+ findings.push({
288
+ level: "info",
289
+ message: `${label} existe pero es ajeno (sin marker argos:file).`
290
+ });
291
+ }
292
+ }
293
+ checkHookScripts(findings, claudeDir, currentVersion);
294
+ checkHookSettings(findings, claudeDir);
295
+ checkWorkspaceRegistryHealth(findings);
296
+ }
297
+ function checkRepo(cwd, findings) {
298
+ if (!hasConfig(cwd)) return;
299
+ const configPath = join(cwd, "argos.config.json");
300
+ let config;
301
+ try {
302
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
303
+ config = ArgosConfigSchema.parse(raw);
304
+ } catch (error) {
305
+ for (const message of describeZodError(error)){
306
+ findings.push({
307
+ level: "error",
308
+ message: `argos.config.json inválido — ${message}`
309
+ });
310
+ }
311
+ return;
312
+ }
313
+ if (hasNaviorConfig(cwd)) {
314
+ findings.push({
315
+ level: "info",
316
+ message: "navori.config.json coexiste con argos.config.json (migración en curso)."
317
+ });
318
+ }
319
+ if (config.qualityGate.fast === NO_GATE_PLACEHOLDER) {
320
+ findings.push({
321
+ level: "warning",
322
+ message: "quality gate placeholder — configura scripts y corre argos adopt --refresh."
323
+ });
324
+ }
325
+ // Ficha drift: does ./CLAUDE.md's ficha block match what adopt would write today?
326
+ const claudeMdPath = join(cwd, "CLAUDE.md");
327
+ const claudeMd = readFileSafe(claudeMdPath, findings, "./CLAUDE.md");
328
+ checkDanglingMarkers(findings, claudeMd, "./CLAUDE.md");
329
+ const fichaBlocks = listBlocks(claudeMd).filter((b)=>b.id === FICHA_BLOCK_ID);
330
+ if (fichaBlocks.length > 1) {
331
+ findings.push({
332
+ level: "warning",
333
+ message: `La ficha está duplicada (${fichaBlocks.length} veces) en ./CLAUDE.md. Corre argos adopt --refresh para sanearla.`
334
+ });
335
+ }
336
+ const fichaBlock = fichaBlocks[0];
337
+ if (!fichaBlock) {
338
+ findings.push({
339
+ level: "warning",
340
+ message: "Falta la ficha en ./CLAUDE.md. Corre argos adopt --refresh."
341
+ });
342
+ } else {
343
+ const expectedFicha = buildFichaContent(config);
344
+ if (!claudeMd.includes(expectedFicha)) {
345
+ findings.push({
346
+ level: "warning",
347
+ message: "La ficha de ./CLAUDE.md quedó vieja. Corre argos adopt --refresh."
348
+ });
349
+ }
350
+ }
351
+ // Stack drift: new relevant libs in package.json not yet recorded.
352
+ const pkg = readPackageJson(cwd);
353
+ if (pkg) {
354
+ const recordedLibs = new Set(config.stack?.libs ?? []);
355
+ const freshLibs = detectLibs(pkg);
356
+ const newLibs = freshLibs.filter((lib)=>!recordedLibs.has(lib));
357
+ if (newLibs.length > 0) {
358
+ findings.push({
359
+ level: "warning",
360
+ message: `Nuevas libs detectadas sin registrar (${newLibs.join(", ")}). Corre argos adopt --refresh.`
361
+ });
362
+ }
363
+ const freshFramework = detectFramework(pkg);
364
+ if (freshFramework && config.stack?.framework && freshFramework !== config.stack.framework) {
365
+ findings.push({
366
+ level: "warning",
367
+ message: `El framework detectado (${freshFramework}) difiere del registrado (${config.stack.framework}). Corre argos adopt --refresh.`
368
+ });
369
+ }
370
+ const freshPackageManager = detectPackageManager(cwd);
371
+ if (freshPackageManager && config.stack?.packageManager && freshPackageManager !== config.stack.packageManager) {
372
+ findings.push({
373
+ level: "warning",
374
+ message: `El package manager detectado (${freshPackageManager}) difiere del registrado (${config.stack.packageManager}). Corre argos adopt --refresh.`
375
+ });
376
+ }
377
+ }
378
+ // Identity drift: current git remote vs the identity recorded in config.
379
+ const remoteUrl = getRemoteOriginUrl(cwd);
380
+ const freshIdentity = remoteUrl ? parseIdentityFromRemote(remoteUrl) ?? undefined : undefined;
381
+ if (freshIdentity && config.identity && freshIdentity !== config.identity) {
382
+ findings.push({
383
+ level: "warning",
384
+ message: `La identidad detectada (${freshIdentity}) difiere de la registrada (${config.identity}). Corre argos adopt --refresh.`
385
+ });
386
+ }
387
+ // Workspace linkage (F2): repo not registered, registered under a stale
388
+ // path, or config.workspace pointing at a name absent from the registry.
389
+ let registry;
390
+ try {
391
+ registry = loadRegistry();
392
+ } catch (err) {
393
+ findings.push({
394
+ level: "error",
395
+ message: `No se pudo leer workspaces.json (${err instanceof Error ? err.message : String(err)}).`
396
+ });
397
+ return;
398
+ }
399
+ const resolution = resolveWorkspaceForRepo(registry, {
400
+ configWorkspace: config.workspace,
401
+ remoteUrl,
402
+ repoPath: cwd
403
+ });
404
+ if (resolution.kind === "unresolved") {
405
+ findings.push({
406
+ level: "info",
407
+ message: "El repo no está vinculado a ningún workspace. Corre argos workspace link."
408
+ });
409
+ } else if (resolution.kind === "resolved") {
410
+ const workspace = registry[resolution.name];
411
+ if (!workspace) {
412
+ findings.push({
413
+ level: "warning",
414
+ message: `argos.config.json referencia el workspace '${resolution.name}', que no existe en el registro. Corre argos workspace link ${resolution.name}.`
415
+ });
416
+ } else {
417
+ const entry = workspace.repos.find((r)=>r.name === config.name);
418
+ if (!entry) {
419
+ findings.push({
420
+ level: "info",
421
+ message: "El repo no está vinculado a ningún workspace. Corre argos workspace link."
422
+ });
423
+ } else {
424
+ let realCwd;
425
+ try {
426
+ realCwd = realpathSync(resolve(cwd));
427
+ } catch {
428
+ realCwd = undefined;
429
+ }
430
+ if (realCwd && entry.path !== realCwd) {
431
+ findings.push({
432
+ level: "warning",
433
+ message: `El repo está registrado en el workspace '${resolution.name}' con un path distinto (${entry.path} vs ${realCwd}). Corre argos workspace link para actualizarlo.`
434
+ });
435
+ }
436
+ }
437
+ }
438
+ }
439
+ }
440
+ /**
441
+ * Core, testable implementation of `argos doctor`: a read-only audit of the
442
+ * global engine and (when cwd is a git repo) the repo's argos.config.json +
443
+ * ficha. Never writes anything.
444
+ */ export function runDoctor(options) {
445
+ const findings = [];
446
+ checkMotor(findings);
447
+ if (isGitRepo(options.cwd)) {
448
+ checkRepo(options.cwd, findings);
449
+ }
450
+ const exitCode = findings.some((f)=>f.level !== "info") ? 1 : 0;
451
+ return {
452
+ findings,
453
+ exitCode
454
+ };
455
+ }
456
+ export const doctorCommand = defineCommand({
457
+ meta: {
458
+ name: "doctor",
459
+ description: "Report drift between the engine, the repo config, and its ficha."
460
+ },
461
+ run () {
462
+ const report = runDoctor({
463
+ cwd: process.cwd()
464
+ });
465
+ if (report.findings.length === 0) {
466
+ console.log("Todo al día.");
467
+ process.exit(0);
468
+ }
469
+ for (const finding of report.findings){
470
+ const padded = finding.level.padEnd(10);
471
+ const label = finding.level === "error" ? pc.red(padded) : finding.level === "warning" ? pc.yellow(padded) : pc.dim(padded);
472
+ console.log(`${label} ${finding.message}`);
473
+ }
474
+ process.exit(report.exitCode);
475
+ }
476
+ });
477
+
478
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +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({ level: \"info\", message: `hooks/${id}.sh existe pero es ajeno (sin marker argos:file).` });\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 * 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({ level: \"info\", message: `${label} existe pero es ajeno (sin marker argos:file).` });\n }\n }\n\n checkHookScripts(findings, claudeDir, currentVersion);\n checkHookSettings(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","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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"}
@@ -0,0 +1,32 @@
1
+ import { type FileStatus } from "../lib/managed-files.js";
2
+ export type InitRowStatus = FileStatus | "error";
3
+ export interface InitRow {
4
+ path: string;
5
+ status: InitRowStatus;
6
+ detail?: string;
7
+ }
8
+ export interface InitOptions {
9
+ language?: "es" | "en";
10
+ }
11
+ export interface InitReport {
12
+ rows: InitRow[];
13
+ summary: string;
14
+ exitCode: 0 | 1;
15
+ backupPath?: string;
16
+ }
17
+ /**
18
+ * Core, testable implementation of `argos init`: installs the Argos engine
19
+ * (CLAUDE.md managed blocks + agents/skills/output-style full files +
20
+ * `~/.argos/global.json`) into `resolveClaudeDir()`. Pure function of the
21
+ * filesystem — no process.exit, no console output.
22
+ */
23
+ export declare function runInit(options?: InitOptions): InitReport;
24
+ export declare const initCommand: import("citty").CommandDef<{
25
+ readonly language: {
26
+ readonly type: "enum";
27
+ readonly options: ["es", "en"];
28
+ readonly default: "es";
29
+ readonly description: "Idioma del motor (global.json).";
30
+ };
31
+ }>;
32
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +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;AAuBjC,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;CACxB;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,CA4J7D;AAED,eAAO,MAAM,WAAW;;;;;;;EAyCtB,CAAC"}