Skip to content

The Forge

The Forge is a problem-first idea workshop shared by bio-Zack and silicon-Zack. It forces discipline: start with problems, not solutions. Ideas flow through four active stages with strict WIP limits, preventing the graveyard problem where ideas accumulate without progress.

The Jeopardy Principle

People naturally start with solutions. "What if we built X?" The Forge makes you go back to the question, like Jeopardy: start with the answer, then articulate what the question was.

When bio-Zack drops a solution ("what if we built async council deliberation?"), the forge captures it immediately as a spark, then asks: "What problem does this solve?" If the problem can be articulated with evidence, the idea advances to smelt. If not, it stays as a spark until the problem emerges naturally.

This is the core forcing function. Capture is always free and immediate. Problem articulation is the gate.

Stages

Spark --> Smelt --> Shape --> Forge
                                \
                         [shipped] [killed] [archived]

Spark

Anything goes. Problems, solutions, friction, hunches. Low friction capture. Either bio-Zack or silicon-Zack can originate sparks. Solution-first entry is fine because smelting forces the problem trace-back later.

A spark file contains a title, description, origin, and optional tags. No problem statement required yet.

Smelt

The Jeopardy phase. Extract the real problem behind the idea. Requires:

  1. Problem statement - One sentence describing the specific pain or opportunity
  2. Evidence - One concrete instance of this problem occurring
  3. Complexity triage - Cynefin-lite classification:
  4. clear - Known fix. Idea is killed and routed to the task list. The forge is for problems that need exploration, not known solutions.
  5. spike - Needs investigation before we even understand the solution space.
  6. complex - Goes into smelt for problem definition, then shape for solution exploration.

When an idea is smelted, the file is renamed to reflect the problem (not the original solution title). The original spark content is preserved under "Original Spark" in the body.

Shape

Explore the solution space. Multiple approaches at fat-marker level (broad strokes, not detailed specs). The appetite field must be set before advancing to forge. Appetite values: tiny, small, medium, large, unknown.

Forge

Converge on one approach. Appetite and boundaries are locked. The idea is ready to build. Only one idea should be in forge stage at a time.

Terminal States

  • shipped - Built and deployed. The idea is done.
  • killed - Decided against, with reason and optional learnings recorded. Killing is gardening, not failure. A killed idea is a decision made.
  • archived - Not killed but not active. Can be resurrected.

WIP Limits

The forge enforces work-in-progress limits to maintain focus:

Stage Limit
spark 7
smelt 4
shape 2
forge 1

If any stage exceeds its limit, the status dashboard shows a WIP warning. If total active ideas exceed 15, the system flags a "system smell" indicating the forge needs pruning.

Ideas untouched for 14+ days are flagged as stale and considered kill candidates.

Silicon-Zack Origination

Silicon-Zack can create sparks too, using origin: "silicon-zack". Three channels, ranked by intrusiveness:

  1. Silent (default) - File spark during /sleep. Bio-Zack discovers it naturally.
  2. Bundled - Mention in weekly forge status via telegram. "2 new sparks this week."
  3. Interrupt (rare, max 1/week) - Telegram nudge for high-conviction, time-sensitive ideas only.

Every AI-originated spark must include a "why now" line. Rate limiting: if the forge has 3+ unengaged silicon-Zack sparks, stop generating new ones and develop existing ones instead.

Python API

All functions are importable from scripts.forge:

from scripts.forge import (
    create_spark,
    smelt_idea,
    list_ideas,
    get_idea,
    add_entry,
    advance_stage,
    kill_idea,
    forge_status,
    rebuild_index,
    COMPLEXITY_VALUES,
)

create_spark

Create a new spark in the forge.

idea = create_spark(
    title="Async Council Deliberation",
    description="What if council could run overnight during /sleep?",
    origin="bio-zack",          # or "silicon-zack"
    tags=["vita-system", "council"],
    related_ideas=["003"],      # optional
    problem_statement=None,     # optional, for problem-first entry
    project=None,               # optional, links to a project-registry id
)
# Returns: {"id": "020", "title": "...", "filename": "020-async-council-deliberation.md", "path": "..."}

If problem_statement is provided, the spark is created with a Problem section already included in the body.

Note: The optional project= argument links an idea to a project in the project registry. It is part of core.py's frontmatter key order, but it is Python-API-only β€” the REST CreateSparkRequest does not expose it.

smelt_idea

The Jeopardy flip. Advance a spark to smelt by articulating the problem.

smelt_idea(
    "003",
    problem_statement="Voice mode architecture is too complex for the actual use case",
    evidence="Realtime API has 5 failure modes for what should be a simple record-process-speak flow",
    complexity="complex",  # "clear", "spike", or "complex"
)
# Returns: True on success

If complexity is "clear", the idea is killed with reason "Routed to task list" instead of advancing to smelt.

The file is renamed so the slug reflects the problem statement rather than the original solution title.

add_entry

Add a dated entry to any idea's body. Used for research notes, thoughts, progress updates.

add_entry(
    "003",
    "Explored three approaches: turn-based, streaming, and hybrid...",
    author="silicon-zack",
    section="Research Notes",  # optional section header
)

advance_stage

Move an idea to a new stage. Valid transitions: smelt to shape, shape to forge (requires appetite set), forge to shipped.

advance_stage("003", "shape")

Use smelt_idea() for the spark to smelt transition, since it requires problem statement and evidence.

Shape to forge is blocked if appetite is still "unknown".

kill_idea

Kill an idea with dignity. Records reason and optional learnings.

kill_idea(
    "005",
    reason="Superseded by forge system",
    learned="The capture pattern was useful though",
)

forge_status

Generate a forge dashboard with counts, active ideas, stale ideas, and WIP warnings.

status = forge_status()
# Returns:
# {
#   "total_active": 7,
#   "counts": {"spark": 2, "smelt": 3, "shape": 2, "forge": 0, "shipped": 1, "killed": 0, "archived": 0},
#   "active_ideas": [...],
#   "stale": [{"id": "003", "title": "...", "stage": "smelt", "days_stale": 18}],
#   "wip_warnings": ["shape: 3/2 (over limit)"],
#   "origin_breakdown": {"bio-zack": 5, "silicon-zack": 2},
#   "system_smell": False,
# }

list_ideas / get_idea

# List active ideas, optionally filtered by stage
ideas = list_ideas(stage="smelt")
ideas = list_ideas(include_terminal=True)  # include shipped/killed/archived

# Get a single idea with full body
idea = get_idea("003")
# Returns full dict with frontmatter fields + "_body", "_path", "_filename"

rebuild_index

Regenerate the _index.md dashboard file. Called automatically during /sleep. The generated index opens with the active-idea count and origin breakdown, then emits a > WARNING line if the system smell trips and one > WIP line per over-limit stage. It follows with a per-stage section (## Spark (N), ## Smelt (N), …) listing each active idea with its origin tag (b/s), appetite, problem statement, and last-touched date, and closes with a ## Kill Candidates (stale >14 days) section.

content = rebuild_index()

Skill Commands

The forge skill (.claude/skills/forge/SKILL.md) auto-triggers when bio-Zack mentions ideas or uses /forge.

Command What it does
/forge Show forge status dashboard
/forge spark [title]: [description] Create a new spark
/forge list [stage?] List ideas, optionally filtered
/forge [id] Display a specific idea
/forge smelt [id] Attempt to smelt a spark
/forge entry [id]: [thought] Add a thought/entry
/forge advance [id] [stage] Move idea to next stage
/forge kill [id]: [reason] Kill with dignity

Auto-triggers also fire when bio-Zack says things like "I have an idea", "what if we", or uses the "idea:" prefix in telegram.

API Endpoints

The forge is exposed via REST at /api/v1/forge:

Method Path Description
GET /api/v1/forge List ideas. Query params: stage, include_terminal
GET /api/v1/forge/status Dashboard with counts, WIP warnings, staleness
GET /api/v1/forge/{idea_id} Get single idea with full body
POST /api/v1/forge Create a spark. Body: {title, description, origin, tags, problem_statement}
POST /api/v1/forge/{idea_id}/smelt Smelt a spark. Body: {problem_statement, evidence, complexity}
POST /api/v1/forge/{idea_id}/entries Add entry. Body: {text, author, section}
PUT /api/v1/forge/{idea_id}/stage Advance stage. Body: {new_stage}
POST /api/v1/forge/{idea_id}/kill Kill idea. Body: {reason, learned}

Briefing Integration

Active forge ideas surface in the living briefing dashboard as Opportunity items. ForgeAdapter (scripts/briefing/adapters/forge.py) calls list_ideas() and maps each active idea's stage onto a briefing state and importance score:

Forge stage Briefing state Importance
spark spotted 0.30
smelt evaluating 0.50
shape evaluating 0.70
forge pursued 0.85

Terminal-stage ideas (shipped/killed/archived) are skipped, since list_ideas() excludes them by default. Each candidate carries the idea's stage, origin, complexity, appetite, tags, and last-touched date in its metadata, with the problem statement (if any) as the summary. This is how an idea moving through the pipeline becomes visible in the daily briefing without any extra wiring.

File Format

Each idea is a markdown file with YAML frontmatter at data/forge/NNN-slug.md. The three-digit ID is zero-padded and sequential. The slug is derived from the title (for sparks) or the problem statement (after smelting).

Frontmatter Fields

---
id: "007"
title: "Example Idea Title"
stage: "smelt"
origin: "bio-zack"
project: "proj_abc123"
created: "2026-02-21"
last_touched: "2026-02-24"
appetite: "unknown"
complexity: "complex"
problem_statement: "One-sentence statement of the underlying problem."
evidence: "A concrete instance of the problem occurring."
last_author: "silicon-zack"
tags: ["example", "placeholder"]
related_ideas: []
---

The fields are emitted in a fixed order by _write_idea() (core.py); any unrecognized keys are appended after the known ones.

Field Values Notes
id 3-digit string Sequential, zero-padded
title string Short descriptive title
stage spark, smelt, shape, forge, shipped, killed, archived Current stage
origin bio-zack, silicon-zack Who created the idea
project string Optional project-registry id (Python-API-only; not set via REST)
created YYYY-MM-DD Creation date
last_touched YYYY-MM-DD Last modification date
appetite tiny, small, medium, large, unknown Size/effort estimate (required before forge)
complexity clear, spike, complex Cynefin-lite classification (defaults to complex on create)
problem_statement string Added during smelt
evidence string Concrete instance of the problem
last_author string Who last modified the idea
tags list of strings Categorization
related_ideas list of strings IDs of related ideas

Body Structure

The markdown body evolves as the idea progresses:

Spark:

# Title

## Spark
*2026-02-24 | bio-zack*

Description of the idea.

After smelt:

# Title

## Problem
Problem statement here.

**Evidence:** Concrete example.

## Original Spark
*2026-02-24 | bio-zack*

Original description.

### Smelted - 2026-02-24

Entries are appended:

### 2026-02-24 | silicon-zack
Research notes or thoughts added via add_entry().

### Research Notes - 2026-02-24 | silicon-zack
Entry with an explicit section header.

Stage transitions are recorded (the body uses a unicode arrow):

### Stage: smelt β†’ shape (2026-02-24)

Kill notes:

### Killed - 2026-02-24
**Reason:** Superseded by newer approach
**Learned:** The capture pattern was useful

Data Files

Path Purpose
data/forge/NNN-slug.md Individual idea files
data/forge/_index.md Auto-generated dashboard (rebuilt during /sleep)
scripts/forge/core.py Core implementation
scripts/forge/__init__.py Public API exports
api/src/routers/forge.py REST API router
scripts/briefing/adapters/forge.py Briefing adapter (ideas β†’ Opportunity items)
.claude/skills/forge/SKILL.md Skill definition for auto-triggers

Integration with /sleep

During the nightly /sleep cycle (00:30 PT), the forge gets a full review:

  1. Sparks >3 days old - Silicon-Zack attempts to smelt them by articulating the problem and evidence. If the spark was solution-first, trace back to the underlying problem.
  2. Smelts - Add research, explore the solution space, attempt advance to shape if promising.
  3. Shapes - Check appetite, verify solutions are still relevant.
  4. Forges - Check progress, verify scope has not crept.
  5. Stale ideas >14 days - Recommend kill or archive.
  6. Complexity triage - Route any "clear" items to the task list during review.
  7. Silicon-Zack origination - If fewer than 3 unengaged silicon sparks exist and a pattern or idea emerged tonight, create a new spark.
  8. Weekly (Sundays) - Generate forge status summary. Flag kill candidates. Resurface one random archived idea.

rebuild_index() runs at the end to keep the dashboard fresh.

Design Principles

  • Sparks are free. Never hesitate to capture. Cost of loss far exceeds cost of noise.
  • Smelting is the gate. Can you articulate the problem and show evidence? If not, keep sparking.
  • Known fixes don't belong here. If complexity is "clear", route to the task list.
  • Killing is gardening. A killed idea is a decision made.
  • Small forge, high temperature. Few ideas, frequently touched, beats many ideas gathering dust.

Where to go next

  • Executive Loop β€” the autonomous OODA cycle that runs /sleep, where the forge gets its nightly review.
  • Living Briefing β€” where active forge ideas surface as Opportunity items.
  • Project Registry β€” the project field links an idea back to a registered project.
  • Improve β€” the sibling system for system-improvement proposals.