{
  "markdown": "# ForgeMySpec\n\n![ForgeMySpec v0.1.0 interactive CLI](docs/cli-demo.png)\n\n[![Tests](https://github.com/ferrarimarlon/forgemyspec/actions/workflows/tests.yml/badge.svg)](https://github.com/ferrarimarlon/forgemyspec/actions/workflows/tests.yml)\n\n**Turn a human request into a machine-executable contract — before the first line of code is written.**\n\nForgeMySpec compiles natural-language requirements into a structured artifact bundle that gives a coding agent a stable, auditable contract to work from. The bundle is a **runtime-ready execution harness for Claude**: concrete files that drive implementation and verification alongside the agent.\n\n## Why Use This?\n\n![ForgeMySpec comparative results](experiments/forgemyspec_chart.png)\n\nForgeMySpec matters most when the task stops being trivial. Once a requirement has interacting rules, validation paths, derived fields, security constraints, or multiple edge cases, “just write the code” starts to look correct long before it is actually safe or complete. ForgeMySpec turns that ambiguity into an executable contract first, so the agent implements against a stable target instead of improvising under context pressure.\n\nAcross 17 benchmark projects, both approaches usually produced something that looked functional. The difference showed up in the parts that are expensive to discover later: silent bugs, structural drift, and security mistakes that do not necessarily break the happy path. ForgeMySpec consistently held quality higher, and the gap widened as the scenarios became more complex.\n\n| | With spec | Without |\n|---|:---:|:---:|\n| Average completeness | 4.85 / 5 | 4.17 / 5 |\n| Security vulnerabilities | 0 | 1 |\n| Structural deviations | 0 | 7 |\n| Silent quality issues | 4 | 9 |\n| Projects with zero issues | 10 / 17 | 6 / 17 |\n\n**The more domain pressure you add, the more ForgeMySpec pulls away.** In simple, closed tasks, direct implementation can be enough. In medium and complex projects, the spec preserves intent while the agent navigates multiple constraints at once. Hidden drift usually starts there, and ForgeMySpec keeps the implementation anchored to the requirement.\n\nThat advantage matters in the places teams actually pay for mistakes: approval flows, invariants, conditional rules, security boundaries, and business logic that cannot be reconstructed reliably from the final code alone. ForgeMySpec keeps those constraints explicit from the start and gives the agent a tighter target to execute against.\n\nFor tiny one-off scripts, the extra structure may not matter. For work with multiple interacting constraints and real failure modes, ForgeMySpec gives the agent a measurable advantage.\n\nFull data: [`experiments/COMPARATIVE_REPORT.md`](experiments/COMPARATIVE_REPORT.md)\n\n---\n\n## How it works\n\nYou write a **prompt**. ForgeMySpec runs a compile pipeline: LLM draft, normalization into a `Spec` model, **lint** against policy, then **packaging** into files the agent can re-read. The repository also ships **Claude Code skills** under `.claude/skills/`, so the same workflow can run **inside** Claude Code (with MCP context when available), not only via the terminal CLI.\n\n```text\n                         +------------------+\n                         |  You write the   |\n                         |  prompt          |\n                         +--------+---------+\n                                  |\n                                  v\n              +-------------------------------------------+\n              |  ForgeMySpec: draft -> normalize -> lint    |\n              |            -> pass gate -> package        |\n              +--------------------+----------------------+\n                                   |\n           +-----------------------+------------------------+\n           |                       |                        |\n           v                       v                        v\n  +----------------+    +----------------------+   +---------------------+\n  |  spec.yaml     |    |  Claude bundle       |   |  Claude Code skills |\n  |  (contract)    |    |  CLAUDE.md,          |   |  in this repo       |\n  |                |    |  implement command,  |   |  (.claude/skills/)  |\n  |                |    |  checklist, evals    |   |  same pipeline      |\n  +--------+-------+    +----------+-----------+   +----------+----------+\n           |                       |                        |\n           +-----------------------+------------------------+\n                                   |\n                                   v\n                        +------------------------+\n                        |  Implement from the    |\n                        |  contract (CLI output  |\n                        |  or in-session skills) |\n                        +------------------------+\n```\n\nFor the linear step list and policy details, see [The Compilation Pipeline](#the-compilation-pipeline) below.\n\n---\n\n## The Problem\n\nIn **Claude Code**, each turn draws on more than the latest user message. Each turn is assembled from a **stack of context sources**—the same architecture that makes the agent capable also dilutes any single requirement over time.\n\nRoughly, that stack looks like this:\n\n```\n1. Claude Code / platform instructions\n2. Project memory — CLAUDE.md, settings, and repo-local rules\n3. Skills — .claude/skills/ (instructions loaded when relevant)\n4. MCP servers — live data and tools (issues, docs, APIs) merged into the session\n5. Current user request              ← shrinks relative to everything else\n6. Conversation history\n7. Tool outputs — diffs, logs, command output, file reads\n```\n\nThe **effective context window** is shared across all of that. So the explicit task you typed is only one slice of what the model must attend to. The stack is powerful — and it is exactly where **drift** begins: the requirement competes with skills output, MCP payloads, and accumulated tool traces.\n\nFrom there, missing details get silently filled by pattern-matching. “Helpful” additions slip in because no hard execution contract exists. Completion gets reported in broad language even when acceptance criteria remain fuzzy.\n\n**ForgeMySpec addresses this** by compiling the request into a **compact contract before implementation churn**, **materialized as files** the agent can re-read as the Claude Code context stack grows.\n\nArchitecturally, each stage targets a specific failure mode:\n\n| Layer | What it solves |\n| --- | --- |\n| **Synthesis** (LLM → structured draft) | Moves the objective from implicit chat into explicit schema fields. |\n| **Normalization** (`Spec` model) | One canonical shape: stable hypothesis/action IDs, deduped lists, typed values—so the contract is **diffable** and comparable across turns. |\n| **Lint + policy gate** | Deterministic enforcement: required sections, traceability (`actions` → `supports` → `hypotheses`), metadata, minimum evidence—**machine-checkable** completion criteria. |\n| **Packaging** (artifact bundle) | **`spec.yaml`** is the single source of truth; **`CLAUDE.md`** aligns **project memory** with guardrails; **checklist** and **scope eval seeds** make acceptance and drift **re-verifiable** after long tool traces. |\n\nTogether, that turns the “small slice” of user intent into a **durable handle** inside the same harness. Claude Code still layers platform rules, skills, MCPs, and tools; the bundle adds a **revisit contract** on disk the agent can reload whenever conversation recall thins out. (See [The Compilation Pipeline](#the-compilation-pipeline) for the linear flow.)\n\n---\n\n## What ForgeMySpec Produces\n\nEach compilation run outputs a bundle of five artifacts:\n\n| Artifact | What It Does |\n|---|---|\n| `spec.yaml` | The operational contract: objective, assumptions, constraints, success criteria, hypotheses, actions, decision rules |\n| `CLAUDE.md` | Persistent project memory: guardrails, known pitfalls, decision log — Claude reads this on every turn |\n| `.claude/commands/implement-from-spec.md` | The implementation entrypoint — a step-by-step execution recipe |\n| `acceptance-checklist.md` | The delivery gate: every criterion stated as a checkable assertion with required evidence |\n| `evals/scope_drift_cases.yaml` | Machine-checkable scope seeds — required and forbidden patterns in the implementation |\n\nThese files give the agent a stable anchor it can revisit throughout a long session: a compact contract on disk, re-readable at any step without keeping the whole requirement in working memory.\n\n---\n\n## Ways To Use It\n\n| Flavor | What It Does |\n|---|---|\n| **Python CLI** (`forgemyspec`) | Runs locally with your API key. Interactive or direct-prompt mode. Writes the artifact bundle to your chosen output directory (default: `forgemyspec-bundle`). |\n| **Claude Code** | **Skills:** `.claude/skills/` (symlinks into `plugins/forgemyspec/skills/`) expose `/forgemyspec` and `/forgemyspec-implement`. **Default agent:** `.claude/settings.json` sets `defaultAgent` to **`forgemyspec-default`**, whose definition lives in `plugins/forgemyspec/agents/forgemyspec-default.md` (symlinked under `.claude/agents/`). That agent preloads those skills and routes spec-first work—no marketplace plugin required. |\n\n**Slash commands (skills):**\n\n- **`/forgemyspec`** — Compile a requirement into `spec.yaml` and the full artifact bundle. Gathers MCP context first.\n- **`/forgemyspec-implement`** — Execute implementation when a bundle already exists. No re-compilation.\n\n---\n\n## Interactive CLI\n\nWrite the task. Choose an output folder. ForgeMySpec generates the bundle. The status panel shows provider, workspace, pipeline stage, and available slash commands.\n\n```bash\n# Interactive mode\n.venv/bin/forgemyspec\n\n# Direct prompt\n.venv/bin/forgemyspec \"build a deterministic SQL expression analyzer CLI\"\n\n# From file\n.venv/bin/forgemyspec --from-file prompt.txt\n```\n\n---\n\n## Using Claude Code (preconfigured)\n\nThis repository is set up for **Claude Code** out of the box: open the project folder in Claude Code and you inherit the same spec-first workflow without installing a marketplace plugin.\n\n| Already in the repo | What it does |\n| --- | --- |\n| `.claude/settings.json` | Sets **`defaultAgent`** to **`forgemyspec-default`**, so new sessions use the ForgeMySpec agent by default. |\n| `.claude/agents/forgemyspec-default.md` | Agent definition (source: `plugins/forgemyspec/agents/`). Preloads the `forgemyspec` and `forgemyspec-implement` skills. |\n| `.claude/skills/` | Symlinks to `plugins/forgemyspec/skills/` — **`/forgemyspec`** and **`/forgemyspec-implement`** are available as slash commands. |\n| Root `CLAUDE.md` | Project memory the agent reads every turn (spec-first rules and conventions). |\n\n**Typical flow**\n\n1. **New feature or ambiguous request** — Run **`/forgemyspec`** (or ask in natural language; the default agent should route to compiling a bundle first). Point the skill at your requirement; it can use MCP tools for repo or ticket context if you have them connected. The bundle lands under a dedicated directory (e.g. `./forgemyspec-bundle/`), not inside `.claude/skills/`.\n2. **You already have a validated `spec.yaml` for the task** — Run **`/forgemyspec-implement`** and follow the bundle’s checklist and commands.\n3. **Keep memory honest** — Put durable decisions in the **bundle’s** `CLAUDE.md` and the root **`CLAUDE.md`** only when they are project-wide; avoid using skills output directories as scratch pads.\n\nIf your Claude Code UI lets you pick an agent, choose **`forgemyspec-default`**; if you rely on defaults only, this repo already selects it for you.\n\n---\n\n## The Compilation Pipeline\n\n```\nHuman request\n    │\n    ▼\nLLM draft JSON\n    │\n    ▼\nNormalization → internal Spec model\n    │\n    ▼\nProgrammatic lint + policy checks\n    │\n    ▼\nScore / pass gate\n    │\n    ▼\nClaude artifact bundle\n```\n\nThe pipeline is deliberately split:\n\n- **Generation** handles synthesis — the LLM turns a prompt into structured JSON\n- **Normalization** handles shape — deduplication, stable IDs, consistent types\n- **Lint** handles enforcement — deterministic checks over structure and traceability\n- **Packaging** handles Claude usability — writing files the agent can re-read mid-session\n\nSemantic truth still depends on the original request. Structural integrity, traceability, and packaging readiness are enforced by code.\n\n---\n\n## The Spec Structure\n\nThe operational contract lives in `spec.yaml`. Every other artifact is a view of the same content.\n\n| Area | Fields | Role |\n|---|---|---|\n| Identity | `version`, `title`, `objective` | What is being built and why |\n| Execution | `execution_mode` | How the run should proceed |\n| Context | `context.system`, `context.assumptions` | Environment framing and explicit premises |\n| Boundaries | `constraints` | Hard limits — what must stay true or stay out |\n| Outcomes | `success_criteria`, `required_evidence` | What \"done\" means and what proof is required |\n| Reasoning | `hypotheses` | Working beliefs with `id`, `description`, `confidence` (0–1) |\n| Work plan | `actions` | Discrete steps with `id`, `type`, `supports` (hypothesis links) |\n| Governance | `decision_rules` | When to stop, escalate, or choose between options |\n| Provenance | `metadata` | Source prompt, generator, model, scope contract |\n\n### Traceability graph\n\nEach action can list hypothesis IDs in `supports`. This links planned work to the hypotheses it validates, so the spec is auditable as a **directed graph** between actions and hypotheses. The linter enforces that every hypothesis is referenced by at least one action when policy requires it.\n\n### Scope contract\n\n`metadata.scope_contract` holds two explicit fences:\n\n```yaml\nmust_include:   # items that must remain in scope\nmust_not_include: # items explicitly fenced out\n```\n\nThis feeds scope evaluation and makes drift detectable against the original intent.\n\n---\n\n## What Lint Checks\n\nThe lint layer applies deterministic checks over the generated spec:\n\n- Required fields and expected types\n- Minimum content counts per section\n- Hypothesis ID format and confidence range\n- Action ID, type, and confirmation flags\n- Traceability links from actions to hypotheses via `supports`\n- Required metadata fields\n- Duplicate or near-duplicate list entries\n\nThis gives every compilation a machine-checkable quality gate before the artifacts reach a coding agent.\n\n---\n\n## Why This Works For Claude\n\nClaude performs best when the execution surface is compact, explicit, and revisitable. A long implementation session is easier to control when constraints are already materialized in files the agent can re-read at any step:\n\n- **one file** for the operational spec\n- **one file** for persistent memory\n- **one checklist** for acceptance\n- **one command** as the implementation entrypoint\n\nThat structure reduces accidental scope expansion and raises the chance of reproducible delivery across runs.\n\n---\n\n## API Key Setup\n\nCreate `./.venv/.env`:\n\n```env\n# Anthropic\nANTHROPIC_API_KEY=\"sk-ant-...\"\nANTHROPIC_MODEL=\"claude-sonnet-4-6\"\n\n# or OpenAI\nOPENAI_API_KEY=\"sk-...\"\nOPENAI_MODEL=\"gpt-4o\"\n```\n\nOr export directly:\n\n```bash\nexport ANTHROPIC_API_KEY=\"sk-ant-...\"\n```\n\n---\n\n## Compiler Policy\n\nAn optional policy file controls how strict compilation and the pass gate should be.\n\n**Default path:** `./.forgemyspec-policy.yaml`  \n**Override:** `export FORGEMYSPEC_POLICY=/path/to/policy.yaml`\n\n```yaml\nmin_items:\n  assumptions: 1\n  constraints: 2\n  success_criteria: 2\n  hypotheses: 1\n  required_evidence: 2\n  actions: 2\n  decision_rules: 2\n\nallowed_action_types: [analyze, design, implement, validate, review]\nrequire_action_support_links: true\nrequired_metadata_fields: [source_prompt]\nscope_contract_field: scope_contract\n\nlint_base_score: 100\nlint_error_penalty: 18\nlint_warning_penalty: 5\nlint_min_passing_score: 70\n\nscope_eval_base_score: 100\nscope_violation_penalty: 25\n```\n\n---\n\n## Architecture\n\n```\nsrc/forgemyspec/\n├── cli.py           ← user flow and interactive session\n├── generator.py     ← compiles draft JSON into internal Spec model\n├── linting.py       ← deterministic quality checks\n├── scope_eval.py    ← evaluates scope contract adherence\n├── claude_skill.py  ← writes the Claude artifact bundle\n└── nlp_policy.py    ← loads policy and scoring configuration\n\n.claude/skills/\n├── forgemyspec/           ← MCP-aware spec compilation skill\n└── forgemyspec-implement/ ← implementation-only skill for existing bundles\n\nexamples/\n├── sample-bundle/   ← reference output: parser CLI\n└── mini-os/         ← reference output: bare-metal x86 OS\n```\n\n---\n\n## Case Study: Building a Bare-Metal OS\n\nThe `examples/mini-os/` directory is a complete end-to-end demonstration. ForgeMySpec compiled a full spec from a **short seed phrase**, and `/implement-from-spec` built a bootable x86 disk image.\n\n![MiniOS v0.1 running in QEMU — boot summary, memory map, and GDT](docs/minios-qemu.png)\n\n### The original prompt\n\nThe checked-in `examples/mini-os/spec.yaml` stores a fuller `metadata.source_prompt` (what the compiler session actually recorded): path, architecture, and tooling constraints layered on top of that seed:\n\n```yaml\nsource_prompt: >\n  build a simple operating system\n```\n\n**What this case study documents**\n\n| Layer | Content |\n| --- | --- |\n| **Seed** | Five-word phrase: `build a simple operating system`. |\n| **Full prompt record** | `metadata.source_prompt` in `spec.yaml` adds repository path (`examples/mini-os`), architecture (x86 bare-metal), stack constraints (minimal resources, no external libraries), deliverables (bootloader + kernel, VGA text), and run target (QEMU). |\n\nSeed plus metadata together are the complete, replayable input stored on disk.\n\n### What the spec compiled\n\nRunning `/forgemyspec` with that prompt text produced the full bundle in one pass:\n\n**Objective** — 512-byte BIOS bootloader + freestanding C kernel → VGA text output → boots in QEMU from a raw disk image. No external libraries. No runtime.\n\n**Hard constraints from `spec.yaml`:**\n- Bootloader must be exactly 512 bytes, ending with `0xAA55` BIOS signature\n- Kernel is freestanding C only — no libc, no crt0, no runtime\n- Zero external libraries; toolchain is `nasm` + `gcc -m32` + `ld`\n- All files inside `examples/mini-os/`\n- `make run` is the single command to boot in QEMU\n\n**Hypotheses the spec reasoned over:**\n\n| ID | Claim | Confidence |\n|---|---|---|\n| h1 | A 512-byte NASM bootloader can load, switch to protected mode, and hand off to a C kernel at `0x1000` | 0.95 |\n| h2 | A freestanding C kernel can write directly to VGA framebuffer `0xB8000`, producing readable coloured output | 0.97 |\n| h3 | A Makefile using only nasm + gcc -m32 + ld can produce a bootable raw image runnable in `qemu-system-x86_64` | 0.92 |\n\n**Actions the spec decomposed the work into:**\n\n| ID | Type | Description |\n|---|---|---|\n| a1 | design | Create directory layout: `boot/`, `kernel/`, `linker.ld`, `Makefile` |\n| a2 | implement | Write `boot/boot.asm` — 16-bit startup, INT 13h disk read, A20, GDT, protected-mode switch, jump to `0x1000` |\n| a3 | implement | Write `kernel/kernel.c` — VGA helpers and `kernel_main` banner |\n| a4 | implement | Write `linker.ld` — sections at `0x1000`, flat binary output |\n| a5 | implement | Write `Makefile` — `all`, `run`, `clean` targets; produce `build/os.img` |\n| a6 | validate | Run `make`, check `boot.bin` size, boot in QEMU, verify VGA output |\n\nEach action declares `supports` links to the hypotheses it validates — the spec is auditable as a graph.\n\n**Scope contract — what the spec explicitly fenced out:**\n\n```yaml\nmust_include:\n  - 512-byte bootloader (NASM)\n  - protected-mode switch\n  - freestanding C kernel\n  - VGA text output\n  - Makefile\n  - QEMU run target\n\nmust_not_include:\n  - libc or any runtime library\n  - filesystem driver\n  - keyboard or interrupt handling\n  - multitasking or scheduling\n  - anything outside examples/mini-os/\n```\n\n### Scope drift evaluation\n\n`evals/scope_drift_cases.yaml` holds 11 machine-checkable seeds derived from the spec:\n\n- **6 negative checks** — patterns that must never appear: `#include <stdio.h>`, `-lpthread`, IDT setup, scheduler keywords\n- **5 positive checks** — files that must exist and contain specific values: `0xAA55`, `0xB8000`, `-ffreestanding`\n\n### Implementation and evidence\n\nRunning `/implement-from-spec` executed the six actions in order. The acceptance checklist was filled with **concrete evidence** (command output, sizes, hex dumps):\n\n```\n$ make\n  [OK] boot.bin     512 bytes\n  [OK] kernel.bin   2445 bytes\n  [OK] os.img       65536 bytes\n  [OK] magic        55aa\n\n$ xxd -s 510 -l 2 build/os.img\n000001fe: 55aa\n\n$ qemu debug port output:\nMiniOS v0.1 — kernel_main reached\n[BOOT] Bootloader: 0x7C00  Kernel: 0x1000  Stack: 0x90000\n[MEM]  VGA: 0xB8000  Conv: 0x00000-0x9FFFF\n[GDT]  Code: 0x08  Data: 0x10\nKernel halted. All systems nominal.\n```\n\nAll acceptance criteria passed: `make` exits 0, `boot.bin` is exactly 512 bytes, bytes 510–511 are `55 AA`, the kernel banner appears in QEMU with coloured VGA sections, and `make clean` removes all artefacts.\n\n### What the spec prevented\n\nThe key shift is *when* the error surfaced: **during spec authoring**, before QEMU or the first boot attempt.\n\n![Errors surfaced per development phase: Spec-Driven vs No Spec](docs/error-phase-comparison.svg)\n\nA spec front-loads known failure modes before the first file exists. The agent reads them during implementation and writes code that already satisfies those constraints, so several failure classes **never reach** a QEMU run. Naming risky cases up front shortens the write → run → diagnose cycle.\n\n#### Errors caught while writing\n\n**Wrong linker output format.** The linker defaults to ELF format even when you need a raw binary. QEMU loads the image, the boot check passes, and execution lands in ELF header bytes; the kernel entry never runs. The screen goes black — identical in appearance to a wrong load address or a missing boot signature. Three different root causes, one symptom; foreknowledge matters. The spec had the fix written down before the Makefile existed: always pass `--oformat binary`. The agent applied it during authoring, avoiding the all-black screen entirely.\n\n**Bootloader overflow.** The bootloader must fit in exactly 512 bytes, and the last two bytes are a fixed boot signature the BIOS requires to recognize the disk as bootable. If the binary grows too large and you trim the wrong bytes, the machine refuses to boot with no error output. The spec made the priority explicit before the assembler file was written: trim strings or data first; **preserve the boot signature**. The agent followed that ordering under the same constraints everyone else faces.\n\n**Garbled screen output.** Each character cell on the screen is encoded as two bytes: color first, character second. Swapping the order fills the screen with glyphs that look alive but stay unreadable. The correct encoding was in the spec before the display code was written; the first VGA write matched that contract.\n\n#### Runtime discoveries folded into persistent memory\n\nA few failures surfaced first in QEMU or on the host. Each was logged into a persistent memory file the agent reads at the start of every session, so the next run starts with that knowledge already in place.\n\n**Wrong function at the kernel entry point.** The bootloader jumps to a fixed memory address expecting to land on the kernel's main function. But the C compiler places functions in whatever order it chooses — and helper functions like screen clear or string print often end up before the main function in the final binary. The bootloader lands in the middle of a helper, the kernel crashes silently, and nothing appears on screen. Once discovered, the fix — forcing the entry point to always be first — was logged permanently. Every subsequent run inherits it and writes the correct code from the start.\n\n**Compiler incompatibility on Apple Silicon.** On Apple Silicon Macs, the standard 32-bit compile flag fails with messages that resemble a missing toolchain install. The underlying issue is architecture mismatch; documenting the correct cross-compiler and flags carried that knowledge forward to every future run on that platform.\n\n#### Scope creep — silent expansion until late review\n\nAn agent asked to \"build a simple OS\" has a natural instinct to keep adding things: keyboard input, a basic scheduler, interrupt handling. Each addition feels helpful. None of them announce themselves as out of scope — they just accumulate quietly.\n\nThe spec's explicit `must_not_include` list made the boundary visible **before** implementation began. Late review no longer had to discover an OS that overshot the original ask by surprise.\n\n---\n\n## What's Next\n\n- Conflict-mediation structure for specs with contradictory requirements\n",
  "bytes": 24796,
  "sha": "f64c0598123a5a5daf6bcd694995467de3bbde4ec2c7e9b49924283f97e4417f",
  "repo_slug": "ferrarimarlon/specforge",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_ferrarimarlon_specforge_specforge_337afc1c/readme"
}