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

titan-gate

Skill94 starsChanged 3 months agoApache-2.0View on GitHub

Validate staged changes — codegraph checks + project lint/build/test, auto-rollback on failure, pass/fail commit gate (Titan Paradigm Phase 4)

  • Deletes or force-pushes

The file

Show its rules and text

We split this skill into the rules it gives an agent

29 rules. About 0 are common, 12 are distinctive, and 17 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈12

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 17

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Force mode: If $ARGUMENTS contains --force, warnings are downgraded (failures still block).

    line 16
  2. Very specific:

    If not in a worktree, stop: "Run /worktree first."

    line 26
  3. Distinctive:

    If nothing staged, stop: "Nothing staged.

    line 32
  4. Very specific:

    Load state (optional): Read .codegraph/titan/titan-state.json if it exists — use for thresholds, baseline comparison, and sync alignment.

    line 34
  5. Distinctive:

    Run the full change validation predicates in one call:

    line 40
  6. Distinctive:

    Check all metrics against thresholds:

    line 80
  7. Distinctive:

    Run in order — stop on first failure:

    line 97
  8. Distinctive:

    If any fail → overall verdict is FAIL → proceed to auto-rollback.

    line 123
  9. Distinctive:

    Verify that code changes don't silently break callers by changing public contracts.

    line 129
  10. Distinctive:

    If the file is new (command fails or returns nothing), skip 5a for this file — new exports cannot break existing callers.

    line 144
  11. Very specific:

    Check if the symbol existed before this change: git show HEAD:<file> and compare function signatures

    line 146
  12. Distinctive:

    If a function's parameter list changed (added required params, removed params, changed types):

    line 147
  13. Very specific:

    If an export was removed entirely and callers exist → FAIL: "Removed export <symbol> still imported by <N> files"

    line 152
  14. Very specific:

    Check the Step 1 codegraph check --staged --boundaries results for boundary violations (already collected — do not re-run).

    line 164
  15. Very specific:

    Add { source, target } to step5cViolations

    line 168
  16. Very specific:

    If the change modifies an index/barrel file (e.g., index.js, mod.rs):

    line 177
  17. Very specific:

    If .codegraph/titan/GLOBAL_ARCH.md does not exist (standalone invocation without Titan artifacts), skip A2 — layer boundaries are unknown.

    line 212
  18. Very specific:

    Read .codegraph/titan/arch-snapshot.json if it exists (created by /titan-run before forge begins).

    line 223
  19. Very specific:

    Use mktemp -d to create a unique temporary directory that persists across Bash invocations (shell variables like $TITAN_TMP_ID do not …

    line 227
  20. Distinctive:

    Use the drift output (which uses content-based matching, not raw IDs, to track community movements across runs):

    line 249
  21. Very specific:

    Read .codegraph/titan/arch-snapshot.json → drift (the pre-forge drift baseline) and compare against $TITAN_ARCH_DIR/current-drift.json:

    line 251
  22. Distinctive:

    If > 5 untouched symbols appear in new drift warnings → FAIL: "Significant community restructuring detected — <N> symbols drifted …

    line 253
  23. Very specific:

    If any directory's cohesion dropped by > 0.2 → WARN: "Directory <dir> cohesion dropped from <X> to <Y>"

    line 257
  24. Very specific:

    If a directory went from above 0.5 to below 0.3 → FAIL: "Directory <dir> became tangled (cohesion <X> → <Y>)"

    line 258
  25. Very specific:

    If any drift warning that was present in the snapshot is absent from $TITAN_ARCH_DIR/current-drift.json → note as positive: "Symbol <name> …

    line 262
  26. Very specific:

    Check titan-state.json → snapshots.lastBatch first.

    line 330
  27. Distinctive:

    When the full Titan pipeline is done (all SYNC phases complete, final GATE passes):

    line 349
  28. Very specific:

    Update titan-state.json (if exists): increment progress.fixed, update fileAudits for fixed files.

    line 387
  29. Distinctive:

    Fast execution: Only staged changes, not full codebase.

    line 437

≈ “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 GATE — Change Validation & State Machine

You are running the GATE phase (State Machine) of the Titan Paradigm.

Your goal: validate staged changes against codegraph quality checks AND the project's own lint/build/test. Produce a clear PASS/WARN/FAIL verdict. Auto-rollback on failure.

Context budget: Lightweight — only checks staged changes. Should complete quickly.

Force mode: If $ARGUMENTS contains --force, warnings are downgraded (failures still block).


Step 0 — Pre-flight

  1. Worktree check:
    git rev-parse --show-toplevel && git worktree list
    If not in a worktree, stop: "Run /worktree first."
  2. Staged changes?
    git diff --cached --name-only
    If nothing staged, stop: "Nothing staged. Use git add first."
  3. Load state (optional). Read .codegraph/titan/titan-state.json if it exists — use for thresholds, baseline comparison, and sync alignment. If missing or corrupt, proceed with defaults.

Step 1 — Structural validation (codegraph)

Run the full change validation predicates in one call:

codegraph check --staged --cycles --blast-radius 30 --boundaries -T --json

This checks: manifesto rules, new cycle introduction, blast radius threshold, and architecture boundary violations. Exit code 0 = pass, 1 = fail.

The blast-radius predicate is call-graph-shape-aware: a touched function's absolute transitive-caller count only counts toward the threshold if the diff actually changed that function's own declaration line or the set of call targets referenced in its body. A function whose body changed without touching a call expression or its own signature (e.g. an inline literal replaced by a named constant) is exempt even with a high absolute caller count — that fan-in is pre-existing risk already accepted by the codebase, not risk this diff introduced. This is the authoritative blast-radius pass/fail — see Step 8.

Also run detailed impact analysis:

codegraph diff-impact --staged -T --json

Extract: changed functions (count + names), direct callers affected, transitive blast radius, historically coupled files.


Step 2 — Cycle check

codegraph cycles --json

Compare against RECON baseline (if titan-state.json exists):

  • New cycles? → FAIL
  • Cycles resolved? → Note as positive

Step 3 — Complexity delta

For each changed file (from diff-impact):

codegraph complexity --file <changed-file> --health -T --json

Check all metrics against thresholds:

  • cognitive > 30 → FAIL
  • halstead.bugs > 1.0 → FAIL (estimated defect)
  • mi < 20 → FAIL
  • Function moved from PASS → FAIL on any metric? → FAIL
  • Function improved but still above threshold? → WARN

Step 4 — Lint, build, and test

Detect project tools from package.json:

node -e "const p=require('./package.json');console.log(JSON.stringify(Object.keys(p.scripts||{})))"

Run in order — stop on first failure:

# Detect lint command with package-manager awareness
lintCmd=$(node -e "const p=require('./package.json');const s=p.scripts||{};if(!s.lint){console.log('NO_LINT_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+' run lint');")
if [ "$lintCmd" != "NO_LINT_SCRIPT" ]; then
  $lintCmd 2>&1 || echo "LINT_FAILED"
fi
# Detect build command with package-manager awareness
buildCmd=$(node -e "const p=require('./package.json');const s=p.scripts||{};if(!s.build){console.log('NO_BUILD_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+' run build');")
if [ "$buildCmd" != "NO_BUILD_SCRIPT" ]; then
  $buildCmd 2>&1 || echo "BUILD_FAILED"
fi
# Detect test command from package.json scripts
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" ]; then
  $testCmd 2>&1 || echo "TEST_FAILED"
fi

If any fail → overall verdict is FAIL → proceed to auto-rollback.


Step 5 — Semantic assertions (API compatibility)

Verify that code changes don't silently break callers by changing public contracts. This goes beyond structural checks — it catches signature changes, removed exports, and new forbidden dependencies.

5a. Export signature stability

Get the list of changed files from diff-impact (Step 1):

codegraph exports <changed-file> -T --json

For each changed file from diff-impact (Step 1):

  • First, check if the file existed before this commit:
    git show HEAD:<changed-file> -- 2>/dev/null | head -1
    If the file is new (command fails or returns nothing), skip 5a for this file — new exports cannot break existing callers.
  • Otherwise, for each exported symbol in the file:
  • Check if the symbol existed before this change: git show HEAD:<file> and compare function signatures
  • If a function's parameter list changed (added required params, removed params, changed types):
    codegraph fn-impact <symbol> -T --json
    Count callers. If callers > 0 and callers are NOT also staged → FAIL: "Signature change in <symbol> breaks <N> callers not updated in this commit: <caller list>"
  • If an export was removed entirely and callers exist → FAIL: "Removed export <symbol> still imported by <N> files"

5b. Import resolution integrity

From the diff-impact results already collected in Step 1, extract any edges where the target symbol or file no longer exists (i.e., the import points to a removed or renamed symbol).

For each such broken edge where the importing file is NOT part of this commit's staged changes → FAIL: "Change broke import resolution for <file>: <import>"

Note: codegraph check does not include import resolution predicates — its checks cover cycles, blast-radius, boundaries, and manifesto rules. Import resolution runs during codegraph build. This step relies on diff-impact's edge data to detect broken imports indirectly by identifying edges that reference removed symbols.

5c. Dependency direction assertions (codegraph boundary rules)

Check the Step 1 codegraph check --staged --boundaries results for boundary violations (already collected — do not re-run). This covers .codegraphrc.json onion-architecture rules and any custom boundary predicates.

Store flagged edges in step5cViolations — a list of { source, target } pairs. For each boundary violation reported by codegraph check:

  • New dependency that violates a configured boundary rule → FAIL: "New upward dependency: <source> → <target> violates layer boundary"
  • Add { source, target } to step5cViolations

Additionally, from the diff-impact results already collected in Step 1, extract any new edges (imports that didn't exist before):

  • New dependency on a module flagged in sync.json as "to be removed" or "to be split" → WARN: "New dependency on <module> which is scheduled for decomposition"

Note: Step 5c relies exclusively on codegraph check --boundaries results. Domain-direction checks against GLOBAL_ARCH.md are handled by Step 5.5 A2 — do not duplicate them here. Pass step5cViolations to A2 so it can skip edges already flagged here.

5d. Re-export chain validation

If the change modifies an index/barrel file (e.g., index.js, mod.rs):

Capture the pre-change export list from the committed version (write the temp path to a sidecar file so it persists across Bash invocations):

BARREL_EXT="${barrel_file##*.}"
BARREL_TMP=$(mktemp "/tmp/titan-barrel-XXXXXX.${BARREL_EXT}")
echo "$BARREL_TMP" > .codegraph/titan/.barrel-tmp
git show HEAD:<barrel-file> > "$BARREL_TMP"
codegraph exports "$BARREL_TMP" -T --json

Then capture the current (staged) export list:

codegraph exports <barrel-file> -T --json

Compare export count before and after. If exports were accidentally dropped (count decreased and the removed exports have callers) → FAIL: "Barrel file <barrel-file> dropped <N> exports that have active callers: <export list>. Use codegraph exports <barrel-file> -T to review."

Clean up the temp file (recover path from sidecar). This MUST run even if Step 5d produced a FAIL verdict — run it before proceeding to Step 9:

BARREL_TMP=$(cat .codegraph/titan/.barrel-tmp 2>/dev/null)
if [ -n "$BARREL_TMP" ]; then rm -f "$BARREL_TMP"; fi
rm -f .codegraph/titan/.barrel-tmp

Step 5.5 — Architectural snapshot comparison

Compare the codebase's architectural properties before and after this change. This catches "technically correct but architecturally wrong" changes — e.g., a valid refactor that puts code in the wrong layer.

A2. Dependency direction between domains (runs unconditionally)

A2 does NOT require arch-snapshot.json — it uses only the Step 1 diff-impact results and GLOBAL_ARCH.md (if available).

If .codegraph/titan/GLOBAL_ARCH.md does not exist (standalone invocation without Titan artifacts), skip A2 — layer boundaries are unknown.

From GLOBAL_ARCH.md, extract the expected dependency direction between domains (e.g., "presentation depends on features, not the reverse").

Check if any new cross-domain dependency violates the expected direction. Use the Step 1 diff-impact results to extract only the edges introduced by the staged changes — do not re-run codegraph deps on the full file (that returns all dependencies including pre-existing ones). For each new edge in the diff-impact output, the source and target file paths are already present in the edge data. Resolve the domain/layer of each endpoint by matching its file path against the domain map in GLOBAL_ARCH.md (e.g., src/presentation/ → presentation layer, src/features/ → features layer). No additional codegraph command is needed — the diff-impact edge output contains the file paths directly.

  • New upward dependency (lower layer importing higher layer) introduced in this diff → check if { source, target } is already in step5cViolations (passed from Step 5c). If yes, skip (already reported). Otherwise → FAIL
  • Pre-existing boundary violations not surfaced by Step 5c's staged-diff results → advisory-only (not gating)
  • New lateral dependency within the same layer → OK

Load pre-forge snapshot (A1, A3, A4 — snapshot-dependent)

Read .codegraph/titan/arch-snapshot.json if it exists (created by /titan-run before forge begins). If missing, skip the remaining assertions (A1, A3, A4) in this step — they require the pre-forge baseline. A2 above already ran unconditionally.

Capture current state

Use mktemp -d to create a unique temporary directory that persists across Bash invocations (shell variables like $TITAN_TMP_ID do not survive between separate Bash tool calls):

TITAN_ARCH_DIR=$(mktemp -d /tmp/titan-arch-XXXXXX)
echo "$TITAN_ARCH_DIR" > .codegraph/titan/.arch-tmpdir
codegraph communities -T --json > "$TITAN_ARCH_DIR/current-communities.json" || echo '{"ARCH_CAPTURE_FAILED":"communities"}' > "$TITAN_ARCH_DIR/current-communities.json"
codegraph structure --depth 2 --json > "$TITAN_ARCH_DIR/current-structure.json" || echo '{"ARCH_CAPTURE_FAILED":"structure"}' > "$TITAN_ARCH_DIR/current-structure.json"
codegraph communities --drift -T --json > "$TITAN_ARCH_DIR/current-drift.json" || echo '{"ARCH_CAPTURE_FAILED":"drift"}' > "$TITAN_ARCH_DIR/current-drift.json"

The path is written to .codegraph/titan/.arch-tmpdir so subsequent Bash invocations can recover it via TITAN_ARCH_DIR=$(cat .codegraph/titan/.arch-tmpdir).

Compare

Before comparing: Check each captured file for ARCH_CAPTURE_FAILED. If a file contains this marker, skip the corresponding assertion (A1/A3/A4) and report: "Skipping <assertion> — codegraph <command> failed during capture."

In a new Bash invocation, recover the temp dir path first:

TITAN_ARCH_DIR=$(cat .codegraph/titan/.arch-tmpdir)

A1. Community stability: Use the drift output (which uses content-based matching, not raw IDs, to track community movements across runs):

Read .codegraph/titan/arch-snapshot.json → drift (the pre-forge drift baseline) and compare against $TITAN_ARCH_DIR/current-drift.json:

  • For each new drift warning in current that was NOT present in the snapshot: if the drifted symbol was NOT touched in the diff → WARN: "Symbol <name> drifted community as a side effect"
  • If > 5 untouched symbols appear in new drift warnings → FAIL: "Significant community restructuring detected — <N> symbols drifted communities. This change may have unintended architectural impact."

A3. Cohesion delta: Compare directory cohesion scores in arch-snapshot.json → structure (baseline) against $TITAN_ARCH_DIR/current-structure.json (current):

  • If any directory's cohesion dropped by > 0.2 → WARN: "Directory <dir> cohesion dropped from <X> to <Y>"
  • If a directory went from above 0.5 to below 0.3 → FAIL: "Directory <dir> became tangled (cohesion <X> → <Y>)"

A4. Resolved drift warnings (positive signal): Compare drift warnings between snapshot and current. A1 already covers new drift warnings — A4 only reports resolved ones:

  • If any drift warning that was present in the snapshot is absent from $TITAN_ARCH_DIR/current-drift.json → note as positive: "Symbol <name> community drift resolved — architecture improved"

Note: A3 and A4 compare the pre-forge baseline against the committed state at gate-run time (the graph DB does not include staged-but-uncommitted changes). They catch cumulative architectural drift across all forge commits made so far, not the individual staged change being validated in this gate run. A1 uses staged-change-aware data (diff-impact) and catches per-change violations. A2 runs unconditionally above (before the snapshot gate) and also uses diff-impact data.

Cleanup (MUST run even on failure or early exit)

This cleanup block MUST execute regardless of the verdict — including FAIL paths and early exits. Run it before proceeding to Step 9 (verdict aggregation), not after.

TITAN_ARCH_DIR=$(cat .codegraph/titan/.arch-tmpdir 2>/dev/null)
if [ -n "$TITAN_ARCH_DIR" ]; then
  rm -rf "$TITAN_ARCH_DIR"
fi
rm -f .codegraph/titan/.arch-tmpdir

Verdict integration

Architectural failures are reported as part of the overall gate verdict. They participate in the PASS/WARN/FAIL aggregation like all other checks.


Step 6 — Branch structural diff

codegraph branch-compare main HEAD -T --json

Cumulative structural impact of all changes on this branch (broader than diff-impact --staged). Detect cumulative drift.


Step 7 — Sync plan alignment

If .codegraph/titan/sync.json exists:

  • Are changed files part of the current execution phase?
  • Are dependencies for these targets already completed?
  • Skipping ahead in execution order? → WARN

Advisory — prevents jumping ahead and creating conflicts.


Step 8 — Blast radius check

The FAIL/PASS decision comes from Step 1's codegraph check --staged --blast-radius 30 predicate — do not re-derive it from diff-impact's raw numbers, which are absolute transitive-caller counts and are NOT shape-aware:

  • Step 1's blast-radius predicate failed → FAIL (a touched function's own call graph shape genuinely changed and its transitive callers exceed 30)
  • Step 1's blast-radius predicate passed but a changed function's raw transitiveCallers (from diff-impact) > 15 → WARN (worth a second look even though not gating — this may include functions Step 1 exempted as pre-existing fan-in)
  • Historically coupled file NOT staged? → WARN ("consider also updating X")

Step 9 — Verdict and auto-rollback

Aggregate all checks:

VerdictMeaning
PASSSafe to commit
WARNWarnings only — commit at your discretion
FAILFailures present — auto-rollback triggered

Auto-rollback on FAIL (cycle/build/test/lint failures)

  1. Restore graph to the most recent snapshot:
    codegraph snapshot restore titan-batch-<N>   # or titan-baseline if no batch snapshot
    Check titan-state.json → snapshots.lastBatch first; fall back to snapshots.baseline.
  2. Unstage changes (preserve in working tree):
    git reset HEAD
  3. Rebuild graph for current working tree state:
    codegraph build

"GATE FAIL: [reason]. Graph restored, changes unstaged but preserved. Fix and re-stage."

For structural and semantic failures (Steps 1 [manifesto/blast-radius/boundary only — not cycles], 3, 5, 5.5, 6-8), do NOT auto-rollback — report the FAIL and let the user decide whether to fix in place or unstage manually. For Step 2 (new cycle), Step 1 cycle violations (from --cycles flag), and Step 4 (lint/build/test), trigger auto-rollback.

Snapshot cleanup on pipeline completion

When the full Titan pipeline is done (all SYNC phases complete, final GATE passes):

codegraph snapshot delete titan-baseline
codegraph snapshot delete titan-batch-<N>   # if any remain

"All Titan snapshots cleaned up. Codebase is in its final validated state."


Step 10 — Update state machine

Append to .codegraph/titan/gate-log.ndjson:

{
  "timestamp": "<ISO 8601>",
  "verdict": "PASS|WARN|FAIL",
  "stagedFiles": ["file1.js"],
  "changedFunctions": 3,
  "blastRadius": 12,
  "checks": {
    "manifesto": "pass|fail",
    "cycles": "pass|fail",
    "complexity": "pass|warn|fail",
    "semanticAssertions": "pass|warn|fail|skipped",
    "archSnapshot": "pass|warn|fail|skipped",
    "lint": "pass|fail|skipped",
    "build": "pass|fail|skipped",
    "tests": "pass|fail|skipped",
    "syncAlignment": "pass|warn|skipped",
    "blastRadius": "pass|warn|fail"
  },
  "rolledBack": false
}

Update titan-state.json (if exists): increment progress.fixed, update fileAudits for fixed files.


Step 11 — Report to user

PASS:

GATE PASS — safe to commit
  Changed: 3 functions across 2 files
  Blast radius: 12 transitive callers
  Structural: pass | Semantic: pass | Architecture: pass
  Lint: pass | Build: pass | Tests: pass
  Complexity: all within thresholds (worst: halstead.bugs 0.3)

WARN:

GATE WARN — review before committing
  Changed: 5 functions across 3 files
  Warnings:
  - utils.js historically co-changes with config.js (not staged)
  - parseConfig MI improved 18 → 35 but still below 50
  - Semantic: new dependency on module scheduled for decomposition
  - Architecture: directory src/domain/ cohesion dropped 0.6 → 0.45

FAIL (cycle/test/lint/build failures — rollback triggered):

GATE FAIL — changes unstaged, graph restored
  Failures:
  - Tests: 2 suites failed
  - New cycle: parseConfig → loadConfig → parseConfig
  Fix issues, re-stage, re-run /titan-gate

FAIL (structural/semantic failures — no rollback):

GATE FAIL — changes preserved for review — manual unstage if needed
  Failures:
  - Semantic: removed export `parseConfig` still imported by 3 files
  - Architecture: new upward dependency presentation/ → domain/
  Staged changes are intact. Fix the issues above, or manually run `git reset HEAD` to unstage.
  Re-stage and re-run /titan-gate when ready.

Rules

  • Fast execution. Only staged changes, not full codebase.
  • Always use --json and -T.
  • Never auto-commit. Verdict only — user decides.
  • Auto-rollback is gentle — git reset HEAD, never git checkout. Work preserved.
  • Append to gate-log.ndjson — the audit trail.
  • Force mode downgrades WARN → PASS but cannot override FAIL.
  • Run the project's own lint/build/test — codegraph checks are necessary but not sufficient.
  • Use the correct check flags: --cycles, --blast-radius <n>, --boundaries.

Self-Improvement

This skill lives at .claude/skills/titan-gate/SKILL.md. Adjust thresholds or rollback behavior after dogfooding.

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.