| name | gpd-compact-state |
| description | Archive historical entries from STATE.md to keep it under the 150-line target |
| argument-hint | [--force] |
| context_mode | project-required |
| allowed-tools | ["read_file","write_file","shell","glob","grep"] |
<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>
Compact STATE.md when it grows too large by archiving historical entries to STATE-ARCHIVE.md.
STATE.md is the project's living memory — it accumulates decisions, insights, and context over the course of a research project. When it exceeds ~150 lines, older entries should be archived to keep the active context window efficient while preserving the full historical record.
Routes to the compact-state workflow which handles:
- Measuring current STATE.md line count
- Identifying archivable entries (completed phases, old decisions, resolved issues)
- Moving historical entries to STATE-ARCHIVE.md
- Preserving recent and actively referenced entries
- Updating cross-references between STATE.md and STATE-ARCHIVE.md
<execution_context>
Archive historical entries from STATE.md to reduce its size. As research projects grow, STATE.md accumulates decisions, session records, metrics, and resolved blockers from many phases. This workflow archives old entries to STATE-ARCHIVE.md, keeping STATE.md lean and under the target line budget.
Triggered automatically when progress.md detects STATE.md exceeds 1500 lines, or manually via $gpd-compact-state.
<required_reading>
Read all files referenced by the invoking prompt's execution_context before starting.
Read these files using the read_file tool:
- ./.codex/get-physics-done/templates/state-archive.md -- Template for STATE-ARCHIVE.md (archive structure, what gets archived, archive format)
</required_reading>
**Load state and check line count:**
INIT=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local init progress --include state)
if [ $? -ne 0 ]; then
echo "ERROR: gpd initialization failed: $INIT"
fi
Extract: state_exists, state_content.
If state_exists is false:
No STATE.md found. Nothing to compact.
Exit.
Count current lines:
STATE_LINES=$(wc -l < .gpd/STATE.md)
Report: "STATE.md is {STATE_LINES} lines."
Check thresholds:
- Under 150 lines: "STATE.md is within target budget. No compaction needed."
- 150-1500 lines: "STATE.md is above target (150 lines) but within emergency budget (1500). Consider manual trimming."
- Over 1500 lines: "STATE.md exceeds emergency budget. Running automatic compaction."
If under 1500 and not forced (--force flag absent): offer to compact anyway or exit.
**Delegate to gpd state compact:**
The gpd CLI handles the detailed archival logic:
RESULT=$(/Users/charlie/.gpd/venv/bin/python -m gpd.runtime_cli --runtime codex --config-dir ./.codex --install-scope local state compact)
if [ $? -ne 0 ]; then
echo "ERROR: state compact failed: $RESULT"
fi
Parse result JSON for: compacted (bool), reason, original_lines, new_lines, archived_lines, warn.
The tool performs these archival operations:
- Decisions: Archives decisions from phases older than (current - 1). Keeps current and previous phase decisions.
- Resolved blockers: Archives blockers marked
[resolved] or struck through (~~...~~). Keeps active blockers.
- Performance metrics: Archives metrics from phases older than (current - 1). Keeps recent metrics.
- Session records: Keeps only the last 3 session records. Archives older ones.
All archived content is appended to .gpd/STATE-ARCHIVE.md with a dated header.
If compacted is false:
Check reason:
"within_budget": STATE.md is already small enough.
"nothing_to_archive": STATE.md is large but nothing qualified for archival (all entries are current).
Report and exit.
**Verify the compacted STATE.md is valid:**
NEW_LINES=$(wc -l < .gpd/STATE.md)
for SECTION in "Current Position" "Project Reference" "Accumulated Context" "Session"; do
grep -q "## ${SECTION}" .gpd/STATE.md || echo "MISSING: ${SECTION}"
done
ls -la .gpd/state.json
If required sections are missing: The compaction was too aggressive. Attempt recovery:
if [ -f .gpd/state.json ]; then
echo "Attempting STATE.md recovery from state.json..."
uv run python - <<'PY'
import json
from pathlib import Path
from gpd.core.state import save_state_json
cwd = Path(".")
state = json.loads((cwd / ".gpd" / "state.json").read_text(encoding="utf-8"))
save_state_json(cwd, state)
PY
RECOVERY_METHOD="regenerated from authoritative state.json"
else
echo "state.json unavailable. Falling back to git restore..."
git checkout -- .gpd/STATE.md
RECOVERY_METHOD="restored from git"
fi
echo "Recovery method: ${RECOVERY_METHOD}"
Report error and recovery method used, then exit.
If state.json sync failed: Do not delete it blindly. Keep .gpd/state.json (and .gpd/state.json.bak if present), inspect gpd state validate, and use $gpd-sync-state or the recovery step above so JSON-only fields are preserved.
**Verify STATE-ARCHIVE.md was created/updated:**
ls -la .gpd/STATE-ARCHIVE.md 2>/dev/null
ARCHIVE_LINES=$(wc -l < .gpd/STATE-ARCHIVE.md 2>/dev/null || echo 0)
Confirm archived content is recoverable.
**Commit compaction results:**
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/STATE.md .gpd/STATE-ARCHIVE.md .gpd/state.json 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 \
"chore: compact STATE.md (${ORIGINAL_LINES} -> ${NEW_LINES} lines)" \
--files .gpd/STATE.md .gpd/STATE-ARCHIVE.md .gpd/state.json
**Present compaction summary:**
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GPD > STATE COMPACTED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**Before:** {original_lines} lines
**After:** {new_lines} lines
**Archived:** {archived_lines} lines to STATE-ARCHIVE.md
### What was archived:
- {N} decisions from phases < {keep_phase_min}
- {N} resolved blockers
- {N} performance metrics from old phases
- {N} historical session records
### Archive location:
.gpd/STATE-ARCHIVE.md ({archive_lines} total lines)
All archived content is recoverable from STATE-ARCHIVE.md or git history.
If STATE.md is still above 150 lines after compaction:
STATE.md is now {new_lines} lines (target: 150).
Remaining entries are all current-phase content. To further reduce:
- Summarize verbose intermediate results
- Move detailed derivation logs to phase SUMMARY.md files
- Keep only the latest key results, not historical progression
<failure_handling>
- STATE.md not found: Nothing to compact. Exit with message.
- gpd state compact fails: Check error output. Common causes: file lock held by another process, corrupt STATE.md parsing. Suggest:
cat .gpd/STATE.md | head -5 to verify file is readable.
- Required sections missing after compaction: Restore from git immediately. Report the bug.
- STATE-ARCHIVE.md write fails: Check disk space and permissions. STATE.md changes are preserved regardless.
</failure_handling>
<success_criteria>
</execution_context>
@.gpd/STATE.md
**Follow the compact-state workflow** from `@./.codex/get-physics-done/workflows/compact-state.md`.
If --force flag is present, skip the line-count check and compact regardless of current size.
The workflow handles all logic including:
- Measuring STATE.md line count against 150-line target
- Identifying historical entries safe to archive
- Creating or appending to STATE-ARCHIVE.md
- Removing archived entries from STATE.md
- Verifying no data was lost (archived + remaining = original)
- Updating state.json to reflect compaction
<success_criteria>