Skip to content

Trace the emitted span-index consumer, THEN rule: cli_run.rs mints an OccurrenceId from a SourceSpan byte offset, a named-forbidden identity input - #9615

Merged
briansrls merged 6 commits into
mainfrom
session/nimble-ram-815
Aug 28, 2026
Merged

briansrls merged 6 commits into
mainfrom
session/nimble-ram-815

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

Auto-opened by session-dashboard for session nimble-ram-815.
Pushing to session/nimble-ram-815 advances this PR.

Worker attestation

Before flipping this PR to ready for review, confirm each item:

  • Title describes the change (not the session id or branch).
  • PR body summarises what and why (replace the TODO below).
  • Tests run: name the command (e.g. npm test, cargo test) and the result.
  • If this closes a work item, the body contains a Closes #N directive.
  • No commits on this branch are surprises (no fork/cherry-pick I did not make).
  • No secrets / credentials / large binaries staged.

Summary

TODO: replace this paragraph with one or two sentences naming the change and its motivation. Reviewers read this first.

Test plan

  • TODO: list the commands that ran (or "no tests changed; relied on CI") and the outcome.

Brian Searls and others added 6 commits August 27, 2026 20:54
… manifest

std.occurrence_identity's acceptance law names SourceSpan a FORBIDDEN identity
input: an OccurrenceId is unique only inside one graph-scoped
OccurrenceIdAllocator. cli_run's emit_module_binding_span_index minted
`OccurrenceId { value: ident_span.start.max(1) }` and recorded the module
declaration's byte range against it. No allocator ran; a byte offset is not an
allocation, and every file's module declaration sits at a near-identical offset,
so the values collide across rows by construction.

Traced the consumer first. Every reader of a ParsedFromSource provenance
discards the field by pattern (`span_index: _` in
v2.compiler.source_authority.module_storage_binding_file_path and at three sites
in gunbc.commit_workflow); the witnesses over host_module_bindings
(v2.test.long.module_binding_host_consistency) join on module identity and
storage path only. The sole span_index_lookup consumers --
v2.lens.identity_captured_navigation.analyze and the provenance tests -- read
artifacts from v2.compiler.parse's stamp pipeline, never this manifest. So the
fabricated identity was unread: DESIGN.md §5's fabricated plausible output
standing where an honest "no occurrences were allocated" was available, and §4b
decoration -- nothing could ever refuse it.

Rows now carry span_index_empty(). This is the delete-first cut (§3): if a
consumer of these rows' provenance appears, it needs REAL stamps and refuses
loudly rather than navigating an offset that happens to be an integer. That
restoration is the follow-on already named in module_storage_host_parse_note --
v1 bootstrap parse stamping NodeOccurrenceId the way parse_production_prepared
does. The .dag note that sanctioned the offset keying as "deterministic and
sufficient" is corrected in the same change; leaving it would keep the authority
asserting a forbidden input is fine.

Also drops ModuleBindingManifestRow.ident_span (dead with the mint) and the
manifest's now-unlisted imports (MintedOccurrence, FromSource, ByteRange,
Textual, span_index_record) -- an unreferenced import is an error in the
emitted module.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…arseable symbol

Two defects on one emitter path. The second was found only because repairing
the first let the artifact reach a parser for the first time.

1. A FORBIDDEN IDENTITY INPUT, WRITE-ONLY.

emit_module_binding_span_index derived an OccurrenceId from the ident span's
byte offset (`start.max(1)`). std.occurrence_identity occurrence_identity_scope_law
names SourceSpan a FORBIDDEN identity input, and the derivation collided besides:
offsets 0 and 1 both produced 1.

Traced to its consumers the value was write-only, which is why it stood. Each row
built its own span_index_empty() and recorded one entry, so the collision could not
manifest within a row; span_index_merge's only production caller is
v2.compiler.02_parse over parser-ALLOCATED ids; span_index_lookup has only test
callers; and the one executing consumer, the module-binding supply gate, compares
(file_path -> module) and discards the field by pattern in
v2.compiler.source_authority module_storage_binding_file_path.

So this was not a defect with a victim -- it was a forbidden input written into a
committed artifact whose innocence rested on no consumer ever reading it, which is
correctness-by-construction inverted and one consumer away from real.

The locus goes with it. SpanIndex.entries is a Map<OccurrenceId, OriginEvent>, so a
producer holding a locus but no allocator identity cannot record the locus without
INVENTING the key -- the carrier makes the honest state representable only as empty.
Emitting empty is that state. The carrier gap is named at the site rather than
papered over with an invented key.

2. AN INCOMPLETE SYMBOL MINT, WHOSE MISSING CASE THE CORPUS ALREADY CONTAINED.

source_root_ingest_symbol_from_stem escaped non-identifier characters and a leading
digit, and stopped. A stem that IS a keyword still lexes as one, so dag/std/import.dag
emitted `^import` and the manifest did not parse:

  expected identifier or `(` after `^`, found keyword

Two stems in the tree reach it: dag/std/import.dag and
dag/extdeps/languages/go/module.dag. The mint promised a valid symbol and returned an
unparseable one with no refusal; the emitter succeeded and wrote the file, and the only
executing consumer is a long/ ReadsLiveTree witness the floor declines -- so nothing
looked.

The keyword test routes through v1_compiler_tokenize is_keyword_text, whose set is
derived from the grammar. A literal list at the mint would be a second authority for
the keyword vocabulary (§3) and would go stale on the next grammar keyword.

MEASURED, by emitting a real 2869-row manifest into a swept root:

  before  ^import     -> parse refuses at the caret
  after   ^sr_import  -> the caret parses

Also drops ModuleBindingManifestRow.ident_span, now written and never read, and the
MintedOccurrence / ByteRange / Textual / FromSource / span_index_record imports the
emitted module no longer uses. The MintedOccurrence drop decrements the population
v2.std.node node_occurrence_id_v2_facade_dissolve_on is waiting on.

NOT CLAIMED: at 2869 rows the emitted manifest then overflows v1_src_dag_parse's
stack on its 2869-deep right-nested Cons. That is pre-existing, untouched here, and
I have ONE data point rather than a threshold -- the smaller-root runs emitted no
manifest at all, so they are not evidence about depth. Reported separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013crMNyLvjKC2Q5UF851PKy
…d-occurrence-id

snappy-dove-250 repaired the same emitter in-session while this branch was in
review -- a duplicate repair, invisible to every gate because each side is
individually correct. Their cli_run.rs is taken WHOLESALE: it is a strict
superset, adding the second defect (source_root_ingest_symbol_from_stem minting
an unparseable `^import` for a keyword file stem, routed through
v1_compiler_tokenize is_keyword_text rather than a literal keyword list), and its
account of why the repair is EMPTY rather than a better id is the better one --
SpanIndex.entries is keyed BY OccurrenceId, so a producer with a locus but no
allocator identity cannot record the locus without inventing the key.

What this branch keeps is the half their commit does not touch:
v2.compiler.source_authority's annotation, which SANCTIONED the offset keying as
"deterministic and sufficient for binding-authority consumers" and stated that
host emission "records ident_span byte ranges in span_index via
span_index_record". Both sentences are false under either repair, and left
standing they keep the canonical authority asserting that a forbidden identity
input is fine -- the defect one level up from the code. The note is restated
against the carrier argument above.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two conflicts, both where main touched the same emitter this branch repairs.

cli_run.rs -- main landed the v2 NodeOccurrenceId facade cut, which re-spelled
this mint as a fully-qualified std.occurrence_identity.OccurrenceId and dropped
the MintedOccurrence wrapper. That is a correct repair of a DIFFERENT defect
(payload-for-carrier) on the same line, and it leaves the byte-offset derivation
standing. This branch deletes the derivation, so its side is taken: there is no
construction left to qualify. Main's import-list trim is subsumed by the wider
trim here.

source_authority.dag -- main renamed NodeOccurrenceId to NodeOccurrenceIdentity
inside module_storage_host_parse_note while this branch rewrote a different
clause of the same string. Composed rather than chosen: main's rename is kept and
this branch's clause ("emission records NO spans -- it emits span_index_empty()")
replaces the stale one, so neither edit is lost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings the three main-side causes this branch was failing on, all closed on main:
  gunbc#9535 the barren test sidecar (BarrenTestSidecar)
  gunbc#9541 the 53 stale namespace-transition admissions
  gunbc#9551 restore the four emit mirrors to what the closure emits (regen drift)
The branch was behind main and inherited all three; the merge is clean and carries
no content change of its own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013crMNyLvjKC2Q5UF851PKy
@briansrls
briansrls marked this pull request as ready for review August 28, 2026 23:18
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-08-28T23:24:07.816268Z 98a02b1 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Not yours — and the build lane already agrees.

required-witnesses-build passes on this branch; only required-witnesses-floor fails, and it fails on main's blocking .dag diagnostics rather than on anything in this diff. The two required lanes carry no needs edge and fail independently, so a floor-only red is a strong signal the cause is upstream.

The run behind the notice (33197503187) was created at 18:02:53Z — over five hours before main's current head, and before three separate main repairs landed. So its verdict describes a main that no longer exists.

A rerun will not clear it: refs/pull/N/merge fixes its base when the ref is created and does not recompute when main moves, so a rerun replays the same stale base. This needs a push after main is green, not a fix.

Eight of the thirteen blocking diagnostics have merged since that run (#9646, #9650); the remainder are individually owned.

— sent from warm-hawk-909

@briansrls
briansrls merged commit 0fd1dd7 into main Aug 28, 2026
2 of 6 checks passed
@briansrls
briansrls deleted the session/nimble-ram-815 branch August 28, 2026 23:22
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.

1 participant