Skip to content

Reject repository prefix collisions without blocking registry access - #1164

Merged
zzet merged 381 commits into
mainfrom
fix/repository-prefix-ownership
Nov 1, 2026
Merged

zzet merged 381 commits into
mainfrom
fix/repository-prefix-ownership

Conversation

@zzet

@zzet zzet commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Tracking a repository with an occupied prefix could block registry access on filesystem checks, misidentify the loaded owner, or let a failed promotion remove another registration's corpus. Observe only the relevant root identities outside the locks, use one bounded deadline, and validate the same owner again before registration, publication or cleanup.

The controller rejects known collisions before waiting on its track lock. Warmup records typed collision skips without publishing changes for the owner's prefix. MCP retains completed track outcomes for ten minutes and returns structured collision details on follow-up requests. Probe, CLI and hook guidance preserve the owner and distinguish unresolved identity from a proven collision. Existing same-directory no-ops remain supported.

The refreshed source includes the exact startup integration from #1162 and its dispatch, edit, compaction and scoped-read coverage dependencies. Both merges applied cleanly. The prior hook resolution retains collision guidance and tracked-name fallback; the MCP deadline fixture compares decoded paths and asserts that preflight rejection stores no track job under the actual request key. No obsolete production indexing API is restored.

Validation at clean integration head 5bc6ea6c6 passed 639 parent race tests with zero failures or skips: 149 selected controls, 201 config tests and 289 daemon tests. The race selection includes the ownership/publication and dynamic capability guards. Repository-wide pinned uncapped lint reported zero issues; formatting, diff, CGO, native vet, workflow-layout and module-tidy checks passed. The original 94-control run and earlier hosted evidence remain attributed to their original source. Exact-head hosted CI remains pending; no performance acceptance is claimed.

Refs #1025; land after #1162. Code may land while the isolated native runtime fixture and the six-runs-per-side ARM64 reconcile, warmup and save comparisons remain open. Those measurements are still required for issue acceptance; this PR does not close #1025 or #831.

zzet added 28 commits October 28, 2026 14:39
zzet added 7 commits October 31, 2026 22:05
…anding

The restart cell read its edit's receipt status once after the ACK and
required it to be pending. On the normal path the ACK itself waits (up to
three seconds) for that receipt, so the status read after it almost always
found it terminal and the cell failed as "receipt terminal before kill"
instead of measuring a kill with a receipt pending.

The cell now sends the edit and, while the ACK is outstanding, polls the
edit's status by its mutation_id every 5 ms. Once the bytes are committed and
the graph receipt is not yet terminal, the harness stops waiting for the ACK
and kills the daemon. The record's ACK time is unavailable, the receipt comes
from the committed status, and the abandoned call is counted censored rather
than as a workload error. An ACK that returns first still leaves one status
read just before the kill to decide, so a terminal receipt keeps qualifying
the record. The stub now holds the ACK the way a daemon waiting on its
receipt does, and the test checks the kill happened with the ACK outstanding.
… completes

A create/delete pair's delete step starts its probes at its own scheduled
activation, but it is sent only after the paired create has every probe
first-correct. Its search, text and caller oracles are absence-shaped, so
while the created file is not yet visible they answer "correct". With the
delete not yet started, each such answer was recorded as "marker visible
before its own edit" and a valid delete became a diagnostic failure whenever
its Poisson gap was shorter than the create's visibility time.

The delete's state now records when its dependency was met, and a correct
answer to a probe sent before that is not applicable to it. A correct
absence answer after the dependency but before the delete itself still
fails the record. A test activates the delete while the create's file does
not exist yet.
Every edit.write request carries whole-file content precomputed in ordinal
order. With several editors, and always in hot_file pairs that share a due
time, two writes can land out of order: the earlier ordinal's content then
drops the later ordinal's marker, and the next ordinal's write puts it back.
The dropped record could still complete, with a first-correct time borrowed
from someone else's write, while the README claimed such lost writes were
measured as failed records.

Several-editor plans now refuse edit.write, and hot_file accepts only
edit.file. edit.batch stays allowed: its old_string precondition makes an
out-of-order write fail visibly, and edit.file anchor insertions do not
depend on order. The README now says this instead of the earlier claim.
The summary ranked only the values it observed. A record that hit the
deadline (or the run end, or failed) before an oracle answered correctly was
dropped from that measure's ranking, so p95/p99 for file-graph, relations,
search and readback came out low exactly in the high-load cells, and the
relations p95 feeding the file-graph lane go/no-go would be understated. The
"missing" count also mixed those records with values that do not apply, such
as a native write's ACK or a coalesced receipt's derived time.

A value missing from a record that did not complete is now censored: it
joins the ranking as +Inf, and a quantile or bootstrap bound whose nearest
rank falls among censored records is unavailable. A value missing from a
completed record, or a measure the record does not carry, is counted as not
applicable. The read table does the same for reads cut off by their deadline
or the run end. The schema goldens replace "missing" with "censored" and
"not_applicable".
… pending

A pure read was classed under_edit while any edit's whole completion loop
was running: the ACK, the readbacks and the long wait for every probe to
become first-correct, up to the edit deadline. That is not the "reads issued
while receipts are pending" the measurement defines, it diluted the writer
and WAL contention the comparison is meant to isolate, and it disagreed with
the per-record pending-read count in the same report.

A sent edit now counts as pending from its send until the harness first
observes its receipt terminal (single receipt, batch transaction or move
reconcile), or until its loop ends without that, as for a failed edit or a
native write, which has no receipt. A test turns the receipt terminal while
the edit still waits for its probes and checks that reads issued then are
between edits.
@zzet
zzet changed the base branch from fix/startup-repo-loading-recovery to main November 1, 2026 09:34
zzet added 19 commits November 1, 2026 11:05
# Conflicts:
#	bench/load/plan.go
#	bench/load/run.go
#	bench/load/scenario.go
#	bench/load/schema.go
# Conflicts:
#	internal/daemon/mcp_request_lifetime.go
#	internal/mcp/batch_transaction.go
#	internal/mcp/edit_serialization.go
* commit '553ed1990e84e74ed44d647500bd230a17d0001c': (277 commits)
  fix(load): snapshot native file identity before replacement
  test(mcp): request full output for deletion measurement evidence
  fix(load): accept native write evidence in edit-probe phase validation
  test(load): decode restart receipt status before checking its fields
  fix(load): count reads under edit only while a sent edit's receipt is pending
  fix(load): rank censored edit records above observed values in quantiles
  fix(load): refuse whole-file edit.write with several editors
  fix(load): ignore a native delete's absence answers before its create completes
  fix(load): kill the restart cell's daemon while its edit ACK is outstanding
  fix(load): take the closing receipt on the restart cell's reopened editor
  docs(load): document live refusals, native writes and lifecycle cells
  feat(load): measure a daemon kill and restart with an acknowledged receipt pending
  feat(load): add native create/delete pairs and a two-editor hot-file sender
  feat(load): add native shell-write and editor-save senders with their own write windows
  feat(load): measure explicit TypeScript and Python relocation refusals live
  docs(load): describe compact, CLI and unavailable GCX accounting
  feat(load): probe through the CLI call verb as its own transport
  feat(load): decode compact text answers for presence-proved call additions
  test(mcp): pin the actual compact text producers used by edit probes
  feat(load): account GCX as an explicitly unavailable output mode
  ...
* commit '553ed1990e84e74ed44d647500bd230a17d0001c': (397 commits)
  fix(load): snapshot native file identity before replacement
  test(mcp): request full output for deletion measurement evidence
  fix(perf): explicitly enable cgo for performance artifacts
  fix(load): accept native write evidence in edit-probe phase validation
  fix(mcp): pass a compatible exact-name fallback to session resolution
  fix(bench): keep PR performance smoke report-only
  test(load): decode restart receipt status before checking its fields
  test(mcp): count scoped file location rows in the shared reader
  fix(mcp): scope bare-name targets for callers and why
  test(mcp): pin bound-session shorthand to the session's repositories
  perf(mcp): resolve bound-session symbol shorthand per repository
  test(mcp): stop claiming the golden test compares dynamic boundaries
  test(mcp): count symbol index rows in the scoped search_symbols test
  test(mcp): show the name-only equality test takes the narrowed read
  docs(sqlite): say what the repo-scoped incoming read still visits
  perf(sqlite): probe a call site's named repositories before the empty prefix
  perf(query): narrow name-only placeholder reads only for a few repositories
  test(sqlite): fence the repo-scoped incoming read by generation
  test(mcp): count smart_context graph rows, not only retrieval rows
  test(mcp): pin repo-scoped search_symbols reads as repositories are added
  ...
…very

* commit '386b2e834b81ca09e7977295a54afc4a2de4f6fd': (396 commits)
  fix(load): snapshot native file identity before replacement
  test(mcp): request full output for deletion measurement evidence
  fix(perf): explicitly enable cgo for performance artifacts
  fix(load): accept native write evidence in edit-probe phase validation
  fix(mcp): pass a compatible exact-name fallback to session resolution
  fix(bench): keep PR performance smoke report-only
  test(load): decode restart receipt status before checking its fields
  test(mcp): count scoped file location rows in the shared reader
  fix(mcp): scope bare-name targets for callers and why
  test(mcp): pin bound-session shorthand to the session's repositories
  perf(mcp): resolve bound-session symbol shorthand per repository
  test(mcp): stop claiming the golden test compares dynamic boundaries
  test(mcp): count symbol index rows in the scoped search_symbols test
  test(mcp): show the name-only equality test takes the narrowed read
  docs(sqlite): say what the repo-scoped incoming read still visits
  perf(sqlite): probe a call site's named repositories before the empty prefix
  perf(query): narrow name-only placeholder reads only for a few repositories
  test(sqlite): fence the repo-scoped incoming read by generation
  test(mcp): count smart_context graph rows, not only retrieval rows
  test(mcp): pin repo-scoped search_symbols reads as repositories are added
  ...

# Conflicts:
#	bench/load/run.go
* commit '386b2e834b81ca09e7977295a54afc4a2de4f6fd':
  test: join completed-request relay before transport cleanup
  test: observe anonymous Linux vacuum files by their actual descriptor
  test: document intentional nil-context vacuum rejection
  test: exceed the real vacuum cache before observing temp spill
  test: compare physical vacuum directories across path aliases
  fix: defer boot compaction after a supported schema rebuild
  fix: defer owned boot compaction until enrichment completes
  test: cover live vacuum cancellation and cross-store scratch ownership
  fix: isolate cancelable compaction on a file-temp connection
* commit 'df40f3621dc72f70dcee08555b4c5389fbcd6600':
  test(mcp): compare scoped unwrapped handler payloads to Go oracle
  test(mcp): count whole-edge reads in scoped file search
@zzet
zzet marked this pull request as ready for review November 1, 2026 14:27
@zzet
zzet merged commit 514ef80 into main Nov 1, 2026
29 of 30 checks passed
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.

Reject a second repository whose folder name is already tracked, on every path (land #954)

1 participant