diff --git a/frontend/scripts/openspec/init-change-workspace.sh b/frontend/scripts/openspec/init-change-workspace.sh index e417495..8f878e7 100755 --- a/frontend/scripts/openspec/init-change-workspace.sh +++ b/frontend/scripts/openspec/init-change-workspace.sh @@ -1,14 +1,15 @@ #!/usr/bin/env bash set -euo pipefail -if [[ $# -lt 1 || $# -gt 2 ]]; then - echo "Usage: $0 [capability-slug]" - echo "Example: $0 add-dashboard-live-usage runtime-migration" +if [[ $# -lt 1 || $# -gt 3 ]]; then + echo "Usage: $0 [capability-slug] [agent-branch]" + echo "Example: $0 add-dashboard-live-usage runtime-migration agent/claude-odin/add-dashboard-live-usage-123456" exit 1 fi CHANGE_SLUG="$1" CAPABILITY_SLUG="${2:-$CHANGE_SLUG}" +AGENT_BRANCH="${3:-agent//}" if [[ "$CHANGE_SLUG" =~ [^a-z0-9-] ]]; then echo "Error: change slug must be kebab-case (lowercase letters, numbers, hyphens)." @@ -24,7 +25,17 @@ CHANGE_DIR="openspec/changes/${CHANGE_SLUG}" SPEC_DIR="${CHANGE_DIR}/specs/${CAPABILITY_SLUG}" TODAY="$(date -u +%Y-%m-%d)" -mkdir -p "$SPEC_DIR" +MINIMAL_RAW="${GUARDEX_OPENSPEC_MINIMAL:-0}" +case "$(printf '%s' "$MINIMAL_RAW" | tr '[:upper:]' '[:lower:]')" in + 1|true|yes|on) MINIMAL=1 ;; + *) MINIMAL=0 ;; +esac + +if [[ "$MINIMAL" -eq 1 ]]; then + mkdir -p "$CHANGE_DIR" +else + mkdir -p "$SPEC_DIR" +fi if [[ ! -f "${CHANGE_DIR}/.openspec.yaml" ]]; then cat > "${CHANGE_DIR}/.openspec.yaml" < "${CHANGE_DIR}/notes.md" < "${CHANGE_DIR}/proposal.md" < "${CHANGE_DIR}/tasks.md" < --base --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. +- [ ] 4.1 Run the cleanup pipeline: \`bash scripts/agent-branch-finish.sh --branch ${AGENT_BRANCH} --base dev --via-pr --wait-for-merge --cleanup\`. This handles commit -> push -> PR create -> merge wait -> worktree prune in one invocation. +- [ ] 4.2 Record the PR URL and final merge state (\`MERGED\`) in the completion handoff. +- [ ] 4.3 Confirm the sandbox worktree is gone (\`git worktree list\` no longer shows the agent path; \`git branch -a\` shows no surviving local/remote refs for the branch). TASKSEOF fi @@ -89,5 +129,5 @@ The system SHALL enforce ${CAPABILITY_SLUG} behavior as defined by this change. SPECEOF fi -echo "[gitguardex] OpenSpec change workspace ready: ${CHANGE_DIR}" -echo "[gitguardex] OpenSpec change spec scaffold: ${SPEC_DIR}/spec.md" +echo "[guardex] OpenSpec change workspace ready: ${CHANGE_DIR}" +echo "[guardex] OpenSpec change spec scaffold: ${SPEC_DIR}/spec.md" diff --git a/frontend/scripts/openspec/init-plan-workspace.sh b/frontend/scripts/openspec/init-plan-workspace.sh index c6dd4da..c96dba3 100755 --- a/frontend/scripts/openspec/init-plan-workspace.sh +++ b/frontend/scripts/openspec/init-plan-workspace.sh @@ -2,8 +2,8 @@ set -euo pipefail if [[ $# -lt 1 ]]; then - echo "Usage: $0 [role ...]" - echo "Example: $0 stabilize-dashboard planner architect critic executor writer verifier" + echo "Usage: $0 [agent-role ...]" + echo "Example: $0 add-ralplan-openspec-plan-export planner architect critic executor writer verifier" exit 1 fi @@ -11,10 +11,14 @@ PLAN_SLUG="$1" shift || true if [[ "$PLAN_SLUG" =~ [^a-z0-9-] ]]; then - echo "Error: plan slug must be kebab-case (lowercase letters, numbers, hyphens)." >&2 + echo "Error: plan slug must be kebab-case (lowercase letters, numbers, hyphens)." exit 1 fi +to_kebab() { + printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//' +} + if [[ $# -gt 0 ]]; then ROLES=("$@") else @@ -24,139 +28,635 @@ fi PLAN_DIR="openspec/plan/${PLAN_SLUG}" mkdir -p "$PLAN_DIR" -write_if_missing() { - local file="$1" - shift - if [[ ! -f "$file" ]]; then - mkdir -p "$(dirname "$file")" - cat > "$file" < "$PLAN_DIR/summary.md" < "$PLAN_DIR/checkpoints.md" </spec.md\`" + echo "Planner also gets \`plan.md\`; executor also gets \`checkpoints.md\`." + echo "Planner plans should follow \`openspec/plan/PLANS.md\`." + } > "$PLAN_DIR/README.md" +fi + +if [[ ! -f "$PLAN_DIR/coordinator-prompt.md" ]]; then + cat > "$PLAN_DIR/coordinator-prompt.md" < "$PLAN_DIR/kickoff-prompts.md" < +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +\`\`\` + +## Prompt B — Wave B (Secondary lane) + +\`\`\`text +You own Wave-B for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-B scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups \`\`\` -" -write_if_missing "$PLAN_DIR/planner/plan.md" "# ExecPlan: ${PLAN_SLUG} +## Prompt C — Wave C (Secondary lane) + +\`\`\`text +You own Wave-C for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-C scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +\`\`\` + +## Prompt D — Integrator lane + +\`\`\`text +You are the integrator for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Integrate completed waves, resolve conflicts, run final verification, and prepare rollout/cutover notes. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Preserve safety-critical behavior unless explicitly planned and tested. +- Keep final output evidence-first. + +Owned scope: +- integration glue and shared touchpoints +- final validation + handoff summary + +Verification: +- + +Final report: +- Files changed +- Integration decisions +- Verification outputs +- Remaining risks +\`\`\` +KICKOFFPROMPTEOF +fi + +if [[ ! -f "$PLAN_DIR/phases.md" ]]; then + cat > "$PLAN_DIR/phases.md" <\` = in progress, space = pending. +Indented sub-bullets are optional metadata consumed by the Plans UI: + +- \`session\`: which agent kind runs the phase (\`codex\` / \`claude\`). +- \`checkpoints\`: comma-separated role checkpoint ids delivered within the phase. +- \`summary\`: one short sentence rendered under the phase title. + +One phase is intended to fit into a single Codex or Claude session task. + +- [ ] [PH01] First milestone title goes here + - session: codex + - checkpoints: P1, A1 + - summary: Describe the single session outcome expected for this phase. +PHASESEOF +fi + +for role in "${ROLES[@]}"; do + ROLE_DIR="$PLAN_DIR/$role" + mkdir -p "$ROLE_DIR" + + if [[ ! -f "$ROLE_DIR/README.md" ]]; then + cat > "$ROLE_DIR/README.md" </spec.md\` + +Use this folder for role notes, artifacts, and status updates. +ROLEEOF + fi + + ROLE_SPEC_SLUG="$(to_kebab "$role")" + if [[ -z "$ROLE_SPEC_SLUG" ]]; then + ROLE_SPEC_SLUG="role" + fi + + if [[ ! -f "$ROLE_DIR/.openspec.yaml" ]]; then + cat > "$ROLE_DIR/.openspec.yaml" < "$ROLE_DIR/proposal.md" < "$ROLE_SPEC_DIR/spec.md" < "$ROLE_DIR/plan.md" < "$ROLE_DIR/checkpoints.md" < "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + architect) + cat > "$ROLE_DIR/tasks.md" < 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. +## 3. Implementation -## Deliverables +- [ ] 3.1 Review plan for strongest antithesis/tradeoff tensions +- [ ] 3.2 Propose synthesis path and guardrails for implementation teams +- [ ] 3.3 Record architecture sign-off notes for downstream execution -- 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. -" +## 4. Checkpoints - write_if_missing "$ROLE_DIR/tasks.md" "# ${role} tasks +- [ ] [A1] READY - Architecture review checkpoint -## Ownership +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark \`N/A\` when solo. + +## 6. Cleanup -- [ ] 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. +- [ ] 6.1 If this lane owns finalization, run \`bash scripts/agent-branch-finish.sh --branch --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + critic) + cat > "$ROLE_DIR/tasks.md" < --base --via-pr --wait-for-merge --cleanup\`. -- [ ] Record PR URL + final \`MERGED\` state in the role handoff or owner change task. -- [ ] Confirm sandbox cleanup, or capture a \`BLOCKED:\` handoff if finish is still pending. -" +- [ ] 6.1 If this lane owns finalization, run \`bash scripts/agent-branch-finish.sh --branch --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + executor) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + writer) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + verifier) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + *) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + esac + fi done -echo "[gitguardex] OpenSpec plan workspace ready: ${PLAN_DIR}" -echo "[gitguardex] Roles: ${ROLES[*]}" +echo "Plan workspace ready: $PLAN_DIR" diff --git a/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/.openspec.yaml b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/.openspec.yaml new file mode 100644 index 0000000..4b8c565 --- /dev/null +++ b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-04-21 diff --git a/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/proposal.md b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/proposal.md new file mode 100644 index 0000000..c620545 --- /dev/null +++ b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/proposal.md @@ -0,0 +1,23 @@ +## Why + +- `gx setup` installs OpenSpec helper scripts that are older than the live `recodee` copies already guiding current work. +- The published `gitguardex` AGENTS contract already promises tier-aware OpenSpec scaffolding, but the installed helper scripts still miss the richer change and plan workspace behavior. +- Downstream repos bootstrapped with `gx setup` should get the same OpenSpec workspace shape that `recodee` is already using. + +## What Changes + +- Sync the published `init-change-workspace.sh` helper to the richer `recodee` version, including: + - T1/minimal notes-only change scaffolding support + - stronger cleanup and Definition-of-Done guidance in `tasks.md` + - optional agent-branch placeholder support for manual scaffolds +- Sync the published `init-plan-workspace.sh` helper to the richer `recodee` version, including: + - coordinator, kickoff, and phases artifacts + - per-role OpenSpec proposal/spec/task scaffolds + - stronger ExecPlan and checkpoint prompts +- Keep runtime/template copies aligned and expand regression coverage for the richer scaffold outputs. + +## Impact + +- Affected surface: `gx setup` / `gx doctor` managed OpenSpec helper scripts plus their runtime/template parity tests. +- User-facing effect: new repos bootstrapped with Guardex get the same richer OpenSpec workspace shape already present in `recodee`. +- Risk: low-to-moderate because the change is limited to scaffold content, but stale tests would hide drift if they are not updated together. diff --git a/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/specs/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/spec.md b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/specs/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/spec.md new file mode 100644 index 0000000..ba4073a --- /dev/null +++ b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/specs/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/spec.md @@ -0,0 +1,26 @@ +## ADDED Requirements + +### Requirement: setup-managed repos receive the richer change scaffold +Guardex setup-managed repos SHALL receive the same richer OpenSpec change scaffold already present in `recodee`. + +#### Scenario: full change scaffold is initialized +- **GIVEN** a repo managed by `gx setup` or `gx doctor` +- **WHEN** the operator runs `scripts/openspec/init-change-workspace.sh ` +- **THEN** the script writes `.openspec.yaml`, `proposal.md`, `tasks.md`, and `specs//spec.md` +- **AND** `tasks.md` includes Definition-of-Done language plus explicit cleanup and merge evidence steps. + +#### Scenario: minimal T1 scaffold is initialized +- **GIVEN** `GUARDEX_OPENSPEC_MINIMAL=1` +- **WHEN** the operator runs `scripts/openspec/init-change-workspace.sh ` +- **THEN** the script creates `.openspec.yaml` and `notes.md` without the full change bundle +- **AND** `notes.md` records the provided agent branch placeholder plus cleanup expectations. + +### Requirement: setup-managed repos receive the richer plan scaffold +Guardex setup-managed repos SHALL receive the same richer OpenSpec plan scaffold already present in `recodee`. + +#### Scenario: plan workspace is initialized +- **GIVEN** a repo managed by `gx setup` or `gx doctor` +- **WHEN** the operator runs `scripts/openspec/init-plan-workspace.sh ` +- **THEN** the script creates summary, checkpoint, and root plan artifacts for the workspace +- **AND** it creates coordinator, kickoff, and phases artifacts +- **AND** each default role receives proposal, spec, and task scaffolds that preserve Spec, Tests, Implementation, Checkpoints, Collaboration, and Cleanup structure. diff --git a/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/tasks.md b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/tasks.md new file mode 100644 index 0000000..23885f5 --- /dev/null +++ b/openspec/changes/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/tasks.md @@ -0,0 +1,25 @@ +## 1. Specification + +- [x] 1.1 Capture the parity gap between `recodee`'s live OpenSpec helpers and the published `gitguardex` setup-managed copies. +- [x] 1.2 Define normative requirements for richer change and plan scaffolds in `specs/agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20/spec.md`. + +## 2. Implementation + +- [x] 2.1 Sync `scripts/openspec/*` and `templates/scripts/openspec/*` to the richer `recodee` scaffolds. +- [x] 2.2 Keep mirrored frontend copies aligned where Guardex still ships duplicate helper surfaces. +- [x] 2.3 Update regression tests to lock the richer scaffold outputs. + +## 3. Verification + +- [x] 3.1 Run focused `node --test` coverage for the OpenSpec scaffold/install tests. +- [x] 3.2 Run `node --check bin/multiagent-safety.js`. +- [x] 3.3 Run `openspec validate agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20 --type change --strict`. +- [x] 3.4 Run `openspec validate --specs`. + +Verification note: `node --test --test-name-pattern OpenSpec test/install.test.js` passed with 4 focused OpenSpec/install tests. `node --test test/metadata.test.js` passed with 14 metadata/parity tests. `node --check bin/multiagent-safety.js` passed. `git diff --check` passed. `openspec validate agent-codex-sync-recodee-openspec-bootstrap-into-gx-2026-04-21-17-20 --type change --strict` passed, and `openspec validate --specs` returned `No items found to validate.` + +## 4. Cleanup + +- [ ] 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 --base --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. diff --git a/scripts/openspec/init-change-workspace.sh b/scripts/openspec/init-change-workspace.sh index e417495..8f878e7 100755 --- a/scripts/openspec/init-change-workspace.sh +++ b/scripts/openspec/init-change-workspace.sh @@ -1,14 +1,15 @@ #!/usr/bin/env bash set -euo pipefail -if [[ $# -lt 1 || $# -gt 2 ]]; then - echo "Usage: $0 [capability-slug]" - echo "Example: $0 add-dashboard-live-usage runtime-migration" +if [[ $# -lt 1 || $# -gt 3 ]]; then + echo "Usage: $0 [capability-slug] [agent-branch]" + echo "Example: $0 add-dashboard-live-usage runtime-migration agent/claude-odin/add-dashboard-live-usage-123456" exit 1 fi CHANGE_SLUG="$1" CAPABILITY_SLUG="${2:-$CHANGE_SLUG}" +AGENT_BRANCH="${3:-agent//}" if [[ "$CHANGE_SLUG" =~ [^a-z0-9-] ]]; then echo "Error: change slug must be kebab-case (lowercase letters, numbers, hyphens)." @@ -24,7 +25,17 @@ CHANGE_DIR="openspec/changes/${CHANGE_SLUG}" SPEC_DIR="${CHANGE_DIR}/specs/${CAPABILITY_SLUG}" TODAY="$(date -u +%Y-%m-%d)" -mkdir -p "$SPEC_DIR" +MINIMAL_RAW="${GUARDEX_OPENSPEC_MINIMAL:-0}" +case "$(printf '%s' "$MINIMAL_RAW" | tr '[:upper:]' '[:lower:]')" in + 1|true|yes|on) MINIMAL=1 ;; + *) MINIMAL=0 ;; +esac + +if [[ "$MINIMAL" -eq 1 ]]; then + mkdir -p "$CHANGE_DIR" +else + mkdir -p "$SPEC_DIR" +fi if [[ ! -f "${CHANGE_DIR}/.openspec.yaml" ]]; then cat > "${CHANGE_DIR}/.openspec.yaml" < "${CHANGE_DIR}/notes.md" < "${CHANGE_DIR}/proposal.md" < "${CHANGE_DIR}/tasks.md" < --base --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. +- [ ] 4.1 Run the cleanup pipeline: \`bash scripts/agent-branch-finish.sh --branch ${AGENT_BRANCH} --base dev --via-pr --wait-for-merge --cleanup\`. This handles commit -> push -> PR create -> merge wait -> worktree prune in one invocation. +- [ ] 4.2 Record the PR URL and final merge state (\`MERGED\`) in the completion handoff. +- [ ] 4.3 Confirm the sandbox worktree is gone (\`git worktree list\` no longer shows the agent path; \`git branch -a\` shows no surviving local/remote refs for the branch). TASKSEOF fi @@ -89,5 +129,5 @@ The system SHALL enforce ${CAPABILITY_SLUG} behavior as defined by this change. SPECEOF fi -echo "[gitguardex] OpenSpec change workspace ready: ${CHANGE_DIR}" -echo "[gitguardex] OpenSpec change spec scaffold: ${SPEC_DIR}/spec.md" +echo "[guardex] OpenSpec change workspace ready: ${CHANGE_DIR}" +echo "[guardex] OpenSpec change spec scaffold: ${SPEC_DIR}/spec.md" diff --git a/scripts/openspec/init-plan-workspace.sh b/scripts/openspec/init-plan-workspace.sh index c6dd4da..c96dba3 100755 --- a/scripts/openspec/init-plan-workspace.sh +++ b/scripts/openspec/init-plan-workspace.sh @@ -2,8 +2,8 @@ set -euo pipefail if [[ $# -lt 1 ]]; then - echo "Usage: $0 [role ...]" - echo "Example: $0 stabilize-dashboard planner architect critic executor writer verifier" + echo "Usage: $0 [agent-role ...]" + echo "Example: $0 add-ralplan-openspec-plan-export planner architect critic executor writer verifier" exit 1 fi @@ -11,10 +11,14 @@ PLAN_SLUG="$1" shift || true if [[ "$PLAN_SLUG" =~ [^a-z0-9-] ]]; then - echo "Error: plan slug must be kebab-case (lowercase letters, numbers, hyphens)." >&2 + echo "Error: plan slug must be kebab-case (lowercase letters, numbers, hyphens)." exit 1 fi +to_kebab() { + printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//' +} + if [[ $# -gt 0 ]]; then ROLES=("$@") else @@ -24,139 +28,635 @@ fi PLAN_DIR="openspec/plan/${PLAN_SLUG}" mkdir -p "$PLAN_DIR" -write_if_missing() { - local file="$1" - shift - if [[ ! -f "$file" ]]; then - mkdir -p "$(dirname "$file")" - cat > "$file" < "$PLAN_DIR/summary.md" < "$PLAN_DIR/checkpoints.md" </spec.md\`" + echo "Planner also gets \`plan.md\`; executor also gets \`checkpoints.md\`." + echo "Planner plans should follow \`openspec/plan/PLANS.md\`." + } > "$PLAN_DIR/README.md" +fi + +if [[ ! -f "$PLAN_DIR/coordinator-prompt.md" ]]; then + cat > "$PLAN_DIR/coordinator-prompt.md" < "$PLAN_DIR/kickoff-prompts.md" < +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +\`\`\` + +## Prompt B — Wave B (Secondary lane) + +\`\`\`text +You own Wave-B for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-B scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups \`\`\` -" -write_if_missing "$PLAN_DIR/planner/plan.md" "# ExecPlan: ${PLAN_SLUG} +## Prompt C — Wave C (Secondary lane) + +\`\`\`text +You own Wave-C for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-C scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +\`\`\` + +## Prompt D — Integrator lane + +\`\`\`text +You are the integrator for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Integrate completed waves, resolve conflicts, run final verification, and prepare rollout/cutover notes. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Preserve safety-critical behavior unless explicitly planned and tested. +- Keep final output evidence-first. + +Owned scope: +- integration glue and shared touchpoints +- final validation + handoff summary + +Verification: +- + +Final report: +- Files changed +- Integration decisions +- Verification outputs +- Remaining risks +\`\`\` +KICKOFFPROMPTEOF +fi + +if [[ ! -f "$PLAN_DIR/phases.md" ]]; then + cat > "$PLAN_DIR/phases.md" <\` = in progress, space = pending. +Indented sub-bullets are optional metadata consumed by the Plans UI: + +- \`session\`: which agent kind runs the phase (\`codex\` / \`claude\`). +- \`checkpoints\`: comma-separated role checkpoint ids delivered within the phase. +- \`summary\`: one short sentence rendered under the phase title. + +One phase is intended to fit into a single Codex or Claude session task. + +- [ ] [PH01] First milestone title goes here + - session: codex + - checkpoints: P1, A1 + - summary: Describe the single session outcome expected for this phase. +PHASESEOF +fi + +for role in "${ROLES[@]}"; do + ROLE_DIR="$PLAN_DIR/$role" + mkdir -p "$ROLE_DIR" + + if [[ ! -f "$ROLE_DIR/README.md" ]]; then + cat > "$ROLE_DIR/README.md" </spec.md\` + +Use this folder for role notes, artifacts, and status updates. +ROLEEOF + fi + + ROLE_SPEC_SLUG="$(to_kebab "$role")" + if [[ -z "$ROLE_SPEC_SLUG" ]]; then + ROLE_SPEC_SLUG="role" + fi + + if [[ ! -f "$ROLE_DIR/.openspec.yaml" ]]; then + cat > "$ROLE_DIR/.openspec.yaml" < "$ROLE_DIR/proposal.md" < "$ROLE_SPEC_DIR/spec.md" < "$ROLE_DIR/plan.md" < "$ROLE_DIR/checkpoints.md" < "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + architect) + cat > "$ROLE_DIR/tasks.md" < 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. +## 3. Implementation -## Deliverables +- [ ] 3.1 Review plan for strongest antithesis/tradeoff tensions +- [ ] 3.2 Propose synthesis path and guardrails for implementation teams +- [ ] 3.3 Record architecture sign-off notes for downstream execution -- 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. -" +## 4. Checkpoints - write_if_missing "$ROLE_DIR/tasks.md" "# ${role} tasks +- [ ] [A1] READY - Architecture review checkpoint -## Ownership +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark \`N/A\` when solo. + +## 6. Cleanup -- [ ] 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. +- [ ] 6.1 If this lane owns finalization, run \`bash scripts/agent-branch-finish.sh --branch --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + critic) + cat > "$ROLE_DIR/tasks.md" < --base --via-pr --wait-for-merge --cleanup\`. -- [ ] Record PR URL + final \`MERGED\` state in the role handoff or owner change task. -- [ ] Confirm sandbox cleanup, or capture a \`BLOCKED:\` handoff if finish is still pending. -" +- [ ] 6.1 If this lane owns finalization, run \`bash scripts/agent-branch-finish.sh --branch --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + executor) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + writer) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + verifier) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + *) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + esac + fi done -echo "[gitguardex] OpenSpec plan workspace ready: ${PLAN_DIR}" -echo "[gitguardex] Roles: ${ROLES[*]}" +echo "Plan workspace ready: $PLAN_DIR" diff --git a/templates/scripts/openspec/init-change-workspace.sh b/templates/scripts/openspec/init-change-workspace.sh old mode 100644 new mode 100755 index e417495..8f878e7 --- a/templates/scripts/openspec/init-change-workspace.sh +++ b/templates/scripts/openspec/init-change-workspace.sh @@ -1,14 +1,15 @@ #!/usr/bin/env bash set -euo pipefail -if [[ $# -lt 1 || $# -gt 2 ]]; then - echo "Usage: $0 [capability-slug]" - echo "Example: $0 add-dashboard-live-usage runtime-migration" +if [[ $# -lt 1 || $# -gt 3 ]]; then + echo "Usage: $0 [capability-slug] [agent-branch]" + echo "Example: $0 add-dashboard-live-usage runtime-migration agent/claude-odin/add-dashboard-live-usage-123456" exit 1 fi CHANGE_SLUG="$1" CAPABILITY_SLUG="${2:-$CHANGE_SLUG}" +AGENT_BRANCH="${3:-agent//}" if [[ "$CHANGE_SLUG" =~ [^a-z0-9-] ]]; then echo "Error: change slug must be kebab-case (lowercase letters, numbers, hyphens)." @@ -24,7 +25,17 @@ CHANGE_DIR="openspec/changes/${CHANGE_SLUG}" SPEC_DIR="${CHANGE_DIR}/specs/${CAPABILITY_SLUG}" TODAY="$(date -u +%Y-%m-%d)" -mkdir -p "$SPEC_DIR" +MINIMAL_RAW="${GUARDEX_OPENSPEC_MINIMAL:-0}" +case "$(printf '%s' "$MINIMAL_RAW" | tr '[:upper:]' '[:lower:]')" in + 1|true|yes|on) MINIMAL=1 ;; + *) MINIMAL=0 ;; +esac + +if [[ "$MINIMAL" -eq 1 ]]; then + mkdir -p "$CHANGE_DIR" +else + mkdir -p "$SPEC_DIR" +fi if [[ ! -f "${CHANGE_DIR}/.openspec.yaml" ]]; then cat > "${CHANGE_DIR}/.openspec.yaml" < "${CHANGE_DIR}/notes.md" < "${CHANGE_DIR}/proposal.md" < "${CHANGE_DIR}/tasks.md" < --base --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. +- [ ] 4.1 Run the cleanup pipeline: \`bash scripts/agent-branch-finish.sh --branch ${AGENT_BRANCH} --base dev --via-pr --wait-for-merge --cleanup\`. This handles commit -> push -> PR create -> merge wait -> worktree prune in one invocation. +- [ ] 4.2 Record the PR URL and final merge state (\`MERGED\`) in the completion handoff. +- [ ] 4.3 Confirm the sandbox worktree is gone (\`git worktree list\` no longer shows the agent path; \`git branch -a\` shows no surviving local/remote refs for the branch). TASKSEOF fi @@ -89,5 +129,5 @@ The system SHALL enforce ${CAPABILITY_SLUG} behavior as defined by this change. SPECEOF fi -echo "[gitguardex] OpenSpec change workspace ready: ${CHANGE_DIR}" -echo "[gitguardex] OpenSpec change spec scaffold: ${SPEC_DIR}/spec.md" +echo "[guardex] OpenSpec change workspace ready: ${CHANGE_DIR}" +echo "[guardex] OpenSpec change spec scaffold: ${SPEC_DIR}/spec.md" diff --git a/templates/scripts/openspec/init-plan-workspace.sh b/templates/scripts/openspec/init-plan-workspace.sh old mode 100644 new mode 100755 index c6dd4da..c96dba3 --- a/templates/scripts/openspec/init-plan-workspace.sh +++ b/templates/scripts/openspec/init-plan-workspace.sh @@ -2,8 +2,8 @@ set -euo pipefail if [[ $# -lt 1 ]]; then - echo "Usage: $0 [role ...]" - echo "Example: $0 stabilize-dashboard planner architect critic executor writer verifier" + echo "Usage: $0 [agent-role ...]" + echo "Example: $0 add-ralplan-openspec-plan-export planner architect critic executor writer verifier" exit 1 fi @@ -11,10 +11,14 @@ PLAN_SLUG="$1" shift || true if [[ "$PLAN_SLUG" =~ [^a-z0-9-] ]]; then - echo "Error: plan slug must be kebab-case (lowercase letters, numbers, hyphens)." >&2 + echo "Error: plan slug must be kebab-case (lowercase letters, numbers, hyphens)." exit 1 fi +to_kebab() { + printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//' +} + if [[ $# -gt 0 ]]; then ROLES=("$@") else @@ -24,139 +28,635 @@ fi PLAN_DIR="openspec/plan/${PLAN_SLUG}" mkdir -p "$PLAN_DIR" -write_if_missing() { - local file="$1" - shift - if [[ ! -f "$file" ]]; then - mkdir -p "$(dirname "$file")" - cat > "$file" < "$PLAN_DIR/summary.md" < "$PLAN_DIR/checkpoints.md" </spec.md\`" + echo "Planner also gets \`plan.md\`; executor also gets \`checkpoints.md\`." + echo "Planner plans should follow \`openspec/plan/PLANS.md\`." + } > "$PLAN_DIR/README.md" +fi + +if [[ ! -f "$PLAN_DIR/coordinator-prompt.md" ]]; then + cat > "$PLAN_DIR/coordinator-prompt.md" < "$PLAN_DIR/kickoff-prompts.md" < +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +\`\`\` + +## Prompt B — Wave B (Secondary lane) + +\`\`\`text +You own Wave-B for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-B scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups \`\`\` -" -write_if_missing "$PLAN_DIR/planner/plan.md" "# ExecPlan: ${PLAN_SLUG} +## Prompt C — Wave C (Secondary lane) + +\`\`\`text +You own Wave-C for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-C scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +\`\`\` + +## Prompt D — Integrator lane + +\`\`\`text +You are the integrator for plan \`${PLAN_SLUG}\` in /home/deadpool/Documents/codex-lb. + +Goal: +Integrate completed waves, resolve conflicts, run final verification, and prepare rollout/cutover notes. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Preserve safety-critical behavior unless explicitly planned and tested. +- Keep final output evidence-first. + +Owned scope: +- integration glue and shared touchpoints +- final validation + handoff summary + +Verification: +- + +Final report: +- Files changed +- Integration decisions +- Verification outputs +- Remaining risks +\`\`\` +KICKOFFPROMPTEOF +fi + +if [[ ! -f "$PLAN_DIR/phases.md" ]]; then + cat > "$PLAN_DIR/phases.md" <\` = in progress, space = pending. +Indented sub-bullets are optional metadata consumed by the Plans UI: + +- \`session\`: which agent kind runs the phase (\`codex\` / \`claude\`). +- \`checkpoints\`: comma-separated role checkpoint ids delivered within the phase. +- \`summary\`: one short sentence rendered under the phase title. + +One phase is intended to fit into a single Codex or Claude session task. + +- [ ] [PH01] First milestone title goes here + - session: codex + - checkpoints: P1, A1 + - summary: Describe the single session outcome expected for this phase. +PHASESEOF +fi + +for role in "${ROLES[@]}"; do + ROLE_DIR="$PLAN_DIR/$role" + mkdir -p "$ROLE_DIR" + + if [[ ! -f "$ROLE_DIR/README.md" ]]; then + cat > "$ROLE_DIR/README.md" </spec.md\` + +Use this folder for role notes, artifacts, and status updates. +ROLEEOF + fi + + ROLE_SPEC_SLUG="$(to_kebab "$role")" + if [[ -z "$ROLE_SPEC_SLUG" ]]; then + ROLE_SPEC_SLUG="role" + fi + + if [[ ! -f "$ROLE_DIR/.openspec.yaml" ]]; then + cat > "$ROLE_DIR/.openspec.yaml" < "$ROLE_DIR/proposal.md" < "$ROLE_SPEC_DIR/spec.md" < "$ROLE_DIR/plan.md" < "$ROLE_DIR/checkpoints.md" < "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + architect) + cat > "$ROLE_DIR/tasks.md" < 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. +## 3. Implementation -## Deliverables +- [ ] 3.1 Review plan for strongest antithesis/tradeoff tensions +- [ ] 3.2 Propose synthesis path and guardrails for implementation teams +- [ ] 3.3 Record architecture sign-off notes for downstream execution -- 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. -" +## 4. Checkpoints - write_if_missing "$ROLE_DIR/tasks.md" "# ${role} tasks +- [ ] [A1] READY - Architecture review checkpoint -## Ownership +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark \`N/A\` when solo. + +## 6. Cleanup -- [ ] 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. +- [ ] 6.1 If this lane owns finalization, run \`bash scripts/agent-branch-finish.sh --branch --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + critic) + cat > "$ROLE_DIR/tasks.md" < --base --via-pr --wait-for-merge --cleanup\`. -- [ ] Record PR URL + final \`MERGED\` state in the role handoff or owner change task. -- [ ] Confirm sandbox cleanup, or capture a \`BLOCKED:\` handoff if finish is still pending. -" +- [ ] 6.1 If this lane owns finalization, run \`bash scripts/agent-branch-finish.sh --branch --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + executor) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + writer) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + verifier) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + *) + cat > "$ROLE_DIR/tasks.md" < --base dev --via-pr --wait-for-merge --cleanup\`. +- [ ] 6.2 Record PR URL + final \`MERGED\` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (\`git worktree list\`, \`git branch -a\`) or append \`BLOCKED:\` and stop. +TASKEOF + ;; + esac + fi done -echo "[gitguardex] OpenSpec plan workspace ready: ${PLAN_DIR}" -echo "[gitguardex] Roles: ${ROLES[*]}" +echo "Plan workspace ready: $PLAN_DIR" diff --git a/test/install.test.js b/test/install.test.js index f8d4fa3..5d329dc 100644 --- a/test/install.test.js +++ b/test/install.test.js @@ -4098,41 +4098,58 @@ test('OpenSpec plan workspace scaffold creates expected role/task structure', () assert.equal(scaffold.status, 0, scaffold.stderr || scaffold.stdout); const planDir = path.join(repoDir, 'openspec', 'plan', planSlug); - const expected = [ + const rootExpected = [ + 'README.md', 'summary.md', 'checkpoints.md', - 'planner/plan.md', - 'planner/prompt.md', - 'planner/tasks.md', - 'architect/prompt.md', - 'architect/tasks.md', - 'critic/prompt.md', - 'critic/tasks.md', - 'executor/prompt.md', - 'executor/tasks.md', - 'writer/prompt.md', - 'writer/tasks.md', - 'verifier/prompt.md', - 'verifier/tasks.md', + 'coordinator-prompt.md', + 'kickoff-prompts.md', + 'phases.md', ]; - for (const rel of expected) { + for (const rel of rootExpected) { assert.equal(fs.existsSync(path.join(planDir, rel)), true, `${rel} missing`); } + for (const role of ['planner', 'architect', 'critic', 'executor', 'writer', 'verifier']) { + assert.equal(fs.existsSync(path.join(planDir, role, 'README.md')), true, `${role}/README.md missing`); + assert.equal(fs.existsSync(path.join(planDir, role, '.openspec.yaml')), true, `${role}/.openspec.yaml missing`); + assert.equal(fs.existsSync(path.join(planDir, role, 'proposal.md')), true, `${role}/proposal.md missing`); + assert.equal(fs.existsSync(path.join(planDir, role, 'tasks.md')), true, `${role}/tasks.md missing`); + assert.equal( + fs.existsSync(path.join(planDir, role, 'specs', role, 'spec.md')), + true, + `${role}/specs/${role}/spec.md missing`, + ); + } + assert.equal(fs.existsSync(path.join(planDir, 'planner', 'plan.md')), true, 'planner/plan.md missing'); + assert.equal( + fs.existsSync(path.join(planDir, 'executor', 'checkpoints.md')), + true, + 'executor/checkpoints.md missing', + ); + + const coordinatorPrompt = fs.readFileSync(path.join(planDir, 'coordinator-prompt.md'), 'utf8'); + assert.match(coordinatorPrompt, /Drive this plan from draft to execution-ready status/); + assert.match(coordinatorPrompt, /kickoff-prompts\.md/); + + const phasesContent = fs.readFileSync(path.join(planDir, 'phases.md'), 'utf8'); + assert.match(phasesContent, /\[PH01\]/); + assert.match(phasesContent, /session: codex/); + const plannerTasks = fs.readFileSync(path.join(planDir, 'planner', 'tasks.md'), 'utf8'); - assert.match(plannerTasks, /## Ownership/); + assert.match(plannerTasks, /# planner tasks/); assert.match(plannerTasks, /## 1\. Spec/); assert.match(plannerTasks, /## 2\. Tests/); assert.match(plannerTasks, /## 3\. Implementation/); assert.match(plannerTasks, /## 4\. Checkpoints/); assert.match(plannerTasks, /## 5\. Collaboration/); assert.match(plannerTasks, /## 6\. Cleanup/); - assert.match(plannerTasks, /gx finish --via-pr --wait-for-merge --cleanup/); - assert.match(plannerTasks, /Claim this role's files in the shared owner branch\/worktree before editing/); + assert.match(plannerTasks, /\[P1\] READY - Initial planning draft checkpoint/); + assert.match(plannerTasks, /bash scripts\/agent-branch-finish\.sh/); - const plannerPrompt = fs.readFileSync(path.join(planDir, 'planner', 'prompt.md'), 'utf8'); - assert.match(plannerPrompt, /claim --branch /); - assert.match(plannerPrompt, /change tasks 4\.1-4\.3/); + const plannerPlan = fs.readFileSync(path.join(planDir, 'planner', 'plan.md'), 'utf8'); + assert.match(plannerPlan, /This ExecPlan is a living document/); + assert.match(plannerPlan, /## Idempotence and Recovery/); }); test('OpenSpec change workspace scaffold creates proposal/tasks/spec defaults', () => { @@ -4157,10 +4174,42 @@ test('OpenSpec change workspace scaffold creates proposal/tasks/spec defaults', assert.equal(fs.existsSync(path.join(changeDir, 'specs', capabilitySlug, 'spec.md')), true, 'spec.md missing'); const tasksContent = fs.readFileSync(path.join(changeDir, 'tasks.md'), 'utf8'); - assert.match(tasksContent, /## 4\. Cleanup/); - assert.match(tasksContent, /gx finish --via-pr --wait-for-merge --cleanup/); - assert.match(tasksContent, /Record PR URL \+ final `MERGED` state in the completion handoff\./); - assert.match(tasksContent, /Confirm sandbox cleanup/); + assert.match(tasksContent, /## Definition of Done/); + assert.match(tasksContent, /append a `BLOCKED:` line under section 4/); + assert.match(tasksContent, /## 4\. Cleanup \(mandatory; run before claiming completion\)/); + assert.match(tasksContent, /Run the cleanup pipeline:/); + assert.match(tasksContent, /Record the PR URL and final merge state \(`MERGED`\)/); + assert.match(tasksContent, /Confirm the sandbox worktree is gone/); +}); + +test('OpenSpec change workspace scaffold supports minimal T1 notes mode', () => { + const repoDir = initRepo(); + + const setupResult = runNode(['setup', '--target', repoDir, '--no-global-install'], repoDir); + assert.equal(setupResult.status, 0, setupResult.stderr || setupResult.stdout); + + const changeSlug = 'change-workspace-minimal'; + const capabilitySlug = 'runtime-migration'; + const agentBranch = 'agent/codex/minimal-change'; + const scaffold = runCmd( + 'bash', + ['scripts/openspec/init-change-workspace.sh', changeSlug, capabilitySlug, agentBranch], + repoDir, + { GUARDEX_OPENSPEC_MINIMAL: '1' }, + ); + assert.equal(scaffold.status, 0, scaffold.stderr || scaffold.stdout); + + const changeDir = path.join(repoDir, 'openspec', 'changes', changeSlug); + assert.equal(fs.existsSync(path.join(changeDir, '.openspec.yaml')), true, '.openspec.yaml missing'); + assert.equal(fs.existsSync(path.join(changeDir, 'notes.md')), true, 'notes.md missing'); + assert.equal(fs.existsSync(path.join(changeDir, 'proposal.md')), false, 'proposal.md should not exist in minimal mode'); + assert.equal(fs.existsSync(path.join(changeDir, 'tasks.md')), false, 'tasks.md should not exist in minimal mode'); + + const notesContent = fs.readFileSync(path.join(changeDir, 'notes.md'), 'utf8'); + assert.match(notesContent, /minimal \/ T1/); + assert.match(notesContent, new RegExp(agentBranch.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))); + assert.match(notesContent, /Commit message is the spec of record/); + assert.match(notesContent, /Record PR URL \+ `MERGED` state/); }); test('validate blocks unapproved deletions until allow-delete is set', () => {