DinoStack

A protocol for shipping software with AI agents

How to tell it's working

The protocol is observational. The conductor narrates delegations as it runs - listen for phrases like:

  • Routing this through orchestration-planner - multiple phases involved.
  • Spawning architect to produce a plan before any code lands.
  • Spawning engineer to implement the cache layer.
  • Handing off to skeptic for adversarial review.
  • Spawning debugger on the failing test.
  • QA engineer verifying acceptance criteria in the browser.
No narration? The task was classified Direct action - handled in the main thread without a subagent. That is the protocol working, not off.

What it is

  • A portable methodology for AI-assisted software development
  • Loaded as a skill - it shapes how your agent plans, implements, and reviews code
  • Mostly passive: you don't drive it with commands
  • Risk-aware delegation, adversarial review, focused sessions
  • Tool-agnostic: Claude Code, Cursor, Codex, Gemini CLI, Kimi, OpenCode, and more
Not a framework you call into. A living protocol that shapes every response, every task, every review - in the background.

What a typical session feels like

  1. You state a goal in plain English - "fix the bug in X", "add feature Y"
  2. The agent classifies risk - small edit vs. real change
  3. Small stuff is handled directly, in the conversation
  4. For bigger work, the agent proposes a plan - agents to spawn, sequencing, review gates
  5. You review the plan together - push back, adjust scope, approve. This is the key decision point.
  6. Approved plan executes: Worker in an isolated worktree, then Skeptic review
  7. You read the summary and decide: ship, revise, or drop
The planning step is collaborative - the agent proposes, you refine. Implementation only starts after you approve.

What you actually get

Fewer regressions
Nothing meaningful merges without an adversarial Skeptic pass. Critical findings block.
Focused sessions
One goal per session. Explicit handoffs. Context stays narrow, output stays sharp.
Better reviews
Every non-trivial change ships with a pre-mortem, a review brief, and a classified findings list.
Institutional memory
Learnings, conventions, and decisions persist across sessions instead of dying with the chat.

A small command surface

Command When you'd reach for it
/ds-init-project One-time setup when bringing the protocol into a repo
/ds-brief Open a planning dialogue before architect/engineer spawn
/ds-implement-ticket Run a ticket end-to-end: architect -> engineer -> skeptic -> PR
/ds-skeptic Force a review pass on recent changes
/ds-wrap On-demand session summarization and memory capture
/ds-memory-update Persist a learning you want to keep
Most sessions don't invoke any of these. Commands are accents, not the interface.

Under the hood - risk classification

The main session agent classifies each task as Trivial, Low, or Elevated, then routes it.

Trivial / Low

  • Reads, answering from memory
  • Screenshots, diagnostic logging
  • Small, reversible edits
  • Trivial work goes to an isolated engineer; Low is direct action

Elevated

  • Writing or changing code
  • Multi-file changes, migrations
  • Spawns Worker + Skeptic in the background
  • Review loop runs automatically
When in doubt, the agent classifies Elevated. The cost of a review is cheap; the cost of a bad change is not.

Under the hood - risk classification (tier declaration)

Tier declaration: every Elevated spawn carries a required Tier: line. Tier 1 = Haiku (opt-in, shallow tasks), Tier 2 = Sonnet (implementation default), Tier 3 = Opus or above (opus/fable; review default: skeptic, security-auditor). Each agent's frontmatter model: is the default; pass a param only to override. Authoring roles (architect, adr-generator, product-discovery) also escalate to Tier 3 on Plan+ADR-tier units.

Under the hood - implicit Trivial batching

Related Trivial tweaks share one draft PR instead of one per change - no command, no configuration.

  • Say "make the border 1px" - it commits, pushes, and opens a draft PR on the first tweak
  • The next related tweak lands on that same PR instead of opening a fresh one
  • Every tweak is still risk-classified and CI still runs on every push; one that turns out non-Trivial mid-batch still gets full adversarial review
  • "Ship it" (or moving to unrelated work, or wrapping the session) marks the PR ready and merges it
The draft state is a mechanical merge gate - gh pr merge refuses a draft PR either way. Once it's open, point a worktree at the tweak branch (fast-forward after each push) to watch changes land live. Needs gh; without it, tweaks fall back to one PR per change.

Under the hood - the agent team

investigator
Maps unfamiliar code
debugger
Root-cause analysis
orchestration-planner
Picks the team and sequencing
architect
Designs before coding
engineer
Implements changes
skeptic
Adversarial review
qa-engineer
Runtime verification
security-auditor
Threat modeling
adr-generator
Decision records
adr-drift-detector
ADR compliance audit
perf-analyst
Performance profiling
release-orchestrator
End-to-end release sequencing
dependency-auditor
Supply-chain review
product-discovery
Shapes intent before planning
learning-extractor
Mines resolved loops for learnings
learnings-agent
Captures learnings on the mandatory triggers
wrap-ticket
Closes out a ticket end-to-end
goal-condition-evaluator
Cheap stop-condition check for open-goal loops

The persistence loop - Engineer -> Skeptic -> QA

Phase 6: Skeptic loop (max 3 fix passes)          Phase 6b: QA loop (max 3 fix passes)
─────────────────────────────────────────         ─────────────────────────────────────
Engineer implements                               (only runs if Phase 6 exits cleanly)
    │
Skeptic reviews ──> sign-off? ──> Phase 6b ──>  QA verifies ──> PASS? ──> Phase 7
    │ Critical/Major found?                           │ failures?
    └── Engineer fix pass ──> loop back              └── Engineer fix pass ──> loop back
    │ cap_reached / convergence? ──> ESCALATE        │ cap / convergence? ──> ESCALATE
  • 3 fix passes per phase - caps are independent (Skeptic cap and QA cap are separate budgets)
  • findings_log carries forward - prior findings tracked by ID; closed findings are not re-litigated
  • Convergence failure - one re-raise of a Critical finding after a claimed fix triggers immediate escalation (does not wait for a second attempt)
  • Escalation reasons: cap_reached, convergence_failure, blocked
The loop is a named protocol primitive - not ad-hoc re-routing. Every iteration emits a breadcrumb: [loop: skeptic | iteration 2/3 | open findings: 1 Critical]
Loop durability: state is written per ticket to .agentic/loop-state-<LOOP_KEY>.json at each phase transition (atomic write), superseding the single legacy .agentic/loop-state.json. Two tickets in one checkout never contend. Loops survive rate limits and session exits — the next session resumes that ticket's own state from the last phase boundary via /ds-implement-ticket's built-in resume check.

When the loop stalls

cap_reached
3 fix passes ran. An unresolved Critical always escalates - the cap never ships a Critical. Otherwise the conductor ships (accepted debt in the PR body) or escalates, per operator approval inside Phase 6 today.
convergence_failure
Skeptic re-raised a Critical finding after the Engineer claimed to fix it. One re-raise is enough - the loop does not wait for a second attempt. Signals a design conflict, not an implementation mistake.
blocked
Engineer returned BLOCKED - hit a design conflict that fix passes cannot resolve. Treated as immediate escalation regardless of iteration count.

The conductor surfaces the raw finding history and waits for human direction. It does not synthesize fix suggestions.

The loop terminates cleanly or escalates. It never runs forever.

Parallel fan-out - N engineers in one message

When orchestration-planner returns 2+ independent units, /ds-implement-ticket Phase 5 fans out:

orchestration-planner
  unit A (merge_order:1, skeptic_strategy:per-unit)
  unit B (merge_order:2, skeptic_strategy:per-unit)
         │
         ▼  single message (parallel)
  ┌──────────────┐    ┌──────────────┐
  │ worktree A   │    │ worktree B   │
  │ engineer A   │    │ engineer B   │
  │ → skeptic A  │    │ → skeptic B  │
  │ (P0 loop)    │    │ (P0 loop)    │
  └──────┬───────┘    └──────┬───────┘
         └────── join ───────┘
               │
         sequential --no-ff merge
         (merge_order: A then B)
               │
         post-merge quality check
Each unit runs its own P0 persistence loop. "Done" = Skeptic signed off, not first commit.

Fan-out join conditions

After all N engineers return, conductor evaluates the join:

All-done
All units reach status: done (Skeptic signed off). Proceed to sequential merge in merge_order.
Partial success
Some done, some failed. Merge green units. Retry failed unit once (depth=1) with preserved worktree. Second failure escalates.
Total failure
All units failed. Clean up worktrees. Escalate with full failure outputs - recommend sequential fallback.
Blocked
Any unit returned Status: BLOCKED. Treat as failed. Conductor cannot resolve - escalate immediately.
Task state tracked in .agentic/tasks.jsonl. Conductor appends all entries across agents (never a rewrite) - workers return summaries only; a task-state fold makes concurrent-session reads safe.

Regression test obligation

Every Critical or Major finding that gets fixed without a test is a latent regression. The fix loop closes the gap:

Per-finding regression test
Worker adds a test that would have failed without the fix. Skeptic verifies it exists before sign-off. Lives in the project test suite.
The regression test is code-level: it catches the specific failure mode so the same bug cannot silently reappear in a future change.

Ship with confidence

Risk-aware delegation. Adversarial review. Focused sessions.
Mostly passive - just describe the work.

github.com/Space-Dinosaurs/DinoStack