feat(workflow): research plans, coding builds — the split was a fiction
deploy / test (push) Successful in 4m1s
deploy / build (push) Successful in 1m36s

`rust_sdlc` gives the research team coding roles and a writable /mission/repo,
so research implemented what it found and the coding phase then opened a clean
tree, produced +0/-0 and failed on the empty-delivery rule. Mission 01a00c57
ended exactly that way: research shipped both INT items itself (+276/-57),
coding delivered nothing.

Worse than the wasted phase is WHERE the code landed. Research ran under a gate
that does not check tests, so its two source changes reached a branch with
`tests_status: null` — never compiled by the gate, never run. Keeping
implementation in the coding phase is what puts it behind `on_green_tests`.

Research now carries a `task` that scopes it to the brief and says plainly that
editing crates/ is not its job this phase, plus a `done_when` describing what
the brief must CONTAIN. The no-source-edits constraint deliberately lives in
the prose and NOT in `done_when`: "and nothing else" phrasings measurably make
a judge invent requirements it was never given.

Coding gets the counterpart `task`: implement the brief's items, one commit
each, tests green. Stated explicitly because a phase that finds a clean tree
and no instructions has historically written a REPORT about the work instead of
doing it — four documentation commits and one implementation, on the run that
became the haiku baseline branch.

Research also gets `commit_policy = "on_green_tests"` as a safety net, so
source it writes anyway still has to pass the suite.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-08-16 16:48:05 -07:00
co-authored by Claude Opus 5
parent d341640255
commit a582dea4fc
@@ -11,6 +11,44 @@ order_idx = 0
[phases.config] [phases.config]
produces = ["md", "pdf"] produces = ["md", "pdf"]
default_topology = "hub_spoke" default_topology = "hub_spoke"
# Research PLANS; coding BUILDS. Without this the split is a fiction:
# `rust_sdlc` gives the research team coding roles and a writable
# /mission/repo, so it implements what it finds and the coding phase then
# opens a clean tree, produces an empty diff and fails. That is exactly how
# mission 01a00c57 ended — research shipped both INT items itself
# (+276/-57) and coding delivered +0/-0.
#
# It also matters WHERE the work lands: research runs under a gate that
# does not check tests, so anything it implements reaches a branch without
# `cargo test` ever running. Keeping implementation in the coding phase is
# what puts it behind `on_green_tests`.
task = """
Produce the implementation brief. Do NOT change source files — the coding \
phase implements what you specify, and it can only do that if you leave it \
something to build.
Write research/IMPLEMENTATION_BRIEF.md. Give every proposed change its own \
numbered INT item, and for each one state: the target file path, the problem \
with the code as it stands, and the change you propose. Read the repository's \
own ROADMAP.md, IMPROVEMENT_LOG.md and CLAUDE.md first so you do not re-propose \
work already merged.
Reporting that an area is already sound is a real result — say so and move on \
rather than manufacturing an item for it.
Writing or editing files under research/ is expected. Editing anything under \
crates/ or src/ is not your task this phase.
"""
# The goal is stated as what the tree must CONTAIN — never "and nothing
# else", which measurably makes a judge invent requirements. The
# no-source-edits constraint lives in `task` above for that reason.
done_when = "research/IMPLEMENTATION_BRIEF.md exists and describes each proposed change as a numbered INT item carrying its target file path, the problem, and the proposed fix"
max_iterations = 2
# Safety net, not the main control. If research edits source anyway, that
# code still has to pass the project's own suite before it reaches a
# cleanly-named branch — the gap that let two untested source changes ship
# on mission 01a00c57.
commit_policy = "on_green_tests"
[[phases]] [[phases]]
kind = "coding" kind = "coding"
@@ -33,6 +71,27 @@ loop = "until_no_more_int_items"
# requirements it was never given. # requirements it was never given.
done_when = "the repository contains an implementation for each INT-XX item listed in the research phase's IMPLEMENTATION_BRIEF, and `cargo test` passes" done_when = "the repository contains an implementation for each INT-XX item listed in the research phase's IMPLEMENTATION_BRIEF, and `cargo test` passes"
max_iterations = 3 max_iterations = 3
# The counterpart to the research phase's `task`: research left a brief and
# no code, so this phase's input is that brief and its output is working
# source. Stated explicitly because a phase that finds a clean tree and no
# instructions has historically written a report about the work instead of
# doing it — four documentation commits and one implementation, on the run
# that produced the haiku baseline branch.
task = """
Implement the INT items in research/IMPLEMENTATION_BRIEF.md.
Work through them in order. For each item, change the real source under \
crates/, run the project's tests, and commit that item before starting the \
next one. A commit per item is what lets a reviewer see which change belongs \
to which finding.
`cargo test` must pass when you are done — the branch is only published \
untagged if it does, and a run that leaves the suite red is not finished.
Writing a document that describes the change does NOT implement it. If you \
believe an item should not be built, say so plainly and explain why rather \
than marking it complete.
"""
# Preamble injected at the head of each iteration's task text so # Preamble injected at the head of each iteration's task text so
# the agents know where the repo lives + how to commit. Covered by # the agents know where the repo lives + how to commit. Covered by
# Slice 3.5c's `workspace-repo-commit-protocol` skill. # Slice 3.5c's `workspace-repo-commit-protocol` skill.