titan-run
Skill94 starsChanged 3 months agoApache-2.0View on GitHub
Run the full Titan Paradigm pipeline end-to-end by dispatching each phase to sub-agents with fresh context windows. Orchestrates recon → gauntlet → sync → forge → grind (+ repo-provided parity audit) automatically.
- Installs packages
In this repository22 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- architectSkill
- bench-checkSkill
- create-skillSkill
- deps-auditSkill
- dogfoodSkill
- fixerSkill
- housekeepSkill
- overseeSkill
- paritySkill
- releaseSkill
- resolveSkill
- sweepSkill
- test-healthSkill
- titan-closeSkill
- titan-forgeSkill
- titan-gateSkill
- titan-gauntletSkill
- titan-grindSkill
- titan-reconSkill
- titan-resetSkill
- titan-syncSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
82 rules. About 0 are common, 33 are distinctive, and 49 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈33
Distinctive · estimate
This author's own choices. Worth a look.
49
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 15
No args → full pipeline from scratch, target .
- Very specific: line 39
Check existing state: Read .codegraph/titan/titan-state.json if it exists.
- Very specific: line 40
If state exists and --start-from not specified, ask user: "Existing Titan state found (phase: <currentPhase>).
- Very specific: line 41
If --yes is set, resume automatically.
- Very specific: line 55
Timestamp validation: After recording completedAt for any phase, verify startedAt < completedAt:
- Distinctive: line 59
If the check fails, log a warning but do not stop the pipeline — clock skew or immediate completion of short phases can cause this.
- Distinctive: line 69
If the install fails, warn the user but continue with whichever version is currently available.
- Very specific: line 75
If merge conflict → stop: "Merge conflict after syncing with main.
- Very specific: line 79
E1. Node dependencies: Check whether node_modules needs installing:
- Very specific: line 99
All test runs in forge/grind/gate agent prompts must reference this file: npx vitest run --config vitest.config.worktree.ts.
- Distinctive: line 116
If any bootstrap step fails, warn but continue — the pipeline can still proceed, and forge/grind agents will catch environment issues at …
- Very specific: line 131
Start immediately — do NOT ask for confirmation before analysis phases.
- Distinctive: line 137
Before spawning any sub-agent, run these checks.
- Very specific: line 150
If this fails (worktree was pruned or moved), stop: "Worktree is no longer valid.
- Very specific: line 153
If .codegraph/titan/titan-state.json should exist at this point (i.e., we're past recon):
- Distinctive: line 157
If CORRUPT → attempt recovery from backup:
- Very specific: line 158
Check if .codegraph/titan/titan-state.json.bak exists.
- Distinctive: line 159
If the backup exists, validate it is valid JSON:
- Very specific: line 163
If the backup is valid → restore it: cp .codegraph/titan/titan-state.json.bak .codegraph/titan/titan-state.json
- Very specific: line 164
If the backup is also corrupt or missing → stop: "State file corrupted with no valid backup.
- Distinctive: line 167
Before every sub-agent dispatch, back up the current state file:
- Very specific: line 171
If a sub-agent corrupts the state, G3 on the next iteration will detect it and restore from .bak.
- Very specific: line 189
If ANY required artifact is missing → stop: "Cannot start from <phase> — <artifact> is missing.
- Distinctive: line 191
If ANY V-check that is normally VALIDATION FAILED would fail → stop with the same message as it would during normal execution.
- Distinctive: line 216
Use the Agent tool to spawn a sub-agent:
- Distinctive: line 230
After the agent returns, validate the artifacts:
- Very specific: line 233
Read .codegraph/titan/titan-state.json and verify ALL of these fields exist and are non-empty:
- Very specific: line 244
If any field is missing, zero, or wrong type → VALIDATION FAILED.
- Very specific: line 249
Must contain ## Domain Map heading
- Distinctive: line 252
If missing or empty → VALIDATION FAILED.
- Very specific: line 258
If NO_SNAPSHOT → WARN (not fatal, but note it: "No baseline snapshot — rollback in GATE will not work").
- Distinctive: line 263
Batch size check: Every batch must have ≤ 5 files.
- Distinctive: line 265
If wildly inconsistent (e.g., 0 batches but 500 nodes) → WARN with details.
- Very specific: line 281
Read .codegraph/titan/gauntlet-summary.json if it exists:
- Very specific: line 282
If "complete": true → run gauntlet post-validation (2d) and skip loop if it passes
- Distinctive: line 338
After the loop completes (or on each iteration if you prefer lightweight checks):
- Very specific: line 357
If missing == true: treat as equivalent to valid == 0 — the file does not exist yet (expected on first iteration, error if the loop should …
- Very specific: line 358
If corrupt > 0: Print "WARNING: <corrupt> corrupt lines in gauntlet.ndjson (likely from a crashed sub-agent).
- Very specific: line 359
If valid == 0 and missing == false: Stop: "gauntlet.ndjson has no valid entries.
- Very specific: line 366
If coverage < 80%: WARN "Gauntlet only audited <N>/<M> targets (<pct>%).
- Distinctive: line 367
If coverage < 50%: VALIDATION FAILED.
- Very specific: line 370
Read first 5 and last 5 entries from gauntlet.ndjson.
- Distinctive: line 378
If any sampled entry is missing required fields → WARN: "Gauntlet entry for <target> is incomplete — sub-agent may have skipped rules.
- Distinctive: line 385
If mismatched → WARN with details (not fatal — the NDJSON is the source of truth, summary is derived).
- Very specific: line 416
If this fails → VALIDATION FAILED.
- Very specific: line 419
Read .codegraph/titan/sync.json and verify:
- Distinctive: line 424
No duplicate phase numbers
- Very specific: line 426
If missing or structurally invalid → VALIDATION FAILED.
- Very specific: line 459
If --start-from forge is used without an existing snapshot, run Step 3.5a normally (captures a pre-forge baseline from the current …
- Very specific: line 463
Before any code changes, snapshot the codebase's architectural properties.
- Very specific: line 558
If --yes is NOT set: stop and wait for user confirmation.
- Very specific: line 559
If --yes IS set: print the summary but continue automatically.
- Very specific: line 571
Read .codegraph/titan/sync.json → count total phases in executionOrder.
- Very specific: line 572
Read .codegraph/titan/titan-state.json → check execution.completedPhases (may not exist yet if forge hasn't started).
- Very specific: line 574
If .codegraph/titan/arch-snapshot.json does not exist: Print: "NOTE: No arch-snapshot.json found.
- Very specific: line 709
Every commit SHA in execution.commits should exist in git log:
- Distinctive: line 713
If any SHA doesn't exist → WARN: "Commit <sha> recorded in state but not found in git history.
- Very specific: line 718
Every FAIL entry with "rolledBack": true should NOT have a corresponding commit in execution.commits
- Very specific: line 737
Read .codegraph/titan/titan-state.json → check grind.completedPhases (may not exist yet if grind hasn't started).
- Very specific: line 843
Read grind.deadSymbolBaseline and grind.deadSymbolCurrent from titan-state.json.
- Distinctive: line 844
If delta > 10: WARN "Grind could not fully adopt forge's helpers.
- Distinctive: line 849
If < 100%: WARN with details
- Distinctive: line 904
After the agent returns:
- Very specific: line 911
If the agent fixed divergences, run V16-style commit audit: git log --oneline $headBefore..$headAfter and print the parity-fix commits.
- Distinctive: line 912
If the agent reports divergences introduced by THIS run that it could not fix → stop: "PARITY failed — this run introduced implementation …
- Very specific: line 922
After forge completes, dispatch /titan-close to produce the final report with before/after metrics and split commits into focused PRs.
- Distinctive: line 938
After the agent returns, verify:
- Distinctive: line 942
If the agent created PRs, print the PR URLs.
- Very specific: line 944
Commit hygiene check: If .claude/skills/ files were modified during this run (e.g., by a V13 regression-fix agent), they must NOT share a …
- Distinctive: line 948
If both are dirty, commit them separately before proceeding to the retrospective.
- Distinctive: line 956
After CLOSE, run a brief retrospective on this pipeline execution and offer to apply findings as skill improvements.
- Distinctive: line 960
Read from disk (no sub-agent needed):
- Very specific: line 1008
After the agent writes retrospective.json, read and print it:
- Very specific: line 1036
If --yes is set → apply automatically without asking.
- Distinctive: line 1040
Run Pre-Agent Gate (G1-G4), back up state, then:
- Distinctive: line 1061
State file missing when expected: Stop with clear message about which prerequisite phase to run.
- Distinctive: line 1064
Merge conflict detected by pre-agent gate: Stop immediately with the conflicting files listed.
- Very specific: line 1066
Parity audit fails on drift introduced by this run: Stop before CLOSE. Retry with /titan-run --start-from parity after fixing or reverting.
- Distinctive: line 1067
Validation failure (any V-check marked FAILED): Stop with details. Warn-level V-checks are logged but don't stop the pipeline.
- Distinctive: line 1074
Run the Pre-Agent Gate (G1-G4) before EVERY sub-agent: No exceptions.
- Very specific: line 1082
Pass --yes through to forge: if the user provided it, so forge skips its per-phase confirmation prompt.
- Very specific: line 1090
When adding new phases: update meta.phases at the top, add the phase to the timestamp list in Step 0.3, add a V-check for the phase's key …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Titan RUN — End-to-End Pipeline Orchestrator
You are the orchestrator for the full Titan Paradigm pipeline. Your job is to dispatch each phase to a sub-agent (fresh context window), validate the results, and loop phases that require multiple invocations — all without human intervention.
You are lightweight. You do NOT run codegraph commands, audit files, or make code changes yourself. You only: (1) spawn sub-agents, (2) read and validate state files, (3) decide what to run next.
Arguments (from $ARGUMENTS):
- No args → full pipeline from scratch, target
. <path>→ target path (passed to recon)--skip-recon→ skip recon (assumes artifacts exist)--skip-gauntlet→ skip gauntlet (assumes artifacts exist)--start-from <phase>→ jump to phase:recon,gauntlet,sync,forge,grind,parity,close--gauntlet-batch-size <N>→ batch size for gauntlet (default: 5)--yes→ skip all confirmation prompts in the orchestrator (pre-pipeline, forge checkpoint, and resume prompts) and in forge (per-phase confirmation)
Step 0 — Pre-flight
- Worktree check:
The Titan pipeline writes artifacts and makes code changes — worktree isolation is required. If you are NOT in a worktree, create one automatically using thegit rev-parse --show-toplevel && git worktree listEnterWorktreetool (fetch it viaToolSearchif needed) with nametitan-run. Do NOT stop and ask the user — just enter the worktree and continue. - Parse arguments. Determine:
targetPath(default:.)startPhase(default:recon)gauntletBatchSize(default:5)autoConfirm→trueif--yesis present, otherwisefalse
Check existing state. Read
.codegraph/titan/titan-state.jsonif it exists.- If state exists and
--start-fromnot specified, ask user: "Existing Titan state found (phase:<currentPhase>). Resume from current state, or start fresh with/titan-resetfirst?" - If
--yesis set, resume automatically.
Initialize the phase timestamps helper. Throughout the pipeline, you will record wall-clock timestamps for each phase. Use this helper to write them into
titan-state.json:# Record phase start (safe for resume — only sets startedAt if not already present): node -e "const fs=require('fs');const s=JSON.parse(fs.readFileSync('.codegraph/titan/titan-state.json','utf8'));s.phaseTimestamps=s.phaseTimestamps||{};s.phaseTimestamps['<PHASE>']=s.phaseTimestamps['<PHASE>']||{};if(!s.phaseTimestamps['<PHASE>'].startedAt){s.phaseTimestamps['<PHASE>'].startedAt=new Date().toISOString();fs.writeFileSync('.codegraph/titan/titan-state.json',JSON.stringify(s,null,2));}" # Record phase completion: node -e "const fs=require('fs');const s=JSON.parse(fs.readFileSync('.codegraph/titan/titan-state.json','utf8'));s.phaseTimestamps=s.phaseTimestamps||{};s.phaseTimestamps['<PHASE>']=s.phaseTimestamps['<PHASE>']||{};s.phaseTimestamps['<PHASE>'].completedAt=new Date().toISOString();fs.writeFileSync('.codegraph/titan/titan-state.json',JSON.stringify(s,null,2));"Replace
<PHASE>withrecon,gauntlet,sync,forge,grind,parity, orclose. Run the start command immediately before dispatching each phase's first sub-agent, and the completion command immediately after post-phase validation passes. If resuming a phase (e.g., gauntlet loop iteration 2+), do NOT overwritestartedAt— only set it if it doesn't already exist.Timestamp validation: After recording
completedAtfor any phase, verifystartedAt < completedAt:node -e "const s=JSON.parse(require('fs').readFileSync('.codegraph/titan/titan-state.json','utf8'));const p=s.phaseTimestamps?.['<PHASE>'];if(p?.startedAt&&p?.completedAt){const start=new Date(p.startedAt),end=new Date(p.completedAt);if(end<=start){console.log('WARNING: <PHASE> completedAt ('+p.completedAt+') is not after startedAt ('+p.startedAt+')');process.exit(0);}console.log('<PHASE> duration: '+((end-start)/60000).toFixed(1)+' min');}else{console.log('WARNING: <PHASE> missing startedAt or completedAt');}"If the check fails, log a warning but do not stop the pipeline — clock skew or immediate completion of short phases can cause this.
- If state exists and
- Install latest codegraph (once, before any sub-agent runs):
Log the installed version:npm install -g @optave/codegraph@latest
If the install fails, warn the user but continue with whichever version is currently available.codegraph --version - Sync with main (once, before any sub-agent runs):
If merge conflict → stop: "Merge conflict after syncing with main. Resolve conflicts and re-rungit fetch origin main && git merge origin/main --no-edit/titan-run." Bootstrap worktree environment (run when
pwdcontains.claude/worktrees/ornode_modulesis absent/stale):E1. Node dependencies: Check whether
node_modulesneeds installing:if [ ! -f node_modules/.package-lock.json ] || [ package.json -nt node_modules/.package-lock.json ]; then npm install --prefer-offline 2>&1 | tail -5 fiThis also builds WASM grammars (via the
preparescript). After this step, all subsequent agent prompts must useTEST_CMD="npx vitest run --config vitest.config.worktree.ts"(see E2).E2. Vitest worktree config: The default
vitest.config.tsexcludes**/.claude/**, matching this path and silently breaking test discovery. Write an override if absent:if [ ! -f vitest.config.worktree.ts ]; then node -e " const fs = require('fs'); const src = fs.readFileSync('vitest.config.ts', 'utf8'); fs.writeFileSync('vitest.config.worktree.ts', src.replace(/'\*\*\/\.claude\/\*\*',?\s*/g, '')); console.log('vitest.config.worktree.ts written'); " fiAll test runs in forge/grind/gate agent prompts must reference this file:
npx vitest run --config vitest.config.worktree.ts.E3. Native binary freshness (only if
crates/exists):NODE_BINARY=$(find node_modules/@optave -name "codegraph-core.node" 2>/dev/null | head -1) if [ -n "$NODE_BINARY" ]; then NEWER_RUST=$(find crates -name "*.rs" -newer "$NODE_BINARY" 2>/dev/null | head -1) if [ -n "$NEWER_RUST" ]; then echo "Rust source newer than binary — rebuilding native addon..." npx napi build --platform --release --manifest-path crates/codegraph-core/Cargo.toml --output-dir . PLATFORM=$(node -e "const os=require('os');const arch=os.arch()==='arm64'?'arm64':'x64';console.log(os.platform()+'-'+arch)") codesign --sign - --force codegraph-core.node 2>/dev/null || true cp codegraph-core.node "node_modules/@optave/codegraph-${PLATFORM}/codegraph-core.node" echo "Native binary rebuilt." fi fiIf any bootstrap step fails, warn but continue — the pipeline can still proceed, and forge/grind agents will catch environment issues at test-run time.
Print plan:
Titan Pipeline — End-to-End Run Target: <path> Starting from: <phase> Gauntlet batch size: <N> Phases: recon → gauntlet (loop) → sync → [PAUSE] → forge (loop) → grind (loop) → close Each phase runs in a sub-agent with a fresh context window. Forge requires explicit confirmation (analysis phases are safe to automate). Grind runs after forge to adopt extracted helpers into consumers.Start immediately — do NOT ask for confirmation before analysis phases. The user invoked
/titan-run; that is the confirmation. Analysis phases (recon, gauntlet, sync) are read-only and safe to automate. The forge checkpoint (Step 3.5b) still applies unless--yesis set.
Pre-Agent Gate (run before EVERY sub-agent dispatch)
Before spawning any sub-agent, run these checks. This catches git state drift, concurrent interference, and corruption left by a crashed agent.
G1. Git health check
git status --porcelain- Unexpected dirty files (files not in
.codegraph/titan/): Print warning with the file list. Ask user to confirm proceeding, or stop. If--yes, log the warning and continue — but do NOT stage or commit these files. - Merge conflicts (lines starting with
UU,AA,DD,AU,UA,DU,UD): Stop immediately: "Unresolved merge conflict detected. Resolve before continuing."
G2. Worktree still valid
git rev-parse --is-inside-work-treeIf this fails (worktree was pruned or moved), stop: "Worktree is no longer valid. Create a new one with /worktree."
G3. State file integrity
If .codegraph/titan/titan-state.json should exist at this point (i.e., we're past recon):
node -e "try { JSON.parse(require('fs').readFileSync('.codegraph/titan/titan-state.json','utf8')); console.log('OK'); } catch(e) { console.log('CORRUPT: '+e.message); process.exit(1); }"- If CORRUPT → attempt recovery from backup:
- Check if
.codegraph/titan/titan-state.json.bakexists. - If the backup exists, validate it is valid JSON:
node -e "try { JSON.parse(require('fs').readFileSync('.codegraph/titan/titan-state.json.bak','utf8')); console.log('BACKUP OK'); } catch(e) { console.log('BACKUP CORRUPT: '+e.message); process.exit(1); }" - If the backup is valid → restore it:
cp .codegraph/titan/titan-state.json.bak .codegraph/titan/titan-state.json - If the backup is also corrupt or missing → stop: "State file corrupted with no valid backup. Run
/titan-resetand start over."
- Check if
G4. State backup
Before every sub-agent dispatch, back up the current state file:
cp .codegraph/titan/titan-state.json .codegraph/titan/titan-state.json.bak 2>/dev/null || trueIf a sub-agent corrupts the state, G3 on the next iteration will detect it and restore from .bak.
Step 0.5 — Artifact pre-validation (phase skip)
Run this step if --start-from was specified, --skip-recon is set, or --skip-gauntlet is set. Any of these flags cause phases to be skipped — their artifacts must exist and be valid before proceeding. When --skip-recon is set, validate recon artifacts. When --skip-gauntlet is set, validate both recon and gauntlet artifacts.
For each phase BEFORE startPhase, run the corresponding V-checks:
| Skipped phase | Required artifacts + checks |
recon | V1 structural fields only (domains, batches, priorityQueue, stats — skip currentPhase == "recon" check since later phases advance it), V2 (GLOBAL_ARCH.md), V3 (snapshot exists — WARN if missing), V4 (cross-check counts) |
gauntlet | V5 (coverage ≥ 50%), V6 (entry completeness sample), V7 (summary consistency); also run NDJSON integrity check (2c) |
sync | V8 (sync.json structure), V9 (targets trace to gauntlet), V10 (dependency order) |
forge | V14 (final state consistency), V15 (gate log consistency); execution block must exist in titan-state.json |
grind | V14, V15; execution.completedPhases must be non-empty in titan-state.json (forge must have run at least one phase) |
If ANY required artifact is missing → stop: "Cannot start from <phase> — <artifact> is missing. Run the full pipeline or start from an earlier phase."
If ANY V-check that is normally VALIDATION FAILED would fail → stop with the same message as it would during normal execution.
WARN-level V-checks from skipped phases are surfaced as prefixed warnings: "[skipped-phase pre-validation] <warning text>" — they do not stop the pipeline.
Step 1 — RECON
Skip if: --skip-recon, --start-from is after recon, or titan-state.json already has currentPhase beyond "recon".
1a. Run Pre-Agent Gate (G1-G4)
1a.1. Record phase start timestamp
Record phaseTimestamps.recon.startedAt (only if not already set — it may exist from a prior crashed run).
Note: On a fresh run, titan-state.json does not yet exist (titan-recon creates it in Step 12). Use this safe variant that creates a minimal stub if the file is missing:
node -e "const fs=require('fs');const p='.codegraph/titan/titan-state.json';let s;try{s=JSON.parse(fs.readFileSync(p,'utf8'));}catch{fs.mkdirSync('.codegraph/titan',{recursive:true});s={};}s.phaseTimestamps=s.phaseTimestamps||{};s.phaseTimestamps['recon']=s.phaseTimestamps['recon']||{};if(!s.phaseTimestamps['recon'].startedAt){s.phaseTimestamps['recon'].startedAt=new Date().toISOString();fs.writeFileSync(p,JSON.stringify(s,null,2));}"This ensures recon.startedAt is recorded even on first-time runs. titan-recon Step 12 merges any existing phaseTimestamps into the full state file it writes.
1b. Dispatch sub-agent
Use the Agent tool to spawn a sub-agent:
prompt: |
You are running the Titan RECON phase. Read and follow the skill file at
.claude/skills/titan-recon/SKILL.md exactly. Target path: <targetPath>.
IMPORTANT: Skip the worktree check (Step 0.1) — the orchestrator already verified this.
IMPORTANT: Skip the "sync with main" step (Step 0.2) — the orchestrator already did this.
Execute Steps 1-13 as documented.1c. Post-phase validation
After the agent returns, validate the artifacts:
V1. titan-state.json structure:
Read .codegraph/titan/titan-state.json and verify ALL of these fields exist and are non-empty:
version— must be a numberinitialized— must be an ISO 8601 stringcurrentPhase— must equal"recon"stats.totalNodes— must be > 0stats.totalEdges— must be > 0stats.totalFiles— must be > 0domains— must be an array with length > 0batches— must be an array with length > 0priorityQueue— must be an array with length > 0
If any field is missing, zero, or wrong type → VALIDATION FAILED. Print which fields failed and stop: "RECON produced incomplete state. Re-run with /titan-run --start-from recon."
V2. GLOBAL_ARCH.md exists and has content:
Read .codegraph/titan/GLOBAL_ARCH.md:
- Must exist
- Must contain
## Domain Mapheading - Must have > 10 lines
If missing or empty → VALIDATION FAILED.
V3. Snapshot created:
codegraph snapshot list 2>/dev/null | grep titan-baseline || echo "NO_SNAPSHOT"If NO_SNAPSHOT → WARN (not fatal, but note it: "No baseline snapshot — rollback in GATE will not work").
V4. Cross-check counts:
titan-state.json → stats.totalFilesshould roughly match the number of targets across all batches (batches are subsets of files, sosum(batch.files.length)should be ≤totalFiles)priorityQueue.lengthshould be > 0 and ≤totalNodes- Batch size check: Every batch must have ≤ 5 files. If any batch exceeds 5, WARN: "Batch
<id>has<N>files (max 5). Large batches cause context overload in gauntlet sub-agents."
If wildly inconsistent (e.g., 0 batches but 500 nodes) → WARN with details.
Print: RECON validated. Domains: <count>, Batches: <count>, Priority targets: <count>, Quality score: <score>
Record phaseTimestamps.recon.completedAt.
Step 2 — GAUNTLET (loop)
Skip if: --skip-gauntlet or --start-from is after gauntlet.
2a. Pre-loop check
Record phaseTimestamps.gauntlet.startedAt (only if not already set — gauntlet may be resuming).
Read .codegraph/titan/gauntlet-summary.json if it exists:
- If
"complete": true→ run gauntlet post-validation (2d) and skip loop if it passes - Otherwise, count completed batches from
titan-state.jsonfor progress tracking
Compute expectedTargetCount from titan-state.json → priorityQueue.length (or sum of batch file counts). This is the ground truth for "how many targets should gauntlet audit."
2b. Gauntlet loop
Set maxIterations = 50 (safety limit).
Set stallCount = 0, maxStalls = 3 (consecutive no-progress iterations before abort).
previousAuditedCount = titan-state.json → progress.audited (or 0)
iteration = 0
while iteration < maxIterations:
iteration += 1
# Run Pre-Agent Gate (G1-G4)
# Dispatch sub-agent
Agent → "Run /titan-gauntlet with batch size <N>.
Read .claude/skills/titan-gauntlet/SKILL.md and follow it exactly.
Batch size: <gauntletBatchSize>.
Skip worktree check and main sync — already handled.
Process as many batches as context allows, then save state and stop."
# Check completion
Read .codegraph/titan/gauntlet-summary.json (if exists)
if "complete": true → break
# Progress tracking
Read .codegraph/titan/titan-state.json
currentAuditedCount = progress.audited
if currentAuditedCount == previousAuditedCount:
stallCount += 1
Print: "WARNING: Gauntlet iteration <iteration> made no progress (stall <stallCount>/<maxStalls>)"
if stallCount >= maxStalls:
Stop: "Gauntlet stalled for <maxStalls> consecutive iterations at <currentAuditedCount>/<expectedTargetCount> targets. Likely stuck on a problematic target. Check gauntlet.ndjson for the last successful entry and investigate the next target in the batch."
else:
stallCount = 0 # reset on any progress
countBeforeUpdate = previousAuditedCount
previousAuditedCount = currentAuditedCount
# Efficiency check: if progress is very slow (< 2 targets per iteration), warn
# Only fire when stallCount == 0 — if stalled, the stall warning already covers it
targetsThisIteration = currentAuditedCount - countBeforeUpdate
if targetsThisIteration == 1 and iteration > 3 and stallCount == 0:
Print: "WARNING: Only 1 target per iteration — agent may be spending too much context. Consider increasing batch size."
Print: "Gauntlet iteration <iteration>: <currentAuditedCount>/<expectedTargetCount> targets audited"2c. NDJSON integrity check
After the loop completes (or on each iteration if you prefer lightweight checks):
node -e "
const fs = require('fs');
const path = '.codegraph/titan/gauntlet.ndjson';
if (!fs.existsSync(path)) {
console.log(JSON.stringify({ valid: 0, corrupt: 0, total: 0, missing: true }));
process.exit(0);
}
const lines = fs.readFileSync(path,'utf8').trim().split('\n');
let valid = 0, corrupt = 0;
for (const line of lines) {
try { JSON.parse(line); valid++; } catch { corrupt++; }
}
console.log(JSON.stringify({ valid, corrupt, total: lines.length, missing: false }));
"- If
missing == true: treat as equivalent tovalid == 0— the file does not exist yet (expected on first iteration, error if the loop should have produced entries). - If
corrupt > 0: Print "WARNING:<corrupt>corrupt lines in gauntlet.ndjson (likely from a crashed sub-agent). These targets may need re-auditing." - If
valid == 0andmissing == false: Stop: "gauntlet.ndjson has no valid entries. Something went wrong."
2d. Post-loop validation
V5. Gauntlet coverage:
- Count distinct
targetvalues ingauntlet.ndjson(valid lines only) - Compare against
expectedTargetCount - If coverage < 80%: WARN "Gauntlet only audited
<N>/<M>targets (<pct>%). Consider re-running with/titan-run --start-from gauntlet." - If coverage < 50%: VALIDATION FAILED. Stop.
V6. Gauntlet entry completeness (sample check):
Read first 5 and last 5 entries from gauntlet.ndjson. Each entry MUST have:
target— non-empty stringfile— non-empty stringverdict— one ofPASS,WARN,FAIL,DECOMPOSEpillarVerdicts— object with keysI,II,III,IVmetrics— object with at leastcognitiveandcyclomatic(numeric)violations— array
If any sampled entry is missing required fields → WARN: "Gauntlet entry for <target> is incomplete — sub-agent may have skipped rules. Fields missing: <list>."
V7. Summary consistency:
Read gauntlet-summary.json:
summary.totalAuditedshould equal the valid NDJSON line countsummary.pass + summary.warn + summary.fail + summary.decomposeshould equalsummary.totalAudited
If mismatched → WARN with details (not fatal — the NDJSON is the source of truth, summary is derived).
Print: GAUNTLET validated. Audited: <N>/<M> targets. Pass: <N>, Warn: <N>, Fail: <N>, Decompose: <N>. NDJSON integrity: <valid>/<total> lines OK.
Record phaseTimestamps.gauntlet.completedAt.
Step 3 — SYNC
Skip if: --start-from is after sync, or titan-state.json has currentPhase: "sync" with existing sync.json.
3a. Run Pre-Agent Gate (G1-G4)
3a.1. Record phase start timestamp
Record phaseTimestamps.sync.startedAt.
3b. Dispatch sub-agent
Agent → "Run /titan-sync. Read .claude/skills/titan-sync/SKILL.md and follow it exactly.
Skip worktree check and main sync — already handled.
Read GAUNTLET artifacts and produce sync.json."3c. Post-phase validation
Pre-V8. Validate sync.json is parseable JSON:
node -e "try { JSON.parse(require('fs').readFileSync('.codegraph/titan/sync.json','utf8')); console.log('JSON OK'); } catch(e) { console.log('JSON INVALID: '+e.message); process.exit(1); }"If this fails → VALIDATION FAILED. Stop: "SYNC produced invalid JSON in sync.json (likely a mismatched bracket/brace). Re-run with /titan-run --start-from sync."
V8. sync.json structure:
Read .codegraph/titan/sync.json and verify:
phase— must equal"sync"executionOrder— must be an array with length > 0- Each entry in
executionOrdermust have:phase(number),label(string),targets(array),commit(string) executionOrderphases must be in ascending order- No duplicate phase numbers
If missing or structurally invalid → VALIDATION FAILED. Stop: "SYNC produced invalid plan. Re-run with /titan-run --start-from sync."
V9. Sync targets trace back to gauntlet batches:
Collect all file paths from titan-state.json → batches[*].files (the ground-truth set gauntlet audited).
Flatten all targets from sync.json → executionOrder[*].targets and check each against that set.
const state = JSON.parse(fs.readFileSync('.codegraph/titan/titan-state.json','utf8'));
const batchFiles = new Set((state.batches || []).flatMap(b => b.files || []));
const allSyncTargets = sync.executionOrder.flatMap(e => e.targets);
if (allSyncTargets.length === 0) { console.log('V9 FAIL: sync.json has no targets — execution plan is empty'); process.exit(1); }
const missingCount = allSyncTargets.filter(t => !batchFiles.has(t)).length;
const pct = missingCount / allSyncTargets.length;
if (pct > 0.2) console.log('V9 WARN:', missingCount + '/' + allSyncTargets.length,
'sync targets not in any gauntlet batch (' + (pct*100).toFixed(0) + '%) — agent may have hallucinated targets');
else console.log('V9 OK —', allSyncTargets.length, 'targets, all traced to gauntlet batches');Note: sync targets are file-level paths (src/foo.ts). Do NOT compare against gauntlet.ndjson → target fields — those are function-level names and will never match.
V10. Execution order dependency check:
For entries with dependencies arrays, verify that each dependency phase number exists in executionOrder and has a lower phase number. Circular dependencies in the execution plan → VALIDATION FAILED.
Print: SYNC validated. Execution phases: <N>, Total targets: <N>, Estimated commits: <N>.
Record phaseTimestamps.sync.completedAt.
Step 3.5 — Pre-forge: Architectural Snapshot + Human Checkpoint
Skip if: --start-from is forge AND .codegraph/titan/arch-snapshot.json already exists. The existing snapshot is the correct pre-forge baseline — re-capturing it mid-forge would overwrite it with a state that already includes prior forge commits, making gate A1/A3 comparisons inaccurate.
If --start-from forge is used without an existing snapshot, run Step 3.5a normally (captures a pre-forge baseline from the current committed state).
3.5a. Capture architectural snapshot
Before any code changes, snapshot the codebase's architectural properties. This becomes the baseline for the architectural comparator in /titan-gate (Step 5.5).
codegraph communities -T --json > .codegraph/titan/arch-snapshot-communities.json
codegraph structure --depth 2 --json > .codegraph/titan/arch-snapshot-structure.json
codegraph communities --drift -T --json > .codegraph/titan/arch-snapshot-drift.jsonCombine into a single snapshot file:
TITAN_HEAD_SHA=$(git rev-parse HEAD)
node -e "
const fs = require('fs');
try {
const communities = JSON.parse(fs.readFileSync('.codegraph/titan/arch-snapshot-communities.json','utf8'));
const structure = JSON.parse(fs.readFileSync('.codegraph/titan/arch-snapshot-structure.json','utf8'));
const drift = JSON.parse(fs.readFileSync('.codegraph/titan/arch-snapshot-drift.json','utf8'));
const snapshot = {
timestamp: new Date().toISOString(),
capturedBefore: 'forge',
headSha: '$TITAN_HEAD_SHA',
communities,
structure,
drift
};
fs.writeFileSync('.codegraph/titan/arch-snapshot.json', JSON.stringify(snapshot, null, 2));
} catch (e) {
console.error('WARNING: Failed to build arch-snapshot.json: ' + e.message);
console.error('Architectural comparison (titan-gate A1/A3/A4) will be skipped.');
}
"Clean up temp files:
rm -f .codegraph/titan/arch-snapshot-communities.json .codegraph/titan/arch-snapshot-structure.json .codegraph/titan/arch-snapshot-drift.jsonThis snapshot is read by /titan-gate Step 5.5 during every commit validation.
3.5b. Human checkpoint
This is a mandatory pause. Analysis phases (recon, gauntlet, sync) are read-only. FORGE makes real code changes and commits. The user must see the plan.
First, determine the snapshot status from Step 3.5a:
snapshotStatus = file_exists('.codegraph/titan/arch-snapshot.json') ? "captured" : "FAILED — gate A1/A3/A4 will be skipped"Divergence check — compute before printing the checkpoint so the warning appears inline:
if git fetch origin main 2>/dev/null; then
mergeBase=$(git merge-base HEAD origin/main)
mainAdvance=$(git rev-list --count $mergeBase..origin/main)
else
mainAdvance="unknown"
fimainAdvanceNote = mainAdvance == "unknown"
? "NOTE: Could not fetch origin/main — skipping divergence check."
: mainAdvance > 0
? "WARNING: main has advanced <mainAdvance> commits since initial sync.\nIf significant, consider re-running: /titan-run --start-from recon"
: ""Print:
================================================================
ANALYSIS COMPLETE — FORGE CHECKPOINT
================================================================
The analysis phases (recon → gauntlet → sync) are done.
FORGE will now make code changes and commit them.
Execution plan summary:
Phase 1: <label> — <N> targets
Phase 2: <label> — <N> targets
...
Total: <N> phases, <N> targets, <N> estimated commits
Architectural snapshot: <snapshotStatus>
<mainAdvanceNote>
Validation layers per commit:
1. Diff Review — does the change match the gauntlet recommendation and sync plan?
2. Titan Gate — structural checks, semantic assertions, architectural comparison, lint/build/test
Proceed with /titan-forge? [y/n]
(Use --yes to skip this checkpoint in future runs)
================================================================If --yes is NOT set: stop and wait for user confirmation. Do NOT proceed.
If --yes IS set: print the summary but continue automatically.
Once the user confirms (or --yes was set), autoConfirm is already true (set from --yes at parse time). If the user confirmed interactively (without --yes), set autoConfirm = true now — forge sub-agents must receive --yes to avoid per-phase confirmation prompts that cannot be answered in a sub-agent context.
Step 4 — FORGE (loop)
4a. Pre-loop check
Record phaseTimestamps.forge.startedAt (only if not already set — forge may be resuming).
Read .codegraph/titan/sync.json → count total phases in executionOrder.
Read .codegraph/titan/titan-state.json → check execution.completedPhases (may not exist yet if forge hasn't started).
If .codegraph/titan/arch-snapshot.json does not exist:
Print: "NOTE: No arch-snapshot.json found. Architectural comparison in /titan-gate (Step 5.5) will be skipped for this run. To enable it, run '/titan-run --start-from sync' to re-capture the pre-forge snapshot."
4b. Forge loop
Set maxIterations = 20 (safety limit).
Set stallCount = 0, maxStalls = 2 (forge stalls are more serious — fewer retries).
previousCompletedPhases = execution.completedPhases (or [])
previousCompletedTargets = execution.completedTargets (or [])
previousFailedTargets = execution.failedTargets (or [])
iteration = 0
while iteration < maxIterations:
iteration += 1
# Run Pre-Agent Gate (G1-G4) — CRITICAL for forge since it commits
# Context: show recent commits so agent has context for V12 commit audit
Print: git log --oneline -5
# Record the HEAD sha before dispatching
headBefore = $(git rev-parse HEAD)
# Determine next phase
Read .codegraph/titan/titan-state.json
completedPhases = execution.completedPhases (or [])
totalPhases = len(sync.json.executionOrder)
if len(completedPhases) >= totalPhases → break
nextPhase = first phase number NOT in completedPhases
# Dispatch sub-agent
yesFlag = "--yes" if autoConfirm else ""
Agent → "Run /titan-forge --phase <nextPhase> <yesFlag>.
Read .claude/skills/titan-forge/SKILL.md and follow it exactly.
Skip worktree check and main sync — already handled.
For each target, the validation flow is:
1. Apply code change
2. Stage files
3. Diff review (Step 9 in forge) — verify diff matches gauntlet recommendation and sync plan intent
4. Run tests
5. Run /titan-gate — read .claude/skills/titan-gate/SKILL.md and follow it exactly.
Gate now includes semantic assertions (Step 5) and architectural snapshot comparison (Step 5.5).
The arch snapshot is at .codegraph/titan/arch-snapshot.json.
6. Commit on success, rollback on failure
Do NOT skip the diff review step — it catches intent drift before gate even runs."
# Post-agent checks
headAfter = $(git rev-parse HEAD)
# V11. Verify commits were actually made (unless all targets failed)
Read .codegraph/titan/titan-state.json
newCompletedPhases = execution.completedPhases (or [])
newCompletedTargets = execution.completedTargets (or [])
newFailedTargets = execution.failedTargets (or [])
# Count total targets processed (succeeded + failed) to distinguish true stalls from all-fail phases
newProcessedCount = len(newCompletedTargets) + len(newFailedTargets)
previousProcessedCount = len(previousCompletedTargets) + len(previousFailedTargets)
if newCompletedPhases == previousCompletedPhases and newProcessedCount == previousProcessedCount:
stallCount += 1
Print: "WARNING: Forge iteration <iteration> made no progress (stall <stallCount>/<maxStalls>)"
if stallCount >= maxStalls:
Stop: "Forge stalled on phase <nextPhase> for <maxStalls> consecutive iterations. Check titan-state.json → execution.failedTargets for details."
else:
stallCount = 0
previousCompletedPhases = newCompletedPhases
previousCompletedTargets = newCompletedTargets
previousFailedTargets = newFailedTargets
# V12. Commit audit — verify commits match expectations
if headAfter != headBefore:
# Get commits made by this agent
git log --oneline <headBefore>..<headAfter>
commitCount = number of commits
Print: "Forge phase <nextPhase>: <commitCount> commits, <completedCount> targets completed, <failedCount> targets failed"
else:
# No commits but phase may have completed (all targets failed/skipped)
Print: "Forge phase <nextPhase>: no commits (all targets failed or skipped)"
# V13. Test suite still green after forge commits (skip if no commits were made)
if headAfter != headBefore:
# Detect test command (same detection as gate Step 4):
testCmd = node -e "const p=require('./package.json');const s=p.scripts||{};const script=s.test?'test':s['test:ci']?'test:ci':null;if(!script){console.log('NO_TEST_SCRIPT');process.exit(0);}const fs=require('fs');const runner=fs.existsSync('yarn.lock')?'yarn':fs.existsSync('pnpm-lock.yaml')?'pnpm':fs.existsSync('bun.lockb')?'bun':'npm';console.log(runner+(script==='test'?' test':' run '+script));"
if testCmd == "NO_TEST_SCRIPT":
Print: "V13: No test script configured — skipping post-forge test run."
else:
Run: <testCmd> 2>&1
if tests fail:
Print: "WARNING: Test suite has failures after forge phase <nextPhase>. Auto-spawning regression-fix agent."
Print: "Failing tests: <list of failing test files>"
Print: "Commits from this phase: git log --oneline <headBefore>..<headAfter>"
# Run Pre-Agent Gate (G1-G4) and back up state
# Then dispatch fix agent:
Agent → "Investigate and fix test regressions introduced by the last forge phase.
Commits in scope: git log --oneline <headBefore>..<headAfter>
Failing tests: <list>
Steps:
1. Read the failing tests to understand what they expect
2. Identify which committed change broke them (git diff <headBefore>..<headAfter>)
3. Fix the root cause — prefer targeted fixes over reverts
4. If Rust source changed: rebuild the native addon before running tests
npx napi build --platform --release --manifest-path crates/codegraph-core/Cargo.toml --output-dir .
PLATFORM=$(node -e "const os=require('os');const arch=os.arch()==='arm64'?'arm64':'x64';console.log(os.platform()+'-'+arch)")
if [[ "$(uname)" == "Darwin" ]]; then codesign --sign - --force codegraph-core.node; fi
cp codegraph-core.node "node_modules/@optave/codegraph-${PLATFORM}/codegraph-core.node"
5. Verify with: <testCmd>
6. Commit fixes with: 'fix: correct regressions from forge phase <N>'
7. Do NOT stage: package-lock.json, vitest.config.worktree.ts, tests/benchmarks/resolution/fixtures/python/__pycache__/
Run all commands INLINE (not in background)."
# After fix agent returns, re-run tests:
Run: <testCmd> 2>&1
if tests still fail:
Print: "CRITICAL: Regression-fix agent could not resolve test failures after forge phase <nextPhase>. Manual intervention required."
Print: "Consider reverting: git revert <headBefore>..HEAD"
Stop.
else:
Print: "V13: Regressions resolved by fix agent. Continuing pipeline."4c. Post-loop validation
V14. Final state consistency:
Read .codegraph/titan/titan-state.json:
execution.completedPhasesshould contain all phase numbers fromsync.json → executionOrderexecution.commitsshould be an array (may be empty if all targets failed)- Every commit SHA in
execution.commitsshould exist in git log:
If any SHA doesn't exist → WARN: "Commitgit cat-file -t <sha><sha>recorded in state but not found in git history. State may be out of sync."
V15. Gate log consistency:
If .codegraph/titan/gate-log.ndjson exists:
- Count PASS vs FAIL entries
- Every FAIL entry with
"rolledBack": trueshould NOT have a corresponding commit inexecution.commits
Print forge summary.
Record phaseTimestamps.forge.completedAt.
Step 4.5 — GRIND (loop)
Grind runs after forge to close the adoption loop. Forge extracts helpers; grind wires them into consumers and removes dead code. Without grind, the dead symbol count inflates with every forge phase.
Skip if: --start-from is parity or close, or titan-state.json → grind.completedPhases already covers all forge phases.
4.5a. Pre-loop check
Record phaseTimestamps.grind.startedAt (only if not already set — grind may be resuming).
Read .codegraph/titan/sync.json → count total phases in executionOrder.
Read .codegraph/titan/titan-state.json → check grind.completedPhases (may not exist yet if grind hasn't started).
4.5b. Grind loop
Set maxIterations = 20 (safety limit — same as forge).
Set stallCount = 0, maxStalls = 2.
previousGrindPhases = grind.completedPhases (or [])
iteration = 0
while iteration < maxIterations:
iteration += 1
# Run Pre-Agent Gate (G1-G4)
# Determine next forge phase to grind
Read .codegraph/titan/titan-state.json
grindCompleted = grind.completedPhases (or [])
forgePhases = execution.completedPhases (or [])
ungroundPhases = forgePhases.filter(p => !grindCompleted.includes(p))
if len(ungroundPhases) == 0 → break
nextPhase = ungroundPhases[0]
headBefore = $(git rev-parse HEAD)
yesFlag = "--yes" if autoConfirm else ""
Agent → "Run /titan-grind --phase <nextPhase> <yesFlag>.
Read .claude/skills/titan-grind/SKILL.md and follow it exactly.
Skip worktree check and main sync — already handled.
For each dead helper from forge phase <nextPhase>:
1. Classify: adopt / re-export / promote / false-positive / intentionally-private / remove
2. For adopt/re-export/promote: wire consumers, stage, run /titan-gate, commit
3. For remove: delete, stage, run /titan-gate, commit
4. Gate on dead-symbol delta at phase end"
# Post-agent checks
headAfter = $(git rev-parse HEAD)
Read .codegraph/titan/titan-state.json
newGrindPhases = grind.completedPhases (or [])
if newGrindPhases == previousGrindPhases:
stallCount += 1
Print: "WARNING: Grind iteration <iteration> made no progress (stall <stallCount>/<maxStalls>)"
if stallCount >= maxStalls:
Stop: "Grind stalled on phase <nextPhase>. Check titan-state.json → grind for details."
else:
stallCount = 0
previousGrindPhases = newGrindPhases
# V16. Commit audit
if headAfter != headBefore:
git log --oneline <headBefore>..<headAfter>
commitCount = number of commits
Print: "Grind phase <nextPhase>: <commitCount> adoption commits"
else:
Print: "Grind phase <nextPhase>: no adoptions needed (forge wired everything correctly)"
# V17. Test suite still green (same as forge V13)
if headAfter != headBefore:
testCmd = <same detection as forge V13>
if testCmd != "NO_TEST_SCRIPT":
Run: <testCmd> 2>&1
if tests fail:
Print: "WARNING: Test suite has failures after grind phase <nextPhase>. Auto-spawning regression-fix agent."
Print: "Failing tests: <list of failing test files>"
Print: "Commits from this phase: git log --oneline <headBefore>..<headAfter>"
# Run Pre-Agent Gate (G1-G4) and back up state
# Then dispatch fix agent:
Agent → "Investigate and fix test regressions introduced by the last grind phase.
Commits in scope: git log --oneline <headBefore>..<headAfter>
Failing tests: <list>
Steps:
1. Read the failing tests to understand what they expect
2. Identify which committed change broke them (git diff <headBefore>..<headAfter>)
3. Fix the root cause — prefer targeted fixes over reverts
4. If Rust source changed: rebuild the native addon before running tests
npx napi build --platform --release --manifest-path crates/codegraph-core/Cargo.toml --output-dir .
PLATFORM=$(node -e "const os=require('os');const arch=os.arch()==='arm64'?'arm64':'x64';console.log(os.platform()+'-'+arch)")
if [[ "$(uname)" == "Darwin" ]]; then codesign --sign - --force codegraph-core.node; fi
cp codegraph-core.node "node_modules/@optave/codegraph-${PLATFORM}/codegraph-core.node"
5. Verify with: <testCmd>
6. Commit fixes with: 'fix: correct regressions from grind phase <N>'
7. Do NOT stage: package-lock.json, vitest.config.worktree.ts, tests/benchmarks/resolution/fixtures/python/__pycache__/
Run all commands INLINE (not in background)."
# After fix agent returns, re-run tests:
Run: <testCmd> 2>&1
if tests still fail:
Print: "CRITICAL: Regression-fix agent could not resolve test failures after grind phase <nextPhase>. Manual intervention required."
Print: "Consider reverting: git revert <headBefore>..HEAD"
Stop.
else:
Print: "V17: Regressions resolved by fix agent. Continuing pipeline."4.5c. Post-loop validation
V18. Dead-symbol delta:
Read grind.deadSymbolBaseline and grind.deadSymbolCurrent from titan-state.json.
- If delta > 10: WARN "Grind could not fully adopt forge's helpers.
<delta>new dead symbols remain." - Otherwise: Print summary.
V19. Grind coverage:
- Count forge phases processed vs total forge phases
- If < 100%: WARN with details
Print grind summary:
GRIND complete.
Dead symbols: <baseline> → <current> (delta: <+/-N>)
Adoptions: <N> helpers wired, <N> removed, <N> false positives logged
Phases ground: <N>/<M>Record phaseTimestamps.grind.completedAt.
Step 4.6 — PARITY (conditional, repo-provided)
Some repos ship multiple implementations of the same logic that must stay in lockstep (e.g. a dual native/WASM engine, a client and server copy of a validator). Forge and grind edit code across the tree; this step verifies those edits didn't leave one implementation behind.
titan-run is repo-agnostic — never assume the target repo has engines, fixtures, or any parity surface. The contract: a repo opts in by shipping its own /parity skill at .claude/skills/parity/SKILL.md (wrapping whatever audit mechanism it uses internally). No skill → no parity phase.
4.6a. Detect the repo's parity mechanism
test -f .claude/skills/parity/SKILL.md && echo "PARITY SKILL FOUND" || echo "NO PARITY SKILL"- NO PARITY SKILL → print
"PARITY skipped — repo provides no /parity skill."and continue to Step 5. Absence is normal for most repos; do not warn. - PARITY SKILL FOUND → continue below.
Skip also if: --start-from is close, or the pipeline made no code changes this run (titan-state.json → execution.commits empty/absent AND no grind adoption commits) — unless --start-from parity was given explicitly, which always runs the audit.
4.6b. Record phase start
Record phaseTimestamps.parity.startedAt.
headBefore=$(git rev-parse HEAD)4.6c. Run Pre-Agent Gate (G1-G4)
4.6d. Dispatch sub-agent
Agent → "Run /parity. Read .claude/skills/parity/SKILL.md and follow it exactly.
Skip worktree check — already handled.
Audit every surface the skill covers. Fix any divergence introduced by
recent commits at the root cause, commit the fixes, and re-verify until
the audit is clean. If a divergence pre-dates this run (verify via
git log on the relevant files), follow the skill's and repo's rules for
pre-existing findings (typically: file an issue, don't expand scope)."4.6e. Post-phase validation
After the agent returns:
headAfter=$(git rev-parse HEAD)git status --short→ the working tree must be clean. The sub-agent commits its fixes; uncommitted changes mean it stopped mid-fix → stop and report.- If the agent fixed divergences, run V16-style commit audit:
git log --oneline $headBefore..$headAfterand print the parity-fix commits. - If the agent reports divergences introduced by THIS run that it could not fix → stop: "PARITY failed — this run introduced implementation drift. Fix before CLOSE or revert the offending commits." Pre-existing divergences filed as issues are not blockers; print the issue URLs.
Print: "PARITY complete: <clean | N divergences fixed | N pre-existing filed as issues>"
Record phaseTimestamps.parity.completedAt.
Step 5 — CLOSE (report + PRs)
After forge completes, dispatch /titan-close to produce the final report with before/after metrics and split commits into focused PRs.
5a. Run Pre-Agent Gate (G1-G4)
5a.1. Record phase start timestamp
Record phaseTimestamps.close.startedAt.
5b. Dispatch sub-agent
Agent → "Run /titan-close. Read .claude/skills/titan-close/SKILL.md and follow it exactly.
Skip worktree check and main sync — already handled."5c. Post-phase validation
After the agent returns, verify:
.codegraph/titan/TITAN_REPORT.mdorgenerated/titan/titan-report-*.mdexists and has content (> 20 lines)- Print: "CLOSE complete. Report:
<report path>"
If the agent created PRs, print the PR URLs.
Commit hygiene check: If .claude/skills/ files were modified during this run (e.g., by a V13 regression-fix agent), they must NOT share a commit with .codegraph/titan/ artifacts. Check:
git status --short | grep -E "\.claude/skills/|generated/titan/|\.codegraph/titan/"If both are dirty, commit them separately before proceeding to the retrospective.
Record phaseTimestamps.close.completedAt.
Step 6 — RETROSPECTIVE (automatic)
After CLOSE, run a brief retrospective on this pipeline execution and offer to apply findings as skill improvements.
6a. Collect run data
Read from disk (no sub-agent needed):
node -e "
const fs = require('fs');
const s = JSON.parse(fs.readFileSync('.codegraph/titan/titan-state.json','utf8'));
const ts = s.phaseTimestamps || {};
const phases = ['recon','gauntlet','sync','forge','grind','parity','close'];
for (const p of phases) {
if (ts[p]?.startedAt && ts[p]?.completedAt) {
const dur = ((new Date(ts[p].completedAt) - new Date(ts[p].startedAt))/60000).toFixed(1);
console.log(p + ': ' + dur + ' min');
}
}
const stalls = s.gauntletStalls || 0;
const forgeStalls = s.execution?.stallCount || 0;
const failed = (s.execution?.failedTargets || []).length;
const grindDelta = (s.grind?.deadSymbolCurrent || 0) - (s.grind?.deadSymbolBaseline || 0);
console.log('gauntlet stalls:', stalls, '| forge stalls:', forgeStalls, '| failed targets:', failed, '| grind delta:', grindDelta);
"6b. Dispatch retrospective agent
Agent → "Analyze this Titan pipeline run and produce a retrospective.
Read:
- .codegraph/titan/titan-state.json (phase timestamps, stalls, failed targets)
- .codegraph/titan/gate-log.ndjson (PASS/WARN/FAIL verdicts per commit)
- .codegraph/titan/gauntlet-summary.json
- .codegraph/titan/issues.ndjson (bugs and anomalies logged during the run)
Produce a JSON file at .codegraph/titan/retrospective.json:
{
'wentWell': [string], // phases/outcomes that ran cleanly
'anomalies': [ // anything that required retries, fixes, or manual intervention
{ phase: string, description: string }
],
'skillRecs': [ // concrete skill improvements, highest-impact first
{ priority: 'P1'|'P2'|'P3', area: string, problem: string, fix: string }
]
}
Keep skillRecs to 3-5 items max. Focus on structural issues (things that would affect every run), not one-off incidents."6c. Print retrospective summary
After the agent writes retrospective.json, read and print it:
node -e "
const fs = require('fs');
if (!fs.existsSync('.codegraph/titan/retrospective.json')) { console.log('retrospective.json not written — skipping summary'); process.exit(0); }
const r = JSON.parse(fs.readFileSync('.codegraph/titan/retrospective.json','utf8'));
console.log('\n=== Titan Retrospective ===');
console.log('\nWent well:');
(r.wentWell || []).forEach(w => console.log(' ✓', w));
if ((r.anomalies||[]).length) {
console.log('\nAnomalies:');
r.anomalies.forEach(a => console.log(' ⚠', a.phase + ':', a.description));
}
if ((r.skillRecs||[]).length) {
console.log('\nSkill improvement recommendations:');
r.skillRecs.forEach(rec => console.log(' ' + rec.priority + ' [' + rec.area + '] ' + rec.fix));
}
console.log('');
"6d. Offer skill improvement
Ask the user:
Would you like me to apply these recommendations to improve the /titan-run skill? [y/n]If --yes is set → apply automatically without asking.
If yes (or --yes):
Run Pre-Agent Gate (G1-G4), back up state, then:
Agent → "Improve .claude/skills/titan-run/SKILL.md based on these recommendations:
<paste skillRecs from retrospective.json>
Rules:
- Use the Edit tool — make targeted changes only, do not rewrite unrelated sections
- One logical change per edit call
- After editing, verify the file is internally consistent (read the changed sections)
- Commit with: 'fix(titan-run): <one-line summary of improvements applied>'
- Do NOT stage: package-lock.json, vitest.config.worktree.ts, .codegraph/titan/"If no: Print "Retrospective saved to .codegraph/titan/retrospective.json — apply recommendations later by editing .claude/skills/titan-run/SKILL.md." and finish.
Error Handling
- Sub-agent returns error: Print the error, stop, and tell the user which phase failed and how to retry (e.g., "Run
/titan-run --start-from gauntlet"). - State file missing when expected: Stop with clear message about which prerequisite phase to run.
- State file corrupt (JSON parse error): Attempt restore from
.bak. If no backup → stop: "State file corrupted. Run/titan-resetand start over." - NDJSON corrupt lines: Warn but continue — partial results are better than none. The corrupt lines are logged so the user knows which targets to re-audit.
- Merge conflict detected by pre-agent gate: Stop immediately with the conflicting files listed.
- Tests fail after forge/grind phase: Auto-spawn a regression-fix agent. If the fix agent resolves the failures, continue the pipeline. If it cannot, stop and print the failing commits so the user can revert.
- Parity audit fails on drift introduced by this run: Stop before CLOSE. Retry with
/titan-run --start-from parityafter fixing or reverting. - Validation failure (any V-check marked FAILED): Stop with details. Warn-level V-checks are logged but don't stop the pipeline.
Rules
- You are the orchestrator, not the executor. Never run codegraph commands, edit source files, or make commits yourself. Only spawn sub-agents and read state files. Exceptions (pure validation/snapshot, no code changes): the post-forge test run (V13), NDJSON integrity checks, the V3 baseline snapshot check (
codegraph snapshot list), and the pre-forge architectural snapshot capture (Step 3.5a) are run directly by the orchestrator. - Run the Pre-Agent Gate (G1-G4) before EVERY sub-agent. No exceptions.
- One sub-agent at a time. Phases are sequential — recon before gauntlet, gauntlet before sync, sync before forge, forge before grind, grind before parity (when the repo provides one), parity before close.
- Fresh context per sub-agent. This is the whole point — each sub-agent gets a clean context window.
- Read AND validate state files after every sub-agent. Trust the on-disk state, not the sub-agent's text output — but verify the state is structurally sound.
- Back up state before every sub-agent. The
.bakfile is your safety net against mid-write crashes. - Mandatory pause before forge unless
--yesis set. Analysis is safe; code changes deserve human review. - Stall detection is strict for forge (2 retries) and looser for gauntlet (3 retries) since gauntlet is more likely to hit context limits legitimately.
- Respect --start-from. Skip phases before the specified starting point, but verify their artifacts exist AND pass validation.
- Pass --yes through to forge if the user provided it, so forge skips its per-phase confirmation prompt. Within the orchestrator,
--yesalso skips the pre-pipeline, forge checkpoint, and resume prompts.
Self-Improvement
This skill lives at .claude/skills/titan-run/SKILL.md. It improves itself automatically via Step 6 (RETROSPECTIVE) at the end of every run.
For manual edits: use the Edit tool for targeted changes. Never rewrite sections unrelated to the fix. Commit skill changes separately from pipeline artifacts (generated/titan/, .codegraph/titan/) — they must not share a commit.
When adding new phases: update meta.phases at the top, add the phase to the timestamp list in Step 0.3, add a V-check for the phase's key artifact, and add the phase to Step 0.5's pre-validation table.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

