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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-21
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Why

- Ralplan-created planning lanes need a visible `masterplan` identity in the
sandbox worktree and OpenSpec plan folder so the owner branch is easy to find
in VS Code and hand off to joined agents.
- Plan role folders need copyable prompts and explicit ownership/completion
checklists so helpers can reuse the same owner worktree instead of spinning up
unrelated branches.

## What Changes

- Prefix plan-backed worktree and plan-workspace identities with
`masterplan` while leaving branch names and change slugs stable.
- Extend the plan scaffold so each role gets a default `prompt.md` plus
ownership, collaboration, and cleanup-blocking checklist items.
- Keep `codex-agent.sh` aligned with the new naming so both the normal launch
path and the fallback sandbox path preserve the same `masterplan` labeling.

## Impact

- Touches Guardex runtime/template helper scripts and their regression suite.
- Existing branches are unaffected; only newly created plan-backed sandboxes get
the new worktree/plan naming.
- Cleanup still stays on the owner change lane; role prompts now make that
explicit for joined helpers.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## ADDED Requirements

### Requirement: Plan-backed sandboxes expose a masterplan identity
GuardeX plan-backed sandboxes SHALL include a `masterplan` label in the
generated worktree path and OpenSpec plan workspace slug whenever OpenSpec plan
bootstrap is enabled.

#### Scenario: agent-branch-start auto-bootstraps a shared planning lane
- **GIVEN** `scripts/agent-branch-start.sh` runs with `GUARDEX_OPENSPEC_AUTO_INIT=true`
- **WHEN** it creates the sandbox worktree and OpenSpec plan slug
- **THEN** the worktree path includes `agent__<role>__masterplan__`
- **AND** the plan folder slug starts with `agent-<role>-masterplan-`
- **AND** the change slug remains based on the original branch name.

### Requirement: Plan role folders ship with shareable helper prompts
Guardex plan workspaces SHALL scaffold each role folder with a default
`prompt.md` and ownership-oriented checklist sections so joined Codex helpers
can work inside the same owner branch/worktree safely.

#### Scenario: init-plan-workspace scaffolds role collaboration defaults
- **GIVEN** the user runs `scripts/openspec/init-plan-workspace.sh <plan-slug>`
- **WHEN** role folders are created for `planner`, `architect`, `critic`,
`executor`, `writer`, and `verifier`
- **THEN** each role folder includes `prompt.md`
- **AND** each role `tasks.md` includes ownership, collaboration, and completion
guidance in addition to the visible Spec/Tests/Implementation/Checkpoints sections
- **AND** the prompt instructs helpers to claim files in the owner lane and to
leave cleanup to the owner change tasks 4.1-4.3.

### Requirement: codex-agent preserves masterplan labeling across safe fallback
`scripts/codex-agent.sh` SHALL preserve the same `masterplan` worktree/plan
labeling whether sandbox creation uses `agent-branch-start.sh` directly or the
safe fallback path.

#### Scenario: codex-agent falls back after an unsafe starter
- **GIVEN** the starter script switches the primary checkout or otherwise fails
the safe sandbox checks
- **WHEN** `scripts/codex-agent.sh` creates the sandbox directly
- **THEN** the fallback worktree path still includes `agent__<role>__masterplan__`
- **AND** the fallback OpenSpec plan slug still starts with `agent-<role>-masterplan-`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## 1. Specification

- [x] 1.1 Finalize proposal scope and acceptance criteria for `agent-codex-ralplan-masterplan-role-prompts-and-owne-2026-04-21-14-48`.
- [x] 1.2 Define normative requirements in `specs/ralplan-masterplan/spec.md`.

## 2. Implementation

- [x] 2.1 Implement scoped behavior changes.
- [x] 2.2 Add/update focused regression coverage.

## 3. Verification

- [x] 3.1 Run targeted project verification commands.
- [x] 3.2 Run `openspec validate agent-codex-ralplan-masterplan-role-prompts-and-owne-2026-04-21-14-48 --type change --strict`.
- [x] 3.3 Run `openspec validate --specs`.

Verification evidence:
- `bash -n scripts/agent-branch-start.sh templates/scripts/agent-branch-start.sh scripts/codex-agent.sh templates/scripts/codex-agent.sh scripts/openspec/init-plan-workspace.sh templates/scripts/openspec/init-plan-workspace.sh`
- `node --test --test-name-pattern "setup agent-branch-start supports optional OpenSpec auto-bootstrap toggles|codex-agent launches codex inside a fresh sandbox worktree and keeps branch/worktree by default|codex-agent restores local branch and falls back to safe worktree start when starter script switches in-place|OpenSpec plan workspace scaffold creates expected role/task structure" test/install.test.js`
- `node --test --test-name-pattern "critical runtime helper scripts stay in sync with templates" test/metadata.test.js`
- `node --test --test-name-pattern "merge branches replays non-conflicting changes onto a dedicated target lane" test/merge-workflow.test.js`
- `openspec validate agent-codex-ralplan-masterplan-role-prompts-and-owne-2026-04-21-14-48 --type change --strict`
- `openspec validate --specs` -> exit 0 with `No items found to validate.`

## 4. Completion

- [ ] 4.1 Finish the agent branch via PR merge + cleanup (`gx finish --via-pr --wait-for-merge --cleanup` or `bash scripts/agent-branch-finish.sh --branch <agent-branch> --base <base-branch> --via-pr --wait-for-merge --cleanup`).
- [ ] 4.2 Record PR URL + final `MERGED` state in the completion handoff.
- [ ] 4.3 Confirm sandbox cleanup (`git worktree list`, `git branch -a`) or capture a `BLOCKED:` handoff if merge/cleanup is pending.
46 changes: 43 additions & 3 deletions scripts/agent-branch-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ OPENSPEC_AUTO_INIT_RAW="${GUARDEX_OPENSPEC_AUTO_INIT:-false}"
OPENSPEC_PLAN_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_PLAN_SLUG:-}"
OPENSPEC_CHANGE_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_CHANGE_SLUG:-}"
OPENSPEC_CAPABILITY_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_CAPABILITY_SLUG:-}"
OPENSPEC_MASTERPLAN_LABEL_RAW="${GUARDEX_OPENSPEC_MASTERPLAN_LABEL-masterplan}"
PRINT_NAME_ONLY=0
POSITIONAL_ARGS=()

Expand Down Expand Up @@ -226,13 +227,35 @@ normalize_bool() {

OPENSPEC_AUTO_INIT="$(normalize_bool "$OPENSPEC_AUTO_INIT_RAW" "1")"

resolve_openspec_masterplan_label() {
local raw="${OPENSPEC_MASTERPLAN_LABEL_RAW:-}"
local label

if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]] || [[ -z "$raw" ]]; then
printf ''
return 0
fi

label="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g')"
printf '%s' "$label"
}

resolve_openspec_plan_slug() {
local branch_name="$1"
local task_slug="$2"
local agent_slug="$2"
local task_slug="$3"
local masterplan_label=""
local branch_leaf=""
if [[ -n "$OPENSPEC_PLAN_SLUG_OVERRIDE" ]]; then
sanitize_slug "$OPENSPEC_PLAN_SLUG_OVERRIDE" "$task_slug"
return 0
fi
masterplan_label="$(resolve_openspec_masterplan_label)"
if [[ -n "$masterplan_label" ]] && [[ "$branch_name" == "agent/${agent_slug}/"* ]]; then
branch_leaf="${branch_name#agent/${agent_slug}/}"
sanitize_slug "agent-${agent_slug}-${masterplan_label}-${branch_leaf}" "$task_slug"
return 0
fi
sanitize_slug "${branch_name//\//-}" "$task_slug"
}

Expand All @@ -255,6 +278,22 @@ resolve_openspec_capability_slug() {
sanitize_slug "$task_slug" "general-behavior"
}

resolve_worktree_leaf() {
local branch_name="$1"
local agent_slug="$2"
local masterplan_label=""
local branch_leaf=""

masterplan_label="$(resolve_openspec_masterplan_label)"
if [[ -n "$masterplan_label" ]] && [[ "$branch_name" == "agent/${agent_slug}/"* ]]; then
branch_leaf="${branch_name#agent/${agent_slug}/}"
printf 'agent__%s__%s__%s' "$agent_slug" "$masterplan_label" "$branch_leaf"
return 0
fi

printf '%s' "${branch_name//\//__}"
}

has_local_changes() {
local root="$1"
if ! git -C "$root" diff --quiet; then
Expand Down Expand Up @@ -497,8 +536,9 @@ done

worktree_root="${repo_root}/${WORKTREE_ROOT_REL}"
mkdir -p "$worktree_root"
worktree_path="${worktree_root}/${branch_name//\//__}"
openspec_plan_slug="$(resolve_openspec_plan_slug "$branch_name" "$task_slug")"
worktree_leaf="$(resolve_worktree_leaf "$branch_name" "$agent_slug")"
worktree_path="${worktree_root}/${worktree_leaf}"
openspec_plan_slug="$(resolve_openspec_plan_slug "$branch_name" "$agent_slug" "$task_slug")"
openspec_change_slug="$(resolve_openspec_change_slug "$branch_name" "$task_slug")"
openspec_capability_slug="$(resolve_openspec_capability_slug "$task_slug")"

Expand Down
49 changes: 47 additions & 2 deletions scripts/codex-agent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ OPENSPEC_AUTO_INIT_RAW="${GUARDEX_OPENSPEC_AUTO_INIT:-true}"
OPENSPEC_PLAN_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_PLAN_SLUG:-}"
OPENSPEC_CHANGE_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_CHANGE_SLUG:-}"
OPENSPEC_CAPABILITY_SLUG_OVERRIDE="${GUARDEX_OPENSPEC_CAPABILITY_SLUG:-}"
OPENSPEC_MASTERPLAN_LABEL_RAW="${GUARDEX_OPENSPEC_MASTERPLAN_LABEL-masterplan}"

normalize_bool() {
local raw="${1:-}"
Expand All @@ -34,6 +35,19 @@ AUTO_CLEANUP="$(normalize_bool "$AUTO_CLEANUP_RAW" "1")"
AUTO_WAIT_FOR_MERGE="$(normalize_bool "$AUTO_WAIT_FOR_MERGE_RAW" "1")"
OPENSPEC_AUTO_INIT="$(normalize_bool "$OPENSPEC_AUTO_INIT_RAW" "1")"

resolve_openspec_masterplan_label() {
local raw="${OPENSPEC_MASTERPLAN_LABEL_RAW:-}"
local label

if [[ "$OPENSPEC_AUTO_INIT" -ne 1 ]] || [[ -z "$raw" ]]; then
printf ''
return 0
fi

label="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g')"
printf '%s' "$label"
}

if [[ -n "$BASE_BRANCH" ]]; then
BASE_BRANCH_EXPLICIT=1
fi
Expand Down Expand Up @@ -161,11 +175,21 @@ sanitize_slug() {
resolve_openspec_plan_slug() {
local branch_name="$1"
local task_slug
local masterplan_label=""
local branch_role=""
local branch_leaf=""
task_slug="$(sanitize_slug "$TASK_NAME" "task")"
if [[ -n "$OPENSPEC_PLAN_SLUG_OVERRIDE" ]]; then
sanitize_slug "$OPENSPEC_PLAN_SLUG_OVERRIDE" "$task_slug"
return 0
fi
masterplan_label="$(resolve_openspec_masterplan_label)"
if [[ -n "$masterplan_label" ]] && [[ "$branch_name" =~ ^agent/([^/]+)/(.+)$ ]]; then
branch_role="${BASH_REMATCH[1]}"
branch_leaf="${BASH_REMATCH[2]}"
sanitize_slug "agent-${branch_role}-${masterplan_label}-${branch_leaf}" "$task_slug"
return 0
fi
sanitize_slug "${branch_name//\//-}" "$task_slug"
}

Expand All @@ -190,6 +214,23 @@ resolve_openspec_capability_slug() {
sanitize_slug "$task_slug" "general-behavior"
}

resolve_worktree_leaf() {
local branch_name="$1"
local masterplan_label=""
local branch_role=""
local branch_leaf=""

masterplan_label="$(resolve_openspec_masterplan_label)"
if [[ -n "$masterplan_label" ]] && [[ "$branch_name" =~ ^agent/([^/]+)/(.+)$ ]]; then
branch_role="${BASH_REMATCH[1]}"
branch_leaf="${BASH_REMATCH[2]}"
printf 'agent__%s__%s__%s' "$branch_role" "$masterplan_label" "$branch_leaf"
return 0
fi

printf '%s' "${branch_name//\//__}"
}

hydrate_local_helper_in_worktree() {
local worktree="$1"
local relative_path="$2"
Expand Down Expand Up @@ -314,7 +355,7 @@ start_sandbox_fallback() {

worktree_root="${repo_root}/.omx/agent-worktrees"
mkdir -p "$worktree_root"
worktree_path="${worktree_root}/${branch_name//\//__}"
worktree_path="${worktree_root}/$(resolve_worktree_leaf "$branch_name")"
if [[ -e "$worktree_path" ]]; then
echo "[codex-agent] Fallback worktree path already exists: $worktree_path" >&2
return 1
Expand Down Expand Up @@ -346,7 +387,11 @@ initial_repo_branch="$(git -C "$repo_root" rev-parse --abbrev-ref HEAD 2>/dev/nu
start_output=""
start_status=0
set +e
start_output="$(GUARDEX_OPENSPEC_AUTO_INIT=0 bash "${repo_root}/scripts/agent-branch-start.sh" "${start_args[@]}" 2>&1)"
start_output="$(
GUARDEX_OPENSPEC_AUTO_INIT="$OPENSPEC_AUTO_INIT" \
GUARDEX_OPENSPEC_MASTERPLAN_LABEL="$OPENSPEC_MASTERPLAN_LABEL_RAW" \
bash "${repo_root}/scripts/agent-branch-start.sh" "${start_args[@]}" 2>&1
)"
start_status=$?
set -e

Expand Down
42 changes: 42 additions & 0 deletions scripts/openspec/init-plan-workspace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ write_if_missing "$PLAN_DIR/README.md" "# Plan Workspace: ${PLAN_SLUG}

Durable pre-implementation planning workspace.

Each role folder includes a copyable \`prompt.md\` for joined Codex helpers.
Helpers reuse the owner branch/worktree, claim the role files they touch, and
leave PR merge + sandbox cleanup to the owner change lane.

Use this command to update checkpoints:

\`\`\`bash
Expand Down Expand Up @@ -89,10 +93,39 @@ for role in "${ROLES[@]}"; do
write_if_missing "$ROLE_DIR/README.md" "# ${role}

Role workspace for \`${role}\`.
"

write_if_missing "$ROLE_DIR/prompt.md" "# ${role} prompt

You are the \`${role}\` lane for shared plan \`${PLAN_SLUG}\`.

## Scope

- Work inside \`openspec/plan/${PLAN_SLUG}/${role}/\` plus directly-related shared plan files you explicitly claim.
- Reuse the owner's branch/worktree instead of creating a separate sandbox unless the owner says otherwise.

## Ownership

- Before editing, claim this role's files in the shared owner lane:
\`python3 scripts/agent-file-locks.py claim --branch <owner-branch> openspec/plan/${PLAN_SLUG}/${role}/README.md openspec/plan/${PLAN_SLUG}/${role}/prompt.md openspec/plan/${PLAN_SLUG}/${role}/tasks.md openspec/plan/${PLAN_SLUG}/checkpoints.md\`
- Record branch, worktree, and scope in \`tasks.md\`.
- Do not change another role's files without reassignment.

## Deliverables

- Complete the role checklist in \`tasks.md\`.
- Leave a handoff with files changed, verification, and risks.
- The owner alone runs the change completion flow and sandbox cleanup after change tasks 4.1-4.3 are done.
"

write_if_missing "$ROLE_DIR/tasks.md" "# ${role} tasks

## Ownership

- [ ] Claim this role's files in the shared owner branch/worktree before editing.
- [ ] Record branch, worktree, and scope for this role.
- [ ] Copy or hand off \`prompt.md\` when another agent joins this role.

## 1. Spec

- [ ] Define requirements and scope for ${role}
Expand All @@ -111,6 +144,15 @@ Role workspace for \`${role}\`.
## 4. Checkpoints

- [ ] Publish checkpoint update for this role

## 5. Collaboration

- [ ] Leave a role handoff with files changed, verification, and risks.
- [ ] Owner records \`accept\`, \`revise\`, or \`reject\` for joined output, or marks \`N/A\` if no helper joined.

## 6. Completion

- [ ] Keep sandbox cleanup blocked until change tasks 4.1-4.3 are complete.
"
done

Expand Down
Loading