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
In this repository22 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- architectSkill
- bench-checkSkill
- create-skillSkill
- deps-auditSkill
- dogfoodSkill
- fixerSkill
- housekeepSkill
- overseeSkill
- paritySkill
- releaseSkill
- resolveSkill
- sweepSkill
- test-healthSkill
- titan-closeSkill
- titan-forgeSkill
- titan-gauntletSkill
- titan-grindSkill
- titan-reconSkill
- titan-resetSkill
- titan-runSkill
- titan-syncSkill
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
- Very specific: line 16
Force mode: If $ARGUMENTS contains --force, warnings are downgraded (failures still block).
- Very specific: line 26
If not in a worktree, stop: "Run /worktree first."
- Distinctive: line 32
If nothing staged, stop: "Nothing staged.
- Very specific: line 34
Load state (optional): Read .codegraph/titan/titan-state.json if it exists — use for thresholds, baseline comparison, and sync alignment.
- Distinctive: line 40
Run the full change validation predicates in one call:
- Distinctive: line 80
Check all metrics against thresholds:
- Distinctive: line 97
Run in order — stop on first failure:
- Distinctive: line 123
If any fail → overall verdict is FAIL → proceed to auto-rollback.
- Distinctive: line 129
Verify that code changes don't silently break callers by changing public contracts.
- Distinctive: line 144
If the file is new (command fails or returns nothing), skip 5a for this file — new exports cannot break existing callers.
- Very specific: line 146
Check if the symbol existed before this change: git show HEAD:<file> and compare function signatures
- Distinctive: line 147
If a function's parameter list changed (added required params, removed params, changed types):
- Very specific: line 152
If an export was removed entirely and callers exist → FAIL: "Removed export <symbol> still imported by <N> files"
- Very specific: line 164
Check the Step 1 codegraph check --staged --boundaries results for boundary violations (already collected — do not re-run).
- Very specific: line 168
Add { source, target } to step5cViolations
- Very specific: line 177
If the change modifies an index/barrel file (e.g., index.js, mod.rs):
- Very specific: line 212
If .codegraph/titan/GLOBAL_ARCH.md does not exist (standalone invocation without Titan artifacts), skip A2 — layer boundaries are unknown.
- Very specific: line 223
Read .codegraph/titan/arch-snapshot.json if it exists (created by /titan-run before forge begins).
- Very specific: line 227
Use mktemp -d to create a unique temporary directory that persists across Bash invocations (shell variables like $TITAN_TMP_ID do not …
- Distinctive: line 249
Use the drift output (which uses content-based matching, not raw IDs, to track community movements across runs):
- Very specific: line 251
Read .codegraph/titan/arch-snapshot.json → drift (the pre-forge drift baseline) and compare against $TITAN_ARCH_DIR/current-drift.json:
- Distinctive: line 253
If > 5 untouched symbols appear in new drift warnings → FAIL: "Significant community restructuring detected — <N> symbols drifted …
- Very specific: line 257
If any directory's cohesion dropped by > 0.2 → WARN: "Directory <dir> cohesion dropped from <X> to <Y>"
- Very specific: line 258
If a directory went from above 0.5 to below 0.3 → FAIL: "Directory <dir> became tangled (cohesion <X> → <Y>)"
- Very specific: line 262
If any drift warning that was present in the snapshot is absent from $TITAN_ARCH_DIR/current-drift.json → note as positive: "Symbol <name> …
- Very specific: line 330
Check titan-state.json → snapshots.lastBatch first.
- Distinctive: line 349
When the full Titan pipeline is done (all SYNC phases complete, final GATE passes):
- Very specific: line 387
Update titan-state.json (if exists): increment progress.fixed, update fileAudits for fixed files.
- Distinctive: line 437
Fast execution: Only staged changes, not full codebase.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Titan 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
- Worktree check:
If not in a worktree, stop: "Rungit rev-parse --show-toplevel && git worktree list/worktreefirst." - Staged changes?
If nothing staged, stop: "Nothing staged. Usegit diff --cached --name-onlygit addfirst." - Load state (optional). Read
.codegraph/titan/titan-state.jsonif 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 --jsonThis 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 --jsonExtract: changed functions (count + names), direct callers affected, transitive blast radius, historically coupled files.
Step 2 — Cycle check
codegraph cycles --jsonCompare 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 --jsonCheck all metrics against thresholds:
cognitive> 30 → FAILhalstead.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"
fiIf 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 --jsonFor each changed file from diff-impact (Step 1):
- First, check if the file existed before this commit:
If the file is new (command fails or returns nothing), skip 5a for this file — new exports cannot break existing callers.git show HEAD:<changed-file> -- 2>/dev/null | head -1 - 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):
Count callers. If callers > 0 and callers are NOT also staged → FAIL: "Signature change incodegraph fn-impact <symbol> -T --json<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 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.
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 }tostep5cViolations
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 --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.
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 --jsonThen capture the current (staged) export list:
codegraph exports <barrel-file> -T --jsonCompare 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-tmpStep 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 instep5cViolations(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-tmpdirso subsequent Bash invocations can recover it viaTITAN_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-tmpdirVerdict 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 --jsonCumulative 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-radiuspredicate failed → FAIL (a touched function's own call graph shape genuinely changed and its transitive callers exceed 30) - Step 1's
blast-radiuspredicate passed but a changed function's rawtransitiveCallers(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:
| Verdict | Meaning |
| PASS | Safe to commit |
| WARN | Warnings only — commit at your discretion |
| FAIL | Failures present — auto-rollback triggered |
Auto-rollback on FAIL (cycle/build/test/lint failures)
- Restore graph to the most recent snapshot:
Checkcodegraph snapshot restore titan-batch-<N> # or titan-baseline if no batch snapshottitan-state.json → snapshots.lastBatchfirst; fall back tosnapshots.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.
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.45FAIL (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-gateFAIL (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
--jsonand-T. - Never auto-commit. Verdict only — user decides.
- Auto-rollback is gentle —
git reset HEAD, nevergit 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.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

