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,358 @@
1
+ import { defineCommand } from "citty";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import pc from "picocolors";
5
+ import { listAgentIds, listSkillFiles, listSkillIds, MANAGED_BLOCK_IDS, readAsset, resolveAssetsDir } from "../lib/assets.js";
6
+ import { writeFileAtomic } from "../lib/atomic-write.js";
7
+ import { createBackup } from "../lib/backup.js";
8
+ import { injectBlock, listBlocks } from "../lib/markers.js";
9
+ import { hasArgosFileMarker, writeManagedFile, writeManagedShellFile } from "../lib/managed-files.js";
10
+ import { resolveArgosHome, resolveClaudeDir } from "../lib/paths.js";
11
+ import { mergeHooksIntoSettings } from "../lib/settings-merge.js";
12
+ import { readCliVersion } from "../lib/version.js";
13
+ /**
14
+ * Ids (basenames under assets/hooks/) of the 2 global hooks argos init
15
+ * installs. See spec 0003 "Hooks globales parametrizados".
16
+ */ const HOOK_IDS = [
17
+ "argos-guard-destructive",
18
+ "argos-quality-gate"
19
+ ];
20
+ /**
21
+ * Outer Claude Code hook timeout (seconds) for argos-quality-gate.sh. Fixed
22
+ * rather than derived from $ARGOS_GATE_TIMEOUT_MS: that env var is read
23
+ * inside the hook at COMMIT time (whatever env the Claude Code session has),
24
+ * not at `argos init` time, so there's nothing meaningful to read here. 600s
25
+ * comfortably covers the hook's own default inner bound (300s) with 2x
26
+ * headroom; a repo whose gate legitimately needs longer than ~590s needs to
27
+ * bump this constant (and rerun `argos init`) alongside its own
28
+ * $ARGOS_GATE_TIMEOUT_MS — not automated in v1.
29
+ */ const QUALITY_GATE_OUTER_TIMEOUT_SECONDS = 600;
30
+ const STATUS_COUNT_ORDER = [
31
+ "created",
32
+ "updated",
33
+ "unchanged",
34
+ "skipped-foreign",
35
+ "error"
36
+ ];
37
+ function summarize(rows) {
38
+ const counts = {
39
+ created: 0,
40
+ updated: 0,
41
+ unchanged: 0,
42
+ "skipped-foreign": 0,
43
+ error: 0
44
+ };
45
+ for (const row of rows)counts[row.status]++;
46
+ const parts = STATUS_COUNT_ORDER.filter((s)=>counts[s] > 0).map((s)=>`${counts[s]} ${s}`);
47
+ return `argos init: ${parts.join(", ")}.`;
48
+ }
49
+ function errorMessage(err) {
50
+ return err instanceof Error ? err.message : String(err);
51
+ }
52
+ /**
53
+ * Write a plain (unmarked) supporting file belonging to an already
54
+ * ownership-checked skill directory — e.g. `references/core.md`,
55
+ * `phases/0-product.md`. Unlike `writeManagedFile`, this never carries or
56
+ * checks the `argos:file` marker itself: ownership for the whole skill
57
+ * directory is decided once, up front, from its `SKILL.md` (see the skills
58
+ * loop in `runInit`), so per-file marker bookkeeping here would be
59
+ * redundant. Reports the same created/updated/unchanged statuses.
60
+ */ function writePlainFile(destPath, sourceContent) {
61
+ if (!existsSync(destPath)) {
62
+ mkdirSync(dirname(destPath), {
63
+ recursive: true
64
+ });
65
+ writeFileAtomic(destPath, sourceContent);
66
+ return "created";
67
+ }
68
+ const current = readFileSync(destPath, "utf-8");
69
+ if (current === sourceContent) return "unchanged";
70
+ writeFileAtomic(destPath, sourceContent);
71
+ return "updated";
72
+ }
73
+ /** Inject one managed CLAUDE.md block, reporting created/updated/unchanged. */ function injectAndReport(claudeMd, id, version, content) {
74
+ const hadBlock = listBlocks(claudeMd).some((b)=>b.id === id);
75
+ const after = injectBlock(claudeMd, id, version, content);
76
+ const status = after === claudeMd ? "unchanged" : hadBlock ? "updated" : "created";
77
+ return {
78
+ claudeMd: after,
79
+ status
80
+ };
81
+ }
82
+ /**
83
+ * Core, testable implementation of `argos init`: installs the Argos engine
84
+ * (CLAUDE.md managed blocks + agents/skills/output-style full files +
85
+ * `~/.argos/global.json`) into `resolveClaudeDir()`. Pure function of the
86
+ * filesystem — no process.exit, no console output.
87
+ */ export function runInit(options = {}) {
88
+ const language = options.language ?? "es";
89
+ const version = readCliVersion();
90
+ const claudeDir = resolveClaudeDir();
91
+ const assetsDir = resolveAssetsDir();
92
+ const rows = [];
93
+ // Backup everything Argos is about to touch, before any write happens. A
94
+ // failed backup means we have no safety net for what's about to be
95
+ // mutated, so it aborts the whole run right here — every subsequent
96
+ // mutation step is skipped, nothing gets touched.
97
+ let backupPath;
98
+ try {
99
+ backupPath = createBackup(claudeDir, [
100
+ "CLAUDE.md",
101
+ "agents",
102
+ "skills",
103
+ "output-styles",
104
+ "hooks",
105
+ "settings.json"
106
+ ]);
107
+ } catch (err) {
108
+ const detail = errorMessage(err);
109
+ rows.push({
110
+ path: "backup",
111
+ status: "error",
112
+ detail
113
+ });
114
+ return {
115
+ rows,
116
+ summary: `backup falló — no se tocó nada (${detail}).`,
117
+ exitCode: 1
118
+ };
119
+ }
120
+ // 1. CLAUDE.md — 5 managed blocks, in order.
121
+ const claudeMdPath = join(claudeDir, "CLAUDE.md");
122
+ let claudeMd = existsSync(claudeMdPath) ? readFileSync(claudeMdPath, "utf-8") : "";
123
+ const blockResults = [];
124
+ for (const id of MANAGED_BLOCK_IDS){
125
+ const content = readAsset(assetsDir, "managed", `${id}.md`).replace(/\n$/, "");
126
+ const result = injectAndReport(claudeMd, id, version, content);
127
+ claudeMd = result.claudeMd;
128
+ blockResults.push({
129
+ id,
130
+ status: result.status
131
+ });
132
+ }
133
+ try {
134
+ mkdirSync(claudeDir, {
135
+ recursive: true
136
+ });
137
+ writeFileAtomic(claudeMdPath, claudeMd);
138
+ for (const b of blockResults)rows.push({
139
+ path: `CLAUDE.md#${b.id}`,
140
+ status: b.status
141
+ });
142
+ } catch (err) {
143
+ const detail = errorMessage(err);
144
+ for (const id of MANAGED_BLOCK_IDS)rows.push({
145
+ path: `CLAUDE.md#${id}`,
146
+ status: "error",
147
+ detail
148
+ });
149
+ }
150
+ // 2. Full-file assets: output-style, agents.
151
+ const fullFiles = [
152
+ [
153
+ "output-styles",
154
+ "argos.md"
155
+ ],
156
+ ...listAgentIds(assetsDir).map((id)=>[
157
+ "agents",
158
+ `${id}.md`
159
+ ])
160
+ ];
161
+ for (const relPath of fullFiles){
162
+ const source = readAsset(assetsDir, ...relPath);
163
+ const dest = join(claudeDir, ...relPath);
164
+ try {
165
+ const status = writeManagedFile(dest, source, version);
166
+ rows.push({
167
+ path: join(...relPath),
168
+ status
169
+ });
170
+ } catch (err) {
171
+ rows.push({
172
+ path: join(...relPath),
173
+ status: "error",
174
+ detail: errorMessage(err)
175
+ });
176
+ }
177
+ }
178
+ // 2a. Skills: each skill directory (SKILL.md plus any `references/`,
179
+ // `phases/`, `assets/`, etc. it ships) is installed as a single unit.
180
+ // Ownership sentinel is SKILL.md's `argos:file` marker:
181
+ // - SKILL.md absent, or present WITH the marker → install/update every
182
+ // file the skill ships.
183
+ // - SKILL.md present WITHOUT the marker (foreign/user-modified) → skip
184
+ // every file under that skill dir, untouched — same policy as a single
185
+ // foreign full-file asset above, extended to the whole directory.
186
+ for (const skillId of listSkillIds(assetsDir)){
187
+ const skillMdDest = join(claudeDir, "skills", skillId, "SKILL.md");
188
+ const isForeignSkill = existsSync(skillMdDest) && !hasArgosFileMarker(readFileSync(skillMdDest, "utf-8"));
189
+ for (const relFile of listSkillFiles(assetsDir, skillId)){
190
+ const relParts = relFile.split("/");
191
+ const relPath = join("skills", skillId, ...relParts);
192
+ if (isForeignSkill) {
193
+ rows.push({
194
+ path: relPath,
195
+ status: "skipped-foreign"
196
+ });
197
+ continue;
198
+ }
199
+ const source = readAsset(assetsDir, "skills", skillId, ...relParts);
200
+ const dest = join(claudeDir, "skills", skillId, ...relParts);
201
+ try {
202
+ const status = relFile === "SKILL.md" ? writeManagedFile(dest, source, version) : writePlainFile(dest, source);
203
+ rows.push({
204
+ path: relPath,
205
+ status
206
+ });
207
+ } catch (err) {
208
+ rows.push({
209
+ path: relPath,
210
+ status: "error",
211
+ detail: errorMessage(err)
212
+ });
213
+ }
214
+ }
215
+ }
216
+ // 2b. Global hooks: full-file shell assets, own shell-comment marker,
217
+ // chmod +x. Same skipped-foreign policy as the full-file assets above.
218
+ // Track which hooks actually landed on disk successfully — a hook whose
219
+ // write threw must NEVER get a settings.json entry (see 2c below): a
220
+ // dangling PreToolUse entry pointing at a script that isn't there hard-
221
+ // blocks every subsequent Bash call.
222
+ const hookWriteFailed = new Map();
223
+ for (const id of HOOK_IDS){
224
+ const relPath = [
225
+ "hooks",
226
+ `${id}.sh`
227
+ ];
228
+ const source = readAsset(assetsDir, ...relPath);
229
+ const dest = join(claudeDir, ...relPath);
230
+ try {
231
+ const status = writeManagedShellFile(dest, source, version);
232
+ rows.push({
233
+ path: join(...relPath),
234
+ status
235
+ });
236
+ hookWriteFailed.set(id, false);
237
+ } catch (err) {
238
+ rows.push({
239
+ path: join(...relPath),
240
+ status: "error",
241
+ detail: errorMessage(err)
242
+ });
243
+ hookWriteFailed.set(id, true);
244
+ }
245
+ }
246
+ // 2c. settings.json — surgical merge of the 2 PreToolUse hook entries.
247
+ // Only writes/updates entries whose command targets one of the 2 scripts
248
+ // above; every other key and hook in the user's settings.json is left
249
+ // untouched (see lib/settings-merge.ts). Only hooks whose script write
250
+ // actually succeeded get an entry built for them at all.
251
+ const settingsPath = join(claudeDir, "settings.json");
252
+ const allHookSpecs = {
253
+ "argos-guard-destructive": {
254
+ scriptPath: join(claudeDir, "hooks", "argos-guard-destructive.sh"),
255
+ matcher: "Bash",
256
+ timeout: 10,
257
+ statusMessage: "argos: guard-destructive"
258
+ },
259
+ "argos-quality-gate": {
260
+ scriptPath: join(claudeDir, "hooks", "argos-quality-gate.sh"),
261
+ matcher: "Bash",
262
+ timeout: QUALITY_GATE_OUTER_TIMEOUT_SECONDS,
263
+ statusMessage: "argos: quality-gate"
264
+ }
265
+ };
266
+ const hookSpecs = HOOK_IDS.filter((id)=>!hookWriteFailed.get(id)).map((id)=>allHookSpecs[id]);
267
+ // Any hook whose write just failed also gets its (possibly pre-existing,
268
+ // from an earlier successful run) settings.json entry stripped out — a
269
+ // script that's gone or broken must never be left with a live entry.
270
+ const failedScriptPaths = HOOK_IDS.filter((id)=>hookWriteFailed.get(id)).map((id)=>allHookSpecs[id].scriptPath);
271
+ const mergeResult = mergeHooksIntoSettings(settingsPath, hookSpecs, {
272
+ removeScriptPaths: failedScriptPaths
273
+ });
274
+ rows.push({
275
+ path: "settings.json",
276
+ status: mergeResult.status,
277
+ detail: mergeResult.detail
278
+ });
279
+ // 3. ~/.argos/global.json
280
+ const argosHome = resolveArgosHome();
281
+ const globalJsonPath = join(argosHome, "global.json");
282
+ const globalJsonContent = `${JSON.stringify({
283
+ version,
284
+ language
285
+ }, null, 2)}\n`;
286
+ try {
287
+ const globalJsonExisted = existsSync(globalJsonPath);
288
+ const globalJsonStatus = !globalJsonExisted ? "created" : readFileSync(globalJsonPath, "utf-8") === globalJsonContent ? "unchanged" : "updated";
289
+ mkdirSync(argosHome, {
290
+ recursive: true
291
+ });
292
+ writeFileSync(globalJsonPath, globalJsonContent, "utf-8");
293
+ rows.push({
294
+ path: "global.json",
295
+ status: globalJsonStatus
296
+ });
297
+ } catch (err) {
298
+ rows.push({
299
+ path: "global.json",
300
+ status: "error",
301
+ detail: errorMessage(err)
302
+ });
303
+ }
304
+ const exitCode = rows.some((r)=>r.status === "error") ? 1 : 0;
305
+ return {
306
+ rows,
307
+ summary: summarize(rows),
308
+ exitCode,
309
+ backupPath
310
+ };
311
+ }
312
+ export const initCommand = defineCommand({
313
+ meta: {
314
+ name: "init",
315
+ description: "Install the Argos engine into the global Claude Code home."
316
+ },
317
+ args: {
318
+ language: {
319
+ type: "enum",
320
+ options: [
321
+ "es",
322
+ "en"
323
+ ],
324
+ default: "es",
325
+ description: "Idioma del motor (global.json)."
326
+ }
327
+ },
328
+ run ({ args }) {
329
+ const report = runInit({
330
+ language: args.language
331
+ });
332
+ const colorize = (status)=>{
333
+ const padded = status.padEnd(18);
334
+ switch(status){
335
+ case "skipped-foreign":
336
+ return pc.yellow(padded);
337
+ case "created":
338
+ return pc.green(padded);
339
+ case "updated":
340
+ return pc.cyan(padded);
341
+ case "error":
342
+ return pc.red(padded);
343
+ default:
344
+ return pc.dim(padded);
345
+ }
346
+ };
347
+ for (const row of report.rows){
348
+ const suffix = row.detail ? ` (${row.detail})` : "";
349
+ console.log(`${colorize(row.status)} ${row.path}${suffix}`);
350
+ }
351
+ console.log("");
352
+ console.log(report.summary);
353
+ if (report.backupPath) console.log(`backup en ${report.backupPath}`);
354
+ process.exit(report.exitCode);
355
+ }
356
+ });
357
+
358
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport pc from \"picocolors\";\nimport {\n listAgentIds,\n listSkillFiles,\n listSkillIds,\n MANAGED_BLOCK_IDS,\n readAsset,\n resolveAssetsDir,\n} from \"../lib/assets.js\";\nimport { writeFileAtomic } from \"../lib/atomic-write.js\";\nimport { createBackup } from \"../lib/backup.js\";\nimport { injectBlock, listBlocks } from \"../lib/markers.js\";\nimport {\n type FileStatus,\n hasArgosFileMarker,\n writeManagedFile,\n writeManagedShellFile,\n} from \"../lib/managed-files.js\";\nimport { resolveArgosHome, resolveClaudeDir } from \"../lib/paths.js\";\nimport { type ArgosHookSpec, mergeHooksIntoSettings } from \"../lib/settings-merge.js\";\nimport { readCliVersion } from \"../lib/version.js\";\n\n/**\n * Ids (basenames under assets/hooks/) of the 2 global hooks argos init\n * installs. See spec 0003 \"Hooks globales parametrizados\".\n */\nconst HOOK_IDS = [\"argos-guard-destructive\", \"argos-quality-gate\"] as const;\n\n/**\n * Outer Claude Code hook timeout (seconds) for argos-quality-gate.sh. Fixed\n * rather than derived from $ARGOS_GATE_TIMEOUT_MS: that env var is read\n * inside the hook at COMMIT time (whatever env the Claude Code session has),\n * not at `argos init` time, so there's nothing meaningful to read here. 600s\n * comfortably covers the hook's own default inner bound (300s) with 2x\n * headroom; a repo whose gate legitimately needs longer than ~590s needs to\n * bump this constant (and rerun `argos init`) alongside its own\n * $ARGOS_GATE_TIMEOUT_MS — not automated in v1.\n */\nconst QUALITY_GATE_OUTER_TIMEOUT_SECONDS = 600;\n\nexport type InitRowStatus = FileStatus | \"error\";\n\nexport interface InitRow {\n path: string;\n status: InitRowStatus;\n detail?: string;\n}\n\nexport interface InitOptions {\n language?: \"es\" | \"en\";\n}\n\nexport interface InitReport {\n rows: InitRow[];\n summary: string;\n exitCode: 0 | 1;\n backupPath?: string;\n}\n\nconst STATUS_COUNT_ORDER: InitRowStatus[] = [\"created\", \"updated\", \"unchanged\", \"skipped-foreign\", \"error\"];\n\nfunction summarize(rows: InitRow[]): string {\n const counts: Record<InitRowStatus, number> = {\n created: 0,\n updated: 0,\n unchanged: 0,\n \"skipped-foreign\": 0,\n error: 0,\n };\n for (const row of rows) counts[row.status]++;\n\n const parts = STATUS_COUNT_ORDER.filter((s) => counts[s] > 0).map((s) => `${counts[s]} ${s}`);\n return `argos init: ${parts.join(\", \")}.`;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Write a plain (unmarked) supporting file belonging to an already\n * ownership-checked skill directory — e.g. `references/core.md`,\n * `phases/0-product.md`. Unlike `writeManagedFile`, this never carries or\n * checks the `argos:file` marker itself: ownership for the whole skill\n * directory is decided once, up front, from its `SKILL.md` (see the skills\n * loop in `runInit`), so per-file marker bookkeeping here would be\n * redundant. Reports the same created/updated/unchanged statuses.\n */\nfunction writePlainFile(destPath: string, sourceContent: string): FileStatus {\n if (!existsSync(destPath)) {\n mkdirSync(dirname(destPath), { recursive: true });\n writeFileAtomic(destPath, sourceContent);\n return \"created\";\n }\n\n const current = readFileSync(destPath, \"utf-8\");\n if (current === sourceContent) return \"unchanged\";\n\n writeFileAtomic(destPath, sourceContent);\n return \"updated\";\n}\n\n/** Inject one managed CLAUDE.md block, reporting created/updated/unchanged. */\nfunction injectAndReport(claudeMd: string, id: string, version: string, content: string) {\n const hadBlock = listBlocks(claudeMd).some((b) => b.id === id);\n const after = injectBlock(claudeMd, id, version, content);\n const status: FileStatus = after === claudeMd ? \"unchanged\" : hadBlock ? \"updated\" : \"created\";\n return { claudeMd: after, status };\n}\n\n/**\n * Core, testable implementation of `argos init`: installs the Argos engine\n * (CLAUDE.md managed blocks + agents/skills/output-style full files +\n * `~/.argos/global.json`) into `resolveClaudeDir()`. Pure function of the\n * filesystem — no process.exit, no console output.\n */\nexport function runInit(options: InitOptions = {}): InitReport {\n const language = options.language ?? \"es\";\n const version = readCliVersion();\n const claudeDir = resolveClaudeDir();\n const assetsDir = resolveAssetsDir();\n const rows: InitRow[] = [];\n\n // Backup everything Argos is about to touch, before any write happens. A\n // failed backup means we have no safety net for what's about to be\n // mutated, so it aborts the whole run right here — every subsequent\n // mutation step is skipped, nothing gets touched.\n let backupPath: string | undefined;\n try {\n backupPath = createBackup(claudeDir, [\"CLAUDE.md\", \"agents\", \"skills\", \"output-styles\", \"hooks\", \"settings.json\"]);\n } catch (err) {\n const detail = errorMessage(err);\n rows.push({ path: \"backup\", status: \"error\", detail });\n return { rows, summary: `backup falló — no se tocó nada (${detail}).`, exitCode: 1 };\n }\n\n // 1. CLAUDE.md — 5 managed blocks, in order.\n const claudeMdPath = join(claudeDir, \"CLAUDE.md\");\n let claudeMd = existsSync(claudeMdPath) ? readFileSync(claudeMdPath, \"utf-8\") : \"\";\n const blockResults: { id: string; status: FileStatus }[] = [];\n for (const id of MANAGED_BLOCK_IDS) {\n const content = readAsset(assetsDir, \"managed\", `${id}.md`).replace(/\\n$/, \"\");\n const result = injectAndReport(claudeMd, id, version, content);\n claudeMd = result.claudeMd;\n blockResults.push({ id, status: result.status });\n }\n try {\n mkdirSync(claudeDir, { recursive: true });\n writeFileAtomic(claudeMdPath, claudeMd);\n for (const b of blockResults) rows.push({ path: `CLAUDE.md#${b.id}`, status: b.status });\n } catch (err) {\n const detail = errorMessage(err);\n for (const id of MANAGED_BLOCK_IDS) rows.push({ path: `CLAUDE.md#${id}`, status: \"error\", detail });\n }\n\n // 2. Full-file assets: output-style, agents.\n const fullFiles: string[][] = [\n [\"output-styles\", \"argos.md\"],\n ...listAgentIds(assetsDir).map((id) => [\"agents\", `${id}.md`]),\n ];\n for (const relPath of fullFiles) {\n const source = readAsset(assetsDir, ...relPath);\n const dest = join(claudeDir, ...relPath);\n try {\n const status = writeManagedFile(dest, source, version);\n rows.push({ path: join(...relPath), status });\n } catch (err) {\n rows.push({ path: join(...relPath), status: \"error\", detail: errorMessage(err) });\n }\n }\n\n // 2a. Skills: each skill directory (SKILL.md plus any `references/`,\n // `phases/`, `assets/`, etc. it ships) is installed as a single unit.\n // Ownership sentinel is SKILL.md's `argos:file` marker:\n // - SKILL.md absent, or present WITH the marker → install/update every\n // file the skill ships.\n // - SKILL.md present WITHOUT the marker (foreign/user-modified) → skip\n // every file under that skill dir, untouched — same policy as a single\n // foreign full-file asset above, extended to the whole directory.\n for (const skillId of listSkillIds(assetsDir)) {\n const skillMdDest = join(claudeDir, \"skills\", skillId, \"SKILL.md\");\n const isForeignSkill = existsSync(skillMdDest) && !hasArgosFileMarker(readFileSync(skillMdDest, \"utf-8\"));\n\n for (const relFile of listSkillFiles(assetsDir, skillId)) {\n const relParts = relFile.split(\"/\");\n const relPath = join(\"skills\", skillId, ...relParts);\n\n if (isForeignSkill) {\n rows.push({ path: relPath, status: \"skipped-foreign\" });\n continue;\n }\n\n const source = readAsset(assetsDir, \"skills\", skillId, ...relParts);\n const dest = join(claudeDir, \"skills\", skillId, ...relParts);\n try {\n const status = relFile === \"SKILL.md\" ? writeManagedFile(dest, source, version) : writePlainFile(dest, source);\n rows.push({ path: relPath, status });\n } catch (err) {\n rows.push({ path: relPath, status: \"error\", detail: errorMessage(err) });\n }\n }\n }\n\n // 2b. Global hooks: full-file shell assets, own shell-comment marker,\n // chmod +x. Same skipped-foreign policy as the full-file assets above.\n // Track which hooks actually landed on disk successfully — a hook whose\n // write threw must NEVER get a settings.json entry (see 2c below): a\n // dangling PreToolUse entry pointing at a script that isn't there hard-\n // blocks every subsequent Bash call.\n const hookWriteFailed = new Map<(typeof HOOK_IDS)[number], boolean>();\n for (const id of HOOK_IDS) {\n const relPath = [\"hooks\", `${id}.sh`];\n const source = readAsset(assetsDir, ...relPath);\n const dest = join(claudeDir, ...relPath);\n try {\n const status = writeManagedShellFile(dest, source, version);\n rows.push({ path: join(...relPath), status });\n hookWriteFailed.set(id, false);\n } catch (err) {\n rows.push({ path: join(...relPath), status: \"error\", detail: errorMessage(err) });\n hookWriteFailed.set(id, true);\n }\n }\n\n // 2c. settings.json — surgical merge of the 2 PreToolUse hook entries.\n // Only writes/updates entries whose command targets one of the 2 scripts\n // above; every other key and hook in the user's settings.json is left\n // untouched (see lib/settings-merge.ts). Only hooks whose script write\n // actually succeeded get an entry built for them at all.\n const settingsPath = join(claudeDir, \"settings.json\");\n const allHookSpecs: Record<(typeof HOOK_IDS)[number], ArgosHookSpec> = {\n \"argos-guard-destructive\": {\n scriptPath: join(claudeDir, \"hooks\", \"argos-guard-destructive.sh\"),\n matcher: \"Bash\",\n timeout: 10,\n statusMessage: \"argos: guard-destructive\",\n },\n \"argos-quality-gate\": {\n scriptPath: join(claudeDir, \"hooks\", \"argos-quality-gate.sh\"),\n matcher: \"Bash\",\n timeout: QUALITY_GATE_OUTER_TIMEOUT_SECONDS,\n statusMessage: \"argos: quality-gate\",\n },\n };\n const hookSpecs: ArgosHookSpec[] = HOOK_IDS.filter((id) => !hookWriteFailed.get(id)).map((id) => allHookSpecs[id]);\n // Any hook whose write just failed also gets its (possibly pre-existing,\n // from an earlier successful run) settings.json entry stripped out — a\n // script that's gone or broken must never be left with a live entry.\n const failedScriptPaths = HOOK_IDS.filter((id) => hookWriteFailed.get(id)).map((id) => allHookSpecs[id].scriptPath);\n const mergeResult = mergeHooksIntoSettings(settingsPath, hookSpecs, { removeScriptPaths: failedScriptPaths });\n rows.push({ path: \"settings.json\", status: mergeResult.status, detail: mergeResult.detail });\n\n // 3. ~/.argos/global.json\n const argosHome = resolveArgosHome();\n const globalJsonPath = join(argosHome, \"global.json\");\n const globalJsonContent = `${JSON.stringify({ version, language }, null, 2)}\\n`;\n try {\n const globalJsonExisted = existsSync(globalJsonPath);\n const globalJsonStatus: FileStatus = !globalJsonExisted\n ? \"created\"\n : readFileSync(globalJsonPath, \"utf-8\") === globalJsonContent\n ? \"unchanged\"\n : \"updated\";\n mkdirSync(argosHome, { recursive: true });\n writeFileSync(globalJsonPath, globalJsonContent, \"utf-8\");\n rows.push({ path: \"global.json\", status: globalJsonStatus });\n } catch (err) {\n rows.push({ path: \"global.json\", status: \"error\", detail: errorMessage(err) });\n }\n\n const exitCode: 0 | 1 = rows.some((r) => r.status === \"error\") ? 1 : 0;\n return { rows, summary: summarize(rows), exitCode, backupPath };\n}\n\nexport const initCommand = defineCommand({\n meta: {\n name: \"init\",\n description: \"Install the Argos engine into the global Claude Code home.\",\n },\n args: {\n language: {\n type: \"enum\",\n options: [\"es\", \"en\"],\n default: \"es\",\n description: \"Idioma del motor (global.json).\",\n },\n },\n run({ args }) {\n const report = runInit({ language: args.language as \"es\" | \"en\" });\n\n const colorize = (status: InitRowStatus): string => {\n const padded = status.padEnd(18);\n switch (status) {\n case \"skipped-foreign\":\n return pc.yellow(padded);\n case \"created\":\n return pc.green(padded);\n case \"updated\":\n return pc.cyan(padded);\n case \"error\":\n return pc.red(padded);\n default:\n return pc.dim(padded);\n }\n };\n for (const row of report.rows) {\n const suffix = row.detail ? ` (${row.detail})` : \"\";\n console.log(`${colorize(row.status)} ${row.path}${suffix}`);\n }\n console.log(\"\");\n console.log(report.summary);\n if (report.backupPath) console.log(`backup en ${report.backupPath}`);\n\n process.exit(report.exitCode);\n },\n});\n"],"names":["defineCommand","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join","pc","listAgentIds","listSkillFiles","listSkillIds","MANAGED_BLOCK_IDS","readAsset","resolveAssetsDir","writeFileAtomic","createBackup","injectBlock","listBlocks","hasArgosFileMarker","writeManagedFile","writeManagedShellFile","resolveArgosHome","resolveClaudeDir","mergeHooksIntoSettings","readCliVersion","HOOK_IDS","QUALITY_GATE_OUTER_TIMEOUT_SECONDS","STATUS_COUNT_ORDER","summarize","rows","counts","created","updated","unchanged","error","row","status","parts","filter","s","map","errorMessage","err","Error","message","String","writePlainFile","destPath","sourceContent","recursive","current","injectAndReport","claudeMd","id","version","content","hadBlock","some","b","after","runInit","options","language","claudeDir","assetsDir","backupPath","detail","push","path","summary","exitCode","claudeMdPath","blockResults","replace","result","fullFiles","relPath","source","dest","skillId","skillMdDest","isForeignSkill","relFile","relParts","split","hookWriteFailed","Map","set","settingsPath","allHookSpecs","scriptPath","matcher","timeout","statusMessage","hookSpecs","get","failedScriptPaths","mergeResult","removeScriptPaths","argosHome","globalJsonPath","globalJsonContent","JSON","stringify","globalJsonExisted","globalJsonStatus","r","initCommand","meta","name","description","args","type","default","run","report","colorize","padded","padEnd","yellow","green","cyan","red","dim","suffix","console","log","process","exit"],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Uninstaller for `argos init`: the mirror image of `runInit` (see
3
+ * commands/init.ts). Removes only what Argos itself owns — a managed
4
+ * CLAUDE.md block, a file carrying the `argos:file`/shell marker, or a
5
+ * settings.json hook entry pointing at an Argos script — and leaves every
6
+ * foreign file, block, and entry byte-identical.
7
+ *
8
+ * Scope: this command only touches `~/.claude` (via `resolveClaudeDir()`)
9
+ * and, with `--purge`, `~/.argos` (via `resolveArgosHome()`) — the global
10
+ * Argos engine and its registry. Repo-side artifacts are intentionally out
11
+ * of scope and are NEVER touched here: a repo's own `argos.config.json` and
12
+ * the "ficha" managed block `argos adopt` writes into that repo's own
13
+ * `CLAUDE.md` both survive `remove` untouched, including `remove --purge`.
14
+ * (See the final "scope" row every report ends with.)
15
+ */
16
+ export type RemoveRowStatus = "removed" | "would-remove" | "skipped-foreign" | "warning" | "info" | "error";
17
+ export type RemoveRowCategory = "claude-md-block" | "agents-file" | "skills-file" | "output-styles-file" | "hooks-file" | "settings-entries" | "argos-home" | "scope-note";
18
+ export interface RemoveRow {
19
+ path: string;
20
+ category: RemoveRowCategory;
21
+ status: RemoveRowStatus;
22
+ detail?: string;
23
+ }
24
+ export interface RemoveOptions {
25
+ /** Actually perform the removal. Default false = dry-run preview, touches nothing on disk. */
26
+ apply?: boolean;
27
+ /** Also remove ~/.argos data (registry, global.json, backups). Backups are removed LAST. */
28
+ purge?: boolean;
29
+ }
30
+ export interface RemoveReport {
31
+ rows: RemoveRow[];
32
+ summary: string;
33
+ exitCode: 0 | 1;
34
+ backupPath?: string;
35
+ /** Non-fatal warnings surfaced alongside the report, e.g. the --purge/backups tradeoff. */
36
+ warnings: string[];
37
+ }
38
+ /**
39
+ * Core, testable implementation of `argos remove`: uninstalls everything
40
+ * `runInit` (commands/init.ts) installs into `resolveClaudeDir()`. Pure
41
+ * function of the filesystem — no process.exit, no console output.
42
+ *
43
+ * Preview by default (`apply: false`): computes the full report without
44
+ * writing anything. `apply: true` performs the removal, backing up
45
+ * everything affected first (same `createBackup` call `runInit` makes,
46
+ * before any mutation). `purge: true` additionally removes `~/.argos` data
47
+ * (kept by default) — backups are removed last and always warned about.
48
+ */
49
+ export declare function runRemove(options?: RemoveOptions): RemoveReport;
50
+ export declare const removeCommand: import("citty").CommandDef<{
51
+ readonly apply: {
52
+ readonly type: "boolean";
53
+ readonly default: false;
54
+ readonly description: "Actually perform the removal (default: dry-run preview, touches nothing).";
55
+ };
56
+ readonly purge: {
57
+ readonly type: "boolean";
58
+ readonly default: false;
59
+ readonly description: "Also remove ~/.argos data (registry, global.json, backups). Irreversible.";
60
+ };
61
+ }>;
62
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,cAAc,GAAG,iBAAiB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5G,MAAM,MAAM,iBAAiB,GACzB,iBAAiB,GACjB,aAAa,GACb,aAAa,GACb,oBAAoB,GACpB,YAAY,GACZ,kBAAkB,GAClB,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4FAA4F;IAC5F,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA2RD;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,aAAkB,GAAG,YAAY,CA4DnE;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;EAkDxB,CAAC"}