Skip to content

thirdshift architect --plan-only: the Architecture review publishes a plan and thirdshift marks it ready - #240

Merged
JacobStephens2 merged 3 commits into
issue-27from
issue-230
Oct 1, 2026
Merged

JacobStephens2 merged 3 commits into
issue-27from
issue-230

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

thirdshift architect [<focus>] --plan-only starts an Architect run from the Launch directory, with no Issue URL.

thirdshift architect "the Spec run" --plan-only
  preflight                      # origin is on GitHub, git identity, HEAD not detached,
                                 # Base branch on origin and not ahead; no Origin match
  launch pull                    # only with launch.pull = true
  worktree <repo>-architect      # detached at origin/<base>, no Issue branch
    Architecture review          # session prompt: prompt::architecture_review(base, focus)
  remove the worktree            # whatever the outcome
  read the final message's last line
    "Architecture review plan: <Issue URL>"
  check the plan                 # in this repository, open, created since the run started,
                                 # not labelled ready-for-human / needs-info / wontfix
  swap needs-triage -> ready-for-agent   # one PUT, other labels kept
  stdout: <plan URL>, exit 0

Any failure after the review starts exits 1 with the cause, then the session log, and changes no label.

 src/
+├── architect.rs     # the Architect run: review, Report (final line), plan checks, label swap
 ├── args.rs          # + Command::Architect, parsed only as the first argument
 ├── issue.rs         # + Repo::of_origin; the Origin match now uses it
 ├── worktree.rs      # + ReviewWorktree: detached, always removed
 ├── session.rs       # + Sessions::run_to_final_message; Logs named for a Run or an Architect run
 ├── prompt.rs        # + architecture_review, and the three final-line prefixes
 ├── github.rs        # + issue (state, labels, createdAt), set_labels
 ├── spec_run.rs      # unready_label now answers for any issue's labels
 └── main.rs          # + architect(), help text
 prompts/
+└── architecture-review.md   # generated
 tests/
+├── architect_run.rs # 20 end-to-end cases
 └── fakes/           # gh: issue create, labels, createdAt; claude: a final message

Three things to know before merging:

Evidence

  • Before: thirdshift architect --plan-only → not a GitHub issue URL: architect, exit 2.
    After: cargo test --test architect_run → 20 passed. The cases:

    plan-only marks the published Ticket ready and prints its URL
    plan-only marks a published Spec ready, leaving its Tickets and other labels
    the Session prompt names the Factory skills, the Base branch and the final line
    a focus goes into the Session prompt
    the review runs detached at origin's Base branch; the Launch directory is never touched
    progress lines cover the review starting, the plan it reported and the label swap
    a failing / interrupted session fails the run and leaves needs-triage
    no final line, or a malformed one, fails the run
    a closed plan / one older than the run / one with another unready label / one in another repository is refused
    detached HEAD, Base branch ahead of origin, no git identity, non-GitHub origin: rejected before any work
    launch pull brings the Launch directory's Base branch up to date first
    
  • Full suite: cargo test → 490 passed, 0 failed. cargo fmt --check and cargo clippy --all-targets -- -D warnings are clean.

  • Parser unit tests cover architect with and without a focus, --plan-only on either side, stray arguments, and architect anywhere but first.

Unaddressed findings

Standards

  • "launch repository" in new src/worktree.rs docs (CONTEXT.md avoids "launch repo"): the file already uses that wording throughout; changing only the new lines would make it inconsistent, and rewording the whole file is outside this Ticket.
  • run::pull_base_branch(&launch, Some(&base), &base) passes the same value twice: the two differ for a Run (a Continuation's base, a detached HEAD); one odd call is cheaper than a second function.
  • ReviewWorktree's drop repeats Worktree's lock-and-remove shape: Worktree also deletes the Issue branch and can be kept; the shared part is three lines.
  • log.exists().then_some(log) mirrors failed_run::fail: one expression; not worth a helper.
  • An empty units slice stands for "sent by an Architect run" on the prompts page: one prompt has no unit; a sender type can come when a second does.
  • (logs, log) travel with base/focus: mirrors the Run's code; bundling them here alone would diverge from it.
  • One-field ArchitectArgs: parallels RunArgs, and Architect run dispatches its plan as a Spec run or a Run #232 adds its flags.

Spec

  • --plan-only is mandatory, not optional: without dispatch (Architect run dispatches its plan as a Spec run or a Run #232) a bare architect would have to do the same thing silently; an argument error says so.
  • A real run needs Headless Factory skills for the Architecture review #229's skills: out of scope here; called out above.
  • Idea and already-filed lines are parsed, then fail the run: the format has to be defined in one place now; making them succeed is Architect run with no Strong candidate: idea issue or already filed #231.
  • A fourth plan check, that the plan is in this repository: thirdshift is about to change labels on the issue the agent named, and Architect run: thirdshift finds and implements a Strong deepening opportunity unattended #27 asks that it "never dispatches the wrong issue".
  • An empty or dash-led focus is rejected: keeps a mistyped flag from becoming the focus.
  • architect merge --plan-only takes merge as the focus: Architect run dispatches its plan as a Spec run or a Run #232 owns merge, no-merge and parallel on architect, including rejecting them with --plan-only.
  • Refactors on the Run path (Repo::of_origin, Logs constructors, main.rs helpers): needed so the Architect run shares the Run's code instead of copying it; the existing suite passes unchanged.
  • "Created after the run started" compares GitHub's time with the local clock: a clock wrong by more than the length of a review is needed to misjudge it; a clock-free check is a bigger design than this Ticket.
  • Nothing requires needs-triage to be present before the swap: the spec's check is "no unready triage label other than needs-triage"; a plan without it still ends ready-for-agent.
  • A git worktree add that fails partway can leave <repo>-architect behind: same as a Run's worktree today; not reproduced.
  • An interrupt during the label write reports interrupted though the swap may have landed: one request wide; not reproduced.

Merge Danger

Door: two-way

A new command and new code paths; reverting the PR removes them. The fixed-format final line is the one thing #229 and #231 will build on.

Blast Radius: contained

The Run path changes only by refactor: the Origin match goes through Repo::of_origin, log names through Logs::of_run, and spec_run::unready_label takes labels rather than a Ticket. thirdshift help gains a wider usage column and an architect paragraph.

Closes #230

🤖 Generated with Claude Code

JacobStephens2 and others added 3 commits October 1, 2026 02:20
…es a plan and thirdshift marks it ready

An Architect run starts from the Launch directory with no Issue URL. It
makes the Run preflight checks that need no issue, the opt-in launch pull,
and runs the Architecture review in a worktree detached at the Base
branch's head on origin. It reads the fixed-format last line of the
review's final message, checks the plan it names, swaps needs-triage for
ready-for-agent in one request, and prints the plan's URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Unready Ticket labels stay in the Spec run, which now answers for any
issue's labels. Marking the plan ready is split from reading the report and
checking the plan. Sessions::run_to_final_message says it runs a session,
and the three gh issue reads share one helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant