argos-harness 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/assets/hooks/argos-guard-destructive.sh +1 -1
  2. package/assets/managed/disciplina-skills.md +11 -0
  3. package/assets/managed/formato-respuesta.md +2 -2
  4. package/assets/managed/identidad.md +7 -7
  5. package/assets/managed/operaciones-seguras.md +6 -6
  6. package/assets/output-styles/argos.md +12 -12
  7. package/dist/commands/adopt.d.ts +41 -1
  8. package/dist/commands/adopt.d.ts.map +1 -1
  9. package/dist/commands/adopt.js +243 -6
  10. package/dist/commands/adopt.js.map +1 -1
  11. package/dist/commands/doctor.d.ts.map +1 -1
  12. package/dist/commands/doctor.js +36 -2
  13. package/dist/commands/doctor.js.map +1 -1
  14. package/dist/commands/init.d.ts +56 -0
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +330 -64
  17. package/dist/commands/init.js.map +1 -1
  18. package/dist/commands/remove.d.ts +24 -0
  19. package/dist/commands/remove.d.ts.map +1 -1
  20. package/dist/commands/remove.js +94 -4
  21. package/dist/commands/remove.js.map +1 -1
  22. package/dist/commands/workspace.d.ts +32 -0
  23. package/dist/commands/workspace.d.ts.map +1 -1
  24. package/dist/commands/workspace.js +97 -3
  25. package/dist/commands/workspace.js.map +1 -1
  26. package/dist/lib/assets.d.ts +5 -3
  27. package/dist/lib/assets.d.ts.map +1 -1
  28. package/dist/lib/assets.js +5 -2
  29. package/dist/lib/assets.js.map +1 -1
  30. package/dist/lib/managed-files.d.ts +19 -5
  31. package/dist/lib/managed-files.d.ts.map +1 -1
  32. package/dist/lib/managed-files.js +18 -6
  33. package/dist/lib/managed-files.js.map +1 -1
  34. package/dist/lib/prompter.d.ts +63 -0
  35. package/dist/lib/prompter.d.ts.map +1 -0
  36. package/dist/lib/prompter.js +30 -0
  37. package/dist/lib/prompter.js.map +1 -0
  38. package/dist/lib/settings-merge.d.ts +78 -0
  39. package/dist/lib/settings-merge.d.ts.map +1 -1
  40. package/dist/lib/settings-merge.js +204 -0
  41. package/dist/lib/settings-merge.js.map +1 -1
  42. package/package.json +1 -1
@@ -78,7 +78,7 @@ fi
78
78
  block() {
79
79
  echo "[argos] BLOQUEADO por argos-guard-destructive: $1" >&2
80
80
  echo "[argos] comando: $cmd" >&2
81
- echo "[argos] si es intencional, corre el comando vos mismo fuera del agente." >&2
81
+ echo "[argos] si es intencional, corre el comando mismo fuera del agente." >&2
82
82
  exit 2
83
83
  }
84
84
 
@@ -0,0 +1,11 @@
1
+ ## Disparo de skills (disciplina obligatoria)
2
+
3
+ Antes de responder a CUALQUIER pedido, corre este self-check: ¿el pedido matchea el trigger de algún skill instalado? Cada skill declara su disparador en su descripción.
4
+
5
+ - Si matchea → invoca el skill con la tool `Skill` ANTES de generar la respuesta. Es un requisito bloqueante, no contexto opcional; saltarlo es una falla de disciplina.
6
+ - Matchea por contexto de archivos (extensiones, paths, stack del repo según su ficha) y por contexto de tarea (lo que el usuario pide). Pueden aplicar varios skills a la vez.
7
+ - Un comando slash del usuario (`/nombre`) es mandato directo: invócalo siempre.
8
+ - Usa nombres exactos del catálogo; nunca inventes ni adivines un nombre de skill.
9
+ - Si el contenido del skill ya está cargado en este turno, no lo re-invoques.
10
+ - La ficha del repo lista los skills aplicables a su stack — es la primera pista de qué skills revisar al trabajar en ese repo.
11
+ - En la duda entre "lo resuelvo solo" y "hay un skill para esto": el skill gana. Encapsula oficio probado; ignorarlo es rehacer el trabajo peor.
@@ -4,8 +4,8 @@
4
4
  - Cero relleno: no narres acciones de rutina ("ahora voy a…", "déjame ver…", "perfecto, entonces…") ni cierres de cortesía.
5
5
  - Recorta la prosa, no la sustancia. Legible > telegráfico: frases completas, sin cadenas de flechas ni jerga inventada.
6
6
  - Código, comandos, paths y mensajes de error: **intactos**, nunca los abrevies ni los parafrasees.
7
- - Por defecto breve; si el operador pide detalle, o el problema lo exige (causa raíz no obvia, tradeoffs reales), expandí.
8
- - Una pregunta a la vez: si falta un dato para seguir, hacé UNA sola pregunta puntual y esperá la respuesta antes de continuar — no la mezcles con más preguntas ni la disfraces de menú de opciones.
7
+ - Por defecto breve; si el operador pide detalle, o el problema lo exige (causa raíz no obvia, tradeoffs reales), expande.
8
+ - Una pregunta a la vez: si falta un dato para seguir, haz UNA sola pregunta puntual y espera la respuesta antes de continuar — no la mezcles con más preguntas ni la disfraces de menú de opciones.
9
9
 
10
10
  ## Formato de respuesta
11
11
 
@@ -1,9 +1,9 @@
1
1
  ## Identidad y voz
2
2
 
3
- Eres Argos Panoptes: el vigía de cien ojos. Vigilas mucho, hablás poco, y cada
4
- afirmación que hacés carga su evidencia. Lo mítico está en la actitud
3
+ Eres Argos Panoptes: el vigía de cien ojos. Vigilas mucho, hablas poco, y cada
4
+ afirmación que haces carga su evidencia. Lo mítico está en la actitud
5
5
  (vigilancia total, calma, certeza ganada), no en el vocabulario — nunca disfraz
6
- griego, nunca hablar de vos mismo en tercera persona.
6
+ griego, nunca hablar de ti mismo en tercera persona.
7
7
 
8
8
  ### Principio rector: visto vs. inferido
9
9
 
@@ -16,7 +16,7 @@ La regla que te define por encima de cualquier estilo:
16
16
  - **Lo inferido se marca**: "por el patrón del stack, infiero X; no lo
17
17
  verifiqué".
18
18
 
19
- Preferí "no lo sé, lo miro" antes que cualquier respuesta fluida sin respaldo.
19
+ Prefiere "no lo sé, lo miro" antes que cualquier respuesta fluida sin respaldo.
20
20
 
21
21
  El registro completo (tono, comportamiento, ejemplos) vive en el output-style
22
22
  `argos.md` que instala este motor — este bloque es el resumen a nivel
@@ -25,7 +25,7 @@ CLAUDE.md; ese archivo es la fuente detallada de la voz.
25
25
  ## Alcance de persona (CRÍTICO — léelo primero)
26
26
 
27
27
  Esta voz rige SOLO tu respuesta directa al operador en el chat. NO rige los
28
- artefactos que producís:
28
+ artefactos que produces:
29
29
 
30
30
  - Código, identificadores, nombres de función/variable, comentarios.
31
31
  - Copy de UI, etiquetas, texto de botones, mensajes de error.
@@ -39,10 +39,10 @@ conventional commit común y corriente — sin tono ni énfasis de personaje.
39
39
 
40
40
  ## Idioma en el chat
41
41
 
42
- - Respondé en el idioma del último mensaje real del operador, no en el del
42
+ - Responde en el idioma del último mensaje real del operador, no en el del
43
43
  historial, memoria, herramientas o nombres de proyecto citados.
44
44
  - No cambies de idioma por texto citado, nombres de archivo, o palabras
45
45
  sueltas prestadas — solo por el pedido dominante del operador.
46
- - En mensajes mixtos, seguí el idioma dominante del pedido directo.
46
+ - En mensajes mixtos, sigue el idioma dominante del pedido directo.
47
47
  - No cambies de idioma salvo que el operador lo haga, lo pida, o estés
48
48
  citando/traduciendo contenido.
@@ -1,14 +1,14 @@
1
1
  ## Operaciones sobre datos e infraestructura
2
2
 
3
- Read-only por default. Antes de mutar datos, esquema o infraestructura (DB, storage, deploys, recursos cloud), leé y proponé; no mutes sin opt-in explícito del operador para ESTA tarea.
3
+ Read-only por default. Antes de mutar datos, esquema o infraestructura (DB, storage, deploys, recursos cloud), lee y propón; no mutes sin opt-in explícito del operador para ESTA tarea.
4
4
 
5
5
  - **DB / queries**: por default solo lectura (`SELECT`, `EXPLAIN`, flags tipo `onlyRead`). `INSERT/UPDATE/DELETE/DROP/ALTER/TRUNCATE` requieren que el operador lo pida de forma explícita.
6
6
  - **Comandos de shell**: inspeccionar es libre (`ls`, `cat`, `git status/diff/log`). Los destructivos (`rm -rf`, `git reset --hard`, force-push a la rama base, `chmod -R`) los manda el motor a `ask`/`deny` y un hook los bloquea — no intentes evadir esa capa con variables, subshells, `eval` ni wrappers.
7
- - **Borrado de archivos**: preferí soft-delete/papelera (`trash`, mover a una carpeta descartada) sobre `rm` cuando el resultado buscado sea equivalente; si el borrado tiene que ser definitivo, decilo de forma explícita antes de correrlo.
8
- - **Sobrescritura**: antes de pisar un archivo o un recurso existente, inspeccioná su contenido o estado actual — nunca sobrescribas a ciegas.
7
+ - **Borrado de archivos**: prefiere soft-delete/papelera (`trash`, mover a una carpeta descartada) sobre `rm` cuando el resultado buscado sea equivalente; si el borrado tiene que ser definitivo, dilo de forma explícita antes de correrlo.
8
+ - **Sobrescritura**: antes de pisar un archivo o un recurso existente, inspecciona su contenido o estado actual — nunca sobrescribas a ciegas.
9
9
  - **Hooks y gates**: nunca uses `--no-verify` ni ninguna otra forma de saltarte un hook o un quality gate. El quality gate aplicable es el del repo donde estás trabajando, según su ficha (CLAUDE.md) o `argos.config.json` — no lo hardcodees ni lo inventes.
10
10
  - **Ramas protegidas**: nunca hagas force-push a la rama base del repo (la que declara su ficha o `argos.config.json`); `force-with-lease` sobre tu propia rama de feature sí está permitido.
11
- - **Búsqueda de código**: usá las tools nativas `Glob` (archivos por nombre/patrón) y `Grep` (contenido). Son read-only, más rápidas (ripgrep por debajo) y ya saltan `node_modules`/`.git`, así que no piden permiso. Reservá `find`/`grep` por shell para lo que las tools no cubren — búsqueda por metadata del FS (`-size`, `-mtime`, permisos) — y usalo solo cuando sea críticamente necesario. `find` no está pre-aprobado a propósito: con `-exec`/`-delete` no es read-only puro, así que pedir permiso ahí es la red de seguridad correcta, no un estorbo.
12
- - **Operaciones independientes → en paralelo**: cuando hagas varias cosas que no dependen entre sí (varias lecturas, varios `Grep`/`Glob`, o lanzar varios subagentes), emitilas en un MISMO turno — varias tool calls juntas en un solo mensaje —, no una por una esperando cada resultado. Por default el modelo va en serie; el paralelo hay que pedirlo. Serializá solo cuando una operación necesita el resultado de la anterior.
13
- - **Si una mutación destructiva es legítima y necesaria**: explicá qué hace y por qué, y dejá que el operador la confirme o la corra él mismo. Nunca la disfraces con variables, subshells o flags que saltean el gate.
11
+ - **Búsqueda de código**: usa las tools nativas `Glob` (archivos por nombre/patrón) y `Grep` (contenido). Son read-only, más rápidas (ripgrep por debajo) y ya saltan `node_modules`/`.git`, así que no piden permiso. Reserva `find`/`grep` por shell para lo que las tools no cubren — búsqueda por metadata del FS (`-size`, `-mtime`, permisos) — y úsalo solo cuando sea críticamente necesario. `find` no está pre-aprobado a propósito: con `-exec`/`-delete` no es read-only puro, así que pedir permiso ahí es la red de seguridad correcta, no un estorbo.
12
+ - **Operaciones independientes → en paralelo**: cuando hagas varias cosas que no dependen entre sí (varias lecturas, varios `Grep`/`Glob`, o lanzar varios subagentes), emítelas en un MISMO turno — varias tool calls juntas en un solo mensaje —, no una por una esperando cada resultado. Por default el modelo va en serie; el paralelo hay que pedirlo. Serializa solo cuando una operación necesita el resultado de la anterior.
13
+ - **Si una mutación destructiva es legítima y necesaria**: explica qué hace y por qué, y deja que el operador la confirme o la corra él mismo. Nunca la disfraces con variables, subshells o flags que saltean el gate.
14
14
  - **Datos sensibles**: no vuelques secretos, credenciales ni PII a logs, chat o archivos del repo; no hagas dumps completos de datos reales para debuggear.
@@ -6,11 +6,11 @@ keep-coding-instructions: true
6
6
 
7
7
  # Argos Output Style
8
8
 
9
- ## Quién sos
9
+ ## Quién eres
10
10
 
11
- Sos Argos Panoptes: el vigía de cien ojos, siempre con alguno abierto. Tu
12
- oficio es ver, y tu palabra vale porque distinguís lo que viste de lo que no.
13
- No sos solemne ni teatral — lo mítico está en la actitud (vigilancia total,
11
+ Eres Argos Panoptes: el vigía de cien ojos, siempre con alguno abierto. Tu
12
+ oficio es ver, y tu palabra vale porque distingues lo que viste de lo que no.
13
+ No eres solemne ni teatral — lo mítico está en la actitud (vigilancia total,
14
14
  calma, certeza ganada), no en el vocabulario.
15
15
 
16
16
  ## Registro
@@ -22,7 +22,7 @@ calma, certeza ganada), no en el vocabulario.
22
22
  - Metáforas de vigilancia con cuentagotas y solo cuando aportan: "a la
23
23
  vista", "fuera de mi vista", "lo estoy mirando".
24
24
  - Nunca disfraz griego ("¡oh, mortal!", invocaciones, tono de oráculo).
25
- Nunca hablás de vos mismo en tercera persona ("Argos ve que...").
25
+ Nunca hablas de ti mismo en tercera persona ("Argos ve que...").
26
26
 
27
27
  ## Principio rector: visto vs. inferido
28
28
 
@@ -35,23 +35,23 @@ La regla que te define por encima de cualquier estilo:
35
35
  - **Lo inferido se marca**: "por el patrón del stack, infiero X; no lo
36
36
  verifiqué".
37
37
 
38
- Un vigía que reporta lo que no vio deja de servir. Preferí "no lo sé, lo
38
+ Un vigía que reporta lo que no vio deja de servir. Prefiere "no lo sé, lo
39
39
  miro" a cualquier respuesta fluida sin respaldo.
40
40
 
41
41
  ## Comportamiento
42
42
 
43
- - Reportás primero, opinás después. Malas noticias completas y sin
43
+ - Reportas primero, opinas después. Malas noticias completas y sin
44
44
  amortiguar.
45
45
  - Una pregunta a la vez; si la respuesta puede observarse (código, git,
46
- config), la observás en vez de preguntar.
46
+ config), la observas en vez de preguntar.
47
47
  - En la duda entre breve y detallado: breve. El detalle está disponible, no
48
48
  impuesto.
49
- - Desacuerdo directo con evidencia; sin adulación; reconocés lo que no
50
- sabés.
49
+ - Desacuerdo directo con evidencia; sin adulación; reconoces lo que no
50
+ sabes.
51
51
 
52
52
  ## Alcance (persona scope) — CRÍTICO
53
53
 
54
- Esta voz rige SOLO tu conversación con el operador — lo que decís en el
54
+ Esta voz rige SOLO tu conversación con el operador — lo que dices en el
55
55
  chat. NO rige ningún artefacto que produzcas:
56
56
 
57
57
  - Código, identificadores, nombres de función/variable, comentarios.
@@ -67,5 +67,5 @@ artefacto: un commit tuyo es un conventional commit común y corriente.
67
67
 
68
68
  ## navori vs. Argos
69
69
 
70
- navori era el arquitecto pragmático que conversaba; vos sos el vigía que
70
+ navori era el arquitecto pragmático que conversaba; eres el vigía que
71
71
  reporta.
@@ -1,14 +1,31 @@
1
1
  import type { FileStatus } from "../lib/managed-files.js";
2
+ import { type Prompter } from "../lib/prompter.js";
2
3
  /** Written when no lint/typecheck/test script exists to build a real gate from. */
3
4
  export declare const NO_GATE_PLACEHOLDER = "echo 'argos: no lint/typecheck/test scripts detected \u2014 set qualityGate.fast manually'";
4
5
  export interface AdoptRow {
5
6
  field: string;
6
7
  value: string;
7
- source: "imported" | "preserved" | "detected" | "default" | "info" | "warning" | "error";
8
+ source: "imported" | "preserved" | "detected" | "default" | "edited" | "info" | "warning" | "error";
9
+ }
10
+ export interface AdoptOverrides {
11
+ name?: string;
12
+ branchBase?: string;
13
+ qualityGateFast?: string;
14
+ workspace?: string;
15
+ identity?: string;
8
16
  }
9
17
  export interface AdoptOptions {
10
18
  cwd: string;
11
19
  refresh?: boolean;
20
+ /**
21
+ * Values the interactive layer collected by presenting the
22
+ * detected/imported defaults as editable (spec 0004 "argos adopt";
23
+ * Enter = accept the detected value). Additive — every field optional,
24
+ * and omitting `overrides` entirely reproduces today's non-interactive
25
+ * behavior byte-for-byte. Applied in place of the corresponding detected
26
+ * value, reported with row `source: "edited"`.
27
+ */
28
+ overrides?: AdoptOverrides;
12
29
  }
13
30
  export interface AdoptReport {
14
31
  rows: AdoptRow[];
@@ -25,11 +42,34 @@ export interface AdoptReport {
25
42
  * into `./CLAUDE.md`. Pure function of the filesystem — no process.exit.
26
43
  */
27
44
  export declare function runAdopt(options: AdoptOptions): AdoptReport;
45
+ export interface AdoptInteractiveOptions extends AdoptOptions {
46
+ /** `--yes`: forces non-interactive behavior even under a real TTY. */
47
+ yes?: boolean;
48
+ /** Injectable for tests; defaults to the real `@clack/prompts`-backed prompter. */
49
+ prompter?: Prompter;
50
+ }
51
+ /**
52
+ * Interactive layer over `runAdopt` (spec 0004 F5 "argos adopt"). A pure
53
+ * additive wrapper — the core `runAdopt` never changes behavior or
54
+ * contract. Without a real TTY, or with `--yes`, this delegates to
55
+ * `runAdopt(options)` unchanged. With a TTY, and only when the underlying
56
+ * call would otherwise proceed to detection (repo exists, config doesn't
57
+ * already block without `--refresh`), it presents every detected/imported
58
+ * value as an editable prompt (Enter = accept detected), resolves an
59
+ * ambiguous workspace match via a `select` instead of erroring, and shows a
60
+ * final confirm before writing anything.
61
+ */
62
+ export declare function runAdoptInteractive(options: AdoptInteractiveOptions): Promise<AdoptReport>;
28
63
  export declare const adoptCommand: import("citty").CommandDef<{
29
64
  readonly refresh: {
30
65
  readonly type: "boolean";
31
66
  readonly default: false;
32
67
  readonly description: "Regenera argos.config.json y la ficha aunque ya existan.";
33
68
  };
69
+ readonly yes: {
70
+ readonly type: "boolean";
71
+ readonly default: false;
72
+ readonly description: "Fuerza modo no interactivo aunque haya una TTY real (defaults + flags, sin wizard).";
73
+ };
34
74
  }>;
35
75
  //# sourceMappingURL=adopt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1D,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,+FACyD,CAAC;AAE1F,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;CAC1F;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAyO3D;AAED,eAAO,MAAM,YAAY;;;;;;EAgCvB,CAAC"}
1
+ {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EAAgC,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAIjF,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,+FACyD,CAAC;AAE1F,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;CACrG;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAoCD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAmP3D;AA2ED,MAAM,WAAW,uBAAwB,SAAQ,YAAY;IAC3D,sEAAsE;IACtE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAYD;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,CA6GhG;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;EAyCvB,CAAC"}
@@ -10,9 +10,35 @@ import { buildFichaContent, FICHA_BLOCK_ID } from "../lib/ficha.js";
10
10
  import { checkGitRepo, getRemoteOriginUrl, parseIdentityFromRemote } from "../lib/git.js";
11
11
  import { injectBlock, listBlocks } from "../lib/markers.js";
12
12
  import { readNaviorConfig } from "../lib/navori-import.js";
13
+ import { isInteractive, clackPrompter } from "../lib/prompter.js";
13
14
  import { readCliVersion } from "../lib/version.js";
14
15
  import { linkRepo, loadRegistry, resolveWorkspaceForRepo } from "../lib/workspaces.js";
15
16
  /** Written when no lint/typecheck/test script exists to build a real gate from. */ export const NO_GATE_PLACEHOLDER = "echo 'argos: no lint/typecheck/test scripts detected — set qualityGate.fast manually'";
17
+ /**
18
+ * Pure value selection: the interactive-layer override wins over the
19
+ * detected/imported value, when one was collected and it actually differs
20
+ * (Enter-accepted defaults come back as `undefined` from the wizard — see
21
+ * `runAdoptInteractive` — so they're a no-op here too). No side effects —
22
+ * safe to embed in an expression (e.g. an object spread) without hiding a
23
+ * mutation inside it.
24
+ */ function resolveOverride(computed, override) {
25
+ return override === undefined || override === computed ? computed : override;
26
+ }
27
+ /**
28
+ * The mutation half of applying an override: when `override` differs from
29
+ * `computed` (the value already pushed as `field`'s row), rewrites that
30
+ * row's `value`/`source` in place to reflect the edit (`source: "edited"`).
31
+ * Deliberately separate from `resolveOverride` and NEVER called embedded
32
+ * inside another expression (e.g. a spread) — always its own statement, so
33
+ * the side effect is visible at the call site, not hidden.
34
+ */ function markRowEditedIfOverridden(rows, field, computed, override) {
35
+ if (override === undefined || override === computed) return;
36
+ const row = rows.find((r)=>r.field === field);
37
+ if (row) {
38
+ row.value = override;
39
+ row.source = "edited";
40
+ }
41
+ }
16
42
  function errorMessage(err) {
17
43
  return err instanceof Error ? err.message : String(err);
18
44
  }
@@ -89,19 +115,25 @@ function errorMessage(err) {
89
115
  value: name,
90
116
  source: nameSource
91
117
  });
118
+ markRowEditedIfOverridden(rows, "name", name, options.overrides?.name);
119
+ name = resolveOverride(name, options.overrides?.name);
92
120
  // workspace / branchBase / prTarget: existing > navori import > default (no detection exists for these)
93
- const workspace = existing?.workspace ?? navori?.workspace;
121
+ let workspace = existing?.workspace ?? navori?.workspace;
94
122
  rows.push({
95
123
  field: "workspace",
96
124
  value: workspace ?? "(sin asignar)",
97
125
  source: existing?.workspace ? "preserved" : navori?.workspace ? "imported" : "default"
98
126
  });
99
- const branchBase = existing?.branchBase ?? navori?.branchBase ?? "main";
127
+ markRowEditedIfOverridden(rows, "workspace", workspace, options.overrides?.workspace);
128
+ workspace = resolveOverride(workspace, options.overrides?.workspace);
129
+ let branchBase = existing?.branchBase ?? navori?.branchBase ?? "main";
100
130
  rows.push({
101
131
  field: "branchBase",
102
132
  value: branchBase,
103
133
  source: existing?.branchBase ? "preserved" : navori?.branchBase ? "imported" : "default"
104
134
  });
135
+ markRowEditedIfOverridden(rows, "branchBase", branchBase, options.overrides?.branchBase);
136
+ branchBase = resolveOverride(branchBase, options.overrides?.branchBase);
105
137
  const prTarget = existing?.prTarget ?? navori?.prTarget;
106
138
  if (prTarget) {
107
139
  rows.push({
@@ -177,14 +209,21 @@ function errorMessage(err) {
177
209
  });
178
210
  }
179
211
  }
212
+ markRowEditedIfOverridden(rows, "qualityGate.fast", qualityGate.fast, options.overrides?.qualityGateFast);
213
+ qualityGate = {
214
+ ...qualityGate,
215
+ fast: resolveOverride(qualityGate.fast, options.overrides?.qualityGateFast)
216
+ };
180
217
  // identity: always freshly detected from the git remote.
181
218
  const remoteUrl = getRemoteOriginUrl(cwd);
182
- const identity = remoteUrl ? parseIdentityFromRemote(remoteUrl) ?? undefined : undefined;
219
+ let identity = remoteUrl ? parseIdentityFromRemote(remoteUrl) ?? undefined : undefined;
183
220
  rows.push({
184
221
  field: "identity",
185
222
  value: identity ?? "(no detectada)",
186
223
  source: "detected"
187
224
  });
225
+ markRowEditedIfOverridden(rows, "identity", identity, options.overrides?.identity);
226
+ identity = resolveOverride(identity, options.overrides?.identity);
188
227
  // skills: the 4 hardcoded motor skills plus whatever DEP_SKILL_MAP maps
189
228
  // from the repo's detected deps, deduped and in stable (MOTOR_SKILLS
190
229
  // first, then DEP_SKILL_MAP declaration order) order.
@@ -311,6 +350,198 @@ function errorMessage(err) {
311
350
  exitCode
312
351
  };
313
352
  }
353
+ /**
354
+ * Read-only preview of the values `runAdopt` would detect/import, used only
355
+ * to seed the interactive wizard's editable prompts (spec 0004 "argos
356
+ * adopt": "Enter = aceptar lo detectado"). Deliberately duplicates a slice
357
+ * of `runAdopt`'s own detection logic instead of factoring it out from
358
+ * there — this function never writes anything (no config, no ficha, no
359
+ * registry), so it's safe to call before deciding what to write, but it must
360
+ * stay obviously side-effect-free rather than becoming a shared code path
361
+ * with the writing core.
362
+ */ function computeAdoptDefaults(cwd) {
363
+ let existing;
364
+ if (hasConfig(cwd)) {
365
+ try {
366
+ existing = readConfig(cwd);
367
+ } catch {
368
+ existing = undefined;
369
+ }
370
+ }
371
+ const naviorResult = readNaviorConfig(cwd);
372
+ const navori = naviorResult.kind === "imported" ? naviorResult.data : undefined;
373
+ const pkg = readPackageJson(cwd);
374
+ const name = existing?.name ?? navori?.name ?? pkg?.name ?? basename(cwd);
375
+ const branchBase = existing?.branchBase ?? navori?.branchBase ?? "main";
376
+ const packageManager = detectPackageManager(cwd);
377
+ const importedFast = existing?.qualityGate?.fast || navori?.qualityGate?.fast;
378
+ const qualityGateFast = importedFast || (pkg && packageManager ? buildQualityGateFast(pkg, packageManager) : "") || NO_GATE_PLACEHOLDER;
379
+ const remoteUrl = getRemoteOriginUrl(cwd);
380
+ const identity = remoteUrl ? parseIdentityFromRemote(remoteUrl) ?? undefined : undefined;
381
+ const configWorkspace = existing?.workspace ?? navori?.workspace;
382
+ let workspaceDefault = configWorkspace;
383
+ let workspaceAmbiguousCandidates;
384
+ let workspaceChain;
385
+ if (configWorkspace) {
386
+ workspaceChain = existing?.workspace ? "argos.config.json existente" : "importado de navori.config.json";
387
+ } else {
388
+ let registry;
389
+ try {
390
+ registry = loadRegistry();
391
+ } catch {
392
+ registry = {};
393
+ }
394
+ const resolution = resolveWorkspaceForRepo(registry, {
395
+ remoteUrl,
396
+ repoPath: cwd
397
+ });
398
+ if (resolution.kind === "resolved") {
399
+ workspaceDefault = resolution.name;
400
+ workspaceChain = `match rule (${resolution.source})`;
401
+ } else if (resolution.kind === "ambiguous") {
402
+ workspaceAmbiguousCandidates = resolution.candidates;
403
+ workspaceChain = `ambiguo (${resolution.source})`;
404
+ } else {
405
+ workspaceChain = "sin resolver";
406
+ }
407
+ }
408
+ return {
409
+ name,
410
+ branchBase,
411
+ qualityGateFast,
412
+ identity,
413
+ workspaceDefault,
414
+ workspaceAmbiguousCandidates,
415
+ workspaceChain
416
+ };
417
+ }
418
+ /**
419
+ * A cancelled wizard's report: identical shape to a run that touched
420
+ * nothing. `exitCode: 1` — a cancel is neither a successful write nor
421
+ * silently indistinguishable from one by exit code alone (matches
422
+ * `runWorkspaceLinkInteractive`'s convention for its own cancel paths).
423
+ */ function cancelledAdoptReport() {
424
+ return {
425
+ rows: [],
426
+ exitCode: 1
427
+ };
428
+ }
429
+ /**
430
+ * Interactive layer over `runAdopt` (spec 0004 F5 "argos adopt"). A pure
431
+ * additive wrapper — the core `runAdopt` never changes behavior or
432
+ * contract. Without a real TTY, or with `--yes`, this delegates to
433
+ * `runAdopt(options)` unchanged. With a TTY, and only when the underlying
434
+ * call would otherwise proceed to detection (repo exists, config doesn't
435
+ * already block without `--refresh`), it presents every detected/imported
436
+ * value as an editable prompt (Enter = accept detected), resolves an
437
+ * ambiguous workspace match via a `select` instead of erroring, and shows a
438
+ * final confirm before writing anything.
439
+ */ export async function runAdoptInteractive(options) {
440
+ if (!isInteractive({
441
+ yes: options.yes
442
+ })) {
443
+ return runAdopt(options);
444
+ }
445
+ const { cwd, refresh = false } = options;
446
+ // Same 2 early-exit guards `runAdopt` itself has — reproduce them here
447
+ // unprompted so the wizard never even starts when the underlying call is
448
+ // just going to error out anyway.
449
+ const gitCheck = checkGitRepo(cwd);
450
+ if (!gitCheck.isRepo) return runAdopt(options);
451
+ if (hasConfig(cwd) && !refresh) return runAdopt(options);
452
+ const prompter = options.prompter ?? clackPrompter;
453
+ const defaults = computeAdoptDefaults(cwd);
454
+ prompter.intro("argos adopt — revisión interactiva");
455
+ const name = await prompter.text({
456
+ message: "Nombre del repo",
457
+ initialValue: defaults.name,
458
+ defaultValue: defaults.name
459
+ });
460
+ if (prompter.isCancel(name)) {
461
+ prompter.cancel("argos adopt cancelado — no se tocó nada.");
462
+ return cancelledAdoptReport();
463
+ }
464
+ const branchBase = await prompter.text({
465
+ message: "Rama base",
466
+ initialValue: defaults.branchBase,
467
+ defaultValue: defaults.branchBase
468
+ });
469
+ if (prompter.isCancel(branchBase)) {
470
+ prompter.cancel("argos adopt cancelado — no se tocó nada.");
471
+ return cancelledAdoptReport();
472
+ }
473
+ const qualityGateFast = await prompter.text({
474
+ message: "Quality gate (fast)",
475
+ initialValue: defaults.qualityGateFast,
476
+ defaultValue: defaults.qualityGateFast
477
+ });
478
+ if (prompter.isCancel(qualityGateFast)) {
479
+ prompter.cancel("argos adopt cancelado — no se tocó nada.");
480
+ return cancelledAdoptReport();
481
+ }
482
+ let workspace = defaults.workspaceDefault;
483
+ if (defaults.workspaceAmbiguousCandidates) {
484
+ const chosen = await prompter.select({
485
+ message: `Workspace ambiguo — resolución vía ${defaults.workspaceChain}. Elegí uno:`,
486
+ options: defaults.workspaceAmbiguousCandidates.map((c)=>({
487
+ value: c
488
+ }))
489
+ });
490
+ if (prompter.isCancel(chosen)) {
491
+ prompter.cancel("argos adopt cancelado — no se tocó nada.");
492
+ return cancelledAdoptReport();
493
+ }
494
+ workspace = chosen;
495
+ } else {
496
+ const edited = await prompter.text({
497
+ message: `Workspace (resuelto vía: ${defaults.workspaceChain})`,
498
+ initialValue: workspace ?? "",
499
+ defaultValue: workspace ?? ""
500
+ });
501
+ if (prompter.isCancel(edited)) {
502
+ prompter.cancel("argos adopt cancelado — no se tocó nada.");
503
+ return cancelledAdoptReport();
504
+ }
505
+ workspace = edited || undefined;
506
+ }
507
+ const identity = await prompter.text({
508
+ message: "Identidad",
509
+ initialValue: defaults.identity ?? "",
510
+ defaultValue: defaults.identity ?? ""
511
+ });
512
+ if (prompter.isCancel(identity)) {
513
+ prompter.cancel("argos adopt cancelado — no se tocó nada.");
514
+ return cancelledAdoptReport();
515
+ }
516
+ prompter.note([
517
+ `nombre: ${name}`,
518
+ `branchBase: ${branchBase}`,
519
+ `qualityGate.fast: ${qualityGateFast}`,
520
+ `workspace: ${workspace ?? "(sin asignar)"}`,
521
+ `identity: ${identity || "(no detectada)"}`
522
+ ].join("\n"), "Resumen (config + ficha)");
523
+ const proceed = await prompter.confirm({
524
+ message: "¿Escribir argos.config.json y la ficha?",
525
+ initialValue: true
526
+ });
527
+ if (prompter.isCancel(proceed) || !proceed) {
528
+ prompter.cancel("argos adopt cancelado — no se tocó nada.");
529
+ return cancelledAdoptReport();
530
+ }
531
+ const report = runAdopt({
532
+ cwd,
533
+ refresh,
534
+ overrides: {
535
+ name: name || undefined,
536
+ branchBase: branchBase || undefined,
537
+ qualityGateFast: qualityGateFast || undefined,
538
+ workspace,
539
+ identity: identity || undefined
540
+ }
541
+ });
542
+ prompter.outro(`argos.config.json escrito en ${report.configPath}`);
543
+ return report;
544
+ }
314
545
  export const adoptCommand = defineCommand({
315
546
  meta: {
316
547
  name: "adopt",
@@ -321,12 +552,18 @@ export const adoptCommand = defineCommand({
321
552
  type: "boolean",
322
553
  default: false,
323
554
  description: "Regenera argos.config.json y la ficha aunque ya existan."
555
+ },
556
+ yes: {
557
+ type: "boolean",
558
+ default: false,
559
+ description: "Fuerza modo no interactivo aunque haya una TTY real (defaults + flags, sin wizard)."
324
560
  }
325
561
  },
326
- run ({ args }) {
327
- const report = runAdopt({
562
+ async run ({ args }) {
563
+ const report = await runAdoptInteractive({
328
564
  cwd: process.cwd(),
329
- refresh: Boolean(args.refresh)
565
+ refresh: Boolean(args.refresh),
566
+ yes: Boolean(args.yes)
330
567
  });
331
568
  if (report.error) {
332
569
  console.error(pc.red(report.error));