| name | gpd-merge-phases |
| description | Merge results from one phase into another |
| argument-hint | <source-phase> <target-phase> |
| context_mode | project-required |
| allowed-tools | ["read_file","write_file","apply_patch","shell","grep","glob"] |
<codex_runtime_notes>
Codex shell compatibility:
- When shell steps call the GPD CLI, use /Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local instead of the ambient
gpd on PATH.
- If you intentionally need the repo environment, keep the runtime pin:
GPD_ACTIVE_RUNTIME=codex uv run gpd ....
</codex_runtime_notes>
Merge the results, artifacts, and state updates from a source phase into a target phase. Useful when phases are reorganized, when a decimal phase (e.g., 2.1) needs to be folded back into its parent, or when parallel investigation branches converge.
Routes to the merge-phases workflow which handles:
- Validating both phases exist
- Copying artifacts (summaries, plans, data files)
- Merging intermediate results and decisions
- Updating the roadmap to reflect the merge
- Updating STATE.md with merge record
<execution_context>
Combine two research phases that turned out to be more tightly coupled than expected. Absorbs a source phase into a target phase, merging plans, summaries, verification results, and convention records. Updates ROADMAP.md, STATE.md, and the dependency graph.
<required_reading>
Read all files referenced by the invoking prompt's execution_context before starting.
</required_reading>
**Parse arguments and load context:**
INIT=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local init phase-op --include state,roadmap)
Extract from $ARGUMENTS: source_phase (to be absorbed) and target_phase (to absorb into).
If arguments incomplete:
Usage: $gpd-merge-phases <source> <target>
<source> Phase number to absorb (will be removed)
<target> Phase number to merge into (will be expanded)
Example: $gpd-merge-phases 5 4
Absorbs Phase 5 into Phase 4.
Exit.
Validate both phases exist and resolve directories:
SOURCE_INFO=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local phase find "${SOURCE_PHASE}")
TARGET_INFO=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local phase find "${TARGET_PHASE}")
If either phase not found: Error with available phases from roadmap.
Extract from find-phase: source_dir (directory), source_name (phase_name), target_dir (directory), target_name (phase_name).
Get goals from roadmap:
SOURCE_GOAL=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local roadmap get-phase "${SOURCE_PHASE}" | python3 -c "import sys,json; print(json.loads(sys.stdin.read()).get('goal',''))")
TARGET_GOAL=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local roadmap get-phase "${TARGET_PHASE}" | python3 -c "import sys,json; print(json.loads(sys.stdin.read()).get('goal',''))")
**Idempotency guard — check if merge was already partially applied:**
if [ ! -d "${SOURCE_DIR}" ]; then
echo "WARNING: Source phase directory ${SOURCE_DIR} does not exist."
echo "This merge may have already been applied (source was absorbed)."
echo ""
echo "Check target phase for merged plans:"
ls "${TARGET_DIR}"/*-PLAN.md 2>/dev/null
echo ""
echo "If the merge is already complete, no further action needed."
echo "If the merge was interrupted, check git log for partial commits."
exit 0
fi
MERGED_MARKER=$(ls "${TARGET_DIR}"/merged-from-phase-${SOURCE_PHASE}-* 2>/dev/null | head -1)
if [ -n "$MERGED_MARKER" ]; then
echo "WARNING: Target already contains merged artifacts from Phase ${SOURCE_PHASE}."
echo "This merge may have been partially applied."
echo ""
echo "Options:"
echo " 1. Continue merge (skip already-copied files)"
echo " 2. Abort (inspect manually)"
echo ""
fi
Verify merge is safe:
-
Adjacency check: Phases should be adjacent or closely related. Warn if |source - target| > 2:
WARNING: Phases {source} and {target} are not adjacent.
Merging distant phases may create dependency issues.
Continue anyway? (y/n)
-
Completion status check:
ls "${SOURCE_DIR}"/*-SUMMARY.md 2>/dev/null | wc -l
ls "${SOURCE_DIR}"/*-PLAN.md 2>/dev/null | wc -l
ls "${TARGET_DIR}"/*-SUMMARY.md 2>/dev/null | wc -l
ls "${TARGET_DIR}"/*-PLAN.md 2>/dev/null | wc -l
Report status of both phases (complete, partial, unstarted).
-
Dependency check: Verify no other phases depend solely on the source phase.
Inspect SUMMARY frontmatter and ROADMAP dependencies directly. Check whether any other phase has requires entries pointing to artifacts that only the source phase provides. Those dependencies must be redirected to the target after the merge. If the dependency picture is nontrivial, reuse the manual graph-building procedure from workflows/graph.md.
Present merge plan to user:
## Merge Plan
**Source:** Phase {S}: {source_name} ({plan_count} plans, {summary_count} summaries)
**Target:** Phase {T}: {target_name} ({plan_count} plans, {summary_count} summaries)
### What will happen:
1. Source plans appended to target (renumbered)
2. Source summaries copied to target
3. Source verification results preserved as-is
4. ROADMAP.md updated (source removed, target expanded)
5. STATE.md updated
6. Dependencies redirected: {list or "none"}
Proceed? (y/n)
Wait for user confirmation.
**Check for content overlap between source and target:**
Read PLAN.md files from both phases. Compare:
- Overlapping objectives (plans that derive/compute the same thing)
- Shared convention declarations
- Duplicate file paths in
files_modified frontmatter
If overlap found:
## Content Overlap Detected
| Source Plan | Target Plan | Overlap |
|------------|------------|---------|
| {S}-01 | {T}-02 | Both compute {quantity} |
These overlapping plans will need manual reconciliation after merge.
**Copy and renumber source plans into target directory:**
-
Determine the next plan number in target: count existing *-PLAN.md files
-
For each source plan:
NEW_NUM=$(printf "%02d" $((TARGET_PLAN_COUNT + SOURCE_INDEX)))
NEW_PREFIX="${TARGET_PHASE_PADDED}-${NEW_NUM}"
-
Copy plan file with new name
-
Update frontmatter in copied plan:
- Update plan number
- Update
depends_on references (source phase refs -> target phase refs)
- Preserve wave assignments (may need adjustment)
-
Copy matching SUMMARY.md files with same renumbering
Source plans are APPENDED to target, never overwrite existing target plans.
**Handle verification and research artifacts:**
for FILE in "${SOURCE_DIR}"/*-VERIFICATION.md "${SOURCE_DIR}"/*-VALIDATION.md; do
if [ -f "$FILE" ]; then
cp "$FILE" "${TARGET_DIR}/merged-from-phase-${SOURCE_PHASE}-$(basename "$FILE")"
fi
done
for FILE in "${SOURCE_DIR}"/*-RESEARCH.md "${SOURCE_DIR}"/*-CONTEXT.md; do
if [ -f "$FILE" ] && ! ls "${TARGET_DIR}"/*-RESEARCH.md 2>/dev/null; then
cp "$FILE" "${TARGET_DIR}/"
fi
done
Copy any scripts, data files, or other artifacts from source to target.
**Reconcile conventions between phases:**
Read convention declarations from SUMMARY.md frontmatter in both phases:
/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local summary-extract "${SOURCE_DIR}"/*-SUMMARY.md --field conventions
/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local summary-extract "${TARGET_DIR}"/*-SUMMARY.md --field conventions
If conventions conflict (same field, different value):
## Convention Conflict
| Field | Source (Phase {S}) | Target (Phase {T}) |
|-------|-------------------|-------------------|
| metric_signature | (-,+,+,+) | (+,-,-,-) |
CRITICAL: This must be resolved before merge completes.
Which convention should the merged phase use?
Wait for user decision. Record decision via gpd CLI:
/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local state add-decision --phase "${TARGET_PHASE}" --summary "Convention resolution for merge: chose {chosen}" --rationale "{user rationale}"
If conventions compatible: No action needed.
**Update ROADMAP.md:**
-
Remove the source phase entry
-
Expand the target phase description to include source objectives:
## Phase {T}: {target_name} (merged with Phase {S}: {source_name})
**Goal:** {target_goal}. Additionally: {source_goal}
-
Renumber all phases after source (if source < target, phases between shift down)
-
Update dependency references throughout: any requires: Phase {S} becomes requires: Phase {T}
Write updated ROADMAP.md.
**Update STATE.md:**
/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local state patch \
"--Current Phase" "${TARGET_PHASE}" \
"--Last Activity Description" "Merged phase ${SOURCE_PHASE} into ${TARGET_PHASE}"
if [ $? -ne 0 ]; then echo "WARNING: state patch failed — phase position may be wrong"; fi
Record merge decision:
/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local state add-decision \
--phase "${TARGET_PHASE}" \
--summary "Merged Phase ${SOURCE_PHASE} (${SOURCE_NAME}) into Phase ${TARGET_PHASE} (${TARGET_NAME})" \
--rationale "${USER_RATIONALE}"
if [ $? -ne 0 ]; then echo "WARNING: state add-decision failed — merge decision not recorded"; fi
**Remove source phase directory:**
SOURCE_FILE_COUNT=$(find "${SOURCE_DIR}" -type f | wc -l)
if [ "${ALL_COPIED}" = "true" ]; then
rm -rf "${SOURCE_DIR}"
else
echo "WARNING: Not all source files were copied. Source directory preserved."
echo "Manual cleanup needed: ${SOURCE_DIR}"
fi
**Commit all merge changes atomically:**
PRE_CHECK=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local pre-commit-check --files .gpd/ROADMAP.md .gpd/STATE.md .gpd/state.json "${TARGET_DIR}" 2>&1) || true
echo "$PRE_CHECK"
/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local commit \
"refactor(phases): merge phase ${SOURCE_PHASE} into phase ${TARGET_PHASE}" \
--files .gpd/ROADMAP.md .gpd/STATE.md .gpd/state.json "${TARGET_DIR}"
**Present merge summary:**
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GPD > PHASES MERGED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Phase {S}: {source_name} absorbed into Phase {T}: {target_name}
**Plans:** {target_original} + {source_count} = {total} plans
**Summaries:** {summary_count} completed
**Convention conflicts:** {count resolved or "none"}
**Dependencies redirected:** {count or "none"}
---
**Also available:**
- $gpd-show-phase {T} -- inspect merged phase
- $gpd-execute-phase {T} -- execute pending plans
- $gpd-validate-conventions -- verify convention consistency
---
<failure_handling>
- Phase not found: List available phases from roadmap. Exit.
- Convention conflict unresolved: Do not proceed with merge. User must decide.
- File copy failure: Preserve source directory. Report which files failed. User can retry or merge manually.
- Circular dependency after merge: Detect during dependency graph update. Warn user and suggest resolution.
</failure_handling>
<success_criteria>
</execution_context>
Format: ` ` — first argument is the source phase, second is the target phase.
Source phase: first argument (e.g., "2.1")
Target phase: second argument (e.g., "2")
@.gpd/STATE.md
@.gpd/ROADMAP.md
Execute the merge-phases workflow from @./.codex/get-physics-done/workflows/merge-phases.md end-to-end.
If --dry-run flag is present, show the merge plan (which artifacts would move, which results would combine) without executing any changes.
The workflow handles:
- Validation -- Both phases exist, source has completed work, target is compatible
- Artifact merge -- Copy summaries, plans, data files from source to target
- Result merge -- Combine intermediate results, avoiding duplicates
- Decision merge -- Merge decisions with phase attribution preserved
- Roadmap update -- Mark source phase as merged, update target description
- State update -- Record the merge as a decision in STATE.md