Skip to content

Commit ffd2013

Browse files
committed
fix: resolve merge conflicts with main
2 parents c4f221f + 08bdc55 commit ffd2013

6 files changed

Lines changed: 73 additions & 13 deletions

File tree

.claude/hooks/snapshot-pre-bash.sh

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,27 @@ if [ -z "$COMMAND" ]; then
2323
exit 0
2424
fi
2525

26-
# Skip read-only commands that can never write files — reduces snapshot overhead
27-
# for the most common Bash calls (ls, cat, grep, git log, git status, etc.).
26+
# Skip commands that can NEVER write files — reduces snapshot overhead for the
27+
# most common read-only Bash calls. Only include commands that have no
28+
# write-capable flags/modes at all. Notably absent:
29+
# - echo, printf — write files via shell redirections (echo … > file)
30+
# - find — can write via -exec sed -i, -exec cp, -delete, etc.
31+
# - awk — can write via redirection or getline
32+
# - node -e/-p — can write files via the Node.js fs module
2833
# sed is intentionally NOT in this list because `sed -i` modifies files in-place.
29-
if echo "$COMMAND" | grep -qE '^\s*(ls|cat|head|tail|grep|find|git\s+(log|status|diff|show|branch|remote|fetch|rev-parse|stash\s+list|ls-files|blame|describe|tag|config\s+--get)|gh\s+(pr|issue|repo)\s+(view|list|status)|echo|printf|pwd|which|node\s+-e|node\s+-p|npx\s+--version|wc|sort|uniq|awk)\b'; then
34+
if echo "$COMMAND" | grep -qE '^\s*(ls|cat|head|tail|grep|git\s+(log|status|diff|show|branch|remote|fetch|rev-parse|stash\s+list|ls-files|blame|describe|tag|config\s+--get)|gh\s+(pr|issue|repo)\s+(view|list|status)|pwd|which|npx\s+--version|wc|sort|uniq)\b'; then
3035
exit 0
3136
fi
3237

3338
# Resolve the project root (worktree-aware — each worktree has its own .claude/)
3439
PROJECT_DIR=$(git rev-parse --show-toplevel 2>/dev/null) || PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
3540

36-
# Key the snapshot file to the project root so parallel worktrees don't collide.
37-
# Use a simple hash of the path — just enough to be unique per worktree.
41+
# Key the snapshot file to (project root, command) so concurrent Bash calls
42+
# within the same session don't overwrite each other's baseline.
43+
# Claude Code can issue multiple Bash tool calls in parallel; using just the
44+
# project hash would mean call B's pre-hook overwrites call A's snapshot before
45+
# A's post-hook runs, silently dropping A's file writes from session-edits.log.
46+
# Including a hash of the command makes each concurrent call use a distinct file.
3847
PROJECT_HASH=$(echo "$PROJECT_DIR" | node -e "
3948
const crypto = require('crypto');
4049
let d='';
@@ -44,7 +53,16 @@ PROJECT_HASH=$(echo "$PROJECT_DIR" | node -e "
4453
});
4554
" 2>/dev/null) || PROJECT_HASH="default"
4655

47-
SNAPSHOT_FILE="/tmp/claude-bash-snapshot-${PROJECT_HASH}.txt"
56+
CMD_HASH=$(echo "$COMMAND" | node -e "
57+
const crypto = require('crypto');
58+
let d='';
59+
process.stdin.on('data',c=>d+=c);
60+
process.stdin.on('end',()=>{
61+
process.stdout.write(crypto.createHash('sha1').update(d.trim()).digest('hex').slice(0,8));
62+
});
63+
" 2>/dev/null) || CMD_HASH="default"
64+
65+
SNAPSHOT_FILE="/tmp/claude-bash-snapshot-${PROJECT_HASH}-${CMD_HASH}.txt"
4866

4967
# Capture current git status --porcelain.
5068
# Lines look like: "XY filename" or "XY orig -> dest" (rename).

.claude/hooks/track-bash-writes.sh

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ fi
2727
# Resolve the project root (worktree-aware — each worktree has its own .claude/)
2828
PROJECT_DIR=$(git rev-parse --show-toplevel 2>/dev/null) || PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
2929

30-
# Reproduce the same project hash used by snapshot-pre-bash.sh
30+
# Reproduce the same snapshot path used by snapshot-pre-bash.sh.
31+
# The snapshot is keyed by (project root, command) so concurrent Bash calls
32+
# within the same session each get a distinct file — preventing parallel calls
33+
# from overwriting each other's baseline.
3134
PROJECT_HASH=$(echo "$PROJECT_DIR" | node -e "
3235
const crypto = require('crypto');
3336
let d='';
@@ -37,7 +40,16 @@ PROJECT_HASH=$(echo "$PROJECT_DIR" | node -e "
3740
});
3841
" 2>/dev/null) || PROJECT_HASH="default"
3942

40-
SNAPSHOT_FILE="/tmp/claude-bash-snapshot-${PROJECT_HASH}.txt"
43+
CMD_HASH=$(echo "$COMMAND" | node -e "
44+
const crypto = require('crypto');
45+
let d='';
46+
process.stdin.on('data',c=>d+=c);
47+
process.stdin.on('end',()=>{
48+
process.stdout.write(crypto.createHash('sha1').update(d.trim()).digest('hex').slice(0,8));
49+
});
50+
" 2>/dev/null) || CMD_HASH="default"
51+
52+
SNAPSHOT_FILE="/tmp/claude-bash-snapshot-${PROJECT_HASH}-${CMD_HASH}.txt"
4153

4254
# If there is no snapshot (hook was not installed yet, or the pre-hook was
4355
# skipped for a read-only command) we have no baseline — exit cleanly.

.claude/skills/titan-run/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ You are the **orchestrator** for the full Titan Paradigm pipeline. Your job is t
1616
- `<path>` → target path (passed to recon)
1717
- `--skip-recon` → skip recon (assumes artifacts exist)
1818
- `--skip-gauntlet` → skip gauntlet (assumes artifacts exist)
19-
- `--start-from <phase>` → jump to phase: `recon`, `gauntlet`, `sync`, `forge`, `grind`, `parity`
19+
- `--start-from <phase>` → jump to phase: `recon`, `gauntlet`, `sync`, `forge`, `grind`, `parity`, `close`
2020
- `--gauntlet-batch-size <N>` → batch size for gauntlet (default: 5)
2121
- `--yes` → skip all confirmation prompts in the orchestrator (pre-pipeline, forge checkpoint, and resume prompts) and in forge (per-phase confirmation)
2222

crates/codegraph-core/src/ast_analysis/dataflow.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,8 @@ fn find_binding(scope_stack: &[ScopeFrame], name: &str) -> Option<BindingInfo> {
908908
}
909909
if let Some(local) = scope.locals.get(name) {
910910
let confidence = match local {
911-
LocalSource::CallReturn { .. } => 0.9,
912-
LocalSource::Destructured { .. } => 0.8,
911+
LocalSource::CallReturn => 0.9,
912+
LocalSource::Destructured => 0.8,
913913
};
914914
return Some(BindingInfo {
915915
binding_type: "local".to_string(),

src/domain/graph/builder/stages/build-edges.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,15 @@ function buildFileCallEdges(
12011201
importedNames,
12021202
typeMap as Map<string, unknown>,
12031203
);
1204-
for (const t of aliasTargets) {
1204+
const sortedAliasTargets =
1205+
aliasTargets.length > 1
1206+
? [...aliasTargets].sort(
1207+
(a, b) =>
1208+
computeConfidence(relPath, b.file, aliasFrom ?? null) -
1209+
computeConfidence(relPath, a.file, aliasFrom ?? null),
1210+
)
1211+
: aliasTargets;
1212+
for (const t of sortedAliasTargets) {
12051213
const edgeKey = `${caller.id}|${t.id}`;
12061214
if (t.id !== caller.id && !seenCallEdges.has(edgeKey) && !ptsEdgeRows.has(edgeKey)) {
12071215
const conf =
@@ -1237,7 +1245,15 @@ function buildFileCallEdges(
12371245
importedNames,
12381246
typeMap as Map<string, unknown>,
12391247
);
1240-
for (const t of aliasTargets) {
1248+
const sortedAliasTargets =
1249+
aliasTargets.length > 1
1250+
? [...aliasTargets].sort(
1251+
(a, b) =>
1252+
computeConfidence(relPath, b.file, aliasFrom ?? null) -
1253+
computeConfidence(relPath, a.file, aliasFrom ?? null),
1254+
)
1255+
: aliasTargets;
1256+
for (const t of sortedAliasTargets) {
12411257
const edgeKey = `${caller.id}|${t.id}`;
12421258
if (t.id !== caller.id && !seenCallEdges.has(edgeKey) && !ptsEdgeRows.has(edgeKey)) {
12431259
const conf =

tests/benchmarks/regression-guard.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,19 @@ const SKIP_VERSIONS = new Set(['3.8.0']);
277277
* exemption above (which was a WASM metric; this is native). Exempt this
278278
* release; remove once 3.13.0+ data confirms the steady-state.
279279
*
280+
* - 3.12.0:No-op rebuild — CI runner variance on a sub-50ms native metric.
281+
* The 3.12.0 baseline captures noopRebuildMs=30 (build benchmark) and
282+
* noopRebuildMs=23 (incremental benchmark); the per-PR gate re-measures
283+
* dev on a fresh runner and lands at 48ms (+60%) and 48ms (+109%) on run
284+
* 27457266151 — both exceed the NOISY_METRIC_THRESHOLD of 50% due to
285+
* sub-50ms variance on shared runners. This PR (#1487) adds warmup runs to
286+
* benchmark.ts on the no-op and 1-file rebuild tiers; on a true no-op
287+
* rebuild no files are re-parsed and build-edges.ts is never reached, so
288+
* none of the code changes in this branch execute on the hot path. The
289+
* delta is entirely shared-runner scheduling noise. Same shape and root
290+
* cause as 3.11.2:No-op rebuild. Exempt this release; remove once
291+
* 3.13.0+ data confirms the steady-state.
292+
*
280293
* - 3.12.0:Full build — root-caused residual feature cost of the Phase 8.x
281294
* resolution work on the native engine. The v3.12.0 publish gate first
282295
* measured 2231 → 3333 (+49%). Local A/B against a v3.11.2 baseline worktree
@@ -328,6 +341,7 @@ const KNOWN_REGRESSIONS = new Set([
328341
'3.11.2:No-op rebuild',
329342
'3.11.2:1-file rebuild',
330343
'3.11.2:Full build',
344+
'3.12.0:No-op rebuild',
331345
'3.12.0:Full build',
332346
'3.12.0:1-file rebuild',
333347
// tree-sitter-erlang devDependency removed (GHSA-rphw-c8qj-jv84 — malware).

0 commit comments

Comments
 (0)