Fábrica: from request to verified system
Claude Code skills that take a PEDIDO.md to a running system, and a script, not the agent, approves every stage.
Results
5/5
requests with 100% of acceptance criteria met, 4 of them unseen
from 17/17 to 31/31 criteria per request
measuredOct 2026runs through the judges' path, checked with fabrica verificar
~30 min
from PEDIDO.md to verified system, no human intervention
27 to 31 min across the 5 runs
measuredOct 2026headless run logs
0
gate retry rounds in the 5 final runs
measuredreports generated by the package
513
tests in the package itself, 0 failures on Windows and Linux
measuredthe repository's test suite
Summary
Context
At the Ideen 2026 Hackathon, the challenge was to take a natural-language request to a working system, with real conception, specification, build and review, and with evidence someone else could check. On its own, a coding agent tends to skip steps, write tests that only confirm its own code, and declare success without proof.
Action
Working alone over three days, I built a Claude Code skill package with nine roles running as clean-context subagents: PM, Architect, Council, QA, Dev, three reviewers and Retro. Every stage ends in a gate decided by a Node script, not by the model. QA writes the acceptance tests and seals them by hash before any code exists, the review runs four security tools, and the evidence is generated from the artifacts themselves.
Result
Through the judges' exact path (claude -p in a clean folder), five requests, four of them unseen, passed with 100% of criteria, from 17/17 to 31/31, in 27 to 31 minutes each and with no gate retry rounds. Before that, 12 subagent runs added up to 339/339 criteria. The package has 513 tests of its own.
Lesson
Reliability in agents comes from taking the decision that the work is done away from the model: whoever approves must be deterministic and external.
Architecture
Long version
The problem
The hackathon kit asked for something simple to say and hard to do: take a PEDIDO.md and deliver a
system that someone else can verify. An agent's typical failure is not writing bad code. It is
saying it is done when it is not, or writing tests shaped around what it implemented itself.
The decisions
1. A script approves. Every stage (Conception, Specification, Build, Review) ends in a gate run
by fabrica.mjs, a dependency-free Node CLI. A failed gate sends the work back to the responsible
role, and on the third retry round the stage is blocked. The agent has no way to "decide" it passed.
2. Tests sealed before the code. QA writes the acceptance tests from the spec and records their hash. If Dev changes a test, the gate fails. When a test contradicts the spec, there is a formal path: Dev disputes it, and QA decides and seals again, with the reason on record.
3. One role per context. There are nine roles, each in a clean-context subagent with its own instruction "card". The security reviewer does not carry the bias of whoever wrote the code.
4. Review through three lenses. Quality, adherence to the request and security, the last one with bandit, pip-audit, detect-secrets and semgrep. An open high- or medium-severity finding fails the final gate.
5. Evidence generated, not declared. The report links criterion → test → result, and the retro lists the run's errors. There is also an offline dashboard and screenshots of the screens with data, like the ones below.

How I measured
I measured through the exact path the judges would use: claude -p with the kit's prompt, in a
clean folder containing only the PEDIDO.md and the skills, with no manual adjustment. The check
was done afterwards, outside the agent.
| Request | Request criteria | Total (with derived) | Gates | Duration | |---|---|---|---|---| | Training: room booking | 10/10 | 19/19 | 4, no retries | 31 min | | Unseen: front-desk visitors | 10/10 | 22/22 | 4, no retries | 27 min | | Unseen: preventive maintenance (criteria in prose only) | 7 → 7 | 17/17 | 4, no retries | 28 min | | Unseen: on-call schedule (cross-cutting rules) | 10/10 | 23/23 | 4, no retries | 31 min | | Unseen: travel expenses (larger scope) | 12/12 | 31/31 | 4, no retries | 31 min |
The derived criteria are written by the Architect from the request's rules: edge cases, validations and the screen.

Where the AI got it wrong
I logged 31 errors. Four of them changed the package:
| Error | What changed |
|---|---|
| A subagent hung on an API failure and the orchestrator stopped to ask the user | Autonomous mode that never asks; the subagent is reopened up to 2 times, resuming from disk |
| Two reviewers sat stuck for 13 min on a file lock, because in Node on Windows, rmSync did not delete a path with an accent and raised no error | Removal with a fallback across the whole package, and lock waits with a deadline |
| A taskkill /IM python.exe took down every Python process on the machine | Killing a process by name is now forbidden; shutdown uses the recorded PID |
| Dev changed code during review with no finding, and the new code was not scanned | The final gate fails code changed after the security scan |
How it compares
I compared the documentation of 19 similar public projects, including Spec Kit, BMAD, Kiro, superpowers and Taskmaster. Fábrica is the only one that combines a script-decided gate, immutable tests before the code, one role per isolated context, security with real tools, and request → system with no human. In return, they support multiple languages and existing projects; Fábrica validated one profile (Python web) for new systems.
Limitations
- Judges' path measured with 5 requests, on Windows only and with a single model. A sixth run stopped midway and is recorded together with the fix.
- One validated profile (FastAPI, SQLite and an HTML/JS screen).
- The synthetic requests were written by me.
Lessons learned
- Gate outside the model. A script that rejects is more reliable than a prompt asking for rigor.
- Seal before you build. With acceptance tests sealed by hash, Dev cannot adjust the yardstick to its own code.
- The error log is the roadmap. I documented 31 AI mistakes during the project, and each one became a rule in the package.