一键导入
titan-gate
Validate staged changes — codegraph checks + project lint/build/test, auto-rollback on failure, pass/fail commit gate (Titan Paradigm Phase 4)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Validate staged changes — codegraph checks + project lint/build/test, auto-rollback on failure, pass/fail commit gate (Titan Paradigm Phase 4)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | titan-gate |
| description | Validate staged changes — codegraph checks + project lint/build/test, auto-rollback on failure, pass/fail commit gate (Titan Paradigm Phase 4) |
| argument-hint | <--force to skip warnings> |
| allowed-tools | Bash, Read, Write, Edit, Grep |
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).
Worktree check:
git rev-parse --show-toplevel && git worktree list
If not in a worktree, stop: "Run /worktree first."
Staged changes?
git diff --cached --name-only
If nothing staged, stop: "Nothing staged. Use git add first."
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.
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.
codegraph cycles --json
Compare against RECON baseline (if titan-state.json exists):
For each changed file (from diff-impact):
codegraph complexity --file <changed-file> --health -T --json
Check all metrics against thresholds:
cognitive > 30 → FAILhalstead.bugs > 1.0 → FAIL (estimated defect)mi < 20 → FAILDetect 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.
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.
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):
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.git show HEAD:<file> and compare function signaturescodegraph fn-impact <symbol> -T --json
Count callers. If callers > 0 and callers are NOT also staged → FAIL: "Signature change in <symbol> breaks callers not updated in this commit: "<symbol> still imported by files"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 : "
Note:
codegraph checkdoes not include import resolution predicates — its checks cover cycles, blast-radius, boundaries, and manifesto rules. Import resolution runs duringcodegraph build. This step relies on diff-impact's edge data to detect broken imports indirectly by identifying edges that reference removed symbols.
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:
<source> → <target> violates layer boundary"{ source, target } to step5cViolationsAdditionally, from the diff-impact results already collected in Step 1, extract any new edges (imports that didn't exist before):
<module> which is scheduled for decomposition"Note: Step 5c relies exclusively on
codegraph check --boundariesresults. Domain-direction checks againstGLOBAL_ARCH.mdare handled by Step 5.5 A2 — do not duplicate them here. Passstep5cViolationsto A2 so it can skip edges already flagged here.
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 exports that have active callers: . 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
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 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.
{ source, target } is already in step5cViolations (passed from Step 5c). If yes, skip (already reported). Otherwise → FAILRead .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.
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-tmpdirso subsequent Bash invocations can recover it viaTITAN_ARCH_DIR=$(cat .codegraph/titan/.arch-tmpdir).
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 — codegraph 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:
<name> drifted community as a side effect"A3. Cohesion delta:
Compare directory cohesion scores in arch-snapshot.json → structure (baseline) against $TITAN_ARCH_DIR/current-structure.json (current):
<dir> cohesion dropped from to "<dir> became tangled (cohesion → )"A4. Resolved drift warnings (positive signal): Compare drift warnings between snapshot and current. A1 already covers new drift warnings — A4 only reports resolved ones:
$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.
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
Architectural failures are reported as part of the overall gate verdict. They participate in the PASS/WARN/FAIL aggregation like all other checks.
codegraph branch-compare main HEAD -T --json
Cumulative structural impact of all changes on this branch (broader than diff-impact --staged). Detect cumulative drift.
If .codegraph/titan/sync.json exists:
Advisory — prevents jumping ahead and creating conflicts.
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:
blast-radius predicate failed → FAIL (a touched function's own call graph shape genuinely changed and its transitive callers exceed 30)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)Aggregate all checks:
| Verdict | Meaning |
|---|---|
| PASS | Safe to commit |
| WARN | Warnings only — commit at your discretion |
| FAIL | Failures present — auto-rollback triggered |
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.
Unstage changes (preserve in working tree):
git reset HEAD
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.
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."
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.
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.
--json and -T.git reset HEAD, never git checkout. Work preserved.--cycles, --blast-radius <n>, --boundaries.This skill lives at .claude/skills/titan-gate/SKILL.md. Adjust thresholds or rollback behavior after dogfooding.
Adopt extracted helpers — find dead symbols from forge, wire them into consumers, replace duplicated inline patterns, and gate on dead-symbol delta (Titan Paradigm Phase 4.5)
Adopt extracted helpers — find dead symbols from forge, wire them into consumers, replace duplicated inline patterns, and gate on dead-symbol delta (Titan Paradigm Phase 4.5)
Audit codebase files against the 4-pillar quality manifesto using RECON work batches, with batch processing and context budget management (Titan Paradigm Phase 2)
Map a codebase's dependency graph, identify hotspots, name logical domains, propose work batches, and produce a ranked priority queue for autonomous cleanup (Titan Paradigm Phase 1)
Local repo maintenance — clean stale worktrees, remove dirt files, sync with main, update codegraph, prune branches, and verify repo health
Check all open PRs, resolve conflicts, update branches, address Claude and Greptile review concerns, fix CI failures, and retrigger reviewers until clean