Skip to content

perf(graph): avoid duplicate pathname stat and time segment opens - #4796

Open
ScriptedAlchemy wants to merge 18 commits into
masterfrom
fix/4532-graph-open-cost-telemetry
Open

ScriptedAlchemy wants to merge 18 commits into
masterfrom
fix/4532-graph-open-cost-telemetry

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

Refs #4532 — partial hot-path and correctness repair. Not full issue acceptance; do not close #4532 on merge of this slice alone.

Root cause and coordination

On the reported 6.6k-file managed macOS repository, cold graph publication timed out three times at 15 minutes with >90% of sampled stack frames in open(). Existing merged #4547 and #4725/#4742 keep up to eight authenticated segment handles per pass, eliminating interleaved reopens. However the current index stores each graph page as a distinct content-addressed file, so cold first-opens remain O(distinct pages). #4533, with ongoing PR #4792, owns the coordinated packed-storage/offset-index cutover. Do not duplicate or bypass that storage work here.

Graph changes

  • Carry already-selected pathname metadata into the authenticated File::open, eliminating an unnecessary second symlink_metadata() per cold segment. Keep opened-handle identity, extent, Windows identity, digest and retention checks.
  • Add cumulative segment_open_wall_seconds and graph_pass_wall_seconds to the existing code_graph_segment_read_pass event alongside segment_open_attempts and segment_reads. The open counter advances only at the actual primary File::open boundary, not for rejected path/extent probes.
  • Clear output on rejected ranges, wrong manifest extent, cancellation, missing fingerprint files and short reads. Recheck caller cancellation/deadline after the possibly slow I/O operation (including failed I/O), and retain typed interruption precedence. This does not interrupt a kernel call already blocked.
  • Prevent failed cached graph reads from promoting LRU recency and thereby evicting a different valid handle.

Late sealed-evidence interruption correctness — bd9b1a6

The full-seal verification callback (distinct from the graph-row reader) previously checked cancellation/deadline only before component I/O. An endpoint-scanned open/read that failed after expiry was consequently classified as sealed corruption. Its read callback now clears stale output first, rechecks after successful or failed I/O, preserves the observed typed interruption, and never commits an interrupted proof. New real partitioned-seal regression verifies the intact generation, truncates disposable segment files after a real range handle opens, requires a nonzero open, exact Cancelled/DeadlineExceeded precedence with one late probe, restores the fixture, and proves a fresh successful verification. Commit 108b1ae ensures the fixture's published read-only segments are made writable only within the disposable test before the deliberately injected truncate, so the assertion measures the intended post-open failure instead of a permission refusal. The test is published but not yet executed. This does not reduce first-opens.

CI repair in 2ecbdf1

Three //crates/tracedecay:automation_runner_test scheduler tests supplied no backend identity, so the production backend_unconfigured guard correctly refused them before their intended schedule/lock checks. Bind the existing test backend to a real temporary-file identity, consistently across the prefilter and retained runner. Preserve manual-schedule, exact-ledger, lock precedence, reacquisition and zero-call assertions. Add a regression proving unconfigured refusal, diagnostic deduplication, and same-occurrence recovery after binding without cooldown or effectful terminal records. No production backend guard is relaxed.

Behavioral regression evidence required

Real-filesystem graph tests cover exact bytes/digest recovery, valid route fallback, fail-closed directory/manifest-size/missing-file paths with zero attempted opens, interleaved reuse and bounded eviction, failed-read LRU neutrality, previous-output clearing, short/truncated file reads, pre/post I/O cancellation/deadline precedence, and a fresh successful pass. The existing cold graph-builder regression proves row/digest parity and observes one first-open per distinct page (not O(1)). Require fresh, nonzero execution at the current head rather than inferring success from source review or earlier heads.

Current verification and remaining acceptance

No budget, storage-format or release change. No production or infrastructure actions. Kev/decision-model work (including draft #4776) and release #4763 are untouched.

@changeset-bot

changeset-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 43db8db

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Recheck cancellation and deadlines after segment reads, including errors,
clear late bytes, and preserve typed interruption precedence. Add real-file
regressions for cancellation, deadline expiry, truncation, and fresh-pass
recovery without changing handle bounds or publication budgets.

Refs #4532

Copy link
Copy Markdown
Owner Author

Published source/test follow-up ed860ca. Refs #4532.

Defect repaired: the pass reader checked interruption only before segment I/O. Endpoint-scanned metadata/open/read work can outlive that probe; a completed read could then return bytes after expiry, while failed I/O could be treated as source corruption. The reader now rechecks the caller's existing probe after the operation, including its error path, clears late output, and retains the original Cancelled/DeadlineExceeded result at the pass boundary. This cannot preempt an OS call already blocked in the kernel and is not a claim that cold-publication stalls are solved.

Falsifiable regressions added:

  • graph_segment_pass_preserves_interruption_after_io: real segment file; cancellation and deadline become visible after the existing segment-open counter advances; requires refusal, empty output, exact interruption, two probes and one segment handle open. A fresh uninterrupted pass must recover exact bytes.
  • graph_segment_failed_read_preserves_post_io_deadline: successful exact read followed by real-file truncation; a deadline observed after the failing cached read must override the source failure, with empty output and no reopen.

Both target the previous missing post-I/O check. They are written, not yet executed: no passing/nonzero Rust test result is claimed. Existing between-read cancellation fixtures were adjusted to still interrupt between reads with the added post-I/O probe; their byte, error and open-count assertions remain intact.

The GitHub update was nonforce, expected-head checked against baab1cb. Only code_graph_manifest.rs changed; published branch history and peer edits were preserved. No competing PR created.

Validation: the exact commit diff was inspected. New-head hosted CI is https://github.com/ScriptedAlchemy/tracedecay/actions/runs/42443095332 (queued when checked). Native coverage is still none: the maintained workflow requires workflow_dispatch with run_os=true and exposes native_platform/native_targets, but this GitHub connector has no dispatch action. No workflow, runner or protection was modified to bypass that limitation. Local Bazel execution and the managed endpoint-scanned macOS reproduction are unavailable here. Independent review remains outstanding.

For the issue/sweep owners: retain this PR as the #4532 lane; coordinated distinct-page packed storage remains #4533. Keep #4532 open until hosted/nonzero/native validation, same-host publication/open-count measurements and all acceptance are proven on master. No merge, release or Kev/decision-model change.

Reuse the short-read-safe segment range reader for whole-file evidence
verification, and reject stale bytes after missing or mismatched paths.
Add real-filesystem recovery and refusal regression coverage.

Refs #4532
Record File::open attempts at the verified open boundary, excluding rejected
path metadata from endpoint-scanned publication telemetry. Regress invalid
file types and mismatched extents without changing durability checks.

Refs #4532

Copy link
Copy Markdown
Owner Author

Refs #4532 — published ffc7ef6 on the existing PR branch using an expected-head, nonforce update. The graph pass's segment_open_attempts telemetry now increments at the actual primary File::open call boundary, not when a pathname merely exists. Before this change, a directory or wrong-size segment counted as an open although no open was attempted. The real-filesystem regression now asserts zero counted opens for both refusal cases and retains the positive exact-byte/one-open case. No storage format, LRU bound, byte verification, deadlines, or publication budgets changed.

Gate status: previous head 36c47e5 passed Repository gates, but the remaining checks were cancelled by this newer push before nonzero Rust tests completed. CI for ffc7ef6 is queued; native=none. Do not merge this PR or close #4532 based on source review or CI gate formatting alone. Independent review, nonzero Bazel tests/Clippy, same-host 6.6k-file endpoint-scanned macOS before/after time and OS-level open counts, and full graph readiness are still unproven. Distinct first-open O(pages) remains #4533's packed-storage scope; no duplicate implementation or change to held draft #4776 / release #4763.

Apply the exact Bazel rustfmt output for the graph-open refusal assertion.

Refs #4532
Promote a pinned graph segment only after its read succeeds. Extend
real-filesystem eviction coverage to prove malformed cached requests
cannot evict a healthy handle or add an unnecessary open.

Refs #4532

Copy link
Copy Markdown
Owner Author

2026-11-08 current-head CI triage for 2fd183c4723f0321b1933080b643cf830bbb5ac7 — new merge blocker, not a graph-source regression. Refs #4532.

Hosted run 42451186352 has now passed Repository gates (Bazel formatting), Feature gates, Clippy, Dashboard and the focused //crates/tracedecay-store-runtime:unit_test target (Linux fleet log reports PASSED in 51.8s; no filter/zero-test-success assertion was substituted). The Linux fleet as a whole is red: //crates/tracedecay:automation_runner_test failed 3 scheduler/lock tests (backend_unconfigured where the fixtures expected scheduler skip/lock outcomes), and //crates/tracedecay:dashboard_api_test failed its self-improvement smoke due to an HTTP global timeout. The fleet recorded 181 of 183 test targets passed, with failures confined to those two unrelated automation/dashboard targets. They do not exercise the changed graph reader source; do not change #4532 code or weaken those tests to hide them. Linux/Windows split jobs are still pending, and native managed macOS is skipped in standard CI.

The targeted store-runtime unit-test success is meaningful hosted Bazel evidence, but it is not independent code review, the same-host Defender/CorpLink before/after graph-publication measurement, nor proof of the cold O(distinct pages) first-open reduction. That format cutover remains coordinated under #4533/#4792. Leave #4796 and #4532 open; no merge or auto-merge. No speculative push while platform CI is pending.

Repair three hosted automation_runner_test failures by supplying the
configured executable identity required by the production prefilter.
Use the same identity for the prefilter and retained runner, preserving
manual-schedule, exact-ledger, live-lock and lock-race assertions.

Add a production-prefilter regression for unconfigured refusal,
deduplication and same-occurrence recovery after binding, with zero
backend calls and no effectful terminal. Do not relax backend admission,
change timeouts, or alter the graph publication changes.

Refs #4532

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔍 Devin Review: 1 flag

Not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

ScriptedAlchemy commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner Author

Published 2ecbdf1d7645d9bca58fe589001b75c109cce7cc directly on this branch, with parent / expected head 2fd183c4723f0321b1933080b643cf830bbb5ac7, using a nonforce compare-and-swap update. Refs #4532.

Concrete CI repair

The three scheduler failures in the Linux fleet log are in //crates/tracedecay:automation_runner_test:

  • jobs::scheduler_trigger_skips_repeat_and_respects_lock_discipline
  • jobs::scheduler_prefilter_live_lock_wins_over_not_due_summary
  • jobs::retained_scheduler_runner_reacquires_after_due_prefilter

Their fixtures passed no backend executable, so the correct production backend_unconfigured guard ran before the scheduling and lock behavior they intended to exercise. The commit binds the existing test backend to a real temporary-file identity and uses that same identity for the prefilter and retained runner. The manual-schedule, exact-ledger deduplication, lock precedence, race/reacquisition and zero-backend-call assertions remain intact. No production guard was relaxed.

A new integration regression exercises the actual prefilter with an unconfigured backend, proves its refusal and diagnostic deduplication, then binds an identity and proves that the same due occurrence becomes admissible without cooldown, backend execution or an effectful terminal record.

Verification and remaining work

The published diff is limited to crates/tracedecay/tests/automation_runner_test/jobs.rs; existing graph fixes and peer commits are preserved. New-head CI run 42469054316 is queued. No local Rust execution occurred; passing tests are not claimed. Required checks include nonzero Bazel //crates/tracedecay:automation_runner_test and the existing graph store-runtime tests, formatting and Clippy.

Correction to the earlier CI summary: the other failure was //crates/tracedecay:dashboard_api_test, automation::final_self_improvement_smoke_covers_autonomous_curation_and_skill_deployment, timing out on the fact_store_curate POST to /api/application/retained/fact_store_curate. This commit does not claim to fix that timeout; no timeout or assertion was weakened. Native platform coverage remains unverified, and independent review plus the same-host endpoint-scanned graph publication measurements are still outstanding.

Coordination: the deterministic scheduler-fixture repair is now on this PR; no duplicate repair branch is needed. #4532 remains open and partial, including the coordinated #4533 storage work. No merge, release, infrastructure or protected Kev/decision-model action was taken.

The sealed proof reader checked interruption only before component I/O.
If an endpoint-scanned read failed after cancellation or deadline expiry,
it could report corruption instead of the observed interruption.

Clear stale output before each proof read, recheck after success or failure,
and retain the typed interruption without publishing a partial proof.
A real partitioned-seal regression corrupts the opened range during the
read, requires the late cancellation/deadline to win with a positive open,
then restores the disposable fixture and proves successful verification.

Refs #4532
Published segment fixtures may be read-only. Make only the disposable
fixture writable before intentionally truncating it during an opened
range read, so the late-interruption regression exercises the read and
not a permission error. Preserve the original expected outcomes.

Refs #4532
The real sealed-evidence interruption test calls the bundle verifier,
but its test module omitted that private helper import. Hosted Bazel
Clippy E0425 identified two unresolved calls. Restore the exact import
without touching graph logic, test assertions, or CI settings.

Refs #4532
Match the hosted Bazel Rust 2024 rustfmt output in the existing proof
regression module. No behavior or assertions change.

This branch has not been deployed

No deployments
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.

code-index: graph publication opens a segment file per page read and never finishes under endpoint scanning

1 participant