Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions codev-skeleton/protocols/aspir/builder-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,23 @@ Follow the implementation plan at: `{{plan.path}}`
{{task_text}}
{{/if}}

## Multi-PR Workflow
## PR Strategy

Your worktree is persistent — it survives across PR merges. You can produce multiple PRs sequentially:
**Do not autonomously open a PR per implementation phase.** Plan phases ship as git commits within a single PR, not as separate PRs. The plan's instruction that "each phase commits independently" refers to git commits, not PRs.

By default, the PR is opened during/after the final implement phase, with all phase-commits already on the branch.

### Architect-requested PRs

The architect MAY request a PR at any point — for spec review, mid-implementation feedback, slicing a large spec into shippable PRs, etc. When the architect explicitly asks for a PR earlier (or for additional PRs), follow that direction. The prohibition is specifically on the *builder* autonomously deciding to open per-phase PRs without architect request.

### Multi-PR Mechanics (when the architect requests sequential PRs)

Your worktree is persistent — it survives across PR merges. When the architect asks for sequential PRs (e.g., to slice a large spec into shippable pieces), use this loop:

1. Cut a branch, open a PR, wait for merge
2. After merge: `git fetch origin main && git checkout -b <next-branch> origin/main`
3. Continue to the next phase, open another PR
3. Continue to the next slice, open another PR

**Important**: Do NOT run `git checkout main` — git worktrees cannot check out a branch that's checked out elsewhere. Always branch off `origin/main` via fetch.

Expand Down
16 changes: 13 additions & 3 deletions codev-skeleton/protocols/spir/builder-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,23 @@ Follow the implementation plan at: `{{plan.path}}`
{{task_text}}
{{/if}}

## Multi-PR Workflow
## PR Strategy

Your worktree is persistent — it survives across PR merges. You can produce multiple PRs sequentially:
**Do not autonomously open a PR per implementation phase.** Plan phases ship as git commits within a single PR, not as separate PRs. The plan's instruction that "each phase commits independently" refers to git commits, not PRs.

By default, the PR is opened during/after the final implement phase, with all phase-commits already on the branch.

### Architect-requested PRs

The architect MAY request a PR at any point — for spec review, mid-implementation feedback, slicing a large spec into shippable PRs, etc. When the architect explicitly asks for a PR earlier (or for additional PRs), follow that direction. The prohibition is specifically on the *builder* autonomously deciding to open per-phase PRs without architect request.

### Multi-PR Mechanics (when the architect requests sequential PRs)

Your worktree is persistent — it survives across PR merges. When the architect asks for sequential PRs (e.g., to slice a large spec into shippable pieces), use this loop:

1. Cut a branch, open a PR, wait for merge
2. After merge: `git fetch origin main && git checkout -b <next-branch> origin/main`
3. Continue to the next phase, open another PR
3. Continue to the next slice, open another PR
4. Repeat

**Important**: Do NOT run `git checkout main` — git worktrees cannot check out a branch that's checked out elsewhere. Always branch off `origin/main` via fetch.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
id: bugfix-744
title: spir-builder-prompt-ambiguous-
protocol: bugfix
phase: verified
plan_phases: []
current_plan_phase: null
gates: {}
iteration: 1
build_complete: false
history: []
started_at: '2026-05-14T20:58:56.293Z'
updated_at: '2026-05-14T21:12:13.608Z'
10 changes: 10 additions & 0 deletions codev/protocols/aspir/builder-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ Follow the implementation plan at: `{{plan.path}}`
{{task_text}}
{{/if}}

## PR Strategy

**Do not autonomously open a PR per implementation phase.** Plan phases ship as git commits within a single PR, not as separate PRs. The plan's instruction that "each phase commits independently" refers to git commits, not PRs.

By default, the PR is opened during/after the final implement phase, with all phase-commits already on the branch.

### Architect-requested PRs

The architect MAY request a PR at any point — for spec review, mid-implementation feedback, slicing a large spec into shippable PRs, etc. When the architect explicitly asks for a PR earlier (or for additional PRs), follow that direction. The prohibition is specifically on the *builder* autonomously deciding to open per-phase PRs without architect request.

## Notifications
Always use `afx send architect "..."` to notify the architect at key moments:
- **Gate reached**: `afx send architect "Project {{project_id}}: <gate-name> ready for approval"`
Expand Down
10 changes: 10 additions & 0 deletions codev/protocols/spir/builder-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ Follow the implementation plan at: `{{plan.path}}`
{{task_text}}
{{/if}}

## PR Strategy

**Do not autonomously open a PR per implementation phase.** Plan phases ship as git commits within a single PR, not as separate PRs. The plan's instruction that "each phase commits independently" refers to git commits, not PRs.

By default, the PR is opened during/after the final implement phase, with all phase-commits already on the branch.

### Architect-requested PRs

The architect MAY request a PR at any point — for spec review, mid-implementation feedback, slicing a large spec into shippable PRs, etc. When the architect explicitly asks for a PR earlier (or for additional PRs), follow that direction. The prohibition is specifically on the *builder* autonomously deciding to open per-phase PRs without architect request.

## Notifications
Always use `afx send architect "..."` to notify the architect at key moments:
- **Gate reached**: `afx send architect "Project {{project_id}}: <gate-name> ready for approval"`
Expand Down
60 changes: 60 additions & 0 deletions packages/codev/src/__tests__/bugfix-744-spir-pr-strategy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Regression test for GitHub Issue #744
*
* The SPIR/ASPIR builder-prompt templates did not state the PR-strategy
* convention explicitly. Builders interpreted "each phase commits
* independently" as "each phase gets its own PR" and shipped per-phase
* PRs that the architect then had to close.
*
* This test verifies that all four SPIR/ASPIR builder-prompt files contain:
* 1. An explicit prohibition on the builder autonomously opening a PR
* per implementation phase.
* 2. The clarification that "each phase commits independently" refers
* to git commits, not PRs.
* 3. The architect-override carve-out — the architect may still request
* a PR at any point (spec review, mid-impl feedback, slicing, etc.).
*/

import { describe, it, expect } from 'vitest';
import * as fs from 'node:fs';
import * as path from 'node:path';

const repoRoot = path.resolve(__dirname, '..', '..', '..', '..');

const PROMPT_FILES = [
'codev/protocols/spir/builder-prompt.md',
'codev-skeleton/protocols/spir/builder-prompt.md',
'codev/protocols/aspir/builder-prompt.md',
'codev-skeleton/protocols/aspir/builder-prompt.md',
];

describe('bugfix-744: SPIR/ASPIR builder-prompt PR strategy', () => {
for (const relPath of PROMPT_FILES) {
const fullPath = path.join(repoRoot, relPath);

it(`${relPath} — prohibits builder from autonomously opening per-phase PRs`, () => {
const content = fs.readFileSync(fullPath, 'utf-8');
expect(content).toMatch(/Do not autonomously open a PR per implementation phase/);
});

it(`${relPath} — clarifies phase-commits are git commits, not PRs`, () => {
const content = fs.readFileSync(fullPath, 'utf-8');
expect(content).toMatch(/refers to git commits, not PRs/);
});

it(`${relPath} — preserves architect-override carve-out`, () => {
const content = fs.readFileSync(fullPath, 'utf-8');
// The architect must be explicitly allowed to request a PR at any point —
// the prohibition is on autonomous builder action, not on PRs themselves.
expect(content).toMatch(/architect MAY request a PR/i);
});

it(`${relPath} — states the default PR-timing (during/after final implement phase)`, () => {
const content = fs.readFileSync(fullPath, 'utf-8');
// The new default replaces the old rigid "ONE PR per spec, opened at the end of
// the implement phase" wording. Builders need to know *when* the default PR opens
// so they don't fall back to per-phase PRs in the absence of architect direction.
expect(content).toMatch(/By default, the PR is opened during\/after the final implement phase/);
});
}
});
Loading