@trycore/spec-build-harness 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/GOVERNANCE.md +26 -3
  3. package/METODOLOGIA.md +22 -3
  4. package/VERSION +1 -1
  5. package/agents/build/api-contract-tester.md +8 -0
  6. package/agents/build/build-orchestrator.md +8 -2
  7. package/agents/build/change-epic-coherence.md +11 -2
  8. package/agents/build/coherence-three-way.md +12 -4
  9. package/agents/build/data-consistency-checker.md +7 -0
  10. package/agents/build/security-reviewer.md +11 -3
  11. package/agents/build/simple-design-reviewer.md +4 -3
  12. package/agents/build/stack-guardian.md +12 -4
  13. package/agents/build/ux-krug-reviewer.md +12 -3
  14. package/agents/build/wiring-adversarial-verifier.md +14 -7
  15. package/commands/build/onboard.md +18 -1
  16. package/commands/build/reflect.md +32 -8
  17. package/commands/build/release.md +84 -0
  18. package/commands/build/slice.md +93 -0
  19. package/commands/build/work.md +68 -0
  20. package/docs/super-power-workflows.md +281 -0
  21. package/hooks/build/build-gate-check.sh +3 -1
  22. package/hooks/build/load-build-state.sh +27 -5
  23. package/hooks/build/release-gate-nudge.sh +40 -0
  24. package/hooks/build/stack-guard.sh +30 -8
  25. package/hooks/build-harness.json +4 -0
  26. package/package.json +1 -1
  27. package/scripts/check-agnostic.sh +1 -1
  28. package/skills/building-a-slice/SKILL.md +21 -0
  29. package/skills/building-a-slice/references/dod.md +3 -1
  30. package/skills/building-a-slice/references/exploration-fanout.md +36 -0
  31. package/skills/building-a-slice/references/state-protocol.md +5 -0
  32. package/skills/building-a-slice/workflows/README.md +25 -0
  33. package/skills/building-a-slice/workflows/explore-fanout.workflow.js +77 -0
  34. package/skills/building-a-slice/workflows/wiring-verify.workflow.js +88 -0
  35. package/skills/releasing-a-version/SKILL.md +21 -0
  36. package/skills/releasing-a-version/references/release-dod.md +2 -1
  37. package/skills/releasing-a-version/workflows/README.md +19 -0
  38. package/skills/releasing-a-version/workflows/release-gate.workflow.js +104 -0
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: "BUILD: Slice"
3
+ description: Punto de entrada del inner loop. Abre o continúa un slice (épica EP-XXX) y conduce el pipeline DoR → change → TDD → smoke → api/data → dod → PR+archive delegando en la skill building-a-slice (o el agente build-orchestrator para épicas multicapa). Respeta el orden estricto de gates y el scaffold como precondición.
4
+ category: Workflow
5
+ tags: [build-harness, inner-loop, slice, trycore]
6
+ ---
7
+
8
+ Lanza el **inner loop** de construcción sobre una épica. Este comando es un **adaptador delgado**: no
9
+ reimplementa el pipeline — **delega** en la skill `building-a-slice` (motor del inner loop) y en `opsx:*`
10
+ (motor de changes). Si algo aquí contradice `METODOLOGIA.md`, **gana la metodología**.
11
+
12
+ **Entrada:** `EP-XXX` o una descripción de la épica. Si viene vacío, usa **AskUserQuestion** para elegir la
13
+ épica desde `docs/03-backlog/epicas.md`.
14
+
15
+ ---
16
+
17
+ ## 1. Preflight
18
+
19
+ ```bash
20
+ test -f .claude/.build-harness-version || echo "NOT_INSTALLED"
21
+ command -v python3 >/dev/null 2>&1 || echo "NO_PYTHON3"
22
+ ```
23
+
24
+ **Si `NOT_INSTALLED`:** este proyecto no tiene el arnés instalado → ejecuta `trycore-build init` y vuelve.
25
+ Stop si no está instalado o falta `python3`.
26
+
27
+ ---
28
+
29
+ ## 2. Leer el estado y decidir punto de entrada
30
+
31
+ ```bash
32
+ python3 - <<'PY'
33
+ import json, os, sys
34
+ p = ".claude/state/build-state.json"
35
+ if not os.path.exists(p): print("NO_STATE"); sys.exit(0)
36
+ try: d = json.load(open(p))
37
+ except Exception as e: print("CORRUPT_STATE", e); sys.exit(0)
38
+ s = d.get("active_slice")
39
+ if not s:
40
+ print("START dor")
41
+ else:
42
+ g = s.get("gates", {})
43
+ abierto = next((k for k, v in g.items() if v is False), None)
44
+ print(f"RESUME {s.get('epica')} fase={s.get('phase')} primer_gate_abierto={abierto}")
45
+ PY
46
+ ```
47
+
48
+ - `NO_STATE`/`CORRUPT_STATE` → reporta y detente (no escribas).
49
+ - `START dor` → no hay slice activo: arranca en **dor** con la épica objetivo.
50
+ - `RESUME …` → ya hay un slice activo: **reanuda en su primer gate abierto** (no abras otro: el modelo es
51
+ secuencial, un solo slice activo).
52
+
53
+ ---
54
+
55
+ ## 3. Precondición de scaffold (y fuente de diseño si hay UI)
56
+
57
+ Antes de escribir código de slice, verifica los gates de proyecto:
58
+
59
+ - `scaffold.confirmed` debe ser `true`. Si es `false` → **STOP**: delega en la **Fase 0** de `building-a-slice`
60
+ (pregunta explícita; el arnés **no genera** el scaffold). No abras el slice.
61
+ - Si el proyecto tiene UI, `design_source.confirmed` debe ser `true` (Fase 0-bis). Si no → **STOP** igual.
62
+
63
+ El hook `scaffold-guard.sh` respalda esto en tiempo real.
64
+
65
+ ---
66
+
67
+ ## 4. Conducir el pipeline (delegar)
68
+
69
+ Invoca la skill **`building-a-slice`** para conducir el inner loop. Para una épica **multicapa / grande**
70
+ (superó el gate de tamaño → `sub_slices[]`), invoca el agente **`build-orchestrator`** (trabaja por fases
71
+ encadenadas y, opcionalmente, conduce la exploración solo-lectura con `workflows/explore-fanout.workflow.js`).
72
+
73
+ - **No** ejecutes `opsx:apply` directamente ni saltes gates: el orden es estricto
74
+ (`dor → change → tdd → smoke → api/data → dod → pr`).
75
+ - **No** dispares reviewers pesados aquí (`security`, `smell`, `ux`, `coherence`, `stack_arch`): pertenecen
76
+ al **Release Gate** (`/build:release`). Hacerlo por slice rompería el modelo de dos loops.
77
+
78
+ ---
79
+
80
+ ## 5. Resumen
81
+
82
+ Al terminar el paso, resume: fase actual, gates cerrados/abiertos y el siguiente gate. Si la épica quedó
83
+ archivada, recuerda el default del Release Gate (ver `/build:release`).
84
+
85
+ ---
86
+
87
+ ## Guardrails
88
+
89
+ - **Un solo slice activo** (secuencial). No abras un segundo mientras haya `active_slice`.
90
+ - **Orden estricto de gates**; un gate no se salta. `dod` exige `wiring_verified: true`.
91
+ - **Sin scaffold confirmado, no hay slice** (el arnés lo exige pero no lo genera).
92
+ - **Agnóstico**: este comando no asume dominio; lo específico entra por `/build:onboard` y `stack-allowlist.json`.
93
+ - Si algo contradice `METODOLOGIA.md`, **gana la metodología**.
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: "BUILD: Work"
3
+ description: Router de entrada (classify-and-act) del arnés. Clasifica el trabajo entrante y enruta a la skill correcta — building-a-micro-change (mantenimiento), building-a-slice (épica/producto nuevo) o releasing-a-version (Release Gate) — codificando los límites duros del micro-change y el default del Release Gate. Es RUTEO, no política: no ejecuta el pipeline, no toca el estado ni crea ramas.
4
+ category: Workflow
5
+ tags: [build-harness, router, classify-and-act, trycore]
6
+ ---
7
+
8
+ **Router puro.** Decide *qué carril* aplica y **delega** en la skill correspondiente. NO ejecuta el pipeline,
9
+ NO escribe `build-state.json`, NO crea ramas. Codifica como **ruteo** (no política nueva) el *decision gate*
10
+ del micro-change y el default del Release Gate de `METODOLOGIA.md` (§2, §4). Si algo contradice la metodología,
11
+ **gana la metodología**.
12
+
13
+ **Entrada:** una descripción del trabajo a hacer.
14
+
15
+ ---
16
+
17
+ ## 1. Preflight
18
+
19
+ ```bash
20
+ test -f .claude/.build-harness-version || echo "NOT_INSTALLED"
21
+ ```
22
+
23
+ Si `NOT_INSTALLED` → ejecuta `trycore-build init` y vuelve.
24
+
25
+ ---
26
+
27
+ ## 2. Clasificar (decision gate)
28
+
29
+ Aplica las reglas en orden:
30
+
31
+ 1. **¿Mantenimiento sin capacidad nueva?** — typo, ajuste de copy/config/docs, bump de dependencia **ya
32
+ permitida**, o fix de **pocas líneas** sin nueva capacidad **Y** sin ninguno de los límites duros del
33
+ paso 3 → carril **`building-a-micro-change`** (`fix/*`|`chore/*` → PR, **sin** abrir `active_slice`).
34
+ 2. **¿Producto nuevo / una épica?** — capacidad nueva, o cualquier límite duro cruzado → carril
35
+ **`building-a-slice`** (una épica `EP-XXX` = un slice = un change = una rama = un PR). Si no hay épica aún,
36
+ el trabajo vuelve a discovery para crearla.
37
+ 3. **¿Toca correr el Release Gate?** — la épica recién archivada **cierra una línea de release** del Story Map,
38
+ o hay **≥ 2 épicas archivadas** desde el último entry de `releases[]` → sugiere el carril
39
+ **`releasing-a-version`** (outer loop). (El destino es la skill existente; este router no depende de
40
+ `/build:release`.)
41
+
42
+ ---
43
+
44
+ ## 3. Límites duros del micro-change (escalan a épica)
45
+
46
+ Si el cambio **añade una dependencia nueva**, **crea un endpoint/API nuevo**, o **toca lógica de dominio o el
47
+ modelo/invariantes de datos** → **deja de ser micro-change** y se enruta a **`building-a-slice`** (épica).
48
+ **Ante la duda, SIEMPRE épica.**
49
+
50
+ ---
51
+
52
+ ## 4. Actuar (delegar) — con degradación headless
53
+
54
+ - **Con TTY**: confirma la clasificación con **una sola** `AskUserQuestion` (ofrece el carril propuesto como
55
+ primera opción "(Recomendado)") y luego invoca la skill elegida.
56
+ - **Sin TTY / headless / entrada ausente**: **no bloquees**. Clasifica determinísticamente y emite por stdout
57
+ `{clasificación, skill recomendada, criterio que disparó la rama}`. Si es **ambiguo**, aplica el **default
58
+ duro**: escalar a épica → `building-a-slice`, declarándolo explícitamente.
59
+
60
+ ---
61
+
62
+ ## Guardrails
63
+
64
+ - **Solo ruteo.** No corres el pipeline, no tocas el estado, no creas ramas: eso es de las skills destino.
65
+ - **Ante la duda, épica.** Nunca degrades un cambio con límite duro a micro-change.
66
+ - **No dupliques gates** ni saltes el orden: las skills destino los gobiernan.
67
+ - **Agnóstico**: vocabulario genérico del arnés; lo específico del dominio entra por `/build:onboard`.
68
+ - Si algo contradice `METODOLOGIA.md`, **gana la metodología**.
@@ -0,0 +1,281 @@
1
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6903d22e13864f88ea55c2d8_b5c98d26c46edc43193e7f7e28a00633a538bb9c-1000x1000.svg)
2
+
3
+ #
4
+
5
+ A
6
+
7
+ harness
8
+
9
+ for
10
+
11
+ every
12
+
13
+ task:
14
+
15
+ dynamic
16
+
17
+ workflows
18
+
19
+ in
20
+
21
+ Claude
22
+
23
+ Code
24
+
25
+ Claude Code can now write and orchestrate its own multi-agent harness on the fly. Here's how dynamic workflows work, and the patterns that get the most out of them.
26
+
27
+
28
+
29
+ [](#)
30
+
31
+ [](#)
32
+
33
+ Get Claude Code
34
+
35
+ curl -fsSL https://claude.ai/install.sh | bash
36
+
37
+ Copy command to clipboard
38
+
39
+ irm https://claude.ai/install.ps1 | iex
40
+
41
+ Copy command to clipboard
42
+
43
+ Or read the [documentation](https://code.claude.com/docs/en/overview)
44
+
45
+ Try Claude Code
46
+
47
+ [Try Claude Code](https://claude.ai/redirect/claudedotcom.v1.e9ed21ea-4023-46bb-ad88-1ac576336b09/code)Try Claude Code
48
+
49
+ Developer docs
50
+
51
+ [Developer docs](https://code.claude.com/docs/en/overview)Developer docs
52
+
53
+ * Category
54
+
55
+ [Claude Code](https://claude.com/blog/category/claude-code)
56
+
57
+ * Product
58
+
59
+ No items found.
60
+
61
+ * Date
62
+
63
+ June 2, 2026
64
+
65
+ * Reading time
66
+
67
+ 5
68
+
69
+ min
70
+
71
+ * Share
72
+
73
+ [Copy link](#)
74
+
75
+
76
+ Last week, we released [dynamic workflows](https://code.claude.com/docs/en/workflows) in Claude Code. Claude can now write its own  [harness](https://code.claude.com/docs/en/glossary#agentic-harness) on the fly, custom-built for the task at hand.
77
+
78
+ While the default Claude Code harness is built for coding, it is also useful for many other types of tasks because, as it turns out, many tasks resemble coding tasks. But there are certain classes of tasks where we have had to build custom harnesses on top of Claude Code to achieve peak performance such as [Research](https://support.claude.com/en/articles/11088861-using-research-on-claude), [security analysis](https://support.claude.com/en/articles/11932705-automated-security-reviews-in-claude-code), [agent teams](https://code.claude.com/docs/en/agent-teams), or [Code Review](https://code.claude.com/docs/en/code-review).
79
+
80
+ Workflows allow you to dynamically create harnesses built on top of Claude Code that enable Claude to solve all of those problems more natively. You can also share and reuse these workflows with others.
81
+
82
+ In this article, I’ll cover my initial workflows experiences and learnings so you can best take full advantage. Keep in mind, best practices are still developing: dynamic workflows often use more tokens and are best suited for complex, high value tasks.
83
+
84
+ ## Example prompts
85
+
86
+ Before diving into the technical details, I’d like to start with several example prompts to get you thinking about the possibilities with workflows:
87
+
88
+ "This test fails maybe 1 in 50 runs. Set up a workflow to reproduce it. Form competing theories about the race, and don't stop until one theory survives the evidence." 
89
+
90
+ "Using a workflow, go through my last 50 sessions and mine them for corrections I keep making and turn the recurring ones into `CLAUDE.md` rules"
91
+
92
+ “Use a workflow to dig through #incidents in Slack for the past six months and find recurring root causes where nobody has filed a ticket." 
93
+
94
+ "Take my business plan and run a workflow where different agents tear it apart from an investor's, a customer's, and a competitor's perspective." 
95
+
96
+ "Here's a folder of 80 resumes, use a workflow to rank them for the backend role and double-check the top ten. Interview me using the AskUserQuestion tool for a rubric."
97
+
98
+ "I need a name for this CLI tool. Use a workflow to brainstorm a bunch of options and run a tournament to pick the top 3." 
99
+
100
+ "Use a workflow to rename our User model to Account everywhere." 
101
+
102
+ “Go through my blog post draft and verify every technical claim against the codebase using a workflow, I don't want to ship anything wrong."
103
+
104
+ ## How dynamic workflows work
105
+
106
+ Dynamic workflows execute a javascript file with a few special functions that help spawn and coordinate [subagents](https://code.claude.com/docs/en/sub-agents):
107
+
108
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f1684f559cc83ff4b465b_image1.png)
109
+
110
+ Dynamic workflows also include standard JavaScript functions like JSON, Math, and Array, to help process data.
111
+
112
+ It’s particularly useful to know that dynamic workflows can decide which models an agent uses and whether subagents are run in their own worktree, allowing Claude to choose the intelligence level and isolation needed.
113
+
114
+ If a workflow is interrupted, for example by user action or quitting the terminal, resuming the session will allow the workflow to pick up where it left off.
115
+
116
+ ## Why dynamic workflows 
117
+
118
+ When you ask the default Claude Code harness to do a task, it needs to both plan and execute in the same context window. For many coding tasks, this is highly effective, but it can break down over long-running, massively parallel, highly structured and/or adversarial tasks.
119
+
120
+ This is because the longer Claude works on a complex task in a single context window, the more it becomes susceptible to a few specific failure modes:
121
+
122
+ * **Agentic laziness** refers to when Claude stops before finishing a particularly complex, multi-part task and declares the job done after partial progress, for example addressing 35 of the 50 items in a security review.
123
+ * **Self-preferential bias** refers to Claude’s tendency to prefer its own results or findings, especially when asked to verify or judge them against a rubric. 
124
+ * **Goal drift** refers to the gradual loss of fidelity to the original objective across many turns, especially after compaction. Each summarization step is lossy, and details like edge-case requirements or "don't do X" constraints can get lost.
125
+
126
+ Creating a workflow helps combat these by orchestrating separate Claude subagents with their own context windows and focused, isolated goals.
127
+
128
+ ## Dynamic vs static workflows
129
+
130
+ You may have previously created a static workflow using the Claude Agent SDK or `claude -p` to coordinate multiple instances of Claude Code together. 
131
+
132
+ But because static workflows need to work for all edge cases, they are usually more generic. With [Claude Opus 4.8](https://www.anthropic.com/news/claude-opus-4-8) and dynamic workflows, Claude is now intelligent enough to write a custom harness tailor-made for your use case.
133
+
134
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f3a0e17e2844bed86f22a_image9.png)
135
+
136
+ ## Helpful patterns when using dynamic workflows
137
+
138
+ You can start using dynamic workflows just by asking Claude to make one, or by using the trigger word “`ultracode`” to ensure that Claude Code creates a workflow. 
139
+
140
+ But building a mental model for how dynamic workflows work will help you understand when to use them and how you might nudge Claude via prompts.
141
+
142
+ There are a few common patterns that Claude might use and compose together when building workflows:
143
+
144
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f16d86247e586b929a407_image10.png)
145
+
146
+ ### Classify-and-act
147
+
148
+ Use a classifier agent to decide on the type of task, and then route to different agents or behavior based on the task. Or, use a classifier at the end to determine output.
149
+
150
+ ### Fan-out-and-synthesize
151
+
152
+ Split up a task into many smaller steps, run an agent on each step and then synthesize those results. This is particularly useful for when there are a large number of smaller steps, or when each step benefits from its own clean context window so they don't interfere or cross-contaminate. The synthesize step is a barrier—it waits for all the fan-out agents, then merges their structured outputs into one result.
153
+
154
+ ### Adversarial verification
155
+
156
+ For each spawned agent, run a separate spawned agent to adversarially verify its output against a rubric or criteria. 
157
+
158
+ ### Generate-and-filter
159
+
160
+ Generate a number of ideas on a topic and then filter them by a rubric or by verification, dedupe duplicates and return only the highest quality, tested ideas.
161
+
162
+ ### Tournament
163
+
164
+ Instead of dividing the work, have agents compete on it. Spawn N agents that each attempt the same task using different approaches. Prompts or models then judge the results in a pairwise fashion using a judging agent until you have a winner.
165
+
166
+ ### Loop until done
167
+
168
+ For tasks with an unknown amount of work, loop spawning agents until a stop condition is met (no new findings, or no more errors in the logs) instead of a fixed number of passes.
169
+
170
+ ## Use cases
171
+
172
+ Think creatively of when and how to ask Claude Code to make dynamic workflows. I’ve found that workflows are sometimes even more useful for non-technical work.
173
+
174
+ ### Migrations and refactors 
175
+
176
+ [Bun](https://bun.com/) was rewritten from Zig to Rust using workflows. You can read more about how that was done in [Jarred’s X thread](https://x.com/jarredsumner/status/2060050578026189172). 
177
+
178
+ The key is to break down the task into a series of steps that need to be operated on for example callsites, failing tests, modules, etc. Spin off a subagent for every fix in a worktree to make the fix, then have another agent adversarially review, and merge them. Consider telling the agent not to use resource intensive commands so that you can maximally parallelize without running out of resources on your machine.
179
+
180
+ ### Deep research
181
+
182
+ We published a deep research skill (`/deep-research`) inside Claude Code that uses dynamic workflows. Specifically, it fans-out web searches, fetches sources, adversarially verifies their claims, and synthesizes a cited report.
183
+
184
+ But you may do this sort of research for more than just web searches. For example, asking Claude to compile a status report from context in Slack or to research how a feature works by exploring a codebase in-depth.
185
+
186
+ ### Deep verification
187
+
188
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f1721824a27cf13da87f4_image2.png)
189
+
190
+ On the other hand, if you have a report where you want to check and source every factual claim that it references you may want to generate a workflow which has one agent identify all of the factual claims and then spin off a subagent to check each one in-detail. You could also have a verification agent check the source subagent to make sure its source is high quality. 
191
+
192
+ ### Sorting
193
+
194
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f173ce727a972001584cc_image3.png)
195
+
196
+ You may have a list of items that you want to sort by some qualitative measurement that you believe that Claude Code is good at evaluating, for example: support tickets sorted by severity of the bug. But if you try to sort 1000+ rows in one prompt, quality degrades and it won't fit in context. Instead run a tournament, a pipeline of pairwise-comparison agents (comparative judgment is more reliable than absolute scoring), or bucket-rank in parallel then merge. Each comparison is its own agent, so the deterministic loop holds the bracket and only the running order stays in context.
197
+
198
+ ### Memory and rule adherence
199
+
200
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f17517076bb59050d90bb_image8.png)
201
+
202
+ If you have a particular set of rules that you find Claude misses or struggles with, even when put into the `CLAUDE.mds`, create a workflow with a list of rules that must be checked by verifier agents—one verifier per rule. Creating a skeptic persona subagent to review the rules to make sure they are in line will help avoid too many false positives.
203
+
204
+ The reverse direction works too: mine your recent sessions and code review comments for corrections you keep making, cluster them with parallel agents, adversarially verify each candidate (would this rule have prevented a real mistake?), and then distill the survivors back into a `CLAUDE.md`.
205
+
206
+ ### Root-cause investigation 
207
+
208
+ Debugging works best when you come up with several independent hypotheses and test them, but if you’re only using one context window, Claude can run into self-preferential bias
209
+
210
+ A workflow can structurally prevent this by spinning up agents to generate hypotheses from disjoint evidence. For example, separate agents for logs, files, and data. Each hypothesis can then face a panel of verifiers and refuters.
211
+
212
+ This isn't just for code. Workflows can be used for sales (why did sales drop in March?), data engineering (why did this pipeline fail?), or any post-mortem exercise.
213
+
214
+ ### Triaging at scale
215
+
216
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f1778dc00d34cca70819d_image6.png)
217
+
218
+ Every team has a support queue, bug reports, or some other backlog that cannot be fully processed by humans. 
219
+
220
+ A triage workflow classifies each item, dedupes against what's already tracked, and takes action. This could mean attempting the fix or escalating to a human user.
221
+
222
+ A useful pattern for triage workflows is quarantine. This involves barring the agents that read untrusted public content from taking high-privilege actions, which are instead done by the agents in charge of acting on the information.
223
+
224
+ Pair triage workflows with /loop to have Claude do this continuously.
225
+
226
+ ### Exploration and taste
227
+
228
+ Workflows can be useful when exploring different approaches to a solution, especially when it is taste based, like design or naming, and would benefit from a rubric.
229
+
230
+ Try asking Claude to explore a bunch of solutions, and give a review agent  a rubric for what a good solution looks like. The task is complete when the review agent feels like it has met the criteria. Solutions can also be ordered or selected via a tournament based on the rubric.
231
+
232
+ ### Evals
233
+
234
+ You can run lightweight evals for particular tasks by spinning off separate agents in a worktree and then spinning off comparison agents to compare and grade the specific outputs against a rubric. For example, evaluating and then refining a skill you’ve created against a particular criteria.
235
+
236
+ ### Model and intelligence routing
237
+
238
+ Create a classifier agent tuned to your tasks that decides which model to use. This can be helpful when your task will involve many tool calls and conducting research prior to execution can identify the best model for the job. 
239
+
240
+ For example, the best model for the task “explain how the auth module works” depends on how many files in the auth module there are and the shape of the codebase. A classifier agent can do this research and then route to Sonnet or Opus based on the expected complexity of the task.
241
+
242
+ ## When not to use dynamic workflows
243
+
244
+ Workflows are new. While there are many use cases where it will create outsized results, they are not needed for every task and may end up using significantly more tokens.
245
+
246
+ It’s best to use workflows creatively to push Claude Code in ways that you haven’t previously. For regular coding tasks, try and ask yourself: does it really need more compute? For example, most traditional coding tasks do not need a panel of 5 reviewers.
247
+
248
+ ## Tips for building dynamic workflows
249
+
250
+ ### Prompting
251
+
252
+ Detailed prompting, using the specific techniques we described above, for dynamic workflows creates the best results.
253
+
254
+ Workflows are not just for large tasks. You can prompt the model to use a “quick workflow.” For example, you can create a quick adversarial review of an assumption.
255
+
256
+ ### Combine with `/goal` and `/loop`
257
+
258
+ When using workflows that can be repeated, for example triage, research, or verification, pair them with `/loop` to be run at regular intervals, and /goal to set a hard completion requirement.
259
+
260
+ ### Token usage budgets
261
+
262
+ You can set explicit token usage budgets for dynamic workflows to limit how many tokens a task uses. You can prompt it with a budget like: “use 10k tokens,” which will set the cap.
263
+
264
+ ### Saving and sharing dynamic workflows
265
+
266
+ You can save workflows by pressing “s” in the workflow menu. You can check these into `~/.claude/workflows` or distribute them via a skill. 
267
+
268
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f17b1ca20533e666c867c_image4.png)
269
+
270
+ To share them via a skill, put your JavaScript workflow files in the skill and folder and reference them in the [SKILL.MD](http://skill.md). To allow for more flexibility, you may want to prompt Claude to think of the workflows in the skill as a template instead of a script that needs to be run verbatim.
271
+
272
+ ![](https://cdn.prod.website-files.com/68a44d4040f98a4adf2207b6/6a1f17cb835cf4f9fd5da921_image7.png)
273
+
274
+ ## A new starting point for discovery 
275
+
276
+ Workflows are a helpful new way to extend Claude Code. I encourage you to think of them as a starting point to explore new ways to use Claude to help accomplish your tasks. There is still much to discover in how to use them best. Let me know what you find. 
277
+
278
+
279
+
280
+ *This article was written by Thariq Shihipar and Sid Bidasaria, members of technical staff at Anthropic working on Claude Code.*
281
+
@@ -18,7 +18,9 @@ if not s: sys.exit(0)
18
18
  g=s.get("gates",{})
19
19
  abiertos=[k for k,v in g.items() if v is False]
20
20
  if abiertos:
21
- print(f"build-gate-check: slice {s.get('hu')} en fase '{s.get('phase')}' con gates abiertos: {', '.join(abiertos)}.", file=sys.stderr)
21
+ epica=s.get('epica') or '?'
22
+ hus=', '.join(s.get('hus') or []) or '—'
23
+ print(f"build-gate-check: slice {epica} [{hus}] en fase '{s.get('phase')}' con gates abiertos: {', '.join(abiertos)}.", file=sys.stderr)
22
24
  print(" No archives ni abras PR hasta cerrarlos (ver building-a-slice / dod.md).", file=sys.stderr)
23
25
  PY
24
26
  exit 0
@@ -12,15 +12,37 @@ BRANCH="$(git -C "$ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'descon
12
12
  if [ -f "$ROOT/package.json" ]; then PHASE="active"; else PHASE="authoring"; fi
13
13
 
14
14
  # Sincroniza harness_phase en el estado (si python3 disponible y el archivo existe).
15
+ # Escritura ATÓMICA + validada: este hook corre en CADA SessionStart (alta frecuencia,
16
+ # headless incluido); una escritura no atómica que se interrumpa truncaría la ÚNICA
17
+ # fuente de verdad. Solo escribe si harness_phase cambia; si algo falla, deja el original
18
+ # intacto (fail-open) y nunca rompe el SessionStart.
15
19
  if [ -f "$STATE" ] && command -v python3 >/dev/null 2>&1; then
16
20
  python3 - "$STATE" "$PHASE" <<'PY' 2>/dev/null || true
17
- import json,sys
21
+ import json,sys,os,tempfile
18
22
  path,phase=sys.argv[1],sys.argv[2]
19
23
  try:
20
- d=json.load(open(path))
21
- if d.get("harness_phase")!=phase:
22
- d["harness_phase"]=phase
23
- json.dump(d,open(path,"w"),indent=2,ensure_ascii=False)
24
+ with open(path) as fh:
25
+ d=json.load(fh)
26
+ # No escribir si no hay cambio.
27
+ if d.get("harness_phase")==phase:
28
+ sys.exit(0)
29
+ # Validación mínima de forma antes de tocar disco (no relajamos el schema completo,
30
+ # solo evitamos persistir algo que claramente no es un build-state).
31
+ if not isinstance(d,dict) or not all(k in d for k in ("version","harness_phase","active_slice","history","releases")):
32
+ sys.exit(0)
33
+ d["harness_phase"]=phase
34
+ dirn=os.path.dirname(path) or "."
35
+ fd,tmp=tempfile.mkstemp(dir=dirn,prefix=".build-state.",suffix=".tmp")
36
+ try:
37
+ with os.fdopen(fd,"w") as out:
38
+ json.dump(d,out,indent=2,ensure_ascii=False)
39
+ out.flush()
40
+ os.fsync(out.fileno())
41
+ os.replace(tmp,path) # sustitución atómica
42
+ except Exception:
43
+ try: os.unlink(tmp)
44
+ except OSError: pass
45
+ raise
24
46
  except Exception:
25
47
  pass
26
48
  PY
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+ # release-gate-nudge.sh — Stop
3
+ # Sugiere correr el Release Gate (releasing-a-version) cuando hay ≥2 épicas archivadas sin
4
+ # auditar desde el último release. NUNCA bloquea el cierre, NUNCA ejecuta trabajo pesado,
5
+ # NUNCA llama al modelo ni escribe estado. Determinista y barato: aritmética de conjuntos
6
+ # sobre epicas[] (archivadas − cubiertas), independiente de timestamps.
7
+ # El criterio "cierra una línea de release" vive en docs/02-user-story-map/ y NO se intenta aquí
8
+ # (lo computa la skill building-a-slice en la fase 8).
9
+ set -uo pipefail
10
+
11
+ ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "${CLAUDE_PROJECT_DIR:-$(pwd)}")"
12
+ STATE="$ROOT/.claude/state/build-state.json"
13
+ [ -f "$STATE" ] || exit 0
14
+ command -v python3 >/dev/null 2>&1 || exit 0 # fail-open: jamás impide cerrar sesión
15
+
16
+ # Mensaje a STDOUT (no stderr): un Stop hook con exit 0 no bloquea el cierre; el 2>/dev/null
17
+ # suprime SOLO trazas de python, nunca el nudge.
18
+ python3 - "$STATE" <<'PY' 2>/dev/null || true
19
+ import json, sys
20
+ try:
21
+ d = json.load(open(sys.argv[1]))
22
+ except Exception:
23
+ sys.exit(0)
24
+ hist = d.get("history") or []
25
+ rels = d.get("releases") or []
26
+ # Épicas ya archivadas (slices cerrados).
27
+ archived = {h.get("epica") for h in hist if isinstance(h, dict) and isinstance(h.get("epica"), str)}
28
+ # Épicas ya cubiertas por ALGÚN release (pending/passed/failed por igual).
29
+ covered = set()
30
+ for r in rels:
31
+ if isinstance(r, dict):
32
+ for e in (r.get("epicas") or []):
33
+ if isinstance(e, str):
34
+ covered.add(e)
35
+ pend = sorted(archived - covered)
36
+ if len(pend) >= 2:
37
+ print(f"💡 Release Gate sugerido: {len(pend)} épicas archivadas sin auditar desde el último release ({', '.join(pend)}).")
38
+ print(" Ejecuta /build:release (o la skill releasing-a-version): corre los gates pesados UNA vez sobre el diff acumulado.")
39
+ PY
40
+ exit 0
@@ -33,20 +33,42 @@ ti=data.get("tool_input",{})
33
33
  fp=ti.get("file_path") or ti.get("path") or ""
34
34
  if not fp.endswith("package.json"):
35
35
  sys.exit(0)
36
- content=ti.get("content") or ti.get("new_string") or ""
37
- if not content.strip():
36
+ content=ti.get("content")
37
+ new=ti.get("new_string")
38
+ old=ti.get("old_string")
39
+ # Nada que verificar si la edición no aporta texto.
40
+ if not (content and content.strip()) and not (new and new.strip()):
38
41
  sys.exit(0)
39
42
  allow=json.load(open(os.environ["ALLOW"])).get("allow",[])
40
43
  def ok(name):
41
44
  return any(fnmatch.fnmatch(name, pat) for pat in allow)
42
- # Extrae nombres de deps tanto de JSON completo como de fragmentos de edición.
43
- deps=set()
44
- try:
45
- pkg=json.loads(content)
45
+ def extract(pkg):
46
+ deps=set()
46
47
  for sec in ("dependencies","devDependencies","peerDependencies","optionalDependencies"):
47
48
  deps.update((pkg.get(sec) or {}).keys())
48
- except Exception:
49
- for m in re.finditer(r'"((?:@[\w.-]+/)?[\w.-]+)"\s*:\s*"[\^~>=<*\d][^"]*"', content):
49
+ return deps
50
+ # Extracción por clave (version-agnóstica) en tres ramas de prioridad decreciente.
51
+ # Las ramas 1 y 2 parsean el documento COMPLETO, así que capturan specs no-semver
52
+ # (github:, file:, git+https:, npm:alias) que la regex de la rama 3 dejaba pasar.
53
+ deps=set(); extracted=False
54
+ # (1) Write con package.json completo en `content`.
55
+ if content and content.strip():
56
+ try:
57
+ deps=extract(json.loads(content)); extracted=True
58
+ except Exception:
59
+ pass
60
+ # (2) Edit: reconstruir el documento POST-edición leyendo el package.json de disco.
61
+ if not extracted and new is not None:
62
+ try:
63
+ with open(fp) as fh: disk=fh.read()
64
+ post = disk.replace(old, new) if old else (new + disk)
65
+ deps=extract(json.loads(post)); extracted=True
66
+ except Exception:
67
+ pass
68
+ # (3) Fallback (solo si 1 y 2 fallan): regex semver ACTUAL, sin ampliar.
69
+ if not extracted:
70
+ frag = content or new or ""
71
+ for m in re.finditer(r'"((?:@[\w.-]+/)?[\w.-]+)"\s*:\s*"[\^~>=<*\d][^"]*"', frag):
50
72
  deps.add(m.group(1))
51
73
  bad=sorted(d for d in deps if d and not ok(d))
52
74
  if bad:
@@ -65,6 +65,10 @@
65
65
  {
66
66
  "type": "command",
67
67
  "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/reflect-nudge.sh\""
68
+ },
69
+ {
70
+ "type": "command",
71
+ "command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/release-gate-nudge.sh\""
68
72
  }
69
73
  ]
70
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trycore/spec-build-harness",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Arnés agéntico de construcción de Trycore para Claude Code: pipeline de dos loops (slice por épica + release gate) con gates de calidad, estado compartido y OpenSpec. Compañero de @trycore/spec-product-flow. Agnóstico al proyecto.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -59,7 +59,7 @@ TARGETS=(
59
59
  for target in "${TARGETS[@]}"; do
60
60
  [[ -e "$target" ]] || continue
61
61
  hits=$(grep -riEn -- "$PATTERN" "$target" 2>/dev/null \
62
- --include='*.md' --include='*.json' --include='*.sh' \
62
+ --include='*.md' --include='*.json' --include='*.sh' --include='*.js' --include='*.mjs' \
63
63
  --exclude-dir='node_modules' || true)
64
64
  if [[ -n "$hits" ]]; then
65
65
  VIOLATIONS+=("$hits")
@@ -60,6 +60,24 @@ inner loop: **≤ ~20 min por épica** y producto que **camina end-to-end en tod
60
60
  > fix-loop → optimizar) y reparte la exploración **"ancho antes que profundo"** con subagentes
61
61
  > **solo-lectura por área** (frontend/backend/datos); el **cableado** lo hace la sesión, no
62
62
  > subagentes que escriben en paralelo. Trocear acota además el tamaño del `wiring_checklist[]`.
63
+ > Para épicas troceadas, esa exploración solo-lectura **puede** conducirse con la plantilla (opcional)
64
+ > `workflows/explore-fanout.workflow.js` — contrato en `references/exploration-fanout.md`. **No** se usa en
65
+ > épicas atómicas (inflaría el inner loop barato); es read-only (no escribe estado) y el cableado sigue
66
+ > siendo de la sesión.
67
+
68
+ ## Workflows (plantillas, no scripts)
69
+
70
+ Los archivos `*.workflow.js` bajo `workflows/` son **plantillas de referencia** que esta skill **conduce**,
71
+ no scripts a correr verbatim (si contradicen `METODOLOGIA.md`, gana la metodología). Reglas duras:
72
+ - **Opt-in y solo para épicas grandes.** Los workflows del inner loop solo aplican a épicas troceadas por el
73
+ gate de tamaño (`sub_slices[]` no vacío); **nunca** en el camino caliente ≤ ~20 min de una épica atómica.
74
+ - **Read-only sobre el estado.** Ningún workflow escribe `build-state.json`: devuelven un diagnóstico y
75
+ `build-orchestrator` (o el agente dueño del gate) aplica el mapeo respetando el protocolo (una transición =
76
+ una escritura; gates monótonos; **validar contra el schema tras escribir**).
77
+ - **Subagentes de exploración = solo-lectura** (Read/Grep/Glob); el cableado lo hace la sesión.
78
+
79
+ Ver `workflows/README.md`. Hoy: `workflows/explore-fanout.workflow.js` (exploración fan-out) y
80
+ `workflows/wiring-verify.workflow.js` (conducción del verificador adversarial del gate `wiring_verified`).
63
81
 
64
82
  ## Fase 0 · Scaffold (Paso 1 fundamental — precondición restrictiva)
65
83
 
@@ -157,6 +175,9 @@ El usuario siempre puede sobreescribir el default. Si acepta, invoca la skill
157
175
  - **`dod` exige `wiring_verified: true`** (verificación adversarial independiente, contexto virgen).
158
176
  El DoD declarativo del gatekeeper es un **piso, no el arreglo**: reusar el mismo agente como
159
177
  generador y verificador produce auto-confirmación. La generación y la verificación van separadas.
178
+ Opcionalmente, esa verificación se **conduce** con la plantilla read-only
179
+ `workflows/wiring-verify.workflow.js` (envuelve al `wiring-adversarial-verifier`); `build-orchestrator`
180
+ sigue siendo quien **escribe** `gates.wiring_verified` a partir del veredicto que la plantilla devuelve.
160
181
  - **Producto completo, no MVP.** El alcance acordado se construye entero. **Recortar o diferir es
161
182
  bloqueante explícito** que requiere acuerdo del equipo — nunca una decisión del modelo. No derives
162
183
  en lo complejo. La verificación es **ejecutada, no por inspección** (ver `METODOLOGIA.md` y el