Architecture

Architecture (V1)

V1 long-form archive. Pre-precision-pass version, preserved for engineers who prefer the dense narrative. New (V2) version: ../architecture.html.

Problem and Motivation

Individual-contributor engineers and QAs currently split work across Jira, Confluence, service repos, automation repos, and ad-hoc prompts. They want a single harness to take one or more Jira epics, generate a PRD, engineering spec, TDD, ERD, ADRs, BDDs, test cases, and a test spec; wear PM / architect / staff-engineer / UX hats without switching tools; share generated drafts with the counterpart (dev ↔ QA) via git for review and approval; plan code changes across multiple service repos in a single ralph workspace-mode session; dispatch parallel autonomous ralph loops; and keep the workbench private, per-bundle, and disposable — not a long-running OS.

Two-Repo Shape

The harness is two GitHub repos, independent, published under <your-org> (defaults to your GitHub login).

Repo Role Lives at
ai-workbench Template. Cloned per work-bundle. Ships skills, scripts, lifecycle aliases, config templates. https://github.com/amit-t/ai-workbench
ai-devkit Global CLI. Installs init.wb, join.wb, update.wb. https://github.com/amit-t/ai-devkit

You never clone ai-workbench directly — init.wb stamps private instances from it via gh repo create --template.

Workbench Directory Tree

A stamped workbench (wb-<label>) looks like this:

wb-<label>/
├── CLAUDE.md                         # session start, plan-mode, role inference
├── AGENTS.md                         # shared agent constitution (Claude + Devin + Codex)
├── README.md                         # what this template does + how to use init.wb
├── .gitignore
├── .workbench-manifest.json          # which paths are template-owned vs user-owned
├── .mcp.json.template                # optional MCPs (Jira, Figma) — env-ref style
├── project.conf                      # filled in by init.wb (identity, epics, repos)
├── EPIC-PIPELINE.md                  # pipeline rollup — one H2 per epic
├── aliases.sh                        # wb.* commands sourced per workbench
├── .github/
│   └── CODEOWNERS                    # initiator + joiners appended
├── product/
│   ├── context-library/
│   │   └── epics/                    # pulled Jira epic bodies (one MD per epic)
│   └── outputs/
│       └── prds/                     # PRDs (lifecycle tracked in .workbench-state/)
├── design/
│   ├── context-library/
│   │   ├── figma-links.md
│   │   └── design-system-ref.md
│   └── outputs/
│       ├── wireframes/
│       ├── screens/
│       └── handoffs/
├── engineering/
│   ├── context-library/
│   └── outputs/
│       ├── specs/                    # engineering spec
│       ├── tdd/                      # technical design docs
│       ├── erd/                      # entity/component diagrams
│       └── adrs/                     # architecture decision records
├── qa/
│   ├── context-library/
│   └── outputs/
│       ├── bdd/                      # Gherkin .feature files
│       ├── test-cases/               # structured test cases (MD or CSV)
│       ├── test-spec/                # QA equivalent of engineering spec
│       └── test-erd/                 # test coverage model
├── ralph/
│   ├── workspace-plan.md             # human-readable rollup of per-repo fix_plans
│   └── dispatch.log                  # parallel loop launch log (gitignored)
├── repos/                            # gitignored — code repos cloned here
│   └── .gitkeep
├── .workbench-state/                 # lifecycle state (shared via git)
│   ├── published.json                # draft → published transitions
│   ├── approved.json                 # published → approved transitions (ralph gate)
│   └── rejected.json                 # reason-tracked rejections
├── steering/                         # template-owned rule files (golden, role, artifact, topic)
├── steering.local/                   # team-owned overlays (add / supersede / remove)
├── .claude/
│   └── settings.json                 # PostToolUse hook re-emits Layer 0 steering on update
├── scripts/
│   ├── lifecycle.py                  # unified publish/approve/reject CLI with flock
│   ├── sync-context.sh               # workbench → repos/{x}/ai/, writes pr_footer.md
│   ├── ralph-context.sh              # internal alias for sync-context.sh, used by ralph-plan
│   ├── ralph-plan.sh                 # wraps `ralph-plan --workspace` with per-repo fallback
│   ├── ralph-dispatch.sh             # wraps `ralph --workspace --parallel N`
│   ├── ralph-enable-check.sh         # preflight that `ralph enable --workspace` ran
│   ├── validate-artifact.py          # blocks publish/approve when target_repos is missing
│   ├── artifact-schema.json          # JSON schema used by validate-artifact.py
│   ├── steering-load.py              # merge template + overlay rules for a scope
│   ├── steering-overlays.py          # render add/supersede/remove footer for ralph PRs
│   ├── steering-lint.py              # validate steering/ and steering.local/
│   ├── steering-post-tool-hook.sh    # Claude Code PostToolUse hook for steering freshness
│   └── register-repo.sh              # append a repo entry to project.conf
├── tests/                            # template smoke tests
│   ├── README.md
│   └── smoke.sh
└── skills/                           # symlinked into .claude/.agents/.devin at init
    ├── epic-intake/SKILL.md
    ├── prd-draft/SKILL.md
    ├── prd-review-panel/SKILL.md
    ├── bdd-gen/SKILL.md
    ├── test-cases-gen/SKILL.md
    ├── test-spec/SKILL.md
    ├── eng-spec/SKILL.md
    ├── tdd/SKILL.md
    ├── erd/SKILL.md
    ├── adr/SKILL.md
    ├── figma-pull/SKILL.md
    ├── ds-screen-gen/SKILL.md
    ├── design-draft/SKILL.md
    ├── design-review/SKILL.md
    ├── ralph-workspace-plan/SKILL.md
    ├── ralph-dispatch/SKILL.md
    ├── grill-me/SKILL.md
    └── pmo-status/SKILL.md

project.conf — The Per-Workbench Manifest

project.conf is a committed shell file written by init.wb and extended by join.wb. Aliases and scripts source it.

#!/usr/bin/env bash
# Workbench configuration — written by init.wb, appended by join.wb

# --- Identity ---
WORKBENCH_LABEL="example"
WORKBENCH_REPO="https://github.com/<your-org>/wb-example"
WORKBENCH_TEMPLATE_UPSTREAM="https://github.com/<your-org>/ai-workbench"
WORKBENCH_CREATED_BY="<gh-user>"
WORKBENCH_CREATED_AT="2026-04-23"

# --- Epics in scope ---
EPICS=("EPIC-001" "EPIC-002")

# --- Managed code repos ---
# Each entry: name=<name>;url=<git_url>;role=<service|automation-tests|shared-lib|infra>;stack=<short>;added_by=<gh-user>
REPOS=(
  "name=example-service;url=https://github.com/<your-org>/example-service;role=service;stack=node-nest;added_by=<gh-user>"
  "name=example-automation-tests;url=https://github.com/<your-org>/example-automation-tests;role=automation-tests;stack=playwright;added_by=<qa-gh-user>"
)

.workbench-manifest.json — Template-Owned vs User-Owned

Only paths in template_owned are touched by update.wb. Everything else (your PRDs, specs, BDDs, test cases, code repos, lifecycle state) is user_owned and never overwritten.

{
  "version": 2,
  "template_owned": [
    "CLAUDE.md",
    "AGENTS.md",
    "README.md",
    "aliases.sh",
    ".gitignore",
    ".workbench-manifest.json",
    ".mcp.json.template",
    "project.conf.template",
    "EPIC-PIPELINE.md.template",
    ".claude/settings.json",
    ".github/CODEOWNERS",
    ".github/workflows/**",
    "scripts/**",
    "skills/**",
    "steering/**",
    "tests/**"
  ],
  "user_owned": [
    "project.conf",
    "EPIC-PIPELINE.md",
    ".mcp.json",
    "product/**",
    "design/**",
    "engineering/**",
    "qa/**",
    "ralph/**",
    "repos/**",
    "steering.local/**",
    ".workbench-state/**"
  ]
}

Rules:

Lifecycle

Every generated artifact (PRD, spec, TDD, ERD, ADR, BDD, test cases, test spec) flows through draft → published → approved. See Artifact lifecycle for the full state machine, downstream preconditions, and lifecycle commands.

Version Notifications

Meaningful wb.* commands (publish, approve, reject, sync-context, ralph-plan, ralph-dispatch, register-repo, steering*) fire a one-shot version check on the first call per 12-hour window. If a newer ai-workbench template is available upstream, a one-line banner is printed before the command runs; the check is fail-open, so offline runs are silent. Trivial list aliases (wb.published, wb.approved, wb.rejected) skip the check. See Versioning + upgrades for the full mapping and the wb.upgrade flow.

Security Model

Naming Rules