Skip to content

fix: detect stale and incomplete graph state - #2858

Open
hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:fix/2841-stale-partial-graph-detection
Open

fix: detect stale and incomplete graph state#2858
hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:fix/2841-stale-partial-graph-detection

Conversation

@hopstreax

@hopstreax hopstreax commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #2841.

Graphify previously treated the presence of graphify-out/graph.json as
sufficient to take the existing-graph fast path. This could cause stale graphs
or partially completed builds to be silently trusted.

This change introduces explicit graph-state inspection and integrates it into
the skill build lifecycle.

What changed

Graph state inspection

Added inspect_graph_state() with six states:

  • ABSENT — no existing graph
  • BUILDING — another Graphify build is currently active
  • INCOMPLETE — intermediate artifacts from an interrupted build remain
  • STALE — the graph no longer represents the current corpus
  • UNVERIFIABLE — freshness cannot be established
  • FRESH — graph provenance and working tree are current

For git-tracked corpora, freshness considers:

  • graph.json's built_at_commit vs current HEAD
  • relevant tracked modifications/deletions/renames
  • supported untracked source files
  • git ignore rules

Graphify's own output directory and unrelated unsupported files are excluded
from dirty-tree detection.

Interrupted-build detection

Known ephemeral artifacts are detected and surfaced as INCOMPLETE, including:

  • .graphify_extract.json
  • .graphify_ast.json
  • .graphify_semantic.json
  • .graphify_chunk_*.json
  • .graphify_analysis.json
  • .graphify_detect.json

Persistent sidecars are explicitly excluded.

Unified build locking

The skill workflow and existing rebuild paths now share the same build-lock
protocol.

The lock provides:

  • cross-process mutual exclusion
  • PID ownership
  • process creation-time verification for PID reuse
  • stale/corrupt lock recovery
  • crash-safe lock release
  • token-based ownership during release
  • protection against an old owner deleting a newer owner's lock

The implementation supports POSIX and Windows locking primitives.

Skill integration

The existing-graph fast path now inspects graph state before deciding whether
to query or rebuild.

The build workflow also:

  1. acquires the build lock
  2. re-inspects graph state using its ownership token
  3. avoids unnecessary rebuilding if another process already produced a fresh graph
  4. safely releases the lock on completion or failure

Generated platform skills and skillgen snapshots were updated accordingly.

Tests

Added comprehensive graph-state/build-lock coverage including:

  • HEAD mismatches
  • dirty tracked files
  • supported untracked files
  • ignored/irrelevant files
  • missing provenance
  • non-git repositories
  • interrupted-build artifacts
  • active builds
  • stale lock recovery
  • PID reuse
  • concurrent lock contention
  • release races
  • owner-aware reinspection

Validation:

  • 49 graph-state tests passed
  • 66 skillgen tests passed
  • 115 watch tests passed locally, with 9 skipped and 2 pre-existing Windows-specific failures
  • Linux CI-equivalent suite: 4693 passed, 30 skipped, 19 pre-existing Windows/environment failures
  • git diff --cached --check clean

The existing watch-lock tests were also updated to validate the new
backward-compatible lock format: PID remains on line 1 while ownership
metadata is stored on subsequent lines.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds a full graph-state and build-locking layer to graphify/detect.py: GraphState/StalenessReason enums, GraphStateResult, and cross-platform lock primitives (acquire_build_lock, _mutex_lock, PID-liveness/create-time checks, lock-file parse/write) plus ephemeral vs. persistent sidecar classification. Introduces is_scan_ignored/resolves_under_root detection helpers and watch-side is_remote_source, write_build_config, and storedsourcepaths_normalize. Regenerates the skill fragments and expected skillgen outputs across all agents (codex, amp, kilo, kiro, windows, droid, etc.) and adds tests covering graph-state freshness/staleness, persistent-sidecar lock handling, and installer/hook wiring.

Worth a look

  • Linux create_time uses wrong stat field index due to comm parenthesesgraphify/detect.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Permission-denied PID probe is treated as deadgraphify/detect.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • PID stored in the build lock is the transient python -c process, not the actual long-running buildgraphify/skill-agents.md · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Repo-controlled .graphify_python is executed via shell word splittinggraphify/skill-claw.md:71 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Build lock is acquired by a short-lived subprocess and is not held during the buildgraphify/skill-claw.md:143 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2582 functions depend on the 1298 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 468 callers, 41 callees
  • new: _rebuild_code() — 98 callers, 51 callees
  • new: detect() — 107 callers, 15 callees
  • new: save_manifest() — 34 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: inspect_graph_state() — 32 callers, 9 callees
  • new: extract_corpus_parallel() — 26 callers, 10 callees
  • …and 29 more — each is listed as a finding

Verification — 2582 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2219 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_rebuild\_lock.

The verifier did not have enough to check \_rebuild\_lock, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `out_dir` is annotated `Path` — outside the synthesizable primitive/collection set

· 3 grounded finding(s) anchored inline below; 34 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/detect.py
lock_path.write_text("\n".join(lines) + "\n", encoding="utf-8")


def acquire_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionacquire_build_lock()

fans out to 7 callees (efferent coupling); 23 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
)


def release_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionrelease_build_lock()

7 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
return sorted(dirty_files)


def inspect_graph_state(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressioninspect_graph_state()

fans out to 9 callees (efferent coupling); 32 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

@hopstreax
hopstreax force-pushed the fix/2841-stale-partial-graph-detection branch from 080c30f to 076c967 Compare August 18, 2026 19:26

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds a GraphState/BuildLockStatus layer to graphify/detect.py: introduces GraphState/StalenessReason enums, GraphStateResult, and cross-platform build-lock primitives (acquire_build_lock, _mutex_lock, PID create-time verification for recycled-PID detection, lock-file parse/write helpers) plus ephemeral/persistent sidecar classification. Threads the new state and locking through graphify/watch.py (stored-source anchoring, gitignore-gated eviction, AST manifest rebuild) and regenerates all graphify_skill_* skill files and their tools/skillgen expected fixtures. Adds test coverage for graph-state transitions, concurrent stale lock takeover, corrupt-graph overwrite refusal, and skill/install regeneration.

Worth a look

  • Permission-denied PIDs are treated as deadgraphify/detect.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • PermissionError is treated as dead PIDgraphify/detect.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • release_build_lock deletes token_file even when it fails to release the lockgraphify/detect.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • release_build_lock deletes token_file even when lock is owned by another tokengraphify/detect.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Project-controlled .graphify_python is executed as a commandgraphify/skill-agents.md:69 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2730 functions depend on the 1565 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 468 callers, 41 callees
  • new: _rebuild_code() — 98 callers, 51 callees
  • new: detect() — 107 callers, 15 callees
  • new: save_manifest() — 34 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: inspect_graph_state() — 32 callers, 9 callees
  • new: extract_corpus_parallel() — 26 callers, 10 callees
  • …and 29 more — each is listed as a finding

Verification — 2730 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2367 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_rebuild\_lock.

The verifier did not have enough to check \_rebuild\_lock, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `out_dir` is annotated `Path` — outside the synthesizable primitive/collection set

· 3 grounded finding(s) anchored inline below; 34 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/detect.py
lock_path.write_text("\n".join(lines) + "\n", encoding="utf-8")


def acquire_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionacquire_build_lock()

fans out to 7 callees (efferent coupling); 23 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
)


def release_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionrelease_build_lock()

7 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
return sorted(dirty_files)


def inspect_graph_state(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressioninspect_graph_state()

fans out to 9 callees (efferent coupling); 32 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

@hopstreax
hopstreax force-pushed the fix/2841-stale-partial-graph-detection branch from 076c967 to de359f5 Compare August 19, 2026 05:10

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds a graph-state and build-lock layer to graphify/detect.py: introduces GraphState/StalenessReason enums, GraphStateResult/BuildLockStatus dataclasses, and cross-platform helpers (_get_process_create_time, _mutex_lock, lock-file parse/write, acquire_build_lock) that detect stale/recycled-PID locks and classify ephemeral vs. persistent sidecar artifacts. Regenerates the per-host skillgen expected fixtures and rationale snapshots to match, and expands watch/install/graph-state/skillgen tests (six-value enum unification, Windows PowerShell fast-path, per-host audit, Kilo/Gemini install artifacts).

Worth a look

  • Build lock never released on early exit / build failuregraphify/skill-agents.md · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Repo-controlled .graphify_python is executed as a shell commandgraphify/skill-agents.md:75 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Fast-path Python import is shadowable by the target repositorygraphify/skill-agents.md:77 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Skill acquires build lock but only releases it on the success pathgraphify/skill-agents.md:668 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Cached interpreter path is executed via unquoted shell expansiongraphify/skill-amp.md:69 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2739 functions depend on the 1574 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 468 callers, 41 callees
  • new: _rebuild_code() — 98 callers, 51 callees
  • new: detect() — 107 callers, 15 callees
  • new: save_manifest() — 34 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: inspect_graph_state() — 32 callers, 9 callees
  • new: extract_corpus_parallel() — 26 callers, 10 callees
  • …and 29 more — each is listed as a finding

Verification — 2739 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2376 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_rebuild\_lock.

The verifier did not have enough to check \_rebuild\_lock, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `out_dir` is annotated `Path` — outside the synthesizable primitive/collection set

· 3 grounded finding(s) anchored inline below; 34 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/detect.py
Comment thread graphify/detect.py
Comment thread graphify/detect.py
@hopstreax
hopstreax force-pushed the fix/2841-stale-partial-graph-detection branch from de359f5 to 20ea437 Compare August 19, 2026 06:13

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds graph-state and build-lock machinery to graphify/detect.py: GraphState/StalenessReason/LockResult enums, GraphStateResult/BuildLockStatus dataclasses, cross-platform process-creation-time and advisory-mutex helpers, and acquire_build_lock with PID-liveness and recycled-PID detection plus stale-lock reclamation. Introduces ephemeral vs. persistent sidecar artifact classification for the .graphify output directory. Updates skillgen fragments/expected skills and adds watch, install, graph-state, and skillgen tests covering lock contention and dirty-graph reporting.

Worth a look

  • Build lock write follows repo-controlled symlinkgraphify/detect.py:2586 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Cached interpreter path is executed from the repository without validationgraphify/skill-agents.md:72 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Dirty extensionless shebang sources are ignored when deciding graph stalenessgraphify/detect.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Windows _is_pid_alive false-positive on unrelated exit codesgraphify/detect.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • _parse_porcelain_z requires literal space at status offset, breaking rename/copy entries with non-space codesgraphify/detect.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2859 functions depend on the 1694 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 468 callers, 41 callees
  • new: _rebuild_code() — 98 callers, 51 callees
  • new: detect() — 109 callers, 15 callees
  • new: save_manifest() — 34 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: inspect_graph_state() — 33 callers, 9 callees
  • new: extract_corpus_parallel() — 26 callers, 10 callees
  • …and 33 more — each is listed as a finding

Verification — 2859 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2496 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_rebuild\_lock.

The verifier did not have enough to check \_rebuild\_lock, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `out_dir` is annotated `Path` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_translate\_bash\_block.

The verifier did not have enough to check \_translate\_bash\_block, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: non-vacuity: domain too small (only 1 distinct inputs exercised, need 3) — 'no divergence' would be near-vacuous

· 3 grounded finding(s) anchored inline below; 38 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/detect.py
lock_path.write_text("\n".join(lines) + "\n", encoding="utf-8")


def acquire_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionacquire_build_lock()

fans out to 7 callees (efferent coupling); 28 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
)


def release_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionrelease_build_lock()

14 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
return sorted(dirty_files)


def inspect_graph_state(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressioninspect_graph_state()

fans out to 9 callees (efferent coupling); 33 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

@hopstreax
hopstreax force-pushed the fix/2841-stale-partial-graph-detection branch from 20ea437 to 0bf03b7 Compare August 19, 2026 07:33
@hopstreax
hopstreax force-pushed the fix/2841-stale-partial-graph-detection branch from 0bf03b7 to ec9ebe7 Compare August 19, 2026 07:44

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds a graph freshness/state model and cross-platform build-lock mechanism to graphify/detect.py: introduces GraphState/StalenessReason/GraphStateResult, LockResult/BuildLockStatus, and acquire_build_lock backed by an OS advisory mutex (_mutex_lock), PID-liveness plus process-create-time validation for stale-lock reclamation, symlink-safe atomic writes, and ephemeral-vs-persistent artifact classification. Regenerates the graphify skill templates across all agent variants (agents/codex/claw/kilo/trae/windows/opencode) and their skillgen expectations for the new install/extract/cluster/health-check steps. Adds test coverage in test_graph_state.py, test_watch.py, test_skillgen.py, and test_install.py for lock reclamation, stale-on-head-mismatch detection, incremental rebuild preservation, and skill body wording.

Worth a look

  • Runs git status with repository-controlled hooks/config enabledgraphify/detect.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Fast-path executes repo-controlled .graphify_pythongraphify/skill-agents.md:69 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Linux create_time uses field index 21 which is fragile for process names containing spaces/parensgraphify/detect.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Linux process start time parsing breaks when /proc stat comm contains spacesgraphify/detect.py:2470 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
  • Mutex lock follows attacker-controlled symlinkgraphify/detect.py:2513 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2877 functions depend on the 1712 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 468 callers, 41 callees
  • new: _rebuild_code() — 98 callers, 51 callees
  • new: detect() — 109 callers, 15 callees
  • new: save_manifest() — 34 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: inspect_graph_state() — 34 callers, 9 callees
  • new: extract_corpus_parallel() — 26 callers, 10 callees
  • …and 33 more — each is listed as a finding

Verification — 2877 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2514 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_rebuild\_lock.

The verifier did not have enough to check \_rebuild\_lock, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `out_dir` is annotated `Path` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_translate\_bash\_block.

The verifier did not have enough to check \_translate\_bash\_block, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: non-vacuity: domain too small (only 1 distinct inputs exercised, need 3) — 'no divergence' would be near-vacuous

· 3 grounded finding(s) anchored inline below; 38 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/detect.py
_safe_write_file(lock_path, "\n".join(lines) + "\n")


def acquire_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionacquire_build_lock()

fans out to 8 callees (efferent coupling); 29 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
)


def release_build_lock(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionrelease_build_lock()

14 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/detect.py
return sorted(dirty_files)


def inspect_graph_state(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressioninspect_graph_state()

fans out to 9 callees (efferent coupling); 34 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No detection of a stale or partially-built graphify-out/ for git-tracked corpora

1 participant