agentleFS
optaveoptave/ops-codegraph-tool/.claude/skills/titan-run/SKILL.md

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

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
  1. Very specific:

    No args → full pipeline from scratch, target .

    line 15
  2. Very specific:

    Check existing state: Read .codegraph/titan/titan-state.json if it exists.

    line 39
  3. Very specific:

    If state exists and --start-from not specified, ask user: "Existing Titan state found (phase: <currentPhase>).

    line 40
  4. Very specific:

    If --yes is set, resume automatically.

    line 41
  5. Very specific:

    Timestamp validation: After recording completedAt for any phase, verify startedAt < completedAt:

    line 55
  6. Distinctive:

    If the check fails, log a warning but do not stop the pipeline — clock skew or immediate completion of short phases can cause this.

    line 59
  7. Distinctive:

    If the install fails, warn the user but continue with whichever version is currently available.

    line 69
  8. Very specific:

    If merge conflict → stop: "Merge conflict after syncing with main.

    line 75
  9. Very specific:

    E1. Node dependencies: Check whether node_modules needs installing:

    line 79
  10. Very specific:

    All test runs in forge/grind/gate agent prompts must reference this file: npx vitest run --config vitest.config.worktree.ts.

    line 99
  11. Distinctive:

    If any bootstrap step fails, warn but continue — the pipeline can still proceed, and forge/grind agents will catch environment issues at …

    line 116
  12. Very specific:

    Start immediately — do NOT ask for confirmation before analysis phases.

    line 131
  13. Distinctive:

    Before spawning any sub-agent, run these checks.

    line 137
  14. Very specific:

    If this fails (worktree was pruned or moved), stop: "Worktree is no longer valid.

    line 150
  15. Very specific:

    If .codegraph/titan/titan-state.json should exist at this point (i.e., we're past recon):

    line 153
  16. Distinctive:

    If CORRUPT → attempt recovery from backup:

    line 157
  17. Very specific:

    Check if .codegraph/titan/titan-state.json.bak exists.

    line 158
  18. Distinctive:

    If the backup exists, validate it is valid JSON:

    line 159
  19. Very specific:

    If the backup is valid → restore it: cp .codegraph/titan/titan-state.json.bak .codegraph/titan/titan-state.json

    line 163
  20. Very specific:

    If the backup is also corrupt or missing → stop: "State file corrupted with no valid backup.

    line 164
  21. Distinctive:

    Before every sub-agent dispatch, back up the current state file:

    line 167
  22. Very specific:

    If a sub-agent corrupts the state, G3 on the next iteration will detect it and restore from .bak.

    line 171
  23. Very specific:

    If ANY required artifact is missing → stop: "Cannot start from <phase> — <artifact> is missing.

    line 189
  24. Distinctive:

    If ANY V-check that is normally VALIDATION FAILED would fail → stop with the same message as it would during normal execution.

    line 191
  25. Distinctive:

    Use the Agent tool to spawn a sub-agent:

    line 216
  26. Distinctive:

    After the agent returns, validate the artifacts:

    line 230
  27. Very specific:

    Read .codegraph/titan/titan-state.json and verify ALL of these fields exist and are non-empty:

    line 233
  28. Very specific:

    If any field is missing, zero, or wrong type → VALIDATION FAILED.

    line 244
  29. Very specific:

    Must contain ## Domain Map heading

    line 249
  30. Distinctive:

    If missing or empty → VALIDATION FAILED.

    line 252
  31. Very specific:

    If NO_SNAPSHOT → WARN (not fatal, but note it: "No baseline snapshot — rollback in GATE will not work").

    line 258
  32. Distinctive:

    Batch size check: Every batch must have ≤ 5 files.

    line 263
  33. Distinctive:

    If wildly inconsistent (e.g., 0 batches but 500 nodes) → WARN with details.

    line 265
  34. Very specific:

    Read .codegraph/titan/gauntlet-summary.json if it exists:

    line 281
  35. Very specific:

    If "complete": true → run gauntlet post-validation (2d) and skip loop if it passes

    line 282
  36. Distinctive:

    After the loop completes (or on each iteration if you prefer lightweight checks):

    line 338
  37. Very specific:

    If missing == true: treat as equivalent to valid == 0 — the file does not exist yet (expected on first iteration, error if the loop should …

    line 357
  38. Very specific:

    If corrupt > 0: Print "WARNING: <corrupt> corrupt lines in gauntlet.ndjson (likely from a crashed sub-agent).

    line 358
  39. Very specific:

    If valid == 0 and missing == false: Stop: "gauntlet.ndjson has no valid entries.

    line 359
  40. Very specific:

    If coverage < 80%: WARN "Gauntlet only audited <N>/<M> targets (<pct>%).

    line 366
  41. Distinctive:

    If coverage < 50%: VALIDATION FAILED.

    line 367
  42. Very specific:

    Read first 5 and last 5 entries from gauntlet.ndjson.

    line 370
  43. Distinctive:

    If any sampled entry is missing required fields → WARN: "Gauntlet entry for <target> is incomplete — sub-agent may have skipped rules.

    line 378
  44. Distinctive:

    If mismatched → WARN with details (not fatal — the NDJSON is the source of truth, summary is derived).

    line 385
  45. Very specific:

    If this fails → VALIDATION FAILED.

    line 416
  46. Very specific:

    Read .codegraph/titan/sync.json and verify:

    line 419
  47. Distinctive:

    No duplicate phase numbers

    line 424
  48. Very specific:

    If missing or structurally invalid → VALIDATION FAILED.

    line 426
  49. Very specific:

    If --start-from forge is used without an existing snapshot, run Step 3.5a normally (captures a pre-forge baseline from the current …

    line 459
  50. Very specific:

    Before any code changes, snapshot the codebase's architectural properties.

    line 463
  51. Very specific:

    If --yes is NOT set: stop and wait for user confirmation.

    line 558
  52. Very specific:

    If --yes IS set: print the summary but continue automatically.

    line 559
  53. Very specific:

    Read .codegraph/titan/sync.json → count total phases in executionOrder.

    line 571
  54. Very specific:

    Read .codegraph/titan/titan-state.json → check execution.completedPhases (may not exist yet if forge hasn't started).

    line 572
  55. Very specific:

    If .codegraph/titan/arch-snapshot.json does not exist: Print: "NOTE: No arch-snapshot.json found.

    line 574
  56. Very specific:

    Every commit SHA in execution.commits should exist in git log:

    line 709
  57. Distinctive:

    If any SHA doesn't exist → WARN: "Commit <sha> recorded in state but not found in git history.

    line 713
  58. Very specific:

    Every FAIL entry with "rolledBack": true should NOT have a corresponding commit in execution.commits

    line 718
  59. Very specific:

    Read .codegraph/titan/titan-state.json → check grind.completedPhases (may not exist yet if grind hasn't started).

    line 737
  60. Very specific:

    Read grind.deadSymbolBaseline and grind.deadSymbolCurrent from titan-state.json.

    line 843
  61. Distinctive:

    If delta > 10: WARN "Grind could not fully adopt forge's helpers.

    line 844
  62. Distinctive:

    If < 100%: WARN with details

    line 849
  63. Distinctive:

    After the agent returns:

    line 904
  64. Very specific:

    If the agent fixed divergences, run V16-style commit audit: git log --oneline $headBefore..$headAfter and print the parity-fix commits.

    line 911
  65. Distinctive:

    If the agent reports divergences introduced by THIS run that it could not fix → stop: "PARITY failed — this run introduced implementation …

    line 912
  66. Very specific:

    After forge completes, dispatch /titan-close to produce the final report with before/after metrics and split commits into focused PRs.

    line 922
  67. Distinctive:

    After the agent returns, verify:

    line 938
  68. Distinctive:

    If the agent created PRs, print the PR URLs.

    line 942
  69. Very specific:

    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 …

    line 944
  70. Distinctive:

    If both are dirty, commit them separately before proceeding to the retrospective.

    line 948
  71. Distinctive:

    After CLOSE, run a brief retrospective on this pipeline execution and offer to apply findings as skill improvements.

    line 956
  72. Distinctive:

    Read from disk (no sub-agent needed):

    line 960
  73. Very specific:

    After the agent writes retrospective.json, read and print it:

    line 1008
  74. Very specific:

    If --yes is set → apply automatically without asking.

    line 1036
  75. Distinctive:

    Run Pre-Agent Gate (G1-G4), back up state, then:

    line 1040
  76. Distinctive:

    State file missing when expected: Stop with clear message about which prerequisite phase to run.

    line 1061
  77. Distinctive:

    Merge conflict detected by pre-agent gate: Stop immediately with the conflicting files listed.

    line 1064
  78. Very specific:

    Parity audit fails on drift introduced by this run: Stop before CLOSE. Retry with /titan-run --start-from parity after fixing or reverting.

    line 1066
  79. Distinctive:

    Validation failure (any V-check marked FAILED): Stop with details. Warn-level V-checks are logged but don't stop the pipeline.

    line 1067
  80. Distinctive:

    Run the Pre-Agent Gate (G1-G4) before EVERY sub-agent: No exceptions.

    line 1074
  81. Very specific:

    Pass --yes through to forge: if the user provided it, so forge skips its per-phase confirmation prompt.

    line 1082
  82. Very specific:

    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 …

    line 1090

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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

  1. Worktree check:
    git rev-parse --show-toplevel && git worktree list
    The Titan pipeline writes artifacts and makes code changes — worktree isolation is required. If you are NOT in a worktree, create one automatically using the EnterWorktree tool (fetch it via ToolSearch if needed) with name titan-run. Do NOT stop and ask the user — just enter the worktree and continue.
  2. Parse arguments. Determine:
    • targetPath (default: .)
    • startPhase (default: recon)
    • gauntletBatchSize (default: 5)
    • autoConfirm → true if --yes is present, otherwise false
  3. Check existing state. Read .codegraph/titan/titan-state.json if it exists.

    • If state exists and --start-from not specified, ask user: "Existing Titan state found (phase: <currentPhase>). Resume from current state, or start fresh with /titan-reset first?"
    • If --yes is 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> with recon, gauntlet, sync, forge, grind, parity, or close. 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 overwrite startedAt — only set it if it doesn't already exist.

    Timestamp validation: After recording completedAt for any phase, verify startedAt < 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.

  4. Install latest codegraph (once, before any sub-agent runs):
    npm install -g @optave/codegraph@latest
    Log the installed version:
    codegraph --version
    If the install fails, warn the user but continue with whichever version is currently available.
  5. Sync with main (once, before any sub-agent runs):
    git fetch origin main && git merge origin/main --no-edit
    If merge conflict → stop: "Merge conflict after syncing with main. Resolve conflicts and re-run /titan-run."
  6. Bootstrap worktree environment (run when pwd contains .claude/worktrees/ or node_modules is absent/stale):

    E1. Node dependencies: Check whether node_modules needs 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
    fi

    This also builds WASM grammars (via the prepare script). After this step, all subsequent agent prompts must use TEST_CMD="npx vitest run --config vitest.config.worktree.ts" (see E2).

    E2. Vitest worktree config: The default vitest.config.ts excludes **/.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');
      "
    fi

    All 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
    fi

    If any bootstrap step fails, warn but continue — the pipeline can still proceed, and forge/grind agents will catch environment issues at test-run time.

  7. 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 --yes is 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-tree

If 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:
    1. Check if .codegraph/titan/titan-state.json.bak exists.
    2. 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); }"
    3. If the backup is valid → restore it: cp .codegraph/titan/titan-state.json.bak .codegraph/titan/titan-state.json
    4. If the backup is also corrupt or missing → stop: "State file corrupted with no valid backup. Run /titan-reset and start over."

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 || true

If 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 phaseRequired artifacts + checks
reconV1 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)
gauntletV5 (coverage ≥ 50%), V6 (entry completeness sample), V7 (summary consistency); also run NDJSON integrity check (2c)
syncV8 (sync.json structure), V9 (targets trace to gauntlet), V10 (dependency order)
forgeV14 (final state consistency), V15 (gate log consistency); execution block must exist in titan-state.json
grindV14, 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 number
  • initialized — must be an ISO 8601 string
  • currentPhase — must equal "recon"
  • stats.totalNodes — must be > 0
  • stats.totalEdges — must be > 0
  • stats.totalFiles — must be > 0
  • domains — must be an array with length > 0
  • batches — must be an array with length > 0
  • priorityQueue — 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 Map heading
  • 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.totalFiles should roughly match the number of targets across all batches (batches are subsets of files, so sum(batch.files.length) should be ≤ totalFiles)
  • priorityQueue.length should 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.json for 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 to valid == 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 == 0 and missing == false: Stop: "gauntlet.ndjson has no valid entries. Something went wrong."

2d. Post-loop validation

V5. Gauntlet coverage:

  • Count distinct target values in gauntlet.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 string
  • file — non-empty string
  • verdict — one of PASS, WARN, FAIL, DECOMPOSE
  • pillarVerdicts — object with keys I, II, III, IV
  • metrics — object with at least cognitive and cyclomatic (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.totalAudited should equal the valid NDJSON line count
  • summary.pass + summary.warn + summary.fail + summary.decompose should equal summary.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 executionOrder must have: phase (number), label (string), targets (array), commit (string)
  • executionOrder phases 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.json

Combine 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.json

This 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"
fi
mainAdvanceNote = 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.completedPhases should contain all phase numbers from sync.json → executionOrder
  • execution.commits should be an array (may be empty if all targets failed)
  • Every commit SHA in execution.commits should exist in git log:
    git cat-file -t <sha>
    If any SHA doesn't exist → WARN: "Commit <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": true should NOT have a corresponding commit in execution.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..$headAfter and 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.md or generated/titan/titan-report-*.md exists 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-reset and 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 parity after 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 .bak file is your safety net against mid-write crashes.
  • Mandatory pause before forge unless --yes is 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, --yes also 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.