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,354 @@
1
+ import { defineCommand } from "citty";
2
+ import { existsSync } from "node:fs";
3
+ import pc from "picocolors";
4
+ import { hasConfig, readConfig } from "../lib/config.js";
5
+ import { getRemoteOriginUrl } from "../lib/git.js";
6
+ import { OPENCLAW_BINARY, planWorkspaceAgents } from "../lib/openclaw-agents.js";
7
+ import { addRemoteMatchRule, linkRepo, loadRegistry, offerMatchRule, resolveWorkspaceForRepo } from "../lib/workspaces.js";
8
+ import { hasBinary as hasBinaryDefault } from "../lib/which.js";
9
+ function errorMessage(err) {
10
+ return err instanceof Error ? err.message : String(err);
11
+ }
12
+ /**
13
+ * Core, testable implementation of `argos workspace link [nombre]`: resolves
14
+ * which workspace the repo at `cwd` belongs to (explicit name > config >
15
+ * match rules) and registers it. When a brand-new workspace was created via
16
+ * an explicit name and the repo has a remote, teaches the registry that
17
+ * remote as a match rule so future repos under the same identity auto-link.
18
+ */ export function runWorkspaceLink(options) {
19
+ const { cwd, explicit, force } = options;
20
+ if (!hasConfig(cwd)) {
21
+ return {
22
+ exitCode: 1,
23
+ error: "No se encontró argos.config.json en este directorio — corre `argos adopt` primero."
24
+ };
25
+ }
26
+ let config;
27
+ try {
28
+ config = readConfig(cwd);
29
+ } catch (err) {
30
+ return {
31
+ exitCode: 1,
32
+ error: `argos.config.json inválido — ${errorMessage(err)}`
33
+ };
34
+ }
35
+ const remoteUrl = getRemoteOriginUrl(cwd);
36
+ let registry;
37
+ try {
38
+ registry = loadRegistry();
39
+ } catch (err) {
40
+ return {
41
+ exitCode: 1,
42
+ error: errorMessage(err)
43
+ };
44
+ }
45
+ const resolution = resolveWorkspaceForRepo(registry, {
46
+ explicit,
47
+ configWorkspace: config.workspace,
48
+ remoteUrl,
49
+ repoPath: cwd
50
+ });
51
+ if (resolution.kind === "unresolved") {
52
+ return {
53
+ exitCode: 1,
54
+ error: "No se pudo resolver un workspace para este repo — pasá un nombre explícito: " + "`argos workspace link <nombre>`."
55
+ };
56
+ }
57
+ if (resolution.kind === "ambiguous") {
58
+ return {
59
+ exitCode: 1,
60
+ error: `Match ambiguo entre workspaces (${resolution.candidates.join(", ")}) — pasá un nombre explícito.`,
61
+ ambiguousCandidates: resolution.candidates
62
+ };
63
+ }
64
+ let linkResult;
65
+ try {
66
+ linkResult = linkRepo(resolution.name, {
67
+ name: config.name,
68
+ path: cwd
69
+ }, {
70
+ force
71
+ });
72
+ } catch (err) {
73
+ return {
74
+ exitCode: 1,
75
+ error: errorMessage(err)
76
+ };
77
+ }
78
+ let matchRuleAdded;
79
+ if (resolution.source === "explicit") {
80
+ const currentMatch = loadRegistry()[resolution.name]?.match ?? {
81
+ remotes: [],
82
+ paths: []
83
+ };
84
+ const offer = offerMatchRule({
85
+ createdWorkspace: linkResult.createdWorkspace,
86
+ viaExplicitName: true,
87
+ remoteUrl,
88
+ currentMatch
89
+ });
90
+ if (offer.shouldPersist && offer.identity) {
91
+ addRemoteMatchRule(resolution.name, offer.identity);
92
+ matchRuleAdded = offer.identity;
93
+ }
94
+ }
95
+ return {
96
+ exitCode: 0,
97
+ workspaceName: resolution.name,
98
+ action: linkResult.action,
99
+ createdWorkspace: linkResult.createdWorkspace,
100
+ matchRuleAdded
101
+ };
102
+ }
103
+ const linkSubCommand = defineCommand({
104
+ meta: {
105
+ name: "link",
106
+ description: "Vincula el repo actual a un workspace (lo crea si no existe)."
107
+ },
108
+ args: {
109
+ name: {
110
+ type: "positional",
111
+ description: "Nombre de workspace explícito",
112
+ required: false
113
+ },
114
+ force: {
115
+ type: "boolean",
116
+ default: false,
117
+ description: "Sobrescribe un choque de nombre (mismo config.name, repo físico distinto)."
118
+ }
119
+ },
120
+ run ({ args }) {
121
+ const report = runWorkspaceLink({
122
+ cwd: process.cwd(),
123
+ explicit: args.name?.trim() || undefined,
124
+ force: Boolean(args.force)
125
+ });
126
+ if (report.error) {
127
+ console.error(pc.red(report.error));
128
+ process.exit(report.exitCode);
129
+ }
130
+ if (report.createdWorkspace) {
131
+ console.log(pc.dim(`Workspace '${report.workspaceName}' creado.`));
132
+ }
133
+ const actionLabel = {
134
+ added: "registrado",
135
+ "updated-path": "path actualizado",
136
+ unchanged: "sin cambios"
137
+ };
138
+ console.log(`${pc.green("✓")} repo ${actionLabel[report.action]} en workspace '${report.workspaceName}'.`);
139
+ if (report.matchRuleAdded) {
140
+ console.log(pc.dim(`El remote '${report.matchRuleAdded}' se guardó como match rule del workspace.`));
141
+ }
142
+ process.exit(report.exitCode);
143
+ }
144
+ });
145
+ /** Core, testable implementation of `argos workspace show [nombre]`. */ export function runWorkspaceShow(name, options = {}) {
146
+ const pathExists = options.pathExists ?? existsSync;
147
+ let registry;
148
+ try {
149
+ registry = loadRegistry();
150
+ } catch (err) {
151
+ return {
152
+ rows: [],
153
+ exitCode: 1,
154
+ error: errorMessage(err)
155
+ };
156
+ }
157
+ if (name) {
158
+ const workspace = registry[name];
159
+ if (!workspace) {
160
+ return {
161
+ rows: [],
162
+ exitCode: 1,
163
+ error: `Workspace '${name}' no encontrado.`
164
+ };
165
+ }
166
+ const rows = workspace.repos.map((r)=>({
167
+ workspace: name,
168
+ name: r.name,
169
+ path: r.path,
170
+ missing: !pathExists(r.path)
171
+ }));
172
+ return {
173
+ rows,
174
+ exitCode: 0
175
+ };
176
+ }
177
+ const rows = [];
178
+ for (const [wsName, workspace] of Object.entries(registry)){
179
+ for (const repo of workspace.repos){
180
+ rows.push({
181
+ workspace: wsName,
182
+ name: repo.name,
183
+ path: repo.path,
184
+ missing: !pathExists(repo.path)
185
+ });
186
+ }
187
+ }
188
+ return {
189
+ rows,
190
+ exitCode: 0
191
+ };
192
+ }
193
+ const showSubCommand = defineCommand({
194
+ meta: {
195
+ name: "show",
196
+ description: "Muestra los repos registrados en uno o todos los workspaces."
197
+ },
198
+ args: {
199
+ name: {
200
+ type: "positional",
201
+ description: "Nombre de workspace (default: todos)",
202
+ required: false
203
+ }
204
+ },
205
+ run ({ args }) {
206
+ const name = args.name?.trim() || undefined;
207
+ const report = runWorkspaceShow(name);
208
+ if (report.error) {
209
+ console.error(pc.red(report.error));
210
+ process.exit(report.exitCode);
211
+ }
212
+ if (report.rows.length === 0) {
213
+ console.log("Ningún repo registrado todavía. Corre `argos workspace link` desde un repo.");
214
+ process.exit(0);
215
+ }
216
+ for (const row of report.rows){
217
+ const flag = row.missing ? pc.red("(path inexistente)") : "";
218
+ console.log(`${pc.dim(row.workspace.padEnd(16))} ${row.name.padEnd(24)} ${row.path} ${flag}`.trimEnd());
219
+ }
220
+ process.exit(0);
221
+ }
222
+ });
223
+ /**
224
+ * Core logic for `workspace agents <nombre>`. Preview (default) never
225
+ * spawns anything — it only formats the commands that would run. `--apply`
226
+ * requires the `openclaw` binary on PATH; a per-repo failure never aborts
227
+ * the rest of the workspace (planWorkspaceAgents already guarantees this),
228
+ * so the exit code reflects the honest partial summary.
229
+ */ export function runWorkspaceAgents(name, options = {}) {
230
+ const apply = Boolean(options.apply);
231
+ const preview = !apply;
232
+ let registry;
233
+ try {
234
+ registry = loadRegistry();
235
+ } catch (err) {
236
+ return {
237
+ exitCode: 1,
238
+ preview,
239
+ error: errorMessage(err),
240
+ rows: []
241
+ };
242
+ }
243
+ const workspace = registry[name];
244
+ if (!workspace) {
245
+ return {
246
+ exitCode: 1,
247
+ preview,
248
+ reason: "workspace-not-found",
249
+ error: `Workspace '${name}' no encontrado.`,
250
+ rows: []
251
+ };
252
+ }
253
+ if (workspace.repos.length === 0) {
254
+ return {
255
+ exitCode: 0,
256
+ preview,
257
+ reason: "no-repos",
258
+ rows: []
259
+ };
260
+ }
261
+ const checkBinary = options.hasBinary ?? hasBinaryDefault;
262
+ if (apply && !checkBinary(OPENCLAW_BINARY)) {
263
+ return {
264
+ exitCode: 1,
265
+ preview,
266
+ reason: "binary-missing",
267
+ rows: []
268
+ };
269
+ }
270
+ const rows = planWorkspaceAgents(workspace.repos, {
271
+ preview,
272
+ prefix: options.prefix ?? "",
273
+ runner: options.runner,
274
+ pathExists: options.pathExists
275
+ });
276
+ const failed = rows.filter((r)=>r.status === "error" || r.status === "missing").length;
277
+ return {
278
+ exitCode: failed > 0 ? 1 : 0,
279
+ preview,
280
+ rows
281
+ };
282
+ }
283
+ const agentsSubCommand = defineCommand({
284
+ meta: {
285
+ name: "agents",
286
+ description: "Crea un agente OpenClaw por repo registrado en el workspace."
287
+ },
288
+ args: {
289
+ name: {
290
+ type: "positional",
291
+ description: "Nombre de workspace",
292
+ required: true
293
+ },
294
+ apply: {
295
+ type: "boolean",
296
+ default: false,
297
+ description: "Ejecuta 'openclaw agents add' de verdad. Sin esto, todo se previsualiza."
298
+ },
299
+ prefix: {
300
+ type: "string",
301
+ description: "Prefijo para cada nombre de agente OpenClaw."
302
+ }
303
+ },
304
+ run ({ args }) {
305
+ const name = args.name;
306
+ const apply = Boolean(args.apply);
307
+ const prefix = args.prefix ?? "";
308
+ const result = runWorkspaceAgents(name, {
309
+ apply,
310
+ prefix
311
+ });
312
+ if (result.reason === "workspace-not-found") {
313
+ console.error(pc.red(result.error ?? `Workspace '${name}' no encontrado.`));
314
+ process.exit(result.exitCode);
315
+ }
316
+ if (result.reason === "no-repos") {
317
+ console.log("Ningún repo registrado en este workspace. Corre `argos workspace link` desde un repo.");
318
+ process.exit(0);
319
+ }
320
+ if (result.reason === "binary-missing") {
321
+ console.error(pc.red(`No se encontró el binario '${OPENCLAW_BINARY}' en PATH. Este comando crea agentes OpenClaw ` + `y está pensado para correr donde OpenClaw está instalado (típicamente el VPS de agentes).`));
322
+ process.exit(result.exitCode);
323
+ }
324
+ const marker = {
325
+ created: pc.green("✓"),
326
+ "would-create": pc.yellow("•"),
327
+ exists: pc.dim("•"),
328
+ missing: pc.red("✗"),
329
+ error: pc.red("✗")
330
+ };
331
+ for (const row of result.rows){
332
+ console.log(`${marker[row.status]} ${row.name.padEnd(24)} ${pc.dim(row.status)} ${row.detail}`);
333
+ }
334
+ const failed = result.rows.filter((r)=>r.status === "error" || r.status === "missing").length;
335
+ const ok = result.rows.length - failed;
336
+ const summary = result.preview ? `${ok}/${result.rows.length} ok · ${failed} fallidos` : `${ok}/${result.rows.length} ok · ${failed} fallidos`;
337
+ console.log("");
338
+ console.log(result.preview ? pc.yellow(`Preview — ${summary}`) : pc.green(`Listo — ${summary}`));
339
+ process.exit(result.exitCode);
340
+ }
341
+ });
342
+ export const workspaceCommand = defineCommand({
343
+ meta: {
344
+ name: "workspace",
345
+ description: "Registro machine-local de workspaces (match rules + flota OpenClaw)."
346
+ },
347
+ subCommands: {
348
+ link: linkSubCommand,
349
+ show: showSubCommand,
350
+ agents: agentsSubCommand
351
+ }
352
+ });
353
+
354
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/workspace.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { existsSync } from \"node:fs\";\nimport pc from \"picocolors\";\nimport { hasConfig, readConfig, type ArgosConfig } from \"../lib/config.js\";\nimport { getRemoteOriginUrl } from \"../lib/git.js\";\nimport {\n OPENCLAW_BINARY,\n planWorkspaceAgents,\n type OpenclawRunner,\n type WorkspaceAgentRow,\n type WorkspaceAgentStatus,\n} from \"../lib/openclaw-agents.js\";\nimport {\n addRemoteMatchRule,\n linkRepo,\n loadRegistry,\n offerMatchRule,\n resolveWorkspaceForRepo,\n type LinkAction,\n} from \"../lib/workspaces.js\";\nimport { hasBinary as hasBinaryDefault } from \"../lib/which.js\";\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n// --- link --------------------------------------------------------------\n\nexport interface WorkspaceLinkOptions {\n cwd: string;\n /** Explicit workspace name passed on the command line, if any. */\n explicit?: string;\n /** Overwrite a name collision (same config.name, different physical repo) instead of refusing. */\n force?: boolean;\n}\n\nexport interface WorkspaceLinkReport {\n exitCode: 0 | 1;\n error?: string;\n ambiguousCandidates?: string[];\n workspaceName?: string;\n action?: LinkAction;\n createdWorkspace?: boolean;\n /** Remote identity persisted as a new match rule, if the offer fired. */\n matchRuleAdded?: string;\n}\n\n/**\n * Core, testable implementation of `argos workspace link [nombre]`: resolves\n * which workspace the repo at `cwd` belongs to (explicit name > config >\n * match rules) and registers it. When a brand-new workspace was created via\n * an explicit name and the repo has a remote, teaches the registry that\n * remote as a match rule so future repos under the same identity auto-link.\n */\nexport function runWorkspaceLink(options: WorkspaceLinkOptions): WorkspaceLinkReport {\n const { cwd, explicit, force } = options;\n\n if (!hasConfig(cwd)) {\n return {\n exitCode: 1,\n error: \"No se encontró argos.config.json en este directorio — corre `argos adopt` primero.\",\n };\n }\n\n let config: ArgosConfig;\n try {\n config = readConfig(cwd);\n } catch (err) {\n return { exitCode: 1, error: `argos.config.json inválido — ${errorMessage(err)}` };\n }\n\n const remoteUrl = getRemoteOriginUrl(cwd);\n let registry;\n try {\n registry = loadRegistry();\n } catch (err) {\n return { exitCode: 1, error: errorMessage(err) };\n }\n const resolution = resolveWorkspaceForRepo(registry, {\n explicit,\n configWorkspace: config.workspace,\n remoteUrl,\n repoPath: cwd,\n });\n\n if (resolution.kind === \"unresolved\") {\n return {\n exitCode: 1,\n error:\n \"No se pudo resolver un workspace para este repo — pasá un nombre explícito: \" +\n \"`argos workspace link <nombre>`.\",\n };\n }\n if (resolution.kind === \"ambiguous\") {\n return {\n exitCode: 1,\n error: `Match ambiguo entre workspaces (${resolution.candidates.join(\", \")}) — pasá un nombre explícito.`,\n ambiguousCandidates: resolution.candidates,\n };\n }\n\n let linkResult;\n try {\n linkResult = linkRepo(resolution.name, { name: config.name, path: cwd }, { force });\n } catch (err) {\n return { exitCode: 1, error: errorMessage(err) };\n }\n\n let matchRuleAdded: string | undefined;\n if (resolution.source === \"explicit\") {\n const currentMatch = loadRegistry()[resolution.name]?.match ?? { remotes: [], paths: [] };\n const offer = offerMatchRule({\n createdWorkspace: linkResult.createdWorkspace,\n viaExplicitName: true,\n remoteUrl,\n currentMatch,\n });\n if (offer.shouldPersist && offer.identity) {\n addRemoteMatchRule(resolution.name, offer.identity);\n matchRuleAdded = offer.identity;\n }\n }\n\n return {\n exitCode: 0,\n workspaceName: resolution.name,\n action: linkResult.action,\n createdWorkspace: linkResult.createdWorkspace,\n matchRuleAdded,\n };\n}\n\nconst linkSubCommand = defineCommand({\n meta: {\n name: \"link\",\n description: \"Vincula el repo actual a un workspace (lo crea si no existe).\",\n },\n args: {\n name: { type: \"positional\", description: \"Nombre de workspace explícito\", required: false },\n force: {\n type: \"boolean\",\n default: false,\n description: \"Sobrescribe un choque de nombre (mismo config.name, repo físico distinto).\",\n },\n },\n run({ args }) {\n const report = runWorkspaceLink({\n cwd: process.cwd(),\n explicit: (args.name as string | undefined)?.trim() || undefined,\n force: Boolean(args.force),\n });\n\n if (report.error) {\n console.error(pc.red(report.error));\n process.exit(report.exitCode);\n }\n\n if (report.createdWorkspace) {\n console.log(pc.dim(`Workspace '${report.workspaceName}' creado.`));\n }\n const actionLabel: Record<LinkAction, string> = {\n added: \"registrado\",\n \"updated-path\": \"path actualizado\",\n unchanged: \"sin cambios\",\n };\n console.log(\n `${pc.green(\"✓\")} repo ${actionLabel[report.action as LinkAction]} en workspace '${report.workspaceName}'.`,\n );\n if (report.matchRuleAdded) {\n console.log(\n pc.dim(`El remote '${report.matchRuleAdded}' se guardó como match rule del workspace.`),\n );\n }\n process.exit(report.exitCode);\n },\n});\n\n// --- show ----------------------------------------------------------------\n\nexport interface WorkspaceShowRepoRow {\n workspace: string;\n name: string;\n path: string;\n missing: boolean;\n}\n\nexport interface WorkspaceShowReport {\n rows: WorkspaceShowRepoRow[];\n exitCode: 0 | 1;\n error?: string;\n}\n\nexport interface WorkspaceShowOptions {\n /** Injectable for tests; defaults to node:fs existsSync. */\n pathExists?: (path: string) => boolean;\n}\n\n/** Core, testable implementation of `argos workspace show [nombre]`. */\nexport function runWorkspaceShow(name?: string, options: WorkspaceShowOptions = {}): WorkspaceShowReport {\n const pathExists = options.pathExists ?? existsSync;\n let registry;\n try {\n registry = loadRegistry();\n } catch (err) {\n return { rows: [], exitCode: 1, error: errorMessage(err) };\n }\n\n if (name) {\n const workspace = registry[name];\n if (!workspace) {\n return { rows: [], exitCode: 1, error: `Workspace '${name}' no encontrado.` };\n }\n const rows = workspace.repos.map((r) => ({\n workspace: name,\n name: r.name,\n path: r.path,\n missing: !pathExists(r.path),\n }));\n return { rows, exitCode: 0 };\n }\n\n const rows: WorkspaceShowRepoRow[] = [];\n for (const [wsName, workspace] of Object.entries(registry)) {\n for (const repo of workspace.repos) {\n rows.push({ workspace: wsName, name: repo.name, path: repo.path, missing: !pathExists(repo.path) });\n }\n }\n return { rows, exitCode: 0 };\n}\n\nconst showSubCommand = defineCommand({\n meta: {\n name: \"show\",\n description: \"Muestra los repos registrados en uno o todos los workspaces.\",\n },\n args: {\n name: { type: \"positional\", description: \"Nombre de workspace (default: todos)\", required: false },\n },\n run({ args }) {\n const name = (args.name as string | undefined)?.trim() || undefined;\n const report = runWorkspaceShow(name);\n\n if (report.error) {\n console.error(pc.red(report.error));\n process.exit(report.exitCode);\n }\n\n if (report.rows.length === 0) {\n console.log(\"Ningún repo registrado todavía. Corre `argos workspace link` desde un repo.\");\n process.exit(0);\n }\n\n for (const row of report.rows) {\n const flag = row.missing ? pc.red(\"(path inexistente)\") : \"\";\n console.log(`${pc.dim(row.workspace.padEnd(16))} ${row.name.padEnd(24)} ${row.path} ${flag}`.trimEnd());\n }\n process.exit(0);\n },\n});\n\n// --- agents ----------------------------------------------------------------\n\nexport interface RunWorkspaceAgentsOptions {\n /** false (default) = preview only; true = actually run `openclaw agents add`. */\n apply?: boolean;\n prefix?: string;\n /** Injectable for tests; defaults to lib/which.ts hasBinary. */\n hasBinary?: (name: string) => boolean;\n /** Injectable for tests; forwarded to planWorkspaceAgents. */\n runner?: OpenclawRunner;\n /** Injectable for tests; forwarded to planWorkspaceAgents. */\n pathExists?: (path: string) => boolean;\n}\n\nexport type RunWorkspaceAgentsEarlyReason = \"workspace-not-found\" | \"no-repos\" | \"binary-missing\";\n\nexport interface RunWorkspaceAgentsResult {\n exitCode: 0 | 1;\n preview: boolean;\n reason?: RunWorkspaceAgentsEarlyReason;\n error?: string;\n rows: WorkspaceAgentRow[];\n}\n\n/**\n * Core logic for `workspace agents <nombre>`. Preview (default) never\n * spawns anything — it only formats the commands that would run. `--apply`\n * requires the `openclaw` binary on PATH; a per-repo failure never aborts\n * the rest of the workspace (planWorkspaceAgents already guarantees this),\n * so the exit code reflects the honest partial summary.\n */\nexport function runWorkspaceAgents(\n name: string,\n options: RunWorkspaceAgentsOptions = {},\n): RunWorkspaceAgentsResult {\n const apply = Boolean(options.apply);\n const preview = !apply;\n\n let registry;\n try {\n registry = loadRegistry();\n } catch (err) {\n return { exitCode: 1, preview, error: errorMessage(err), rows: [] };\n }\n const workspace = registry[name];\n if (!workspace) {\n return {\n exitCode: 1,\n preview,\n reason: \"workspace-not-found\",\n error: `Workspace '${name}' no encontrado.`,\n rows: [],\n };\n }\n\n if (workspace.repos.length === 0) {\n return { exitCode: 0, preview, reason: \"no-repos\", rows: [] };\n }\n\n const checkBinary = options.hasBinary ?? hasBinaryDefault;\n if (apply && !checkBinary(OPENCLAW_BINARY)) {\n return { exitCode: 1, preview, reason: \"binary-missing\", rows: [] };\n }\n\n const rows = planWorkspaceAgents(workspace.repos, {\n preview,\n prefix: options.prefix ?? \"\",\n runner: options.runner,\n pathExists: options.pathExists,\n });\n const failed = rows.filter((r) => r.status === \"error\" || r.status === \"missing\").length;\n return { exitCode: failed > 0 ? 1 : 0, preview, rows };\n}\n\nconst agentsSubCommand = defineCommand({\n meta: {\n name: \"agents\",\n description: \"Crea un agente OpenClaw por repo registrado en el workspace.\",\n },\n args: {\n name: { type: \"positional\", description: \"Nombre de workspace\", required: true },\n apply: {\n type: \"boolean\",\n default: false,\n description: \"Ejecuta 'openclaw agents add' de verdad. Sin esto, todo se previsualiza.\",\n },\n prefix: {\n type: \"string\",\n description: \"Prefijo para cada nombre de agente OpenClaw.\",\n },\n },\n run({ args }) {\n const name = args.name as string;\n const apply = Boolean(args.apply);\n const prefix = (args.prefix as string | undefined) ?? \"\";\n\n const result = runWorkspaceAgents(name, { apply, prefix });\n\n if (result.reason === \"workspace-not-found\") {\n console.error(pc.red(result.error ?? `Workspace '${name}' no encontrado.`));\n process.exit(result.exitCode);\n }\n if (result.reason === \"no-repos\") {\n console.log(\"Ningún repo registrado en este workspace. Corre `argos workspace link` desde un repo.\");\n process.exit(0);\n }\n if (result.reason === \"binary-missing\") {\n console.error(\n pc.red(\n `No se encontró el binario '${OPENCLAW_BINARY}' en PATH. Este comando crea agentes OpenClaw ` +\n `y está pensado para correr donde OpenClaw está instalado (típicamente el VPS de agentes).`,\n ),\n );\n process.exit(result.exitCode);\n }\n\n const marker: Record<WorkspaceAgentStatus, string> = {\n created: pc.green(\"✓\"),\n \"would-create\": pc.yellow(\"•\"),\n exists: pc.dim(\"•\"),\n missing: pc.red(\"✗\"),\n error: pc.red(\"✗\"),\n };\n for (const row of result.rows) {\n console.log(`${marker[row.status]} ${row.name.padEnd(24)} ${pc.dim(row.status)} ${row.detail}`);\n }\n\n const failed = result.rows.filter((r) => r.status === \"error\" || r.status === \"missing\").length;\n const ok = result.rows.length - failed;\n const summary = result.preview\n ? `${ok}/${result.rows.length} ok · ${failed} fallidos`\n : `${ok}/${result.rows.length} ok · ${failed} fallidos`;\n console.log(\"\");\n console.log(result.preview ? pc.yellow(`Preview — ${summary}`) : pc.green(`Listo — ${summary}`));\n process.exit(result.exitCode);\n },\n});\n\nexport const workspaceCommand = defineCommand({\n meta: {\n name: \"workspace\",\n description: \"Registro machine-local de workspaces (match rules + flota OpenClaw).\",\n },\n subCommands: {\n link: linkSubCommand,\n show: showSubCommand,\n agents: agentsSubCommand,\n },\n});\n"],"names":["defineCommand","existsSync","pc","hasConfig","readConfig","getRemoteOriginUrl","OPENCLAW_BINARY","planWorkspaceAgents","addRemoteMatchRule","linkRepo","loadRegistry","offerMatchRule","resolveWorkspaceForRepo","hasBinary","hasBinaryDefault","errorMessage","err","Error","message","String","runWorkspaceLink","options","cwd","explicit","force","exitCode","error","config","remoteUrl","registry","resolution","configWorkspace","workspace","repoPath","kind","candidates","join","ambiguousCandidates","linkResult","name","path","matchRuleAdded","source","currentMatch","match","remotes","paths","offer","createdWorkspace","viaExplicitName","shouldPersist","identity","workspaceName","action","linkSubCommand","meta","description","args","type","required","default","run","report","process","trim","undefined","Boolean","console","red","exit","log","dim","actionLabel","added","unchanged","green","runWorkspaceShow","pathExists","rows","repos","map","r","missing","wsName","Object","entries","repo","push","showSubCommand","length","row","flag","padEnd","trimEnd","runWorkspaceAgents","apply","preview","reason","checkBinary","prefix","runner","failed","filter","status","agentsSubCommand","result","marker","created","yellow","exists","detail","ok","summary","workspaceCommand","subCommands","link","show","agents"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ import { defineCommand, runMain } from "citty";
2
+ import { initCommand } from "./commands/init.js";
3
+ import { adoptCommand } from "./commands/adopt.js";
4
+ import { doctorCommand } from "./commands/doctor.js";
5
+ import { removeCommand } from "./commands/remove.js";
6
+ import { workspaceCommand } from "./commands/workspace.js";
7
+ import { readCliVersion } from "./lib/version.js";
8
+ const main = defineCommand({
9
+ meta: {
10
+ name: "argos",
11
+ version: readCliVersion(),
12
+ description: "Argos — global-first harness for Claude Code"
13
+ },
14
+ subCommands: {
15
+ init: initCommand,
16
+ adopt: adoptCommand,
17
+ doctor: doctorCommand,
18
+ remove: removeCommand,
19
+ workspace: workspaceCommand
20
+ }
21
+ });
22
+ runMain(main);
23
+
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { defineCommand, runMain } from \"citty\";\nimport { initCommand } from \"./commands/init.js\";\nimport { adoptCommand } from \"./commands/adopt.js\";\nimport { doctorCommand } from \"./commands/doctor.js\";\nimport { removeCommand } from \"./commands/remove.js\";\nimport { workspaceCommand } from \"./commands/workspace.js\";\nimport { readCliVersion } from \"./lib/version.js\";\n\nconst main = defineCommand({\n meta: {\n name: \"argos\",\n version: readCliVersion(),\n description: \"Argos — global-first harness for Claude Code\",\n },\n subCommands: {\n init: initCommand,\n adopt: adoptCommand,\n doctor: doctorCommand,\n remove: removeCommand,\n workspace: workspaceCommand,\n },\n});\n\nrunMain(main);\n"],"names":["defineCommand","runMain","initCommand","adoptCommand","doctorCommand","removeCommand","workspaceCommand","readCliVersion","main","meta","name","version","description","subCommands","init","adopt","doctor","remove","workspace"],"mappings":"AAAA,SAASA,aAAa,EAAEC,OAAO,QAAQ,QAAQ;AAC/C,SAASC,WAAW,QAAQ,qBAAqB;AACjD,SAASC,YAAY,QAAQ,sBAAsB;AACnD,SAASC,aAAa,QAAQ,uBAAuB;AACrD,SAASC,aAAa,QAAQ,uBAAuB;AACrD,SAASC,gBAAgB,QAAQ,0BAA0B;AAC3D,SAASC,cAAc,QAAQ,mBAAmB;AAElD,MAAMC,OAAOR,cAAc;IACzBS,MAAM;QACJC,MAAM;QACNC,SAASJ;QACTK,aAAa;IACf;IACAC,aAAa;QACXC,MAAMZ;QACNa,OAAOZ;QACPa,QAAQZ;QACRa,QAAQZ;QACRa,WAAWZ;IACb;AACF;AAEAL,QAAQO"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Ordered ids of the 5 managed CLAUDE.md blocks. Order defines the order the
3
+ * blocks appear in the rendered file. Ids are the basenames (without `.md`)
4
+ * of `assets/managed/*.md`.
5
+ */
6
+ export declare const MANAGED_BLOCK_IDS: readonly ["identidad", "formato-respuesta", "aterrizaje", "orquestacion", "operaciones-seguras"];
7
+ /**
8
+ * Resolve the Argos assets directory (`managed/`, `agents/`, `skills/`,
9
+ * `output-styles/`) relative to the currently running module. See
10
+ * `resolvePackageRoot` for the resolution strategy.
11
+ */
12
+ export declare function resolveAssetsDir(fromUrl?: string): string;
13
+ /** Read a text asset file relative to the assets directory. */
14
+ export declare function readAsset(assetsDir: string, ...relPath: string[]): string;
15
+ /** List agent ids (basenames without `.md`) found under `assets/agents/`. */
16
+ export declare function listAgentIds(assetsDir: string): string[];
17
+ /** List skill ids (directory names) found under `assets/skills/`. */
18
+ export declare function listSkillIds(assetsDir: string): string[];
19
+ /**
20
+ * Recursively list every file shipped under a skill's asset directory
21
+ * (`assets/skills/<skillId>/`), as relative paths from that directory with
22
+ * forward slashes regardless of platform (e.g. `SKILL.md`,
23
+ * `references/core.md`, `phases/0-product.md`). Sorted for deterministic
24
+ * output. Some skills are a single `SKILL.md`; ~15 also ship load-bearing
25
+ * subdirectories (`references/`, `phases/`, `assets/`) that this walks too —
26
+ * without it, only `SKILL.md` would ever reach the user's `~/.claude/skills`.
27
+ */
28
+ export declare function listSkillFiles(assetsDir: string, skillId: string): string[];
29
+ //# sourceMappingURL=assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/lib/assets.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,kGAMpB,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,MAAwB,GAAG,MAAM,CAE1E;AAED,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAEzE;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAKxD;AAED,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAKxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAY3E"}
@@ -0,0 +1,57 @@
1
+ import { readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { resolvePackageRoot } from "./package-root.js";
4
+ /**
5
+ * Ordered ids of the 5 managed CLAUDE.md blocks. Order defines the order the
6
+ * blocks appear in the rendered file. Ids are the basenames (without `.md`)
7
+ * of `assets/managed/*.md`.
8
+ */ export const MANAGED_BLOCK_IDS = [
9
+ "identidad",
10
+ "formato-respuesta",
11
+ "aterrizaje",
12
+ "orquestacion",
13
+ "operaciones-seguras"
14
+ ];
15
+ /**
16
+ * Resolve the Argos assets directory (`managed/`, `agents/`, `skills/`,
17
+ * `output-styles/`) relative to the currently running module. See
18
+ * `resolvePackageRoot` for the resolution strategy.
19
+ */ export function resolveAssetsDir(fromUrl = import.meta.url) {
20
+ return join(resolvePackageRoot(fromUrl), "assets");
21
+ }
22
+ /** Read a text asset file relative to the assets directory. */ export function readAsset(assetsDir, ...relPath) {
23
+ return readFileSync(join(assetsDir, ...relPath), "utf-8");
24
+ }
25
+ /** List agent ids (basenames without `.md`) found under `assets/agents/`. */ export function listAgentIds(assetsDir) {
26
+ return readdirSync(join(assetsDir, "agents")).filter((f)=>f.endsWith(".md")).map((f)=>f.slice(0, -3)).sort();
27
+ }
28
+ /** List skill ids (directory names) found under `assets/skills/`. */ export function listSkillIds(assetsDir) {
29
+ return readdirSync(join(assetsDir, "skills"), {
30
+ withFileTypes: true
31
+ }).filter((entry)=>entry.isDirectory()).map((entry)=>entry.name).sort();
32
+ }
33
+ /**
34
+ * Recursively list every file shipped under a skill's asset directory
35
+ * (`assets/skills/<skillId>/`), as relative paths from that directory with
36
+ * forward slashes regardless of platform (e.g. `SKILL.md`,
37
+ * `references/core.md`, `phases/0-product.md`). Sorted for deterministic
38
+ * output. Some skills are a single `SKILL.md`; ~15 also ship load-bearing
39
+ * subdirectories (`references/`, `phases/`, `assets/`) that this walks too —
40
+ * without it, only `SKILL.md` would ever reach the user's `~/.claude/skills`.
41
+ */ export function listSkillFiles(assetsDir, skillId) {
42
+ const root = join(assetsDir, "skills", skillId);
43
+ const out = [];
44
+ const walk = (dir, prefix)=>{
45
+ for (const entry of readdirSync(dir, {
46
+ withFileTypes: true
47
+ })){
48
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
49
+ if (entry.isDirectory()) walk(join(dir, entry.name), rel);
50
+ else out.push(rel);
51
+ }
52
+ };
53
+ walk(root, "");
54
+ return out.sort();
55
+ }
56
+
57
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/assets.ts"],"sourcesContent":["import { readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { resolvePackageRoot } from \"./package-root.js\";\n\n/**\n * Ordered ids of the 5 managed CLAUDE.md blocks. Order defines the order the\n * blocks appear in the rendered file. Ids are the basenames (without `.md`)\n * of `assets/managed/*.md`.\n */\nexport const MANAGED_BLOCK_IDS = [\n \"identidad\",\n \"formato-respuesta\",\n \"aterrizaje\",\n \"orquestacion\",\n \"operaciones-seguras\",\n] as const;\n\n/**\n * Resolve the Argos assets directory (`managed/`, `agents/`, `skills/`,\n * `output-styles/`) relative to the currently running module. See\n * `resolvePackageRoot` for the resolution strategy.\n */\nexport function resolveAssetsDir(fromUrl: string = import.meta.url): string {\n return join(resolvePackageRoot(fromUrl), \"assets\");\n}\n\n/** Read a text asset file relative to the assets directory. */\nexport function readAsset(assetsDir: string, ...relPath: string[]): string {\n return readFileSync(join(assetsDir, ...relPath), \"utf-8\");\n}\n\n/** List agent ids (basenames without `.md`) found under `assets/agents/`. */\nexport function listAgentIds(assetsDir: string): string[] {\n return readdirSync(join(assetsDir, \"agents\"))\n .filter((f) => f.endsWith(\".md\"))\n .map((f) => f.slice(0, -3))\n .sort();\n}\n\n/** List skill ids (directory names) found under `assets/skills/`. */\nexport function listSkillIds(assetsDir: string): string[] {\n return readdirSync(join(assetsDir, \"skills\"), { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n}\n\n/**\n * Recursively list every file shipped under a skill's asset directory\n * (`assets/skills/<skillId>/`), as relative paths from that directory with\n * forward slashes regardless of platform (e.g. `SKILL.md`,\n * `references/core.md`, `phases/0-product.md`). Sorted for deterministic\n * output. Some skills are a single `SKILL.md`; ~15 also ship load-bearing\n * subdirectories (`references/`, `phases/`, `assets/`) that this walks too —\n * without it, only `SKILL.md` would ever reach the user's `~/.claude/skills`.\n */\nexport function listSkillFiles(assetsDir: string, skillId: string): string[] {\n const root = join(assetsDir, \"skills\", skillId);\n const out: string[] = [];\n const walk = (dir: string, prefix: string) => {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (entry.isDirectory()) walk(join(dir, entry.name), rel);\n else out.push(rel);\n }\n };\n walk(root, \"\");\n return out.sort();\n}\n"],"names":["readdirSync","readFileSync","join","resolvePackageRoot","MANAGED_BLOCK_IDS","resolveAssetsDir","fromUrl","url","readAsset","assetsDir","relPath","listAgentIds","filter","f","endsWith","map","slice","sort","listSkillIds","withFileTypes","entry","isDirectory","name","listSkillFiles","skillId","root","out","walk","dir","prefix","rel","push"],"mappings":"AAAA,SAASA,WAAW,EAAEC,YAAY,QAAQ,UAAU;AACpD,SAASC,IAAI,QAAQ,YAAY;AACjC,SAASC,kBAAkB,QAAQ,oBAAoB;AAEvD;;;;CAIC,GACD,OAAO,MAAMC,oBAAoB;IAC/B;IACA;IACA;IACA;IACA;CACD,CAAU;AAEX;;;;CAIC,GACD,OAAO,SAASC,iBAAiBC,UAAkB,YAAYC,GAAG;IAChE,OAAOL,KAAKC,mBAAmBG,UAAU;AAC3C;AAEA,6DAA6D,GAC7D,OAAO,SAASE,UAAUC,SAAiB,EAAE,GAAGC,OAAiB;IAC/D,OAAOT,aAAaC,KAAKO,cAAcC,UAAU;AACnD;AAEA,2EAA2E,GAC3E,OAAO,SAASC,aAAaF,SAAiB;IAC5C,OAAOT,YAAYE,KAAKO,WAAW,WAChCG,MAAM,CAAC,CAACC,IAAMA,EAAEC,QAAQ,CAAC,QACzBC,GAAG,CAAC,CAACF,IAAMA,EAAEG,KAAK,CAAC,GAAG,CAAC,IACvBC,IAAI;AACT;AAEA,mEAAmE,GACnE,OAAO,SAASC,aAAaT,SAAiB;IAC5C,OAAOT,YAAYE,KAAKO,WAAW,WAAW;QAAEU,eAAe;IAAK,GACjEP,MAAM,CAAC,CAACQ,QAAUA,MAAMC,WAAW,IACnCN,GAAG,CAAC,CAACK,QAAUA,MAAME,IAAI,EACzBL,IAAI;AACT;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASM,eAAed,SAAiB,EAAEe,OAAe;IAC/D,MAAMC,OAAOvB,KAAKO,WAAW,UAAUe;IACvC,MAAME,MAAgB,EAAE;IACxB,MAAMC,OAAO,CAACC,KAAaC;QACzB,KAAK,MAAMT,SAASpB,YAAY4B,KAAK;YAAET,eAAe;QAAK,GAAI;YAC7D,MAAMW,MAAMD,SAAS,GAAGA,OAAO,CAAC,EAAET,MAAME,IAAI,EAAE,GAAGF,MAAME,IAAI;YAC3D,IAAIF,MAAMC,WAAW,IAAIM,KAAKzB,KAAK0B,KAAKR,MAAME,IAAI,GAAGQ;iBAChDJ,IAAIK,IAAI,CAACD;QAChB;IACF;IACAH,KAAKF,MAAM;IACX,OAAOC,IAAIT,IAAI;AACjB"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Write `content` to `path` atomically.
3
+ *
4
+ * Every plain `writeFileSync` in this codebase writes in place — if the
5
+ * process dies mid-write (OOM kill, power loss, a killed CI job), `path`
6
+ * is left holding truncated/torn content. For a hook shell script that
7
+ * means a syntax error, which turns into a hard PreToolUse block on every
8
+ * single Bash call until the user manually deletes or fixes the file.
9
+ *
10
+ * This writes to a randomly-named `.tmp` file in the SAME directory as
11
+ * `path` (so the follow-up rename stays on one filesystem and is atomic),
12
+ * then `renameSync`s it into place. A crash before the rename leaves
13
+ * `path` completely untouched; the stray tmp file is cleaned up on any
14
+ * failure this function can observe.
15
+ */
16
+ export declare function writeFileAtomic(path: string, content: string, mode?: number): void;
17
+ //# sourceMappingURL=atomic-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic-write.d.ts","sourceRoot":"","sources":["../../src/lib/atomic-write.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAoBlF"}
@@ -0,0 +1,41 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { chmodSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
+ import { basename, dirname, join } from "node:path";
4
+ /**
5
+ * Write `content` to `path` atomically.
6
+ *
7
+ * Every plain `writeFileSync` in this codebase writes in place — if the
8
+ * process dies mid-write (OOM kill, power loss, a killed CI job), `path`
9
+ * is left holding truncated/torn content. For a hook shell script that
10
+ * means a syntax error, which turns into a hard PreToolUse block on every
11
+ * single Bash call until the user manually deletes or fixes the file.
12
+ *
13
+ * This writes to a randomly-named `.tmp` file in the SAME directory as
14
+ * `path` (so the follow-up rename stays on one filesystem and is atomic),
15
+ * then `renameSync`s it into place. A crash before the rename leaves
16
+ * `path` completely untouched; the stray tmp file is cleaned up on any
17
+ * failure this function can observe.
18
+ */ export function writeFileAtomic(path, content, mode) {
19
+ const dir = dirname(path);
20
+ const tmpPath = join(dir, `.${basename(path)}.${randomBytes(6).toString("hex")}.tmp`);
21
+ try {
22
+ writeFileSync(tmpPath, content, "utf-8");
23
+ // Force the exact mode on the tmp file (not just the create-time `mode`
24
+ // option, which is subject to the process umask) so callers get the
25
+ // same guarantee a direct `chmodSync` on the final path would have —
26
+ // rename() preserves whatever permissions the tmp file already has.
27
+ if (mode !== undefined) chmodSync(tmpPath, mode);
28
+ renameSync(tmpPath, path);
29
+ } catch (err) {
30
+ try {
31
+ rmSync(tmpPath, {
32
+ force: true
33
+ });
34
+ } catch {
35
+ // Best-effort cleanup — the original error is what matters to the caller.
36
+ }
37
+ throw err;
38
+ }
39
+ }
40
+
41
+ //# sourceMappingURL=atomic-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/atomic-write.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { chmodSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\n\n/**\n * Write `content` to `path` atomically.\n *\n * Every plain `writeFileSync` in this codebase writes in place — if the\n * process dies mid-write (OOM kill, power loss, a killed CI job), `path`\n * is left holding truncated/torn content. For a hook shell script that\n * means a syntax error, which turns into a hard PreToolUse block on every\n * single Bash call until the user manually deletes or fixes the file.\n *\n * This writes to a randomly-named `.tmp` file in the SAME directory as\n * `path` (so the follow-up rename stays on one filesystem and is atomic),\n * then `renameSync`s it into place. A crash before the rename leaves\n * `path` completely untouched; the stray tmp file is cleaned up on any\n * failure this function can observe.\n */\nexport function writeFileAtomic(path: string, content: string, mode?: number): void {\n const dir = dirname(path);\n const tmpPath = join(dir, `.${basename(path)}.${randomBytes(6).toString(\"hex\")}.tmp`);\n\n try {\n writeFileSync(tmpPath, content, \"utf-8\");\n // Force the exact mode on the tmp file (not just the create-time `mode`\n // option, which is subject to the process umask) so callers get the\n // same guarantee a direct `chmodSync` on the final path would have —\n // rename() preserves whatever permissions the tmp file already has.\n if (mode !== undefined) chmodSync(tmpPath, mode);\n renameSync(tmpPath, path);\n } catch (err) {\n try {\n rmSync(tmpPath, { force: true });\n } catch {\n // Best-effort cleanup — the original error is what matters to the caller.\n }\n throw err;\n }\n}\n"],"names":["randomBytes","chmodSync","renameSync","rmSync","writeFileSync","basename","dirname","join","writeFileAtomic","path","content","mode","dir","tmpPath","toString","undefined","err","force"],"mappings":"AAAA,SAASA,WAAW,QAAQ,cAAc;AAC1C,SAASC,SAAS,EAAEC,UAAU,EAAEC,MAAM,EAAEC,aAAa,QAAQ,UAAU;AACvE,SAASC,QAAQ,EAAEC,OAAO,EAAEC,IAAI,QAAQ,YAAY;AAEpD;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASC,gBAAgBC,IAAY,EAAEC,OAAe,EAAEC,IAAa;IAC1E,MAAMC,MAAMN,QAAQG;IACpB,MAAMI,UAAUN,KAAKK,KAAK,CAAC,CAAC,EAAEP,SAASI,MAAM,CAAC,EAAET,YAAY,GAAGc,QAAQ,CAAC,OAAO,IAAI,CAAC;IAEpF,IAAI;QACFV,cAAcS,SAASH,SAAS;QAChC,wEAAwE;QACxE,oEAAoE;QACpE,qEAAqE;QACrE,oEAAoE;QACpE,IAAIC,SAASI,WAAWd,UAAUY,SAASF;QAC3CT,WAAWW,SAASJ;IACtB,EAAE,OAAOO,KAAK;QACZ,IAAI;YACFb,OAAOU,SAAS;gBAAEI,OAAO;YAAK;QAChC,EAAE,OAAM;QACN,0EAA0E;QAC5E;QACA,MAAMD;IACR;AACF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copy `entries` (files or directories, relative to `claudeDir`) into a
3
+ * timestamped backup directory under `<argos home>/backups/` before a
4
+ * destructive write. Missing entries are skipped silently — there is
5
+ * nothing to protect. Returns the backup directory path.
6
+ *
7
+ * The directory name carries a short random suffix alongside the ISO
8
+ * timestamp so two backups taken within the same millisecond never collide.
9
+ */
10
+ export declare function createBackup(claudeDir: string, entries: string[]): string;
11
+ //# sourceMappingURL=backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/lib/backup.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAoBzE"}