Skip to content

requires none / requires opaque in both seeds; an absent requirements edge is undeclared, not none (D13 ruling B) - #12960

Merged
gunbai-bot[bot] merged 49 commits into
mainfrom
session/sleek-boar-665-requires-none-opaque
Oct 2, 2026
Merged

gunbai-bot[bot] merged 49 commits into
mainfrom
session/sleek-boar-665-requires-none-opaque

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #12911 (v2 requires edge) and #12937 (v1 requires parse), both in the merge queue. Until they land this diff contains their commits.

Why

D13 step (b) derives a function's demand from the operations it calls. With #12911's reading (absent edge = "no requirements"), every unaudited operation, and every one added later, silently reads as requiring nothing. That is the fail-open default DESIGN §5 forbids. The lane owner ruled B: every operation declares one of three forms, all on the one ^arrow_resource_requirements_edge, and an absent edge is undeclared, which step (b) reads as Undecided. The Network audit (loyal-crab-214) writes the rows: 236 NotNetwork ops get requires none, and 12 runtime-argv exec ops get requires opaque.

⚠️ Reversal of #12911, stated for deliberate review

#12911 said "no requirements has one form: the absent edge". This PR reverses that. docs/plans/arrow-contract-edges.md carries a section on the reversal, and it scopes requires none as none of the audited vocabulary (Network today), which is not a Filesystem/Clock/Entropy claim.

What

  • v2 grammar: requires none and requires opaque are their own productions under op_requires, because a literal terminal stamps its class, not its word. They are whole clauses: a member after either refuses.
  • v2 lowering: both lower onto the same edge as childless Atoms, ^requirements_declared_none and ^requirements_opaque. v2.std.arrow_contract admits exactly the three target shapes. Resolve walks only the member Conj and carries the Atoms unwalked.
  • v1 parse: parse_op_requires_clause carries each word as ONE requires property whose value is the word as a string literal (matched by text, since none is a v1 keyword literal). It is the same property a resource member uses, and the reader tells the forms apart by the value's shape, because a property's name is read back from its span. A second requires clause on one operation refuses at parse (review 73995).
  • v1 reader: operation_requires_members becomes the closed operation_requires_declaration = RequiresUndeclared | RequiresNone | RequiresOpaque | RequiresResources { members }, the answer D13 step (c) consumes. compile_dag_operation_requires reports the arm first (undeclared / none / opaque / resources, ..). The seed mirror is regenerated (claim_executor --required-regen).

Controls

v2 (v2.test.claim.normalize.operation_requires_edge):

  • none and opaque lower to their Atoms;
  • requires none, N refuses;
  • the fidelity claims.

v1 (test.claim.v1_operation_requires_parse_witness_test):

  • none and opaque are carried as their own forms;
  • an operation without a clause is undeclared, not none;
  • requires none, Net refuses;
  • the member forms now report resources, ...

🤖 Generated with Claude Code

gunbc-ci-auto-heal and others added 30 commits October 1, 2026 01:24
… claim), closed and not binders

XL-2 PR2a under the 2026-10-01 side-chat ruling (option A). An Arrow may carry
^arrow_effect_claims_edge (readonly / idempotent) and ^arrow_execution_mode_claim_edge
(hermetic), each at most once and each a closed vocabulary arrow_signature_edges_conform
enumerates. Neither counts as the type-binder edge. Duplicates, unknown labels and
hermetic among the effect claims refuse. Identity is order-independent. No producer
emits them yet: lowering and the pipeline readers' metadata arms land together in PR2c
(docs/plans/arrow-contract-edges.md).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…er: PR2c lands)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… only; no empty claims edge

- review 73521: the claim words are no longer literals in v2.std.node. std.effects gains
  EffectClaim (ReadonlyClaim | IdempotentClaim); hermetic is std.execution_mode Hermetic.
  New v2.std.arrow_contract holds the only spellings as exhaustive projections from those
  types and checks each contract edge's target; v2.std.type_binder runs it on every Arrow
  and reads node's arrow_named_edge_is_non_binder instead of its own allowlist. The
  label-to-variant inverse is a declared bounded residue (no constructor enumeration yet).
- GitHub review 5374647982: an effect-claims edge must hold at least one claim, so "no
  claims" has one form (the absent edge). Reds added for an empty claims edge and an empty
  mode edge; every test checks both walls.
- std_effects.rs stage0 mirror regenerated (required-regen fixed point, round 2).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s dead Wet/Record arms

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ded variant, no std presence predicate

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…13-pr2

# Conflicts:
#	src/v2/std/type_binder.dag
…ath a declared resource (D13 step a0)

Stacked on #12863. Grammar productions for std.resources' `resource` form, with
every entry read or refused at the entry (v1 skips acquire/release bodies).
Capabilities lower through the operation reader; kind/mode/expires/acquire are
read against std.resources ResourceKind/ResourceMode and std.execution_mode into
a DeclaredResourceContract on a new DeclaredTypeKind arm, captured at normalize.
SymbolIndex gains declared_resources, filled from the captured resource names.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eads as an alias)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… compiler closure does not pull std.resources' imports

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ndex mark's consumer and the contract gap

- DeclaredResource carries only { name }. kind/mode/expires/acquire are still read
  against their homes and refuse at the entry, but no consumer reads them yet, so
  they are not carried. That gap is declared as gunbc.recurring_failure_mode
  resource_contract_validated_but_not_carried, with the trigger: the first consumer
  of those facts lands and carries the contract.
- SymbolIndex declared_resources names its production consumer as a declared
  frontier: D13 step (a)'s resolve check on a `requires` member, with deletion if
  step (a) is abandoned.
- The two claims over the eval-step budget now read smaller fixtures: one for the
  census (a resource with one capability beside a record) and one for the full door
  (every property entry, no capability).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…not as a malformed entry

GitHub review 5378770924: a capability reads input/output blocks through the shared
io grammar, which admits `from "key"` and `= expr` tails; body_lower_operation sets
them aside, and the capability arm wrapped that in the generic resource_entry_unread
at the whole capability. It now refuses with the owned fatal cause services use,
service_realization_unreachable, at the capability, with interface_member_unmodeled
pending at each tail. resource_entry_unread is reached only by a malformed entry.
Controls for both tail forms; main merged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ments_edge; resolve checks each member is a declared resource (D13 step a)

Stacked on #12898. Grammar `requires` member on operations; lowering to a nonempty
Conj on the operation Arrow (absent when not declared, so a requirement-free Arrow
is unchanged). v2.std.node: third contract edge, at most one. Readers, for all three
contract edges (first producer, per eager-heron-413): infer and type_binder skip
them as metadata; resolve carries the claim edges unwalked and walks the
requirements edge in the Arrow's type scope, refusing a member that is not a
declared resource (symbol_index_declares_resource_at, its first production reader)
or that repeats one. Single-module resolve now marks the tree's own resources.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rrow_resource_requirements

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d_list left the element generic)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…5-requires-edge

# Conflicts:
#	src/v2/compiler/03_resolve.dag
#	src/v2/std/symbol_index.dag
…-name spine, not by re-searching the parse

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…5-requires-edge

# Conflicts:
#	src/v2/compiler/04_infer.dag
…ion runs once, in the lowering

The normalize capture re-ran body_lower_resource_read, which validates every entry
the lowering had already decided, to obtain only the name (DESIGN section 2:
duplicated work). A refused declaration refuses its module, so no captured name
outlives one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, so each annotation attaches to its own declaration (review 73765)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…lies members at that interface (DESIGN 3 witness rule)

The end-to-end RED re-ran normalize and resolve for one decision and sat over the
new-witness eval-step budget (78,096 vs 72,300). resolve_requirement_member_refusal_optional
reads only the index from the context, so it now takes the index; the RED and a
discriminating control supply resolved members at that interface, and the full
route stays exercised by the resolving positive and the not-a-resource RED.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e family; step (b) named as the requirements edge's demand consumer, with trigger and abandonment disposition

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… a frontier note this change replaced

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… as a requires property (D13 step b0)

The seed compiles the corpus, so it must parse the member v2 already admits
(dag_grammar_op_requires_expr) before any extdeps operation can declare the
resources it reaches. Carried only: one `requires` property per member, whose
value is the parsed type expression; every v1 consumer of operation properties
selects by name or prefix, so no other v1 behaviour reads it. Controls compile
through the real seed route: one and two members compile; a non-type member and
an empty requires refuse. Generated stage0 regeneration follows from CI's recipe.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 15 commits October 1, 2026 19:06
claim_executor --required-regen (candidate written to target/stage0-regen-candidate;
the only drifted mirror is v1_compiler_parse.rs).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…terface; drop the full-route positive that sat at the new-witness budget

72,309 of 72,300 eval steps on the composed revision (merge-group run 36906065859):
its cost is fixed normalize+resolve overhead, not fixture size. The real route
stays exercised end to end by the not-a-resource RED; the positive verdict is the
decision-interface control over the census index.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e }, paired with the same op without it compiling clean

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… consumer) and a seed query exposing it; carry controls

Gap 2 of the #12937 review: acceptance does not show the members are carried.
v1.compiler.parse operation_requires_members is the one reader of an
operation's parsed requires members, in order; its production consumer is D13
step (c). compile_dag_operation_requires parses one source with the seed's own
parser and returns the members through that reader; a parse error or missing
service/operation refuses. Controls: one member, two in order, none. Seed-growth
justification and primitive egress disposition rows filed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…the surface roster projects them

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s from src/v1 (claim_executor --required-regen)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es' into session/sleek-boar-665-requires-none-opaque
… edge is undeclared, not none (D13 ruling B; reverses #12911)

v2: the two words are their own productions under op_requires and lower onto the
one ^arrow_resource_requirements_edge as childless Atoms (^requirements_declared_none,
^requirements_opaque); arrow_contract admits the three target shapes; resolve walks
only the member Conj. v1: parse_op_requires_clause carries the words as whole
clauses (a member after either refuses), and the reader becomes the closed
operation_requires_declaration = RequiresUndeclared | RequiresNone | RequiresOpaque
| RequiresResources, which compile_dag_operation_requires reports. The doc states
the reversal and scopes none to the audited vocabulary (Network today). Controls in
both seeds.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ust emitter projects no filter in an if condition)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…m_executor --required-regen)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…(a property's name reads back from its span), and the record RED moves to the resolve boundary

v1: 'requires none' / 'requires opaque' are the one requires property whose value
is the word as a string literal; field_init_node_name_at reads a name back from the
source at its span, so differently named markers spanned on the requires token read
as 'requires'. The reader tells the forms apart by the value's shape.
v2: the whole-module record RED rose to 72,394 of 72,300; per the lane ruling the
real route is kept and its boundary moved. Lowering stays held on source text by
the census claim; resolution of the edge is held by resolve_node over an operation
Arrow of that shape and a filled index, as a RED/control pair differing only in
whether T is a marked resource.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…5-requires-none-opaque

# Conflicts:
#	docs/plans/arrow-contract-edges.md
#	src/v2/compiler/03_resolve.dag
#	src/v2/compiler/body_lowering_fold.dag
#	src/v2/extdeps/languages/dag.dag
#	src/v2/std/arrow_contract.dag
#	src/v2/test/claim/normalize/operation_requires_edge_test.dag
gunbc-ci-auto-heal and others added 4 commits October 2, 2026 00:16
…5-requires-none-opaque

# Conflicts:
#	dag/gunbc/operation_requires_query_seed_growth.dag
#	dag/gunbc/primitive_egress/dispositions_seed_query.dag
#	dag/test/claim/v1_operation_requires_parse_witness_test.dag
#	src/v1/02_parse.dag
#	src/v1/stage0/src/cli_run/emit_host.rs
#	src/v1/stage0/src/v1_compiler_parse.rs
…ed-name spine, so the index fill reads its path

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…arse (review 73995)

Two clauses (requires none + requires Filesystem) were both carried and the reader
answered none, discarding the declared demand. v2 already refuses the repeat at
lowering; v1 now refuses it at parse, so the conflicting state cannot be carried.
Controls: a second clause after none, and after opaque, refuses.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Addressing review 73995 in 43da08e. The finding was correct and blocking: v1's parse_op_body_entries accepted any number of requires entries, and operation_requires_declaration merged their members. So requires none plus a separate requires Filesystem read as RequiresNone, discarding the declared demand (and opaque plus Network read as RequiresOpaque). v2 already refused the repeat at lowering (body_lowering_reason_operation_requires_repeated), so the two seeds disagreed.

Fix, construction over validation: v1 now refuses a SECOND requires clause at parse, so the conflicting state can never be carried, and the reader never sees two clauses to arbitrate. The comment at the clause parser now states both rules: one clause per operation, and a member after a whole-clause word refuses. New REDs in test.claim.v1_operation_requires_parse_witness_test: a_second_requires_clause_after_none_refuses and a_second_requires_clause_after_opaque_refuses. The single-clause positives are unchanged, so each RED differs only by the second clause. The seed mirror is regenerated.

— sent from sleek-boar-665

@briansrls briansrls 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.

APPROVE-MERGE at exact head 43da08efcbdb2905c8faff99d42767ab17819230.

No findings.

The deliberate #12911 reversal is modeled coherently and fail-closed in both seeds:

  • The one ^arrow_resource_requirements_edge has exactly three declared target forms: a nonempty resource-reference Conj, the childless ^requirements_declared_none Atom, or the childless ^requirements_opaque Atom. An absent edge is not reinterpreted as an empty target; it remains the distinguishable undeclared state that D13 step (b) must map to DemandUndecided.
  • v2 gives none and opaque discriminable productions ahead of the general type-list arm. Lowering projects all three source forms onto the same edge, the contract wall admits only the two exact childless markers or a nonempty Conj, and resolve walks only the Conj while carrying the prevalidated marker Atoms unwalked.
  • v1 exposes one closed OperationRequiresDeclaration answer (RequiresUndeclared | RequiresNone | RequiresOpaque | RequiresResources). The parser prevents the conflicting population rather than asking that reader to arbitrate it: requires none, R / requires opaque, R refuse, and any second requires clause refuses before it can be carried. Thus neither none nor opaque can silently dominate a separately declared resource demand.
  • The seed query now reports the arm before any resources, so the controls distinguish undeclared, declared-none, opaque, and ordered resources rather than conflating absence with an empty list. The generated stage0 mirror moves with the source.
  • The committed design explicitly scopes requires none to the audited vocabulary (Network today), preserving direct capability-derived Filesystem/Clock/Entropy demand rather than turning none into a universal effect assertion.

The approved #12911 and #12937 exact heads are ancestors of this head, and the later changes preserve their boundary evidence while adding the closed declaration forms and the one-clause construction wall.

Ordering remains binding: D13 step (b) must not land until #12965's Network population and the 236 requires none / 12 requires opaque rows are complete. This PR makes absence fail-closed; it does not itself complete that population.

Non-blocking PR-description note: the v1 implementation no longer uses separately named requires_none / requires_opaque properties. It carries one requires property whose value identifies the word, then the closed reader decodes it. Updating that bullet would make the PR body match the landed representation.

Exact-head floor, generated, emit-build, and witnesses pass. Merge-queue landing only: the actual merge_group candidate must pass against then-current main; no direct merge or check bypass.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit 56d6eb1 Oct 2, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/sleek-boar-665-requires-none-opaque branch October 2, 2026 03:47
gunbai-bot Bot pushed a commit that referenced this pull request Oct 2, 2026
…: #12960's requirements-edge claim builds and reads the core ArrowResourceRequirementsEdge; its member labels are Authored

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Oct 2, 2026
…declarer

std.resources (#12960) made the bare read ambiguous; the module calls Filesystem.Write, the
extdeps.filesystem.filesystem_io service.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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