@damiangilgonzalez/harness 1.3.13 → 1.3.15

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 (40) hide show
  1. package/README.md +15 -9
  2. package/manifest.json +60 -4
  3. package/package.json +1 -1
  4. package/scripts/doctor.js +13 -4
  5. package/scripts/install-apply.js +73 -9
  6. package/scripts/lib/backups.js +13 -0
  7. package/scripts/lib/default-skill-floor.js +14 -0
  8. package/scripts/lib/domains.js +1 -1
  9. package/scripts/lib/onboarding-apply.js +73 -12
  10. package/scripts/lib/onboarding.js +8 -0
  11. package/scripts/lib/repair.js +8 -4
  12. package/scripts/lib/review-findings.js +175 -0
  13. package/scripts/rsc.js +51 -3
  14. package/skills/code-review/SKILL.md +17 -1
  15. package/skills/domain-modeling/{CONTEXT-FORMAT.md → GLOSSARY-FORMAT.md} +9 -9
  16. package/skills/domain-modeling/SKILL.md +14 -12
  17. package/skills/harness/SKILL.md +6 -0
  18. package/skills/harness/references/wiki-protocol.md +5 -0
  19. package/skills/implement-spec/SKILL.md +43 -0
  20. package/skills/implement-spec/evals/cases.yaml +33 -0
  21. package/skills/init/references/accompaniment-and-profile.md +1 -1
  22. package/skills/orient/SKILL.md +9 -1
  23. package/skills/orient/references/orientation-contract.md +1 -1
  24. package/skills/pr/CREDITS.md +3 -0
  25. package/skills/pr/SKILL.md +173 -0
  26. package/skills/pr/evals/cases.yaml +33 -0
  27. package/skills/retro/SKILL.md +47 -0
  28. package/skills/retro/evals/cases.yaml +32 -0
  29. package/skills/suggest/SKILL.md +1 -1
  30. package/skills/wait-what/SKILL.md +1 -1
  31. package/targets/_md-block.js +1 -1
  32. package/targets/agents.js +37 -1
  33. package/targets/claude.js +25 -16
  34. package/targets/hook-once.mjs +6 -3
  35. package/targets/memory.js +1 -1
  36. package/targets/sello.mjs +2 -2
  37. package/targets/session-memory-core.mjs +1 -1
  38. package/targets/session-start.mjs +2 -2
  39. package/targets/ship-guard.mjs +1 -1
  40. package/targets/worktree-reaper.mjs +1 -1
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: pr
3
+ description: "Use when writing a PR body: a visual summary, before/after evidence, and the merge danger (one-way or two-way door, blast radius)."
4
+ tags: ["pull-request", "review", "evidence", "risk"]
5
+ profiles: [core, ui, full]
6
+ origin: damiangil
7
+ metadata:
8
+ credits:
9
+ skill: show-me
10
+ author: Dex Horthy
11
+ organisation: Humanlayer
12
+ url: "https://github.com/humanlayer/skills/blob/main/plugins/show-me/skills/show-me/SKILL.md"
13
+ ---
14
+
15
+ Usa esta plantilla para escribir el cuerpo de la PR:
16
+
17
+ ```markdown
18
+ ## Resumen
19
+
20
+ <diagrama, esbozo de diff o árbol>
21
+
22
+ ## Evidencia
23
+
24
+ - **Antes:** <captura/salida/ejecución de test que falla>
25
+ **Después:** <captura/salida/ejecución de test que pasa>
26
+
27
+ ## Peligro de fusión
28
+
29
+ **Puerta:** <de un sentido o de dos sentidos>
30
+
31
+ <opcional: descripción>
32
+
33
+ **Radio de impacto:** <descripción en una palabra>
34
+
35
+ <opcional: posibles consecuencias de fusionar>
36
+ ```
37
+
38
+ ## Secciones
39
+
40
+ Sáltate los preámbulos y deja la prosa breve. Usa el lenguaje del dominio del usuario que está en `GLOSSARY.md`.
41
+
42
+ ### Resumen
43
+
44
+ Elige la vista más pequeña que deje clara la idea clave.
45
+
46
+ - Muestra una lógica o un algoritmo como pseudocódigo:
47
+
48
+ ```text
49
+ on(save)
50
+ if content is unchanged
51
+ return cached result
52
+ write new content
53
+ return fresh result
54
+ ```
55
+
56
+ - Muestra el flujo de control en ejecución como un árbol de llamadas:
57
+
58
+ ```text
59
+ submitForm
60
+ createSession
61
+ persistPrompt
62
+ launchAgent
63
+ navigateToSession
64
+ ```
65
+
66
+ - Muestra la estructura de la UI como un árbol de componentes, con el estado y los límites de módulo que importan:
67
+
68
+ ```text
69
+ <SessionPage> (apps/example/src/routes/session.tsx)
70
+ useSessionEvents()
71
+ <SessionToolbar>
72
+ <RunSkillButton> (packages/ui)
73
+ ```
74
+
75
+ - Muestra de qué se encarga cada fichero, o un refactor amplio, como un árbol de ficheros poco profundo:
76
+
77
+ ```text
78
+ src/
79
+ ├── commands/ # interpreta las acciones del usuario
80
+ ├── sessions/ # guarda el estado de la sesión
81
+ └── transport/ # envía las peticiones a la API
82
+ ```
83
+
84
+ - Muestra la interacción entre componentes, el flujo de control o el flujo de datos con Mermaid:
85
+
86
+ ```mermaid
87
+ sequenceDiagram
88
+ participant User
89
+ participant UI
90
+ participant Daemon
91
+ User->>UI: choose command
92
+ UI->>Daemon: send expanded prompt
93
+ Daemon-->>UI: stream result
94
+ ```
95
+
96
+ - Usa `diff` cuando lo importante es qué cambia y la forma de alrededor ya existe. Ajusta la forma del diff al tema.
97
+
98
+ Para un cambio de componente:
99
+
100
+ ```diff
101
+ <SessionPage>
102
+ useSessionEvents()
103
+ <SessionToolbar>
104
+ + <RunSkillButton />
105
+ <SessionTimeline>
106
+ + <SkillResultCard />
107
+ ```
108
+
109
+ Para un cambio en la disposición de ficheros:
110
+
111
+ ```diff
112
+ src/
113
+ ├── commands/
114
+ +│ └── show-me.ts # expande el slash command
115
+ ├── sessions/
116
+ -└── transport.ts
117
+ +└── transport/
118
+ + ├── client.ts
119
+ + └── stream.ts
120
+ ```
121
+
122
+ Para un cambio en un árbol o pila de llamadas:
123
+
124
+ ```diff
125
+ submitForm
126
+ createSession
127
+ persistPrompt
128
+ + expandSkillMention
129
+ launchAgent
130
+ - navigateToSession
131
+ + navigateToSession
132
+ + subscribeToEvents
133
+ ```
134
+
135
+ Para un cambio de estado o de flujo de control:
136
+
137
+ ```diff
138
+ on(save)
139
+ - write content
140
+ + if content is unchanged
141
+ + return cached result
142
+ + write new content
143
+ + invalidate cache
144
+ ```
145
+
146
+ - Muestra el bloque entero cuando casi todo es nuevo, cuando omitir contexto escondería de quién es algo o en qué orden va, o cuando el usuario necesita una forma objetivo que pueda copiar:
147
+
148
+ ```ts
149
+ function expandSkill(command: string): string {
150
+ const skillName = command.slice(1);
151
+ return `use the ${skillName} skill`;
152
+ }
153
+ ```
154
+
155
+ #### Guía
156
+
157
+ Pon cada visual junto al texto corto al que apoya. Quédate solo con las llamadas, ficheros, props, estados y límites que hacen falta para responder a la pregunta actual del usuario, o a las opciones para resolver el punto que se está discutiendo.
158
+
159
+ Puedes usar uno de estos, puedes usar varios; es poco probable que uses todos. Usa tu criterio y no abrumes al usuario.
160
+
161
+ ### Evidencia
162
+
163
+ Pruebas concretas de que el cambio funciona. Muestra un antes y un después.
164
+
165
+ Las capturas de pantalla son lo mejor, cuando el entorno lo permite y el cambio es visual.
166
+
167
+ La evidencia basada en ejecución va justo detrás: resultados de tests, salida de consola. Muestra el test exacto que antes fallaba y ahora pasa, en pseudocódigo.
168
+
169
+ ### Peligro de fusión
170
+
171
+ Di si es una puerta de un sentido o de dos sentidos. Por una puerta de dos sentidos se puede volver atrás; por una de un sentido, no. Una PR que es barata de revertir tiene menos riesgo. Los cambios que implican acciones destructivas o decisiones difíciles de revertir son puertas de un sentido.
172
+
173
+ El radio de impacto es el alcance posible de los efectos que introduce la PR. Considera todas las posibilidades. Ejemplos: saltos de layout, roturas para quien consume el código, el comportamiento en móvil, etc.
@@ -0,0 +1,33 @@
1
+ skill: pr
2
+
3
+ should_trigger:
4
+ - prompt: "Escribe el cuerpo de la PR de esta rama."
5
+ why: "Disparador directo de pr."
6
+ - prompt: "Abre la PR y explica el cambio con un diagrama y el antes y después."
7
+ why: "Disparador directo de pr: resumen visual y evidencia."
8
+ - prompt: "Write the PR description for these changes."
9
+ why: "Disparador directo de pr."
10
+ - prompt: "Prepara la descripción del pull request con el riesgo de fusionarlo."
11
+ why: "Disparador directo de pr: peligro de fusión y radio de impacto."
12
+ - prompt: "¿Qué pongo en la PR para que se revise rápido?"
13
+ why: "Disparador directo de pr."
14
+
15
+ should_not_trigger:
16
+ - prompt: "Revisa el código de esta PR."
17
+ route_to: "code-review"
18
+ why: "Revisar el código es el trabajo de code-review, no de pr."
19
+ - prompt: "Haz el commit de estos cambios con un buen mensaje."
20
+ route_to: "git-workflow"
21
+ why: "El mensaje de commit es el trabajo de git-workflow, no de pr."
22
+ - prompt: "Implementa la spec entera."
23
+ route_to: "implement-spec"
24
+ why: "Implementar la spec es el trabajo de implement-spec, no de pr."
25
+ - prompt: "Escribe la spec de esta funcionalidad antes de tocar código."
26
+ route_to: "to-spec"
27
+ why: "Redactar la spec es el trabajo de to-spec, no de pr."
28
+
29
+ capability:
30
+ - scenario: "El usuario quiere el cuerpo de una PR que se revise de un vistazo."
31
+ must_include:
32
+ - "Peligro de fusión"
33
+ - "Radio de impacto"
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: retro
3
+ description: "Conduct a retrospective on a coding session: find what in the agent's environment (navigation, checks, standards, steering files, tooling) should change so future runs go better."
4
+ tags: ["retrospective", "session-review", "agent-environment"]
5
+ disable-model-invocation: true
6
+ profiles: [core, ui, full]
7
+ origin: damiangil
8
+ ---
9
+
10
+ El usuario ha pedido una **retrospectiva**. Vas a proponer mejoras en el **entorno** del agente de código para que las próximas ejecuciones salgan mejor.
11
+
12
+ ## Pasos
13
+
14
+ 1. Llama a la herramienta Skill con `writing-for-agents` para tener la guía de estilo.
15
+
16
+ 2. Lee las fuentes primarias de la sesión que indique el usuario. Puede que tengas que buscar en los registros de sesión de esta máquina (en Claude Code, `~/.claude/projects/`). Si el usuario no indica ninguna, usa la sesión actual.
17
+
18
+ 3. Busca candidatos a mejora en estas categorías:
19
+
20
+ - **Navegación**: ¿le costó al agente encontrar los ficheros correctos? ¿Hay dependencias ocultas entre ficheros? ¿Un **puntero de navegación** lo pondría más fácil? _Úsalo cuando_ la sesión tardó mucho en encontrar una información.
21
+ - **Comprobaciones automáticas**: ¿hay comprobaciones automáticas que pillarían los errores que cometió el agente? Linting, tipos, tests, linters del sistema de ficheros. Lee primero el comando de comprobación del propio repo (los scripts `lint`/`check` de su `package.json` o de su herramienta de build, su workflow de CI), para que el hallazgo sea una comprobación que ya existe pero está sin conectar o rota en silencio, y no una reinvención. Un repo sin ninguna **barrera** (ni hook de pre-commit ni job de CI que ejecute su lint/typecheck/test) es en sí un hallazgo: un repo sin lint es una oportunidad perdida permanente, no un punto de partida neutro. _Úsalo cuando_ el agente cometió un error que una comprobación automática habría pillado, o el repo no tiene ninguna barrera.
22
+ - **Estándares de código**: ¿hay que darle al **agente revisor** una regla nueva que haga cumplir? ¿Hay que quitar o aclarar una regla existente? Clasifica primero la infracción: una **mecánica** (un patrón sintáctico fijo, una API prohibida, una forma de import, una regla de ubicación de ficheros) lleva una comprobación determinista, sin más: una regla propia en el linter del repo, un hook de pre-commit nuevo o un job de CI nuevo, lo que salga más barato según el lenguaje y la barrera que ya tenga el repo. Por defecto, construye la comprobación antes que escribir la regla. Reserva `CODING_STANDARDS.md` para las **decisiones de criterio** de verdad (coherencia entre ficheros, "encaja con el estilo de alrededor", cualquier cosa que ninguna barrera pueda sustituir). _Úsalo cuando_ el agente revisor no pilló un error.
23
+ - **AGENTS.md / CLAUDE.md global**: ¿hay instrucciones de dirección que deberían pasar a los estándares de código (o a comprobaciones automáticas)? _Úsalo cuando_ el fichero es especialmente grande, en el repo O en el ámbito global del usuario.
24
+ - **Economía de herramientas**: ¿hizo el agente llamadas a herramientas caras que se podrían simplificar? ¿Hay alguna herramienta propia (CLIs, MCPs) que gaste muchos tokens? _Úsalo cuando_ el agente hizo una llamada cara.
25
+ - **Instrucciones sin efecto**: busca instrucciones en los ficheros de dirección que no cambian el comportamiento del agente. _Úsalo cuando_ los ficheros de dirección son grandes y difíciles de manejar.
26
+ - **Acceso a la información**: busca formas de darle al agente más acceso a la información. Volcar los logs del servidor de desarrollo, acceso de solo lectura a servicios de terceros. _Úsalo cuando_ el agente no tenía una información clave.
27
+
28
+ 4. Presenta estos candidatos al usuario, ordenados por gravedad. Tú no aplicas nada: el usuario decide qué se cambia.
29
+
30
+ ## Referencia
31
+
32
+ ### Implementación frente a revisión
33
+
34
+ Recuerda que todo el trabajo pasa por dos fases: implementación y revisión. El agente que implementa es el que más **presión de contexto** tiene: se encarga de explorar, escribir el código y depurar los fallos.
35
+
36
+ El agente revisor es el que menos presión de contexto tiene: recibe un diff, así que no tiene que explorar. Muchas veces no necesita escribir código ni depurar.
37
+
38
+ Eso significa que el agente revisor debe ser el responsable de hacer cumplir los estándares de código, no el que implementa.
39
+
40
+ ### Ficheros
41
+
42
+ Tienes acceso a varios ficheros en el repo:
43
+
44
+ - `CLAUDE.md`/`AGENTS.md`: estos ficheros entran en la ventana de contexto de cualquier agente que trabaje en el repo. Hay que usarlos con muchísima moderación, normalmente solo para **punteros de navegación** a otros ficheros.
45
+ - `CODING_STANDARDS.md`: este fichero se lee durante la revisión, no durante la implementación. Añade **punteros de navegación** a carpetas de docs si el fichero de estándares pasa de 1.000 líneas.
46
+ - Docs: usa los docs como ficheros de referencia, señalados desde otros ficheros. Busca docs existentes antes de escribir otros nuevos.
47
+ - Skills: usa skills para docs (porque su descripción entra en la ventana de contexto del agente) o para comandos que invoca el usuario. Sigue los consejos de la skill `writing-for-agents`.
@@ -0,0 +1,32 @@
1
+ skill: retro
2
+
3
+ should_trigger:
4
+ - prompt: "Haz una retrospectiva de esta sesión."
5
+ why: "Disparador directo de retro."
6
+ - prompt: "Revisa la conversación de ayer y dime qué falló en el entorno del agente."
7
+ why: "Disparador directo de retro: leer sesiones pasadas."
8
+ - prompt: "Run a retro on the last coding session."
9
+ why: "Disparador directo de retro."
10
+ - prompt: "¿Qué hooks o comprobaciones habrían evitado los errores de esta sesión?"
11
+ why: "Disparador directo de retro: comprobaciones automáticas."
12
+ - prompt: "Audita la sesión y propón mejoras para el CLAUDE.md y las herramientas."
13
+ why: "Disparador directo de retro."
14
+
15
+ should_not_trigger:
16
+ - prompt: "Revisa el código de esta rama."
17
+ route_to: "code-review"
18
+ why: "Revisar código es el trabajo de code-review, no de retro."
19
+ - prompt: "Resume la conversación para que otro agente siga."
20
+ route_to: "handoff"
21
+ why: "El traspaso de la sesión es el trabajo de handoff, no de retro."
22
+ - prompt: "Escribe una skill nueva para esto."
23
+ route_to: "writing-for-agents"
24
+ why: "Escribir documentos para agentes es el trabajo de writing-for-agents, no de retro."
25
+ - prompt: "Escribe el cuerpo de la PR de esta rama."
26
+ route_to: "pr"
27
+ why: "El cuerpo de la PR es el trabajo de pr, no de retro."
28
+
29
+ capability:
30
+ - scenario: "El usuario quiere saber qué cambiar en el entorno del agente tras una sesión."
31
+ must_include:
32
+ - "gravedad"
@@ -56,7 +56,7 @@ pairs with test-driven development and a verification pass before anything is ca
56
56
 
57
57
  Exact skill names and order: `grill-with-docs` or `wayfinder` -> `superpowers:brainstorming` or
58
58
  `to-spec` (and `write-adr` for decisions) -> `superpowers:writing-plans` ->
59
- `superpowers:executing-plans` (after `wayfinder`: `to-tickets` -> `implement`) -> `code-review`.
59
+ `superpowers:executing-plans` (big spec: `to-tickets` -> `implement-spec`) -> `code-review` -> `pr`.
60
60
  On Claude Code this rule also arrives as a per-turn hook; the brevity here is deduplication,
61
61
  not relaxation.
62
62
 
@@ -7,4 +7,4 @@ profiles: [core, ui, full]
7
7
  origin: damiangil
8
8
  ---
9
9
 
10
- Espera, no entiendo a dónde has llegado con esto. Vuelve a plantearlo: dame algo de contexto, habla en Inglés Técnico Simplificado ASD-STE100 (aplícalo igual en español: frases cortas, una idea por frase, vocabulario consistente), y usa el lenguaje ubicuo de `CONTEXT.md` (sigue `CONTEXT-MAP.md` hasta el correcto si el repo tiene más de uno).
10
+ Espera, no entiendo a dónde has llegado con esto. Vuelve a plantearlo: dame algo de contexto, habla en Inglés Técnico Simplificado ASD-STE100 (aplícalo igual en español: frases cortas, una idea por frase, vocabulario consistente), y usa el lenguaje ubicuo de `GLOSSARY.md` (sigue `GLOSSARY-MAP.md` hasta el correcto si el repo tiene más de uno).
@@ -21,7 +21,7 @@ export function writeSkill(id, fromDir, toPath) {
21
21
  export function wireHook(paths, sourceMd, policy = {}) {
22
22
  const full = stripFrontmatter(readFileSync(sourceMd, 'utf8'));
23
23
  const body = policy.codeHooks === false
24
- ? `# rsc-suggest — always-on operations layer\n\nRead \`docs/wiki/harness/user-profile.md\` before acting. If the user wants to build, add or change something, route it through \`grill-with-docs\` or \`wayfinder\`, then write the spec with \`superpowers:brainstorming\` or \`to-spec\` (decisions go to \`write-adr\`) before any code, then build it with \`superpowers:writing-plans\` (or \`to-tickets\` then \`implement\` when it came out of \`wayfinder\`), and review it with \`code-review\` before merging (si toca pantalla, \`flujo-interfaz\` dice que skill de diseno manda) — unless it is a one-line change, typo, or config bump, which skips the chain. Use \`orient\` to keep the user situated and \`suggest\` to offer a missing skill only when the current task needs it. Close with the configured orientation block.\n`
24
+ ? `# rsc-suggest — always-on operations layer\n\nRead \`docs/wiki/harness/user-profile.md\` before acting. If the user wants to build, add or change something, route it through \`grill-with-docs\` or \`wayfinder\`, then write the spec with \`superpowers:brainstorming\` or \`to-spec\` (decisions go to \`write-adr\`) before any code, then build it with \`superpowers:writing-plans\` (or \`to-tickets\` then \`implement-spec\` for a big spec or one that came out of \`wayfinder\`), and review it with \`code-review\` before merging, writing the PR body with \`pr\` (si toca pantalla, \`flujo-interfaz\` dice que skill de diseno manda) — unless it is a one-line change, typo, or config bump, which skips the chain. Use \`orient\` to keep the user situated and \`suggest\` to offer a missing skill only when the current task needs it. Close with the configured orientation block.\n`
25
25
  : full;
26
26
  const block = `${MARK_START}\n${body}\n${MARK_END}`;
27
27
  let doc = existsSync(paths.hookTarget) ? readFileSync(paths.hookTarget, 'utf8') : '';
package/targets/agents.js CHANGED
@@ -68,7 +68,15 @@ ${REFUTER_FOUR_INPUTS}
68
68
  3. Did you inspect the relevant **caller, import, and relevant test**?
69
69
  4. Can the severity survive the **existing guards** you verified?
70
70
 
71
- If an answer is no, lower the severity or omit the finding. Every **HIGH or CRITICAL** needs the line and failure mode in the report. **Zero findings with an attack list is valid.**
71
+ If an answer is no, lower the severity or omit the finding. Every **blocker or should-fix** needs the line and failure mode in the report. **Zero findings with an attack list is valid.**
72
+
73
+ **Report findings in one shape, so the panel can be consolidated** — a fenced ${'`json findings`'} block holding an array (empty when you found nothing):
74
+
75
+ ${'```'}json findings
76
+ [{ "lens": "<your lens>", "severity": "blocker|should-fix|nit|question", "file": "path/from/repo/root", "line": 42, "claim": "one sentence: what is wrong", "failure_scenario": "concrete input + state -> wrong result", "evidence": "the exact changed line, quoted" }]
77
+ ${'```'}
78
+
79
+ ${'`rsc review consolidate`'} merges what several lenses reported about the same place and sends each unique blocker or should-fix to ${'`finding-verifier`'}, whose job is to prove it false. A blocker or should-fix with no ${'`file`'}, ${'`line`'} or ${'`failure_scenario`'} is downgraded to a question there, mechanically.
72
80
 
73
81
  **Common false positives to reject:** an equivalent mutant with no diverging input; a documented dummy value that never reaches a sink; a deliberate boundary already enforced by a caller; generated/vendor code outside the change; style preference presented as correctness; and a theoretical race with no shared state or overlapping lifetime.
74
82
 
@@ -126,8 +134,36 @@ ${REFUTER_CONTRACT}
126
134
 
127
135
  **Check the mapping both ways:** every acceptance criterion needs a falsification procedure that can be made to fail, and every test should trace to something someone asked for.`,
128
136
  },
137
+ // The second half of ECC's orch-review, adapted: after `rsc review consolidate` collapses the panel's
138
+ // duplicates, every unique blocker/should-fix gets ONE more fresh context whose default is that the
139
+ // finding is false. A refuter attacks the diff; the verifier attacks the finding. Same asymmetry,
140
+ // pointed the other way — which is what stops an exaggerated lens from reaching the author as a blocker.
141
+ {
142
+ name: 'finding-verifier',
143
+ desc: 'Adversarial verifier of review findings: takes ONE consolidated finding and tries to prove it false against the code. Default stance: the finding is false; only a reproduced or traced failure is CONFIRMED. Fresh context, edits nothing.',
144
+ body: `You are the **finding verifier** for this project. ${'`code-review`'} hands you **one** finding that survived ${'`rsc review consolidate`'} — a blocker or should-fix some refuter lens reported against a diff. Your job is to **prove it false**. Your starting position is that it is false; the finding has to beat you.
145
+
146
+ **Your inputs:** the finding (location, claim, failure scenario, evidence) plus the same four the lenses had —
147
+
148
+ ${REFUTER_FOUR_INPUTS}
149
+
150
+ **You do NOT get** the refuter's reasoning or the builder's defence. Judge the claim against the code, not against either story.
151
+
152
+ **How to try to kill it:**
153
+ 1. Read the cited line **and** its callers, guards and tests — the check that makes it impossible often lives two functions up, or in a caller that never passes that input.
154
+ 2. Try the failure scenario for real when you can: run the test, execute the command, or write a throwaway check in a temp directory outside the repo. An observed failure outranks any argument.
155
+ 3. Ask whether the change **caused** it. A defect that was already there is real but does not block this delivery.
156
+
157
+ **Verdict — exactly one, with its proof:**
158
+ - **CONFIRMED** — you reproduced it, or traced a reachable path from a concrete input to the wrong result. Quote the output or the path. Only this verdict may block.
159
+ - **REFUTED** — you found what makes it impossible (the guard, the caller, the type, the test). Cite it with file and line.
160
+ - **UNPROVEN** — neither: it becomes a question for the human, and questions never block.
161
+
162
+ Also state whether the severity holds. A CONFIRMED finding whose blast radius is narrow is a should-fix, not a blocker — say so. You fix nothing and edit no file: your output is the verdict, the proof, and the commands you ran.`,
163
+ },
129
164
  ];
130
165
 
166
+
131
167
  export const BASE_AGENT_NAMES = Object.freeze(AGENTS.map((agent) => agent.name));
132
168
  export { stackAgents, stackAgentNames, validateAgentCatalog };
133
169
  export const allAgentNames = () => [...BASE_AGENT_NAMES, ...stackAgentNames()];
package/targets/claude.js CHANGED
@@ -182,19 +182,6 @@ export function wireHook(paths, sourceMd, policy = {}) {
182
182
  );
183
183
  settings.hooks.PreToolUse.push({ matcher: SHELL_TOOLS, hooks: [{ type: 'command', command: sgCmd }] });
184
184
 
185
- // Danger guard: a PreToolUse(Bash) hook that DENIES irreversible foot-gun commands
186
- // (rm -rf, git push --force, DROP/TRUNCATE, DELETE/UPDATE without WHERE, dd to /dev,
187
- // curl|bash, …) when the user-profile says the user is NON-technical (default-safe
188
- // when no profile exists yet; never guards a fully `technical` user). Materialized +
189
- // node-run (Windows-safe), idempotent, fail-open, opt-out via .rsc/.no-danger-guard.
190
- const dgDest = join(paths.projectRoot, '.rsc', 'danger-guard.mjs');
191
- copyFileSync(join(HERE, 'danger-guard.mjs'), dgDest);
192
- const dgCmd = viaBootstrap('guard', at('.rsc', 'danger-guard.mjs'), `"${P}"`);
193
- settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
194
- (e) => !hookWiringOf(e).includes('.rsc/danger-guard.'),
195
- );
196
- settings.hooks.PreToolUse.push({ matcher: SHELL_TOOLS, hooks: [{ type: 'command', command: dgCmd }] });
197
-
198
185
  // Gitmoji guard: a PreToolUse(Bash) hook that DENIES a `git commit` whose message
199
186
  // carries no gitmoji (gitmoji.dev) in front of the Conventional Commits header. The
200
187
  // convention lives in `git-workflow`; prose asks, this hook decides — at the one
@@ -226,18 +213,18 @@ export function wireHook(paths, sourceMd, policy = {}) {
226
213
  (e) => !hookWiringOf(e).includes('.rsc/userprompt-gate.'),
227
214
  );
228
215
  settings.hooks.UserPromptSubmit.push({ hooks: [{ type: 'command', command: fgCmd }] });
229
- written.push(sgDest, dgDest, gmDest, fgDest, join(paths.projectRoot, '.rsc', 'sello.mjs'));
216
+ written.push(sgDest, gmDest, fgDest, join(paths.projectRoot, '.rsc', 'sello.mjs'));
230
217
  } else {
231
218
  for (const event of ['PreToolUse', 'UserPromptSubmit']) {
232
219
  if (!settings.hooks[event]) continue;
233
220
  settings.hooks[event] = settings.hooks[event].filter((entry) => {
234
221
  const body = hookWiringOf(entry);
235
- return !body.includes('.rsc/ship-guard.') && !body.includes('.rsc/danger-guard.') &&
222
+ return !body.includes('.rsc/ship-guard.') &&
236
223
  !body.includes('.rsc/gitmoji-guard.') && !body.includes('.rsc/userprompt-gate.');
237
224
  });
238
225
  if (!settings.hooks[event].length) delete settings.hooks[event];
239
226
  }
240
- for (const name of ['ship-guard.mjs', 'danger-guard.mjs', 'gitmoji-guard.mjs', 'userprompt-gate.mjs', 'sello.mjs']) {
227
+ for (const name of ['ship-guard.mjs', 'gitmoji-guard.mjs', 'userprompt-gate.mjs', 'sello.mjs']) {
241
228
  rmSync(join(paths.projectRoot, '.rsc', name), { force: true });
242
229
  }
243
230
  written.push(operationsSuggest);
@@ -248,6 +235,28 @@ export function wireHook(paths, sourceMd, policy = {}) {
248
235
  for (const id of policy.plugins) settings.enabledPlugins[id] = true;
249
236
  }
250
237
 
238
+ // Danger guard: its own decision, not part of the code-hook block above (#273). `init` promises it
239
+ // to non-technical and mixed users whatever the project is, and a plan that predates the field is
240
+ // read as "yes": a non-technical operations install gets the guard it was missing on its next sync,
241
+ // and a technical user gets a guard that stands down at runtime.
242
+ settings.hooks.PreToolUse ||= [];
243
+ settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter((e) => !hookWiringOf(e).includes('.rsc/danger-guard.'));
244
+ if (policy.dangerGuard !== false) {
245
+ // Danger guard: a PreToolUse(Bash) hook that DENIES irreversible foot-gun commands
246
+ // (rm -rf, git push --force, DROP/TRUNCATE, DELETE/UPDATE without WHERE, dd to /dev,
247
+ // curl|bash, …) when the user-profile says the user is NON-technical (default-safe
248
+ // when no profile exists yet; never guards a fully `technical` user). Materialized +
249
+ // node-run (Windows-safe), idempotent, fail-open, opt-out via .rsc/.no-danger-guard.
250
+ const dgDest = join(paths.projectRoot, '.rsc', 'danger-guard.mjs');
251
+ copyFileSync(join(HERE, 'danger-guard.mjs'), dgDest);
252
+ const dgCmd = viaBootstrap('guard', at('.rsc', 'danger-guard.mjs'), `"${P}"`);
253
+ settings.hooks.PreToolUse.push({ matcher: SHELL_TOOLS, hooks: [{ type: 'command', command: dgCmd }] });
254
+ written.push(dgDest);
255
+ } else {
256
+ rmSync(join(paths.projectRoot, '.rsc', 'danger-guard.mjs'), { force: true });
257
+ }
258
+ if (!settings.hooks.PreToolUse.length) delete settings.hooks.PreToolUse;
259
+
251
260
  mkdirSync(dirname(file), { recursive: true });
252
261
  writeFileSync(file, JSON.stringify(settings, null, 2) + '\n');
253
262
 
@@ -90,6 +90,7 @@ export function claimOnce(key, { dir = markerDir(), windowMs = 30_000, now = Dat
90
90
  // definition: the hook emits it and `rsc doctor` measures it from the same constant. Anything
91
91
  // that reports a byte count for text it does not own drifts the moment the text changes.
92
92
  export const WORKFLOW_GATE_TEXT = `===== workflow gate · metodologia (maxima prioridad) =====
93
+ Responde en el idioma en que escribe la persona, no en el de este texto.
93
94
  Si el usuario pide construir, anadir o cambiar algo (en cualquier idioma, se juzga la intencion),
94
95
  sigue esta cadena ANTES de escribir codigo. Ninguna skill escribe codigo de una feature hasta que
95
96
  el que esta claro y el usuario ha dado el visto bueno.
@@ -100,10 +101,12 @@ el que esta claro y el usuario ha dado el visto bueno.
100
101
  Cada decision dificil de revertir se registra con \`write-adr\`, en docs/adr/.
101
102
  2. Escribir la spec: \`to-spec\`, o \`superpowers:brainstorming\` para cerrarla por secciones.
102
103
  Sin spec escrita no se programa.
103
- 3. Construir: \`superpowers:writing-plans\` -> \`superpowers:executing-plans\`. Solo el trabajo que
104
- salio de \`wayfinder\` va con \`to-tickets\` -> \`implement\`, ticket a ticket.
104
+ 3. Construir: \`superpowers:writing-plans\` -> \`superpowers:executing-plans\`. Spec grande o que
105
+ salio de \`wayfinder\` -> \`to-tickets\` -> \`implement-spec\` (subagentes en paralelo sobre el
106
+ grafo de tickets); un solo ticket suelto -> \`implement\`.
105
107
  Si la tarea toca pantalla, invoca ademas \`flujo-interfaz\`: dice que skill de diseno manda.
106
- 4. Antes de fusionar: \`code-review\` (estandares del repo + lo que pedia la spec).
108
+ 4. Antes de fusionar: \`code-review\` (estandares del repo + lo que pedia la spec), y el cuerpo
109
+ de la PR con \`pr\` (resumen visual, evidencia antes/despues, peligro de fusion).
107
110
  Siempre: \`superpowers:test-driven-development\` y \`superpowers:verification-before-completion\`
108
111
  antes de dar nada por terminado. Los bugs entran por \`superpowers:systematic-debugging\`.
109
112
  Cambio de una linea, typo o ajuste de configuracion -> hazlo y di que te saltas la cadena.
package/targets/memory.js CHANGED
@@ -35,7 +35,7 @@ export function memoryEnabledForProject(cwd = process.cwd()) {
35
35
  }
36
36
 
37
37
  function git(cwd, args) {
38
- try { return execFileSync('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim(); } catch { return null; }
38
+ try { return execFileSync('git', args, { windowsHide: true, cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim(); } catch { return null; }
39
39
  }
40
40
 
41
41
  function rel(cwd, path) {
package/targets/sello.mjs CHANGED
@@ -103,7 +103,7 @@ export function isEnabled(root) {
103
103
  // The CLI can run from any subdirectory; the guard always runs from the project
104
104
  // root. Both must compute the same candidate, so both resolve to the git toplevel.
105
105
  export function resolveRoot(root) {
106
- const r = spawnSync('git', ['-C', root, 'rev-parse', '--show-toplevel'], { encoding: 'utf8' });
106
+ const r = spawnSync('git', ['-C', root, 'rev-parse', '--show-toplevel'], { windowsHide: true, encoding: 'utf8' });
107
107
  return r.status === 0 ? (r.stdout || '').trim() || root : root;
108
108
  }
109
109
 
@@ -211,7 +211,7 @@ export function lensesRequired(tier, cfg = null) {
211
211
  // name matches no file on disk, so the file would hash as deleted and any later
212
212
  // mutation of it would sail through the gate. -z gives raw NUL-separated paths.
213
213
  function git(root, ...args) {
214
- const r = spawnSync('git', ['-C', root, '-c', 'core.quotePath=false', ...args], {
214
+ const r = spawnSync('git', ['-C', root, '-c', 'core.quotePath=false', ...args], { windowsHide: true,
215
215
  encoding: 'utf8', maxBuffer: 64 * 1024 * 1024,
216
216
  });
217
217
  return r.status === 0 ? (r.stdout || '') : null;
@@ -48,7 +48,7 @@ function cleanId(value, prefix = 'session') {
48
48
 
49
49
  function git(cwd, args) {
50
50
  try {
51
- return { ok: true, out: execFileSync('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], maxBuffer: 2 * 1024 * 1024 }).trim() };
51
+ return { ok: true, out: execFileSync('git', args, { windowsHide: true, cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], maxBuffer: 2 * 1024 * 1024 }).trim() };
52
52
  } catch {
53
53
  return { ok: false, out: '' };
54
54
  }
@@ -255,8 +255,8 @@ if (has('.git')) {
255
255
  // those make the fingerprint and an unchanged one reuses the last notice. Safe because `reap`
256
256
  // re-classifies before it removes anything.
257
257
  const trunk = W.resolveTrunk(root);
258
- const tip = trunk ? spawnSync('git', ['-C', root, 'rev-parse', trunk], { encoding: 'utf8' }).stdout : '';
259
- const list = spawnSync('git', ['-C', root, 'worktree', 'list', '--porcelain'], { encoding: 'utf8' }).stdout;
258
+ const tip = trunk ? spawnSync('git', ['-C', root, 'rev-parse', trunk], { encoding: 'utf8', windowsHide: true }).stdout : '';
259
+ const list = spawnSync('git', ['-C', root, 'worktree', 'list', '--porcelain'], { encoding: 'utf8', windowsHide: true }).stdout;
260
260
  const fingerprint = `${W.isCleanupEnabled(root)}\n${trunk}\n${tip}\n${list}`;
261
261
  const cacheFile = join(root, '.rsc', 'worktree-sweep.json');
262
262
  let cached = null;
@@ -67,7 +67,7 @@ const MERGE = /\bgit\s+merge\b/;
67
67
  if (!TRUNK.test(command) && !MERGE.test(command)) allow();
68
68
 
69
69
  const git = (...args) => {
70
- const r = spawnSync('git', ['-C', root, ...args], { encoding: 'utf8' });
70
+ const r = spawnSync('git', ['-C', root, ...args], { windowsHide: true, encoding: 'utf8' });
71
71
  return r.status === 0 ? (r.stdout || '').trim() : null;
72
72
  };
73
73
 
@@ -73,7 +73,7 @@ function git(cwd, args) {
73
73
  // 64 MiB, because node's 1 MiB default kills git mid-write on any worktree with a few thousand
74
74
  // stray files and hands back a truncated-but-successful-looking result. Measured: in the 1.0-1.15 MB
75
75
  // band the same unchanged worktree flipped between verdicts across runs.
76
- const r = spawnSync('git', ['-C', cwd, ...args], { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
76
+ const r = spawnSync('git', ['-C', cwd, ...args], { windowsHide: true, encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
77
77
  // `raw` matters for porcelain output: its leading space is a status code, not padding, and
78
78
  // trimming it shifted every path by one character — so the message naming the file about to be
79
79
  // lost named a file that does not exist. A refusal has to be true to be actionable (P6).