Skip to content

Commit e6d76c8

Browse files
authored
feat(skills): small-model hardening — context budgets, handoff schema, spec-lint, interview rubric, isolated reviews (#105)
## What One coordinated hardening pass so the workflow skills run reliably on **small/cheap executor models** (modest context windows, no prompt caching). Six improvements, minimal diffs, all extending existing in-repo mechanisms: 1. **Explicit context budgets** — `execute-phase` 2.7.0 (≤ 10 full-file reads per phase beyond the unit's own docs; targeted ≤ 50-line reads and greps free; fixed Step 0 minimum set; summarize-don't-hold), `review-implementation` 1.3.0 (diff + ≤ 10 context files, findings reduced to table rows immediately), and a per-pass budget in `review-change` 2.6.0. 2. **Fresh context per phase + file-based handoff** — `progress.md` gets a fixed per-phase entry schema (`Done / Remains / Gotchas / Files / Next`), created beside the SPEC on P1 for phased XS/S and `--fix` units; the same-session re-read shortcut is removed (one phase = one fresh conversation). `plan-feature-scaffold` 1.11.0 documents the file accordingly. 3. **Structural vagueness detection** — `design-feature` 2.2.0: one question per turn (never batched), a fixed six-slot vagueness rubric (affected users/roles · error & edge states · data shape · boundaries & limits · out of scope · success criteria), the mandatory-question rule (no requirement without a verifiable AC), the reframe-as-measurable technique, a new `### Deferred decisions` SPEC section, and structural escalation (≥ 3 empty slots → `NEEDS_INPUT`). `plan-feature-from-issue` 1.5.0 mirrors the rubric and gains a fixed ≥ 3-slot hand-off threshold to `design-feature`. 4. **Deterministic gates on artifacts** — new **Spec-lint** (modeled on the Phase-lint: presence checks only, fail-closed) in both SPEC templates; run by `design-feature` (product boxes, before stamping `designed`), `plan-feature-scaffold` (all boxes, before its report), and `plan-fix` 2.4.0 (fix-template boxes, before the draft commit). 5. **Reviews isolated per axis, tables only** — `review-change` 2.6.0: new default *Isolation rule* (subagent / headless / fresh-conversation tiers, same as `--adversarial`); each pass receives only scope + its checklist + named docs and returns only its fixed table + PASS|FAIL; the orchestrator holds tables, never sources; in-turn composition stays as the documented inline fallback. 6. **Other strong-model-judgment steps fixed** — structural per-criterion SPEC-drift table in `review-change`; fixed numeric cheap-fix bound (≤ ~15 lines, ≤ 2 files, no public API/schema change) in `review-implementation`; dev-scenario failure-mode seed categories in the feature SPEC template; README (EN+ES) guidance for running the whole flow on a homogeneous small-model fleet. ## Why The skills are executed day to day by small models (Qwen3.6, DeepSeek-V4-Flash, MiMo-2.5 class) with modest context and no caching. Steps that assumed strong-model judgment (open-ended discovery reads, batched interviews, in-turn review composition, "a few lines" heuristics) degrade there; this pass converts them to caps, fixed schemas, and presence gates. ## Evidence - `npx skills add . --list` discovers all skills (run, output clean). - `bump-skill` authoring lints on the 7 changed skills: `→ Next:` / `## Portability` / `## Turn contract` present; no `S1`/"Step N" phase labels (only the standard "Step 0" section names). - Versions bumped + CHANGELOG.md / CHANGELOG.es.md rows + release-log entries; README.md / README.es.md updated in the same change (bilingual-sync rule honored). ## Pending - `docs/workflow/GOLDEN_FIXTURE.md` smoke test with the weakest fleet model (manual procedure) — recommended before merge for the `execute-phase` / `plan-feature-scaffold` / `design-feature` / `review-*` wording changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
2 parents 7929d53 + f3445d6 commit e6d76c8

19 files changed

Lines changed: 431 additions & 90 deletions

File tree

CHANGELOG.es.md

Lines changed: 26 additions & 0 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Large diffs are not rendered by default.

README.es.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,30 @@ se mueve rápido; contrástalo con un leaderboard actual antes de fijar nada):
286286
**Gemma 3 27B**, **Phi-4-mini** — corren en local, suficientes para trabajo
287287
tipo grep.
288288

289+
### Ejecutar todo el flujo con una flota de modelos pequeños/baratos
290+
291+
Los skills están endurecidos para modelos ejecutores pequeños (ventanas de
292+
contexto modestas, sin caché de prompt): checklists fijas en lugar de juicio,
293+
las puertas de presencia Phase-lint y Spec-lint, un esquema fijo de handoff en
294+
`progress.md` con conversación nueva por fase, presupuestos de contexto por
295+
fase/pasada, y revisiones aisladas por eje que devuelven solo tablas de
296+
hallazgos. En una flota sin ningún modelo de clase frontier:
297+
298+
- **Ejecución** (`execute-phase`, `log-session`, mantenimiento de docs) está
299+
diseñada para el tier más barato — una fase por conversación, handoff vía
300+
`progress.md`, máximo 10 lecturas de fichero completo por fase.
301+
- **Planificación, revisión y auditoría** (`design-feature`, `plan-feature`,
302+
`plan-fix`, `review-change`, `audit-pr`, `product-audit`) siguen usando el
303+
**modelo más fuerte que tengas**, aunque no sea frontier — y nunca uno más
304+
débil que el que escribió el cambio.
305+
- **Revisiones**: mantén el aislamiento por eje por defecto (cada pasada un
306+
contexto nuevo, retorno solo-tabla) y prefiere `--adversarial 2` en cambios
307+
`L` o sensibles — N revisores baratos y descorrelacionados recuperan parte
308+
de lo que un único revisor pequeño no ve.
309+
- **Divide más.** La regla de división obligatoria (≤ ~5 fases, una capa por
310+
fase) es la palanca principal: fases más pequeñas son lo que hace fiable la
311+
ejecución barata. Ante la duda, corta más pequeño.
312+
289313
#### <img src="docs/assets/nan-cloud.svg" alt="Logo de NaN Cloud" width="20" height="19"> Ejecutar sobre [NaN.builders](https://cloud.nan.builders/r/7GK06FX8)
290314

291315
[NaN Cloud](https://cloud.nan.builders/r/7GK06FX8) sirve la frontera open-weight

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,30 @@ fast; sanity-check against a current leaderboard before pinning):
277277
- **Small & cheap** (⇔ Haiku): **Qwen3 4–14B**, **Mistral Small 3.1**,
278278
**Gemma 3 27B**, **Phi-4-mini** — local-friendly, fine for grep-shaped work.
279279

280+
### Running the whole flow on a small/cheap fleet
281+
282+
The skills are hardened for small executor models (modest context windows, no
283+
prompt caching): fixed checklists instead of judgment calls, the Phase-lint
284+
and Spec-lint presence gates, a fixed `progress.md` handoff schema with a
285+
fresh conversation per phase, per-phase/per-pass context budgets, and reviews
286+
isolated per axis returning findings tables only. On a fleet with no
287+
frontier-class model at all:
288+
289+
- **Execution** (`execute-phase`, `log-session`, doc bookkeeping) is designed
290+
for the cheapest tier — one phase per conversation, handoff via
291+
`progress.md`, at most 10 full-file reads per phase.
292+
- **Planning, review, and audit** (`design-feature`, `plan-feature`,
293+
`plan-fix`, `review-change`, `audit-pr`, `product-audit`) still get the
294+
**strongest model you have**, even if that model isn't frontier-class —
295+
and never one weaker than the model that wrote the change.
296+
- **Reviews**: keep the per-axis isolation default (each pass a fresh
297+
context, table-only return) and prefer `--adversarial 2` on `L` or
298+
sensitive changes — N cheap, decorrelated reviewers recover part of what a
299+
single small reviewer misses.
300+
- **Split more.** The mandatory-split rule (≤ ~5 phases, one layer per
301+
phase) is the main lever: smaller phases are what make cheap execution
302+
reliable. When in doubt, cut smaller.
303+
280304
#### <img src="docs/assets/nan-cloud.svg" alt="NaN Cloud logo" width="20" height="19"> Running on [NaN.builders](https://cloud.nan.builders/r/7GK06FX8)
281305

282306
[NaN Cloud](https://cloud.nan.builders/r/7GK06FX8) serves the open-weight

docs/features/_TEMPLATE/SPEC.md

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,52 @@ sweep — that is `product-audit`'s job). n/a if none apply.
115115
Product-definition decisions the project lead must make (or has made) before
116116
implementation starts. Record the chosen option and the rationale.
117117

118+
### Deferred decisions
119+
120+
Decisions deliberately postponed instead of resolved now — the interview's
121+
"we'll decide later" answers land here, never silently dropped. One row per
122+
decision; a deferred decision with no decide-by trigger is not deferred, it
123+
is lost. Write `none` when the section is empty.
124+
125+
| Decision | Why deferred | Decide by (trigger or phase) |
126+
|---|---|---|
127+
128+
### Spec-lint (mechanical — presence checks only)
129+
130+
Structural gate on this SPEC, modeled on the Phase-lint: every box is a
131+
presence check a weak model can verify without judgement — fail-closed, no
132+
quality opinion. Two runners: `design-feature` runs the **product boxes**
133+
before stamping `## Design status: designed`; `plan-feature-scaffold` runs
134+
**all boxes** (product boxes re-run as a regression check) before its
135+
completion report. Any FAIL → fix the SPEC or end `NEEDS_INPUT` — never
136+
stamp `designed` or report the scaffold over a failed box.
137+
138+
Product boxes:
139+
140+
- [ ] No template placeholders left in the product half —
141+
`grep -nE '<(where|surface|name|reason|list|role)'` over the sections
142+
above returns nothing. The fenced Capability-closure template block is
143+
**replaced** by the instantiated rows when the closure is walked — a
144+
SPEC still containing the generic block fails this box.
145+
- [ ] `#### Out of scope / non-goals` has ≥ 1 concrete bullet — never empty.
146+
- [ ] Every Capability closure row is filled or `n/a: <reason>` — zero blank
147+
rows.
148+
- [ ] Every `#### In scope` bullet maps to ≥ 1 Acceptance criterion (same
149+
wording or an explicit reference) — an in-scope item with no criterion
150+
FAILs.
151+
- [ ] Every Acceptance criterion is a runnable command OR labelled
152+
`read-verified` — an unlabelled prose criterion FAILs.
153+
- [ ] `### Deferred decisions` exists; every row has a decide-by trigger, or
154+
the section reads `none`.
155+
156+
Engineering boxes (additionally, at scaffold time):
157+
158+
- [ ] `### Dev scenarios` has ≥ 1 failure-mode row, or an explicit
159+
`n/a: <reason>`.
160+
- [ ] Every phase passes the 8-box Phase-lint below (already mandatory).
161+
- [ ] No template placeholders left anywhere in the file (same grep, whole
162+
file).
163+
118164
## Design status
119165

120166
`not designed` — capability closure not yet complete. `design-feature` sets
@@ -164,7 +210,12 @@ prefers integration and architecture tests over heavy mocking.
164210

165211
The situations this feature introduces that must be reproducible in local
166212
dev — happy path **and** failure modes (empty/degraded state, races,
167-
outages, mass changes, data loss). For each, name it and state how it is
213+
outages, mass changes, data loss). Seed the failure modes from this **fixed
214+
category list** — walk every category and write a scenario or
215+
`n/a: <reason>` (unaided recall under-enumerates; the list makes coverage a
216+
presence check): empty/zero state · invalid or oversized input · permission
217+
denied / wrong role · dependency outage or timeout · concurrent/duplicate
218+
action · limit or threshold hit. For each, name it and state how it is
168219
reached through an **existing** mechanism (queued message, guard threshold,
169220
manual override, stubbed source) — scenarios are orchestration, never new
170221
domain. If the project has a runnable dev-scenario harness, register each

docs/fix/_TEMPLATE/SPEC.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,21 @@ own fix folder or feature where each belongs.
4848

4949
## Acceptance
5050

51-
Objective, verifiable conditions for "done".
51+
Objective, verifiable conditions for "done". Each criterion is a runnable
52+
command where possible, or labelled `read-verified` — never unlabelled prose.
53+
54+
### Spec-lint (mechanical — presence checks only)
55+
56+
Run by `plan-fix` before committing the draft; fail-closed, no quality
57+
judgement. Any FAIL → fix the SPEC before the commit.
58+
59+
- [ ] No template placeholders left (`grep -nE '<(topic|n|task|command|expected)'`
60+
over the filled sections returns nothing — the `### P1` scaffold lines
61+
are replaced, not kept).
62+
- [ ] `### Out of scope` has ≥ 1 concrete bullet — never empty.
63+
- [ ] Every `## Acceptance` criterion is a runnable command OR labelled
64+
`read-verified`.
65+
- [ ] Every phase passes the 8-box Phase-lint below (already mandatory).
5266

5367
## Phases
5468

docs/workflow/FEATURE_WORKFLOW.es.md

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,16 @@ listado).
3232

3333
`design-feature <slug>`:
3434

35-
- Incorpora la entrevista de idea-en-bruto (problema y objetivo, alcance
36-
dentro/fuera, pistas de arquitectura, preocupaciones transversales) cuando
37-
se parte de cero.
35+
- Incorpora la entrevista de idea-en-bruto cuando se parte de cero — **una
36+
pregunta por turno, nunca en lote**, cada una con un valor por defecto
37+
recomendado. La lista de preguntas es una **rúbrica de vaguedad** fija de
38+
seis huecos (usuarios/roles afectados · estados de error y borde · forma de
39+
los datos · límites y umbrales · fuera de alcance · criterios de éxito);
40+
todo requisito sin criterio de aceptación verificable es automáticamente la
41+
siguiente pregunta, la redacción vaga se reformula como objetivos medibles,
42+
las respuestas "decidir más tarde" aterrizan en la sección
43+
`### Deferred decisions` del SPEC, y ≥ 3 huecos vacíos terminan el turno en
44+
`NEEDS_INPUT` en lugar de adivinar.
3845
- Ejecuta **investigación proporcional**: primero la checklist de cierre de
3946
capacidades (barata), investigación externa/de dominio solo cuando el
4047
dominio es nuevo para el proyecto — sin investigación de mercado
@@ -61,8 +68,11 @@ listado).
6168
mantiene uniforme, pero pasarla es barato.
6269

6370
Una vez que cada fila de cierre está rellenada o explícitamente marcada
64-
`n/a`, `design-feature` fija `## Design status` en `designed` y entrega el
65-
control a `/plan-feature <slug>`.
71+
`n/a` **y todas las casillas de producto del Spec-lint de la plantilla de SPEC
72+
marcan** (comprobaciones mecánicas de presencia: sin placeholders,
73+
fuera-de-alcance no vacío, cada criterio ejecutable o `read-verified`,
74+
decisiones diferidas presentes), `design-feature` fija `## Design status` en
75+
`designed` y entrega el control a `/plan-feature <slug>`.
6676

6777
### La puerta de redirección
6878

@@ -159,8 +169,11 @@ equivalente, `docs/fix/<n>-<topic>/review-findings.md`.
159169
trabaja sobre `main`). **En P1 primero confirma los artefactos de
160170
planificación por separado** (`docs(NN-slug): planning artifacts`), de
161171
modo que el historial de planificación quede aparte de la implementación.
162-
2. Lee `progress.md` (qué hicieron las fases anteriores), luego `SPEC.md` +
163-
`TASKS.md` de la fase solicitada.
172+
2. Lee `progress.md` (el **registro de handoff de fase** — una entrada fija
173+
`Done / Remains / Gotchas / Files / Next` por fase), luego `SPEC.md` +
174+
`TASKS.md` de la fase solicitada. Ese es todo el handoff — cada fase corre
175+
en una conversación nueva bajo un presupuesto de contexto explícito (≤ 10
176+
lecturas de fichero completo más allá de los docs propios de la unidad).
164177
3. Implementa **solo esa fase****tests primero** en el trabajo de
165178
core/dominio y orquestación: los tests de aceptación/integración de la
166179
fase se escriben en rojo, y luego se implementa hasta verde (los
@@ -170,7 +183,8 @@ equivalente, `docs/fix/<n>-<topic>/review-findings.md`.
170183
build). **Nunca confirma en rojo** — un fallo que no se puede arreglar
171184
dentro del alcance va a `known-issues.md` y la ejecución se detiene con un
172185
informe.
173-
5. Actualiza `TASKS.md`, `progress.md`, `testing.md`, `known-issues.md` (y
186+
5. Actualiza `TASKS.md`, `progress.md` (añadiendo la entrada de handoff de la
187+
fase en el esquema fijo), `testing.md`, `known-issues.md` (y
174188
`decisions.md` si la arquitectura se movió). Cuando la realidad
175189
contradice el plan, se actualizan `TASKS.md`/`PLAN.md` y el porqué se
176190
registra en `decisions.md` — nunca una divergencia silenciosa.

docs/workflow/FEATURE_WORKFLOW.md

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,14 @@ view).
2828

2929
`design-feature <slug>`:
3030

31-
- Folds in the raw-idea interview (problem & goal, scope in/out, architecture
32-
hints, cross-cutting concerns) when starting from zero.
31+
- Folds in the raw-idea interview when starting from zero — **one question per
32+
turn, never batched**, each with a recommended default. The question list is
33+
a fixed six-slot **vagueness rubric** (affected users/roles · error & edge
34+
states · data shape · boundaries & limits · out of scope · success criteria);
35+
any requirement without a verifiable acceptance criterion is automatically
36+
the next question, vague wording is reframed as measurable targets, "decide
37+
later" answers land in the SPEC's `### Deferred decisions` section, and ≥ 3
38+
rubric slots left empty ends the turn `NEEDS_INPUT` instead of guessing.
3339
- Runs **proportional research**: the capability-closure checklist first
3440
(cheap), external/domain research only when the domain is new to the project
3541
— no systematic per-feature market research.
@@ -50,8 +56,11 @@ view).
5056
closure rows resolve to `n/a` — the gate stays uniform, but passing it is
5157
cheap.
5258

53-
Once every closure row is filled or explicitly `n/a`, `design-feature` sets
54-
`## Design status` to `designed` and hands off to `/plan-feature <slug>`.
59+
Once every closure row is filled or explicitly `n/a` **and the SPEC template's
60+
Spec-lint product boxes all tick** (mechanical presence checks: no placeholders,
61+
out-of-scope non-empty, every criterion runnable or `read-verified`, deferred
62+
decisions present), `design-feature` sets `## Design status` to `designed` and
63+
hands off to `/plan-feature <slug>`.
5564

5665
### The redirect gate
5766

@@ -140,16 +149,20 @@ ledger. `execute-phase`'s fold cycle ticks each folded row `folded: yes`;
140149
(it never works on `main`). **On P1 it first commits the planning artifacts
141150
separately** (`docs(NN-slug): planning artifacts`), so planning history
142151
stays apart from implementation.
143-
2. Reads `progress.md` (what prior phases did), then `SPEC.md` + `TASKS.md`
144-
for the requested phase.
152+
2. Reads `progress.md` (the **phase handoff record** — a fixed
153+
`Done / Remains / Gotchas / Files / Next` entry per phase), then `SPEC.md`
154+
+ `TASKS.md` for the requested phase. That is the whole handoff — each
155+
phase runs in a fresh conversation under an explicit context budget (≤ 10
156+
full-file reads beyond the unit's own docs).
145157
3. Implements **only that phase****tests first** on core/domain and
146158
orchestration work: the phase's acceptance/integration tests are written
147159
red, then implemented to green (the SPEC's dev scenarios are the test
148160
list). No bundling, no premature abstraction, no unrelated refactors.
149161
4. Runs the project's verification gate (type-check, tests, build). **Never
150162
commits red** — an unfixable-within-scope failure goes to
151163
`known-issues.md` and execution stops with a report.
152-
5. Updates `TASKS.md`, `progress.md`, `testing.md`, `known-issues.md` (and
164+
5. Updates `TASKS.md`, `progress.md` (appending the phase's handoff entry in
165+
the fixed schema), `testing.md`, `known-issues.md` (and
153166
`decisions.md` if architecture moved). When reality contradicts the plan,
154167
`TASKS.md`/`PLAN.md` are updated and the why recorded in `decisions.md`
155168
never a silent divergence.

docs/workflow/REVIEW_AND_CLASSIFY.es.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ proyecto (chequeo de tipos, tests, build).
3333
## Cómo invocarla
3434

3535
- `/review-change` — el orquestador: ejecuta los ejes aplicables a esta
36-
plataforma y sintetiza una tabla + una checklist de verificación manual.
37-
Úsala antes de un PR.
36+
plataforma — cada pasada **aislada por defecto** (contexto limpio, devuelve
37+
solo su tabla de hallazgos; la composición en el mismo turno es el fallback
38+
para agentes que no pueden abrir contextos nuevos) — y sintetiza una tabla
39+
+ una checklist de verificación manual. Úsala antes de un PR.
3840
- `/review-implementation` — solo el motor; por defecto usa el **diff de la
3941
rama actual frente a `main`**.
4042
- Pasa una ruta/glob para ampliar o acotar el alcance, p. ej.

docs/workflow/REVIEW_AND_CLASSIFY.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ tests, build).
2929
## How to invoke
3030

3131
- `/review-change` — the orchestrator: runs the applicable axes for this platform
32-
and synthesizes one table + a manual-verification checklist. Use this before a PR.
32+
— each pass **isolated by default** (context-clean, returns only its findings
33+
table; in-turn composition is the fallback for agents that can't spawn fresh
34+
contexts) — and synthesizes one table + a manual-verification checklist. Use
35+
this before a PR.
3336
- `/review-implementation` — just the engine; defaults to the **current branch diff
3437
vs `main`**.
3538
- Pass a path/glob to widen or narrow scope, e.g. *"review-implementation on

0 commit comments

Comments
 (0)