Repository navigation
requires none / requires opaque in both seeds; an absent requirements edge is undeclared, not none (D13 ruling B) - #12960
Conversation
… 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>
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
…5-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
…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>
|
Addressing review 73995 in 43da08e. The finding was correct and blocking: v1's Fix, construction over validation: v1 now refuses a SECOND — sent from sleek-boar-665 |
briansrls
left a comment
There was a problem hiding this comment.
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_edgehas exactly three declared target forms: a nonempty resource-reference Conj, the childless^requirements_declared_noneAtom, or the childless^requirements_opaqueAtom. 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
noneandopaquediscriminable 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
OperationRequiresDeclarationanswer (RequiresUndeclared | RequiresNone | RequiresOpaque | RequiresResources). The parser prevents the conflicting population rather than asking that reader to arbitrate it:requires none, R/requires opaque, Rrefuse, and any secondrequiresclause refuses before it can be carried. Thus neithernonenoropaquecan 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 noneto the audited vocabulary (Network today), preserving direct capability-derived Filesystem/Clock/Entropy demand rather than turningnoneinto 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.
…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>
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 getrequires none, and 12 runtime-argv exec ops getrequires opaque.#12911 said "no requirements has one form: the absent edge". This PR reverses that.
docs/plans/arrow-contract-edges.mdcarries a section on the reversal, and it scopesrequires noneas none of the audited vocabulary (Network today), which is not a Filesystem/Clock/Entropy claim.What
requires noneandrequires opaqueare their own productions underop_requires, because a literal terminal stamps its class, not its word. They are whole clauses: a member after either refuses.^requirements_declared_noneand^requirements_opaque.v2.std.arrow_contractadmits exactly the three target shapes. Resolve walks only the member Conj and carries the Atoms unwalked.parse_op_requires_clausecarries each word as ONErequiresproperty whose value is the word as a string literal (matched by text, sincenoneis 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 secondrequiresclause on one operation refuses at parse (review 73995).operation_requires_membersbecomes the closedoperation_requires_declaration = RequiresUndeclared | RequiresNone | RequiresOpaque | RequiresResources { members }, the answer D13 step (c) consumes.compile_dag_operation_requiresreports 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):requires none, Nrefuses;v1 (
test.claim.v1_operation_requires_parse_witness_test):requires none, Netrefuses;resources, ...🤖 Generated with Claude Code