@damiangilgonzalez/harness 1.3.16 → 1.3.18
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.
- package/README.md +113 -658
- package/manifest.json +2 -2
- package/package.json +1 -1
- package/scripts/doctor.js +1 -1
- package/scripts/rsc.js +63 -1
- package/skills/building-agents/SKILL.md +1 -1
- package/skills/code-review/SKILL.md +3 -1
- package/skills/flujo-interfaz/SKILL.md +7 -0
- package/skills/grill-with-docs/SKILL.md +0 -1
- package/skills/harness/references/daily-curation-automation.md +2 -1
- package/skills/harness/references/wiki-protocol.md +3 -1
- package/skills/implement/SKILL.md +2 -1
- package/skills/implement-spec/SKILL.md +5 -4
- package/skills/init/SKILL.md +7 -5
- package/skills/orient/SKILL.md +3 -0
- package/skills/orient/references/orientation-contract.md +9 -0
- package/skills/postgresdb/SKILL.md +1 -1
- package/skills/pr/SKILL.md +15 -1
- package/skills/pr/evals/cases.yaml +6 -0
- package/skills/suggest/SKILL.md +5 -5
- package/skills/to-spec/SKILL.md +0 -1
- package/skills/to-tickets/SKILL.md +0 -1
- package/skills/wayfinder/SKILL.md +0 -1
- package/targets/_md-block.js +1 -1
- package/targets/claude.js +21 -1
- package/targets/danger-guard.mjs +114 -52
- package/targets/hook-once.mjs +44 -13
- package/targets/memory.js +6 -1
- package/targets/session-memory-adapter.mjs +4 -1
- package/targets/session-memory-core.mjs +40 -8
- package/targets/session-start.mjs +2 -1
- package/targets/ship-guard.mjs +26 -9
- package/targets/userprompt-gate.mjs +7 -2
- package/targets/worklog-checkpoint.mjs +16 -1
- package/targets/worktree-reaper.mjs +144 -4
package/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.3.
|
|
2
|
+
"version": "1.3.18",
|
|
3
3
|
"counts": {
|
|
4
4
|
"skills": 294,
|
|
5
5
|
"agents": 34,
|
|
@@ -3805,7 +3805,7 @@
|
|
|
3805
3805
|
},
|
|
3806
3806
|
{
|
|
3807
3807
|
"id": "pr",
|
|
3808
|
-
"description": "Use when writing a PR body: a visual summary, before/after evidence,
|
|
3808
|
+
"description": "Use when writing a PR body or opening a PR: a visual summary, before/after evidence, the merge danger (one-way or two-way door, blast radius), and a title checked against the repo's CI title rule before `gh pr create`.",
|
|
3809
3809
|
"tags": [
|
|
3810
3810
|
"pull-request",
|
|
3811
3811
|
"review",
|
package/package.json
CHANGED
package/scripts/doctor.js
CHANGED
|
@@ -261,7 +261,7 @@ export function doctor({ target, home, cwd }) {
|
|
|
261
261
|
// #277 — the three "missing" lists share one shape, { id, path, action }, so whoever builds on top
|
|
262
262
|
// of doctor reads them the same way; and `healthy` is what the exit code says.
|
|
263
263
|
for (const [id, e] of Object.entries(state.skills)) {
|
|
264
|
-
for (const f of e.files) if (!existsSync(f)) report.missing.push({ id, path: f, action: 'Run `npx @
|
|
264
|
+
for (const f of e.files) if (!existsSync(f)) report.missing.push({ id, path: f, action: 'Run `npx @damiangilgonzalez/harness sync` to restore this managed skill.' });
|
|
265
265
|
}
|
|
266
266
|
report.healthy = report.hookWired && !report.missing.length && !missingAgents.length && !missingCommands.length;
|
|
267
267
|
return report;
|
package/scripts/rsc.js
CHANGED
|
@@ -885,11 +885,72 @@ async function main() {
|
|
|
885
885
|
const root = W.resolveMainRoot(process.cwd());
|
|
886
886
|
const sub = argv[1];
|
|
887
887
|
|
|
888
|
+
if (sub === 'new') {
|
|
889
|
+
// Creating is not cleaning, so the cleanup opt-out does not apply here. Two things a worktree
|
|
890
|
+
// was measured lacking when it is born: a current base (local main was 400 commits behind
|
|
891
|
+
// origin) and what git does not track (.env, dependencies). The base is fixed here; the rest
|
|
892
|
+
// is the project's own hook, because only the project knows what makes it runnable.
|
|
893
|
+
const branchAt = argv.indexOf('--branch');
|
|
894
|
+
const branch = branchAt >= 0 ? argv[branchAt + 1] : undefined;
|
|
895
|
+
if (branchAt >= 0 && (!branch || branch.startsWith('--'))) { say('rsc: --branch needs a branch name.'); process.exitCode = 1; return; }
|
|
896
|
+
const name = argv.slice(2).find((a, i, all) => !a.startsWith('--') && all[i - 1] !== '--branch');
|
|
897
|
+
if (!name) { say('Use: npx @damiangilgonzalez/harness worktrees new <nombre> [--branch <rama>]'); process.exitCode = 1; return; }
|
|
898
|
+
const out = W.createWorktree(root, name, { branch });
|
|
899
|
+
if (!out.created) { say(`rsc: ${out.reason}`); process.exitCode = 1; return; }
|
|
900
|
+
if (!out.fetched) say(`⚠️ git fetch origin failed (${out.fetchError || 'no detail'}); starting from the last known ${out.base}, which may be stale.`);
|
|
901
|
+
say(`✅ worktree ${out.path}`);
|
|
902
|
+
say(` branch ${out.branch}, from ${out.base}`);
|
|
903
|
+
const hook = W.findPrepareHook(out.path, root);
|
|
904
|
+
if (hook) {
|
|
905
|
+
say(` preparing it: ${hook}`);
|
|
906
|
+
const ran = W.runPrepareHook(hook, out.path, root);
|
|
907
|
+
if (!ran.ok) { say(`⚠️ the preparation hook failed (${ran.reason}). The worktree exists; finish preparing it by hand.`); process.exitCode = 1; }
|
|
908
|
+
} else {
|
|
909
|
+
say(` No preparation hook (${W.PREPARE_HOOKS.join(' or ')}): .env files and dependencies are NOT copied — create the hook to do it on every new worktree.`);
|
|
910
|
+
}
|
|
911
|
+
say(`Next: cd "${out.path}"`);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
|
|
888
915
|
if (!W.isCleanupEnabled(root)) {
|
|
889
916
|
say(`worktree cleanup is off for this project (.rsc/${W.OPT_OUT}). Delete that file to turn it back on.`);
|
|
890
917
|
return;
|
|
891
918
|
}
|
|
892
919
|
|
|
920
|
+
if (sub === 'reap' && argv.includes('--merged')) {
|
|
921
|
+
// The bulk answer to "delete the worktrees" — asked four times in one project, with up to
|
|
922
|
+
// fourteen open. Merged is judged against origin's trunk AFTER a fetch, so a branch landed in
|
|
923
|
+
// the forge an hour ago counts. Without --confirm this only lists: one look, then one yes.
|
|
924
|
+
const fetched = W.fetchOrigin(root);
|
|
925
|
+
if (!fetched.ok) say(`⚠️ git fetch origin failed (${fetched.err || 'no detail'}); judging against the last known trunk.`);
|
|
926
|
+
const all = W.classifyWorktrees(root);
|
|
927
|
+
const merged = W.mergedCandidates(all);
|
|
928
|
+
const held = all.filter((c) => c.verdict === 'ask' && !merged.includes(c));
|
|
929
|
+
if (!merged.length) say('No merged worktree that can be removed in bulk.');
|
|
930
|
+
if (!argv.includes('--confirm')) {
|
|
931
|
+
if (merged.length) {
|
|
932
|
+
say(`${merged.length} merged worktree(s), clean, removable in one go:`);
|
|
933
|
+
for (const c of merged) say(` ${c.path}${c.branch ? ` (${c.branch})` : ''}`);
|
|
934
|
+
}
|
|
935
|
+
for (const c of held) say(W.describe(c));
|
|
936
|
+
if (merged.length) say('\nRemove them all: npx @damiangilgonzalez/harness worktrees reap --merged --confirm');
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
for (const c of merged) {
|
|
940
|
+
const out = W.reapWorktree(root, c.path, { confirmed: true });
|
|
941
|
+
if (out.removed) {
|
|
942
|
+
say(`✅ removed ${out.path}`);
|
|
943
|
+
if (out.branchKept) say(` branch ${out.branch} kept — git will not delete it safely, and while it exists the commits are recoverable.`);
|
|
944
|
+
} else {
|
|
945
|
+
say(`⏸ kept ${c.path} — ${out.reason}`);
|
|
946
|
+
process.exitCode = 1;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
// What a bulk yes never covers, said out loud so nobody thinks it was forgotten.
|
|
950
|
+
for (const c of held) say(`⏸ kept ${c.path} — ${W.refusal(c)}`);
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
|
|
893
954
|
const candidates = W.classifyWorktrees(root).filter((c) => c.verdict !== 'skip');
|
|
894
955
|
|
|
895
956
|
if (sub === 'reap') {
|
|
@@ -920,6 +981,7 @@ async function main() {
|
|
|
920
981
|
say('');
|
|
921
982
|
say('Remove the safe ones: npx @damiangilgonzalez/harness worktrees reap');
|
|
922
983
|
say('Remove one by name: npx @damiangilgonzalez/harness worktrees reap <path> [--confirm]');
|
|
984
|
+
say('Remove every merged: npx @damiangilgonzalez/harness worktrees reap --merged [--confirm]');
|
|
923
985
|
return;
|
|
924
986
|
}
|
|
925
987
|
case 'capabilities': {
|
|
@@ -1195,7 +1257,7 @@ async function main() {
|
|
|
1195
1257
|
return void (await runPurge(argv.includes('--dry-run'), argv.includes('--with-docs')));
|
|
1196
1258
|
default:
|
|
1197
1259
|
say(`rsc: unknown command '${cmd}'.`);
|
|
1198
|
-
say('Use: npx @damiangilgonzalez/harness onboard | reassess | add <id...> | install --profile <p> | consult "<text>" | list | capabilities [--full|gap-log] | audit | registry refresh | doctor | sync | memory <on|off|status|save|resume|learn|metrics> | sello <on|off|status|…> | worktrees [reap [path] [--confirm]] | backups | restore <id|latest> | upgrade | repair | uninstall <id> | purge');
|
|
1260
|
+
say('Use: npx @damiangilgonzalez/harness onboard | reassess | add <id...> | install --profile <p> | consult "<text>" | list | capabilities [--full|gap-log] | audit | registry refresh | doctor | sync | memory <on|off|status|save|resume|learn|metrics> | sello <on|off|status|…> | worktrees [new <nombre> [--branch <rama>] | reap [path|--merged] [--confirm]] | backups | restore <id|latest> | upgrade | repair | uninstall <id> | purge');
|
|
1199
1261
|
say('Any command takes --target <claude|codex|cursor|copilot|gemini|…> (comma-separate for several)');
|
|
1200
1262
|
say(' → without it, rsc uses the assistant already installed here; if two are, it asks instead of guessing.');
|
|
1201
1263
|
process.exitCode = 1;
|
|
@@ -14,7 +14,7 @@ A thin provider adapter, a disciplined agent loop, schema-validated tools, provi
|
|
|
14
14
|
|
|
15
15
|
> Program against a **capability interface**, never a vendor SDK. Vendor specifics (model id, tool-schema shape, JSON mode, caching, token limits) live behind one adapter resolved from config. Model names and prices rot — if one appears in business logic it's a bug, and re-verify the dated tables before quoting a number.
|
|
16
16
|
|
|
17
|
-
**Hand off instead when:** a new non-trivial feature has no approved spec + plan under `docs/wiki/sdd/` → stop and write one first (the `to-spec` skill,
|
|
17
|
+
**Hand off instead when:** a new non-trivial feature has no approved spec + plan under `docs/wiki/sdd/` → stop and write one first (the `to-spec` skill, then `to-tickets`), which routes back here once the plan is approved; one-line/low-risk changes go straight through. Anthropic-SDK internals (caching, thinking, batch) in a file that *only* imports `anthropic` → `claude-api` if your environment has it, since this skill stays multi-provider. Workspace scaffolding → [`harness`](../harness/SKILL.md). Choosing *which* coding agent to use → agent-eval territory. Pure prompt-wording tuning with no architecture change → prompt engineering, not this. A one-shot throwaway prompt, or no retrieval/tools/loop/evals at all → you don't need an agent; call the SDK directly and say so.
|
|
18
18
|
|
|
19
19
|
## Decision rules (read before writing code)
|
|
20
20
|
|
|
@@ -38,6 +38,8 @@ Busca el spec de origen, en este orden:
|
|
|
38
38
|
|
|
39
39
|
Cualquier cosa en el repo que documente cómo debe escribirse el código, como `CODING_STANDARDS.md` o `CONTRIBUTING.md`. (En este proyecto: `CLAUDE.md` y `docs/CARTA-MAGNA.md`.)
|
|
40
40
|
|
|
41
|
+
Si no encuentras ninguna, **no lo calles**: el eje de Estándares solo tendrá el smell baseline, y el reporte final debe decirlo en su primera línea ("Estándares: el repo no documenta estándares; solo se revisó el smell baseline"). Ofrece generar un `CODING_STANDARDS.md` inicial a partir de las convenciones que se observan en el repo (nombres, estructura, manejo de errores, tests). No lo escribas sin un sí del usuario.
|
|
42
|
+
|
|
41
43
|
Además de lo que el repo documente, el eje de Estándares siempre lleva el **smell baseline** de abajo — un conjunto fijo de code smells de Fowler (_Refactoring_, cap. 3) que aplica incluso cuando el repo no documenta nada. Dos reglas lo condicionan:
|
|
42
44
|
|
|
43
45
|
- **El repo manda.** Un estándar documentado del repo siempre gana; donde el repo avale algo que el baseline marcaría, suprime el smell.
|
|
@@ -74,7 +76,7 @@ Envía un único mensaje con dos llamadas a la herramienta `Agent`. Usa el subag
|
|
|
74
76
|
- La ruta o el contenido recuperado del spec.
|
|
75
77
|
- El encargo: "Reporta: (a) requisitos que el spec pedía y que faltan o están parciales; (b) comportamiento en el diff que no se pidió (scope creep); (c) requisitos que parecen implementados pero cuya implementación parece incorrecta. Cita la línea del spec por cada hallazgo. Menos de 400 palabras."
|
|
76
78
|
|
|
77
|
-
Si falta el spec, sáltate el sub-agente de Spec y anótalo en el reporte final.
|
|
79
|
+
Si falta el spec, sáltate el sub-agente de Spec y anótalo en el reporte final. Si faltan las fuentes de estándares, lanza igual el de Estándares con el baseline, y anótalo también junto con la oferta del `CODING_STANDARDS.md`.
|
|
78
80
|
|
|
79
81
|
### 5. Verificar los graves antes de presentarlos
|
|
80
82
|
|
|
@@ -80,6 +80,13 @@ de las skills de diseno. Las mecanicas del framework son de `angular`, `react` o
|
|
|
80
80
|
| Un flujo pierde usuarios a mitad | `leyes-de-retencion` -> `mejor-redaccion` -> `mejor-accesibilidad` |
|
|
81
81
|
| Solo pulir lo que ya hay | `revision-interfaz` |
|
|
82
82
|
|
|
83
|
+
## Cuando cuenta como hecho
|
|
84
|
+
|
|
85
|
+
Un cambio visual no esta hecho sin una **captura del entorno donde el usuario lo va a probar**
|
|
86
|
+
(su navegador, su URL, su viewport; no un test ni un render aislado si el usuario no prueba ahi).
|
|
87
|
+
Que compile y pasen los tests no dice nada de como se ve. Si no puedes abrirlo, dilo y no lo
|
|
88
|
+
declares terminado: "no lo he mirado en un navegador" es un trabajo sin acabar, no un matiz.
|
|
89
|
+
|
|
83
90
|
## Donde encaja en la metodologia
|
|
84
91
|
|
|
85
92
|
Esta cadena vive **dentro** del paso de construir, no lo sustituye. El trabajo sigue llegando con
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: grill-with-docs
|
|
3
3
|
description: "A relentless interrogation to sharpen a plan or design, which also builds documentation (ADRs and a glossary) along the way."
|
|
4
4
|
tags: ["planning", "questioning", "documentation", "adr"]
|
|
5
|
-
disable-model-invocation: true
|
|
6
5
|
profiles: [core, ui, full]
|
|
7
6
|
origin: damiangil
|
|
8
7
|
---
|
|
@@ -42,7 +42,8 @@ process inbox/, then scan the workspace (minus .rscignore) for un-ingested docum
|
|
|
42
42
|
applying Clean-as-you-go (move loose root-level + inbox files into raw/ after a
|
|
43
43
|
verified ingest; copy files nested in user-maintained folders and propose
|
|
44
44
|
consolidation), record them in wiki/.ingested.json, and list ambiguous folders as
|
|
45
|
-
proposals (do not grab them). Then compile pending raw/worklog/ material
|
|
45
|
+
proposals (do not grab them). Then compile pending raw/worklog/ material (skip this
|
|
46
|
+
step if raw/worklog/ does not exist; do not list a missing folder) into wiki/
|
|
46
47
|
pages (update existing before creating new), keep frontmatter + relative markdown
|
|
47
48
|
links OKF-consistent, append significant decisions to wiki/harness/decisions.md,
|
|
48
49
|
refresh the .base-backed navigation, recompute scores.json + the score: property,
|
|
@@ -417,7 +417,9 @@ safety rule the curation pass honors.
|
|
|
417
417
|
### Steps
|
|
418
418
|
|
|
419
419
|
1. **Capture.** Write the worklog to `raw/worklog/YYYY-MM-DD-<slug>.md`
|
|
420
|
-
(`status: unprocessed`). Infer `topic` from content.
|
|
420
|
+
(`status: unprocessed`). Infer `topic` from content. If `raw/worklog/` does
|
|
421
|
+
not exist yet, create it (`mkdir -p`) — never list it blindly: the checkpoint
|
|
422
|
+
hook already says whether it exists and how many worklogs it holds.
|
|
421
423
|
2. **Compile.** Run the normal Compile (Fetch is a no-op — the worklog is already
|
|
422
424
|
`raw`): distill durable points into `wiki/<topic>/` articles (update existing
|
|
423
425
|
before creating new), add markdown-link cross-refs + `## Related`, cascade.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: implement
|
|
3
3
|
description: "Implements a piece of work from a spec or a set of tickets."
|
|
4
4
|
tags: ["implementation", "spec", "tickets"]
|
|
5
|
-
disable-model-invocation: true
|
|
6
5
|
profiles: [core, ui, full]
|
|
7
6
|
origin: damiangil
|
|
8
7
|
---
|
|
@@ -14,6 +13,8 @@ Usa TDD (superpowers:test-driven-development) donde sea posible, en las costuras
|
|
|
14
13
|
|
|
15
14
|
Ejecuta el typechecking con regularidad, archivos de test sueltos con regularidad, y la suite de tests completa una vez al final.
|
|
16
15
|
|
|
16
|
+
Si el trabajo cambia algo visible, no está hecho hasta que lo hayas mirado: adjunta una captura del entorno donde el usuario lo va a probar. Si no puedes abrirlo, dilo y no lo des por terminado.
|
|
17
|
+
|
|
17
18
|
Al terminar, usa /code-review para revisar el trabajo.
|
|
18
19
|
|
|
19
20
|
Commitea tu trabajo en la rama actual.
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
name: implement-spec
|
|
3
3
|
description: "Implement the result of /to-spec and /to-tickets in code, orchestrating parallel implementer subagents over the ticket graph."
|
|
4
4
|
tags: ["implementation", "spec", "tickets", "subagents", "orchestration"]
|
|
5
|
-
disable-model-invocation: true
|
|
6
5
|
profiles: [core, ui, full]
|
|
7
6
|
origin: damiangil
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
Te han dado una spec. Esa spec debería tener tickets asociados que describen cómo implementarla.
|
|
9
|
+
Te han dado una spec. Esa spec debería tener tickets asociados que describen cómo implementarla. Si no los tiene, **para**: lanza `to-tickets` sobre la spec y vuelve aquí con el grafo ya publicado. Sin tickets no hay frontera que repartir, y esto se convierte en una implementación a ciegas.
|
|
11
10
|
|
|
12
11
|
El issue tracker debería estar descrito en `docs/agents/issue-tracker.md`. Si falta, pregunta al usuario dónde viven los tickets y cómo se cierra el trabajo (PR, issue, fichero).
|
|
13
12
|
|
|
@@ -30,9 +29,11 @@ Lanza los **subagentes implementadores** en segundo plano siempre que se pueda,
|
|
|
30
29
|
4. Usa **subagentes implementadores** para implementar cada ticket, cada uno en su propio worktree y en su propia rama (`superpowers:using-git-worktrees`). Cada subagente implementador:
|
|
31
30
|
- confirma que su worktree parte de la rama de integración antes de empezar, y se reinicia sobre ella si no;
|
|
32
31
|
- llama a la herramienta Skill con `superpowers:test-driven-development` para construir el ticket;
|
|
33
|
-
- fusiona la punta de la rama de integración en su propia rama antes de decir que ha terminado
|
|
32
|
+
- fusiona la punta de la rama de integración en su propia rama antes de decir que ha terminado;
|
|
33
|
+
- si el ticket cambia algo visible, adjunta una captura del entorno donde el usuario lo va a probar;
|
|
34
|
+
- entrega un informe final de **150 palabras como máximo**: qué cambió, ficheros, resultado de los tests y bloqueos. El detalle va al commit o al ticket, no a la respuesta. Pon este tope literal en el prompt de cada subagente: cada entrega entra entera en tu contexto, y decenas de entregas largas te hacen olvidar lo que acaba de decir el usuario.
|
|
34
35
|
|
|
35
|
-
5. Cuando un **subagente implementador** termina, fusiona su trabajo en la rama de integración con un **subagente fusionador**.
|
|
36
|
+
5. Cuando un **subagente implementador** termina, revisa su entrega antes de fusionar. Si toca algo visible y no trae captura, o dice que no lo ha mirado en un navegador, **no está hecho**: devuélvesela para que lo mire. Si la entrega es buena, fusiona su trabajo en la rama de integración con un **subagente fusionador**.
|
|
36
37
|
|
|
37
38
|
6. Si eso cambia la **frontera** de tickets disponibles, lanza más **subagentes implementadores** para los tickets nuevos. Así se mantiene la máxima concurrencia.
|
|
38
39
|
|
package/skills/init/SKILL.md
CHANGED
|
@@ -165,11 +165,13 @@ means the user starts clean.
|
|
|
165
165
|
machine and flags overlap or skills with no footprint, so the project starts with the right set
|
|
166
166
|
rather than a pile. Summarize at their level.
|
|
167
167
|
4. **Tell them about the danger guard.** A `technical_level` of `non-technical` or `mixed` (and the
|
|
168
|
-
state before any profile exists) turns on a `PreToolUse` guard
|
|
169
|
-
`rm -rf`, `git push --force`, `git reset --hard`, `DROP`/`TRUNCATE`,
|
|
170
|
-
`WHERE`, `dd` to a device, `curl | bash
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
state before any profile exists) turns on a `PreToolUse` guard for irreversible commands —
|
|
169
|
+
`rm -rf`, `git push --force`, `git reset --hard`, `git branch -D`, `DROP`/`TRUNCATE`,
|
|
170
|
+
`DELETE`/`UPDATE` with no `WHERE`, `dd` to a device, `curl | bash`. For `non-technical` (or no
|
|
171
|
+
profile) Claude Code asks the user to confirm each one, saying what the command destroys; their
|
|
172
|
+
yes is the order that runs it. For `mixed` it only warns. A fully `technical` user is never
|
|
173
|
+
guarded. It turns off only if the user explicitly asks: `.rsc/.no-danger-guard`.
|
|
174
|
+
Mention it when you set a non-technical level, so a later confirmation is not a surprise.
|
|
173
175
|
|
|
174
176
|
### Phase 5 — HANDOFF
|
|
175
177
|
|
package/skills/orient/SKILL.md
CHANGED
|
@@ -63,6 +63,9 @@ The dial is spoken, not configured: when the user says "explícame más / menos"
|
|
|
63
63
|
tanto" or "enséñame", update `accompaniment_level` in the profile, confirm in one line, and apply
|
|
64
64
|
the new depth from this turn on.
|
|
65
65
|
|
|
66
|
+
When a front closes (PR merged or opened, ticket done), `➡️` offers `handoff` and a fresh session
|
|
67
|
+
before more work in this one; see the contract.
|
|
68
|
+
|
|
66
69
|
At a real fork, ask. Deciding alone is faster and wrong — the fork is the moment the person's
|
|
67
70
|
judgment is worth more than yours.
|
|
68
71
|
|
|
@@ -28,6 +28,15 @@ Read `docs/wiki/harness/user-profile.md`. Two fields combine: `accompaniment_lev
|
|
|
28
28
|
|
|
29
29
|
`technical_level` is orthogonal (plain language for `non-technical` even at L0; skip 101s for `technical` even at L3). Missing profile → assume `non-technical` + **L3** and offer to set the dial.
|
|
30
30
|
|
|
31
|
+
## When a front closes
|
|
32
|
+
|
|
33
|
+
A front ("frente") closes when its PR is merged or opened, or its ticket is done. That turn's `➡️`
|
|
34
|
+
proposes `handoff` and a new session as the first option, instead of starting the next front here.
|
|
35
|
+
A session that runs for days through several `/compact` loses what the user just said: each
|
|
36
|
+
compaction and each subagent hand-back pushes the latest instructions further out. A handoff
|
|
37
|
+
document carries what matters; the new session starts with room for it. If the user prefers to
|
|
38
|
+
continue, continue — offer once per front, not every turn.
|
|
39
|
+
|
|
31
40
|
## Division of labor
|
|
32
41
|
|
|
33
42
|
- `orient` guides the **person** (this contract).
|
|
@@ -13,7 +13,7 @@ fix slow SQL, run zero-downtime migrations, and operate/secure the database. Too
|
|
|
13
13
|
example is runnable.
|
|
14
14
|
|
|
15
15
|
New, non-trivial feature with no approved spec + plan under `docs/wiki/sdd/`? Hand off to
|
|
16
|
-
the `to-spec` skill before writing feature code (
|
|
16
|
+
the `to-spec` skill before writing feature code (then `to-tickets`); build
|
|
17
17
|
straight from here only for a genuinely one-line, low-risk change.
|
|
18
18
|
|
|
19
19
|
Deep dives: [schema-and-indexing](references/schema-and-indexing.md) (types, constraints, every index
|
package/skills/pr/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pr
|
|
3
|
-
description: "Use when writing a PR body: a visual summary, before/after evidence,
|
|
3
|
+
description: "Use when writing a PR body or opening a PR: a visual summary, before/after evidence, the merge danger (one-way or two-way door, blast radius), and a title checked against the repo's CI title rule before `gh pr create`."
|
|
4
4
|
tags: ["pull-request", "review", "evidence", "risk"]
|
|
5
5
|
profiles: [core, ui, full]
|
|
6
6
|
origin: damiangil
|
|
@@ -171,3 +171,17 @@ La evidencia basada en ejecución va justo detrás: resultados de tests, salida
|
|
|
171
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
172
|
|
|
173
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.
|
|
174
|
+
|
|
175
|
+
## Título
|
|
176
|
+
|
|
177
|
+
Antes de `gh pr create`, comprueba que el título pasa el check de CI del repo. Un título mal formado tumba la PR aunque el código esté bien.
|
|
178
|
+
|
|
179
|
+
1. Busca la regla: `grep -rnE "semantic-pull-request|pull_request\.title|commitlint" .github/workflows/` y, si aparece commitlint, su configuración (`commitlint.config.*`, `.commitlintrc*`, `package.json`). En `amannn/action-semantic-pull-request` mira `types`, `scopes`, `requireScope` y `subjectPattern`.
|
|
180
|
+
2. Saca la regex o los tipos permitidos y prueba el título:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
node -e 'const re=/^(feat|fix|docs|refactor|test|chore)(\([\w-]+\))?!?: .+/u; const t=process.argv[1]; console.log(re.test(t)?"OK":"FALLA: "+t)' "fix(pr): valida el título"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Si el repo antepone un gitmoji u otro prefijo, inclúyelo en la regex tal como lo pida la regla.
|
|
187
|
+
3. Si falla, corrige el título antes de crear la PR. Si no hay ningún check de título, sigue la convención de los commits recientes (`git log --oneline -10`).
|
|
@@ -11,6 +11,8 @@ should_trigger:
|
|
|
11
11
|
why: "Disparador directo de pr: peligro de fusión y radio de impacto."
|
|
12
12
|
- prompt: "¿Qué pongo en la PR para que se revise rápido?"
|
|
13
13
|
why: "Disparador directo de pr."
|
|
14
|
+
- prompt: "Abre la PR, pero que el título no vuelva a tumbar el CI."
|
|
15
|
+
why: "Disparador directo de pr: el título se valida contra el check del repo."
|
|
14
16
|
|
|
15
17
|
should_not_trigger:
|
|
16
18
|
- prompt: "Revisa el código de esta PR."
|
|
@@ -31,3 +33,7 @@ capability:
|
|
|
31
33
|
must_include:
|
|
32
34
|
- "Peligro de fusión"
|
|
33
35
|
- "Radio de impacto"
|
|
36
|
+
- scenario: "El repo tiene un check de título de PR en sus workflows."
|
|
37
|
+
must_include:
|
|
38
|
+
- ".github/workflows"
|
|
39
|
+
- "gh pr create"
|
package/skills/suggest/SKILL.md
CHANGED
|
@@ -34,8 +34,8 @@ The shape of the chain:
|
|
|
34
34
|
when the effort will not fit one sitting.
|
|
35
35
|
- Once the shape is known, capture it as a spec, and give any call that would be costly to undo
|
|
36
36
|
its own ADR.
|
|
37
|
-
-
|
|
38
|
-
|
|
37
|
+
- Small work builds straight from the clarified ask; big work is split into tickets first and
|
|
38
|
+
built from them. A screen also routes through `flujo-interfaz`.
|
|
39
39
|
- Review the finished change against the repo's standards and against the spec before merging.
|
|
40
40
|
|
|
41
41
|
Two exceptions, and say out loud when you take one:
|
|
@@ -54,9 +54,9 @@ whole run — advance through the phases without re-asking.
|
|
|
54
54
|
If a step's skill is not installed, offer to add it (§2) before routing. `implement` always
|
|
55
55
|
pairs with test-driven development and a verification pass before anything is called done.
|
|
56
56
|
|
|
57
|
-
Exact skill names
|
|
58
|
-
`
|
|
59
|
-
`
|
|
57
|
+
Exact skill names, by size. Small: `superpowers:brainstorming` or `grill-with-docs` ->
|
|
58
|
+
`implement`. Big: `grill-with-docs` or `wayfinder` -> `to-spec` -> `to-tickets` ->
|
|
59
|
+
`implement-spec`. Both: `write-adr` for decisions, then `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
|
|
package/skills/to-spec/SKILL.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: to-spec
|
|
3
3
|
description: "Turns the current conversation into a spec (PRD) and publishes it to the project's issue tracker — no interview, just a synthesis of what has already been discussed."
|
|
4
4
|
tags: ["spec", "prd", "issue-tracker"]
|
|
5
|
-
disable-model-invocation: true
|
|
6
5
|
profiles: [core, ui, full]
|
|
7
6
|
origin: damiangil
|
|
8
7
|
---
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: to-tickets
|
|
3
3
|
description: "Breaks down a plan, a spec, or the current conversation into a set of \\"tracer bullet\\" tickets (vertical slices), each declaring which tickets block it, and publishes them to the configured tracker — as local files (one per ticket) or as issues with native blocking links in a real tracker."
|
|
4
4
|
tags: ["tickets", "planning", "issue-tracker"]
|
|
5
|
-
disable-model-invocation: true
|
|
6
5
|
profiles: [core, ui, full]
|
|
7
6
|
origin: damiangil
|
|
8
7
|
---
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: wayfinder
|
|
3
3
|
description: "Plans a huge chunk of work — more than fits in a single agent session — as a shared map of decision tickets in the repo's issue tracker, and resolves them one at a time until the path to the destination is clear."
|
|
4
4
|
tags: ["planning", "issue-tracker", "large-scale-work"]
|
|
5
|
-
disable-model-invocation: true
|
|
6
5
|
profiles: [core, ui, full]
|
|
7
6
|
origin: damiangil
|
|
8
7
|
---
|
package/targets/_md-block.js
CHANGED
|
@@ -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,
|
|
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, pick the chain by size and chain each step yourself. Small (one sitting, one ticket): clarify with \`superpowers:brainstorming\` (idea still vague) or \`grill-with-docs\` (a plan to harden), then build with \`implement\`. Big: \`grill-with-docs\` or \`wayfinder\` -> \`to-spec\` -> \`to-tickets\` -> \`implement-spec\`. Hard-to-reverse decisions go to \`write-adr\`; review with \`code-review\` and write the PR with \`pr\` 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`
|
|
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/claude.js
CHANGED
|
@@ -9,6 +9,15 @@ const HERE = dirname(fileURLToPath(import.meta.url));
|
|
|
9
9
|
// so a `Bash`-only matcher let `git push --force` or a commit without gitmoji through unasked.
|
|
10
10
|
const SHELL_TOOLS = 'Bash|PowerShell';
|
|
11
11
|
|
|
12
|
+
// Mods de la terminal de Claude Code que el harness deja activados en cada proyecto.
|
|
13
|
+
// `cache-tax` mantiene caliente la caché del prompt en las pausas, y eso gasta tokens.
|
|
14
|
+
export const CLAUDE_CODE_MODS = Object.freeze([
|
|
15
|
+
{ id: 'skins@hellosverre-mods', marketplace: 'hellosverre-mods', repo: 'hellosverre/claude-skins' },
|
|
16
|
+
{ id: 'savvy-progress@claude-kit', marketplace: 'claude-kit', repo: 'johnnyvizz/claude-kit' },
|
|
17
|
+
{ id: 'filetree@claude-code-filetree', marketplace: 'claude-code-filetree', repo: 'data-goblin/claude-code-filetree' },
|
|
18
|
+
{ id: 'cache-tax@claude-code-mods', marketplace: 'claude-code-mods', repo: 'karanb192/claude-code-mods' },
|
|
19
|
+
]);
|
|
20
|
+
|
|
12
21
|
export function writeSkill(id, fromDir, toPath) {
|
|
13
22
|
// Migrate away from the legacy nested layout (.claude/skills/rsc/<id>) that
|
|
14
23
|
// Claude Code never discovered — it only reads .claude/skills/<name>/SKILL.md.
|
|
@@ -166,7 +175,8 @@ export function wireHook(paths, sourceMd, policy = {}) {
|
|
|
166
175
|
|
|
167
176
|
if (policy.codeHooks !== false) {
|
|
168
177
|
// Ship guard: a PreToolUse(Bash) hook that DENIES switching to / merging the trunk
|
|
169
|
-
// while the current feature branch has
|
|
178
|
+
// while the current feature branch has unpushed commits (uncommitted changes only get a
|
|
179
|
+
// worktree hint: they may be the user's own) — forcing the
|
|
170
180
|
// commit → push → PR close (the `ship` skill). Materialized + node-run (Windows-safe),
|
|
171
181
|
// registered idempotently, fail-open, opt-out via .rsc/.no-ship-guard. Other
|
|
172
182
|
// (non-rsc) PreToolUse hooks are preserved.
|
|
@@ -235,6 +245,16 @@ export function wireHook(paths, sourceMd, policy = {}) {
|
|
|
235
245
|
for (const id of policy.plugins) settings.enabledPlugins[id] = true;
|
|
236
246
|
}
|
|
237
247
|
|
|
248
|
+
// Los mods de Claude Code van en cada install y update, se use el flujo o no. Con el marketplace
|
|
249
|
+
// en `extraKnownMarketplaces`, Claude Code ofrece instalarlos al abrir el proyecto. Un `false`
|
|
250
|
+
// que alguien puso a mano es una decisión suya y se respeta.
|
|
251
|
+
settings.extraKnownMarketplaces ||= {};
|
|
252
|
+
settings.enabledPlugins ||= {};
|
|
253
|
+
for (const { id, marketplace, repo } of CLAUDE_CODE_MODS) {
|
|
254
|
+
settings.extraKnownMarketplaces[marketplace] ||= { source: { source: 'github', repo } };
|
|
255
|
+
if (settings.enabledPlugins[id] !== false) settings.enabledPlugins[id] = true;
|
|
256
|
+
}
|
|
257
|
+
|
|
238
258
|
// Danger guard: its own decision, not part of the code-hook block above (#273). `init` promises it
|
|
239
259
|
// to non-technical and mixed users whatever the project is, and a plan that predates the field is
|
|
240
260
|
// read as "yes": a non-technical operations install gets the guard it was missing on its next sync,
|