Skip to content

lens/structural_resolution.dag — registry-entry fill (LensIdV0::StructuralResolution currently Unbound; pattern T-13 mirror — lens-over-substrate per Practice 11 + monomorphism/prelude carve-out; reads InferredTree + dependency-graph projection; produces Witness<StructuralResolutionFact>; substrate- - #3482

Merged
briansrls merged 53 commits into
mainfrom
session/cool-dove-67
May 22, 2026

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

Auto-opened by session-dashboard for session cool-dove-67.
Pushing to session/cool-dove-67 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.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: cf72219b · Trigger: schedule
  • Thinking: 291s wall

BLOCKING (8)

Root Cause

  • src/v4/lens/structural_resolution.dag The structural-resolution lens was filled before its declared dependency projection substrate landed → land the v4.std.dependency authority in this PR or keep the registry row Unbound.
  • src/v4/lens/structural_resolution.dag The lens invents a lookup-miss reason downstream instead of consuming an infer-owned Symbol → add the reason to compiler/04_infer.dag or remove this status branch.
  • src/v4/lens/structural_resolution.dag The output carrier stores evidence and its derived label independently → encode the status variants as evidence-carrying cases or make status a computed accessor.
  • src/v4/lens/structural_resolution.dag StructuralResolutionStatus has no case for unrelated infer violations → either carry the original diagnostic or restrict the lens to facts it can classify faithfully.
  • src/v4/lens/structural_resolution.dag The claim fixtures need output comparison but the PR adds local equality helpers → consume canonical equality/content_hash/TestClaim comparison or add a bounded dissolution receipt.
  • src/v4/test/claim/lens_structural_resolution/binds_to_resolved.dag The new claim fixtures copied an older InferredFacts shape → include a SymbolicCost witness as existing v4 claims do.
  • src/v4/test/claim/lens_structural_resolution/prelude_carve_out.dag The new claim fixtures copied an older InferredFacts shape → include a SymbolicCost witness as existing v4 claims do.
  • src/v4/test/claim/lens_structural_resolution/unbound_symbol_at_use.dag The new claim fixtures copied an older InferredFacts shape → include a SymbolicCost witness as existing v4 claims do.

⚠️ The PR needs compile-surface fixes and one substrate carrier reshape before this registry entry can be treated as filled.

import v4.compiler.resolve {
resolve_reason_unbound_symbol
}
import v4.std.dependency {

This comment was marked as resolved.

import v4.compiler.infer {
InferredFacts,
InferredTree,
infer_facts_lookup_miss

This comment was marked as resolved.

Comment thread src/v4/lens/structural_resolution.dag Outdated
dependency: DependencyView
source_facts: Witness<InferredFacts>
dependent_facts: Witness<InferredFacts>
status: StructuralResolutionStatus

This comment was marked as resolved.

Comment thread src/v4/lens/structural_resolution.dag Outdated
} else {
match dependent_facts {
Holds { value: _ } => BindingResolved
Violates { diagnostic: _ } => FactsLookupMiss

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current session/cool-dove-67 HEAD — accepted; fixed.

The finding was correct on the reviewed commit (cf72219ba): the fallback arm mapped any other Violates to FactsLookupMiss, which mislabeled unknown infer diagnostics.

Fix (cfea91a + 2512781): added UnresolvedInferWitness to the closed status sum; the fallback is now Violates { diagnostic: _ } => UnresolvedInferWitness. FactsLookupMiss is only produced when dependent_facts.reason == infer_facts_lookup_miss (04_infer.dag:76). No fabricated relabeling of other typed failures.

— sent from cool-dove-67

Comment thread src/v4/lens/structural_resolution.dag Outdated
witness(tree: tree, dependencies: dependency_lens(root: tree.root))
}

fn status_eq(a: StructuralResolutionStatus, b: StructuralResolutionStatus) -> Bool {

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against HEAD — accepted; fixed (dd506c9b7).

Removed status_eq entirely. StructuralResolutionStatus is only reachable via status_of_dependency_fact / status_for_dependency (pure projections from dependency + dependent_facts). dependency_fact_eq now compares those authoritative fields only, so TestClaim equality cannot diverge from the derived status and there is no hand-rolled coproduct equality to disposition.

— sent from cool-dove-67

}

fn sr_claim_facts() -> InferredFacts {
InferredFacts {

This comment was marked as resolved.

}

fn sr_mod_claim_facts() -> InferredFacts {
InferredFacts {

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against HEAD — accepted; fixed (32bb845ce).

The spirit of the finding is correct: the InferredFacts literal was incomplete. The required field in src/v4/compiler/04_infer.dag today is canonical: CanonicalGroundingWitness (line 58) — there is no cost field on InferredFacts (cost lens output is a separate projection per P3/homomorphism doc).

prelude_carve_out.dag (and the sibling claims) now wire canonical via the same stub witness pattern as pipeline_rejections.dag / infer_emit_compile_anchor.dag.

— sent from cool-dove-67

}

fn sr_unbound_resolved_facts() -> InferredFacts {
InferredFacts {

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against current session/cool-dove-67 HEAD (32bb845ce) — accepted; already fixed.

The reviewed commit omitted a required InferredFacts field. On today's 04_infer.dag that field is canonical: CanonicalGroundingWitness (line 58), not cost — InferredFacts has no cost member.

sr_unbound_resolved_facts() now includes:

canonical: sr_unbound_canonical_witness(resolved: resolved)

via the same stub witness pattern as pipeline_rejections.dag / prelude_carve_out.dag.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: scheduled api-review on cf72219b — verified against HEAD 32bb845ce

Reviewed all 8 BLOCKING items against current session/cool-dove-67. Several were valid on cf72219b; subsequent commits address them. Item-by-item:

1. v4.std.dependency not landed — not applicable on HEAD

src/v4/std/dependency.dag is on origin/main since #3451 (894ae0659). Merge-base includes it. Registry row stays Bound { path: "v4.lens.structural_resolution" }.

2. Invented lookup-miss reason — not applicable on HEAD

infer_facts_lookup_miss is declared in src/v4/compiler/04_infer.dag:76 and imported by the lens; FactsLookupMiss only fires when dependent_facts carries that reason.

3. Evidence + derived label stored independently — fixed (251278175)

Removed status from StructuralResolutionDependencyFact. Status is only via status_of_dependency_fact (computed accessor from dependency + dependent_facts).

4. No case for unrelated infer violations — fixed (cfea91a89)

Added UnresolvedInferWitness for Violates that are neither unbound nor lookup-miss (no fabricated relabeling).

5. Local equality helpers — fixed (dd506c9b7)

Removed hand-rolled status_eq. fact_eq / dependency_fact_eq compare authoritative fields only (T-13 mirror: effect_fact_eq pattern). TestClaims use fact_eq in *_claim_holds().

6–8. Claims need SymbolicCost on InferredFacts — wrong field name on HEAD

InferredFacts in 04_infer.dag:54–58 requires canonical: CanonicalGroundingWitness, not SymbolicCost. SymbolicCost is lens/cost.dag output (cost_lens), not an infer fact field. All three claims now include canonical (32bb845ce), matching pipeline_rejections.dag / infer_emit_compile_anchor.dag. T-13 sibling lens claims (effect_depends_on, etc.) use the same InferredFacts stub shape for compile-only fixtures.

Commits since reviewed SHA: cfea91a89, 251278175, dd506c9b7, 32bb845ce.

— sent from cool-dove-67

@briansrls
briansrls marked this pull request as ready for review May 21, 2026 05:08
@briansrls

Copy link
Copy Markdown
Contributor Author

Re: codex REQUEST_CHANGES — dependency_lens classifier (accepted; fixed)

Verified: finding was correct on prior HEAD — classify_node_edge_usage returned Contains for every edge, so at(tree) via dependency_lens could not surface BindsTo / ModuleDependsOn / PreludeCarveOut.

Fix (0ba468e8e):

  • src/v4/std/dependency.dag: structural classification — Bind parent → BindsTo; TypeNode + Named → BindsTo; dependency_module_import_edge / dependency_bootstrap_depends_edge labels → ModuleDependsOn / BootstrapDependsOn.
  • TestClaims now call at(tree) (live dependency_lens) instead of witness(tree, [hand-authored DependencyView]).
  • prelude_carve_out fixture edge uses dependency_module_import_edge so at path produces PreludeCarveOut.

witness(tree, dependencies) remains for tests that inject explicit dependency rows; at is the authoritative integrated path.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: codex REQUEST_CHANGES (review 15704) — both findings addressed (c489b12b4)

1. Missing Symbol import — accepted; fixed

  • src/v4/std/dependency.dag: import v4.std.node { …, Symbol, … } for dependency_module_import_edge / dependency_bootstrap_depends_edge data rows.
  • src/v4/lens/structural_resolution.dag: import v4.std.node { Node, Symbol } for witness_reason_is.

2. Claims ignore status projection — accepted; fixed

fact_eq compares authoritative substrate fields only (P2 — status is derived). Added TestClaim-only ratchet:

  • status_eq + fact_projects_status(fact, expected) in the lens module (🟢 terminal — claim use only).
  • All three claims now assert fact_eq(...) && fact_projects_status(fact: actual, expected: <BindingResolved|UnboundSymbolAtUse|PreludeCarveOut>) so a wrong status_for_dependency mapping fails the claim.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: cursor/composer-2.5 APPROVE (review 15719 on c489b12b4) — verified

Verdict accepted. Reviewed against HEAD — matches lane-A brief: registry bind, dependency_lens + infer witness read path, at(tree) integration, fact_projects_status status ratchet on claims.

Exploratory (non-blocking): _ => BindingResolved in status_for_dependency is intentional for this lens’s scope (file header: binding / module / bootstrap resolution only). Consumers that need per-DependencyKind infer-violation classification should use lenses scoped to those dimensions (cf. idempotency’s per-kind verdicts). No change in this PR.

Merge posture: Awaiting second distinct api-review APPROVE and codex re-review on current HEAD (prior codex RC items addressed in 0ba468e8e / c489b12b4).

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: codex REQUEST_CHANGES (review 15731) — accepted; fixed

Verified: ComputationNode { behavior: Bind } => BindsTo was wrong. 03_resolve.dag:438-488 (resolve_bind_edges) treats bind positional edges by index (binder target / outer / inner), not uniformly as use-site bindings.

Fix: Removed blanket Bind-parent → BindsTo. Staged classifier now classifies BindsTo only via dependency_binds_to_edge marker (plus module/bootstrap markers). Bind positional children → Contains until T-9 resolve writes inline BindsTo substrate facts per position.

TestClaims already use dependency_binds_to_edge on at(tree) fixtures; no behavioral change to claimed paths.

— sent from cool-dove-67

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: c9750d2d · Trigger: schedule
  • Thinking: 313s wall

BLOCKING (5)

Root Cause

  • src/v4/test/claim/lens_structural_resolution/binds_to_resolved.dag The new claim fixtures were authored against a canonical/constraint witness shape that is not present in v4 std or InferredFacts → either land that substrate contract in this PR or build the fixtures from the current InferredFacts shape.
  • src/v4/lens/structural_resolution.dag StructuralResolutionFact consumes the whole dependency_lens output but StructuralResolutionStatus only models resolution cases → filter to resolution dependency kinds or model an explicit non-resolution case.

⚠️ The registry fill is close, but the new claim fixtures still do not compile against the current v4 substrate and the lens fabricates BindingResolved for non-resolution dependencies.

fact_eq,
fact_single_dependency_projects_status
}
import v4.std.cardinality { RankingDimension, TerminationProof }

This comment was marked as resolved.

BindsTo,
DependencyView,
dependency_binds_to_edge
}

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified on HEAD abe24a51d and origin/main — finding is incorrect (no code change needed).

src/v4/std/witness.dag declares and owns StructuralPropertyWitness (lines 4, 18–21); it is not Witness-only. The claim import matches the substrate contract used by 04_infer.dag (canonical: CanonicalGroundingWitness built from StructuralPropertyWitness fields) and existing claims such as workflow/pipeline_rejections.dag.

git ls-tree origin/main -- src/v4/std/witness.dag   # present
rg StructuralPropertyWitness src/v4/std/witness.dag # type declared in-module

The review bot likely inspected a stale or shallow tree snapshot; the module resolves on current main.

— sent from cool-dove-67

}
}
}

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified on HEAD and origin/main — finding is incorrect (no code change needed).

InferredFacts.descent is Witness<TerminationProof>, not bare TerminationProof:

type InferredFacts {
  resolved_type: Node
  inhabits: AlgebraRef
  descent: Witness<TerminationProof>
  canonical: CanonicalGroundingWitness
}

The claim’s descent: Holds { value: TerminationProof { ... } } is the correct witness carrier shape (same pattern as workflow/pipeline_rejections.dag with Violates). The reviewer misread the field type.

— sent from cool-dove-67

InferredFacts {
resolved_type: resolved,
inhabits: AlgebraRef {
algebra: sr_claim_node(s: sr_algebra_symbol),

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified on HEAD abe24a51d and origin/main — finding is incorrect (no code change needed).

InferredFacts includes canonical: CanonicalGroundingWitness in 04_infer.dag (Wave-3-A T-9, merged #3464):

type InferredFacts {
  resolved_type: Node
  inhabits: AlgebraRef
  descent: Witness<TerminationProof>
  canonical: CanonicalGroundingWitness
}

The claim fixture at line 92 matches that contract; infer also populates canonical from grounding witnesses (04_infer.dag ~127). The bot inspected a stale infer shape.

— sent from cool-dove-67

Violates { diagnostic: _ } => UnresolvedInferWitness
}
}
}

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified on HEAD abe24a51d — finding was valid on the reviewed shape; already fixed (e21fa4dd0).

The bot flagged the old _ => BindingResolved wildcard. Current status_for_dependency exhaustively matches DependencyKind: only BindsTo can reach BindingResolved (via status_for_binding_facts); ModuleDependsOn / BootstrapDependsOn → PreludeCarveOut; Contains, TypeDependsOn, DataDependsOn, and all other kinds → OutOfScopeDependencyKind (never BindingResolved without binding witnesses).

fn status_for_dependency(...) -> StructuralResolutionStatus {
  match view.kind {
    BindsTo => status_for_binding_facts(...)
    ModuleDependsOn => PreludeCarveOut
    BootstrapDependsOn => PreludeCarveOut
    Contains => OutOfScopeDependencyKind
    ...
  }
}

No further change for this specific finding.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Reply to claude-opus-4-7 review (artifact 15744) — verified on HEAD abe24a51d:

  1. status_for_dependency wildcard — Accepted; fixed (e21fa4dd0). Replaced _ => BindingResolved with exhaustive DependencyKind match. Only BindsTo consults status_for_binding_facts; ModuleDependsOn / BootstrapDependsOn → PreludeCarveOut; all other kinds (Contains, TypeDependsOn, DataDependsOn, …) → new OutOfScopeDependencyKind so coproduct dissolution does not report resolved without reading binding witnesses.

  2. classify_node_edge_usage Positional dead arm — Accepted; fixed (e21fa4dd0). Collapsed to Positional => Contains until T-9 bind-edge 0/1/inner differentiation lands; removed unused Bind / ComputationNode imports (abe24a51d).

  3. UnresolvedInferWitness reachability — Valid concern, intentional (e21fa4dd0). After the two named reason checks, remaining Violates maps to UnresolvedInferWitness (fail-closed); Holds → BindingResolved. Added one-line comment on that arm. This is not unreachable — it is the staging bucket for infer diagnostics this lens does not yet name-symbol-project.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Reply to claude-opus-4-7 review 15753 (APPROVE)

Verified on HEAD — thank you for the APPROVE.

Non-blocking observations:

  1. Exhaustive DependencyKind → compile break on new variant — agreed; intentional fail-closed (coproduct dissolution). No change.
  2. Duplicated claim fixture scaffolding — noted for a follow-up shared fixture module once generated claim execution lands; out of scope for this registry-fill PR.
  3. Unused sr_*_edge_symbol decls — accepted; removed in $(git rev-parse --short HEAD 2>/dev/null || echo next push) (edges already use dependency_*_edge markers).

Prior inline blockers (codex @ c9750d2d / abe24a51d): replied on-thread — constraints.dag / witness.dag / canonical / Witness<TerminationProof> descent / OutOfScopeDependencyKind were all valid on current main; several bot findings were stale tree snapshots.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Reply to cursor review 15762 (APPROVE) — verified on HEAD c69903aac.

Verdict: Acknowledged — no blocking findings; scope matches registry fill + brief pin, v4-only, fail-closed binding path.

Exploratory observations (no code change in this PR):

  1. Missing claims (FactsLookupMiss, UnresolvedInferWitness, BootstrapDependsOn → PreludeCarveOut) — agreed as coverage gap; deferred to a follow-up claim batch. This PR’s three scaffolds ratchet the principal arms (BindingResolved, UnboundSymbolAtUse, ModuleDependsOn → PreludeCarveOut) required for the lane-A freeze row.
  2. status_eq / fact_eq ratchet — intentional 🟢 terminal TestClaim helpers, same pattern as ownership.dag / sibling lenses; not a Practice-10 violation for lens-local claim equality.

Prior chore: removed unused sr_*_edge_symbol decls (c69903aac).

— sent from cool-dove-67

briansrls and others added 14 commits May 21, 2026 07:02
Do not relabel unknown infer Violates as FactsLookupMiss; add terminal
status_eq disposition comment (T-13 mirror).

Co-authored-by: Cursor <cursoragent@cursor.com>
dependency_fact_eq compares authoritative witnesses + dependency only;
status_of_dependency_fact is a pure projection (Practice 10).

Co-authored-by: Cursor <cursoragent@cursor.com>
04_infer InferredFacts requires canonical: CanonicalGroundingWitness
(not a cost field). Align all lens_structural_resolution claims with
pipeline_rejections / infer_emit_compile_anchor stub pattern.

Co-authored-by: Cursor <cursoragent@cursor.com>
Import Symbol from v4.std.node in dependency.dag and structural_resolution.dag.
Add fact_projects_status for behavior-driven status assertions in claims.

Co-authored-by: Cursor <cursoragent@cursor.com>
…laims

- Import List/Bool/Int/Symbol/Positional explicitly in lens + dependency modules.
- Narrow dependency classifier: BindsTo only on Bind parents or
  dependency_binds_to_edge marker; record-field Named edges stay Contains.
- Mark classifier staged (dissolve-on T-9 resolve-ground facts).
- TestClaims: descent as Witness<TerminationProof>; fact_single_dependency_projects_status.

Co-authored-by: Cursor <cursoragent@cursor.com>
Enumerate all dependency kinds instead of wildcard BindingResolved;
non-binding kinds map to OutOfScopeDependencyKind. Collapse redundant
Positional classifier arms until T-9 bind-edge differentiation.

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove dead sr_*_edge_symbol data decls; edges use dependency_*_edge markers.

Co-authored-by: Cursor <cursoragent@cursor.com>
@briansrls
briansrls force-pushed the session/cool-dove-67 branch from c69903a to 253900f Compare May 21, 2026 07:02
@briansrls

Copy link
Copy Markdown
Contributor Author

Reply to claude-opus-4-7 review 15771 (APPROVE) — verified on rebased HEAD 253900ff5.

Verdict: Acknowledged — no blocking findings. Registry Bound path, brief §3 mirror, closed status_for_dependency / fail-closed status_for_binding_facts, and T-9-staged classifier match current code.

Exploratory (no change this PR):

  1. Duplicated LensStructuralResolutionClaim across three claim files — agreed; collapse into a shared lens_structural_resolution fixture module when generated claim execution lands (same deferral as review 15753).
  2. status_eq nested match — intentional 🟢 terminal TestClaim ratchet (sibling-lens pattern); no substrate Eq derivation yet.

Post-rebase: brief conflict with unused_parameters (#3483) resolved; both registry rows bound.

— sent from cool-dove-67

briansrls and others added 2 commits May 21, 2026 20:53
Resolve process_numeric_refinements.dag import conflict: keep single
EqualsClaim import (both sides had coproduct fix; HEAD wins).

Co-authored-by: Cursor <cursoragent@cursor.com>
TASKS.md T-13 inventory now includes structural_resolution (eighth
closed lens). Registry smoke module comment drops deleted STRUCTURE.md
in favor of INVARIANTS.md §P2 (ledger-doc retirement).

Co-authored-by: Cursor <cursoragent@cursor.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Re: cursor APPROVE @ 625e26eec (exploratory observations)

Verified all three against current code:

  1. TASKS.md T-13 inventory — Valid drift: registry/pin already list structural_resolution as the eighth closed lens while TASKS.md still named only {parallelism,effect,ownership,idempotency}. Fixed in docs: align T-13 task list… (same PR branch).

  2. v4_lens_registry_dag_smoke_test.rs → STRUCTURE.md — Pre-existing stale cite (STRUCTURE.md deleted per docs/modeling-discipline.md ledger-doc retirement). Module comment now points at INVARIANTS.md §P2 + the lane-A pin §3 (authorities already named in the next sentence).

  3. witness() always Holds — Intentional T-13 projection posture (same as parallelism / effect / ownership / idempotency): unresolved binding is carried in StructuralResolutionFact.status / ClassifiedDependencyView, not suppressed via Violates. No code change.

No blocking findings in the review artifact; merge conflict with main was resolved via merge commit 625e26eec.

— sent from cool-dove-67

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 731ca1a0 · Trigger: schedule
  • Thinking: 442s wall

BLOCKING (1)

Root Cause

  • src/v4/compiler/04_infer.dag unresolved-infer witness fixtures need a declared infer diagnostic reason → add/export the canonical reason in compiler/infer or reuse an existing exported infer diagnostic.

⚠️ One new claim imports an undeclared infer diagnostic reason; fix that authority before merging.

AlgebraRef,
InferredFacts,
InferredTree,
infer_descent_not_derived

This comment was marked as resolved.

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: inline @ unresolved_infer_witness.dag:13 (21:16Z) + codex RC @ 731ca1a0

Verified on current HEAD — finding is incorrect as stated: infer_descent_not_derived is declared in src/v4/compiler/04_infer.dag (data infer_descent_not_derived: Symbol + infer_descent_not_derived_diagnostic producer) since Wave-3-A T-9 (#3464); same at review SHA 731ca1a0 (04_infer.dag:77–110).

Commit fix(v4): lens claims consume infer/resolve diagnostic factories anyway: the three Violates-path claim fixtures now import the producer APIs (infer_descent_not_derived_diagnostic, infer_facts_lookup_miss_diagnostic, unbound_symbol_diagnostic) instead of re-importing reason Symbols and hand-building Diagnostic literals — matches infer_ground_add_mvp.dag P2 posture.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: claude APPROVE @ 646689487 (exploratory)

Verified all three observations on current code:

  1. Registry smoke compile_to_dag → parse-only — Intentional, documented in harness + INVARIANTS.md §P5(b) row (post-Substrate hardening bundle: node well-formedness arity + bootstrap fixpt digest-equality + TestClaim coproduct + P9 single-owner shape (operator pre-cleared) #3503 P9 Symbol/List; M1(2.7) isolated lowering). Source-text receipts for T-23 closed set + StructuralResolution binding compensate; dissolve back when M2 multi-module load lands (not in this PR scope).

  2. OutOfScopeDependencyKind flattening (13 DependencyKind arms) — Deliberate Practice 11 scope-narrowing for this lens; view.kind retains full discrimination.

  3. Reason-symbol equality in status_for_binding_facts — Fail-closed today (UnresolvedInferWitness bucket); staged comment at :76–79 flags T-9 bridge dependency. No change.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: inline @ unresolved_infer_witness.dag:13 + codex RC @ 731ca1a0 (infer diagnostic authority)

Verified on current HEAD (646689487+):

  • infer_descent_not_derived is declared in src/v4/compiler/04_infer.dag (data @ L101, factory infer_descent_not_derived_diagnostic @ L122, used by infer_descent_witness_for_node). Same was true at 731ca1a0 — the scheduled review was stale relative to the PR’s infer substrate.
  • Valid P2 nit: the claim imported the raw reason Symbol and hand-built Diagnostic, which looks like a parallel authority even when the symbol exists.

Fix (fix(v4): lens claims consume infer/resolve diagnostic factories): all three Violates-path claims now import producer APIs:

  • unresolved_infer_witness → infer_descent_not_derived_diagnostic
  • facts_lookup_miss → infer_facts_lookup_miss_diagnostic
  • unbound_symbol_at_use → unbound_symbol_diagnostic (resolve)

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: claude APPROVE @ 646689487 (exploratory observations)

  1. Registry smoke compile_to_dag → parse-only — Acknowledged. Post-Substrate hardening bundle: node well-formedness arity + bootstrap fixpt digest-equality + TestClaim coproduct + P9 single-owner shape (operator pre-cleared) #3503 P9 Symbol/List in registry.dag blocks isolated lowering; harness documents the downgrade and adds source-text receipts for the closed T-23 set + StructuralResolution binding. Dissolves back when M2 multi-module load lands (same posture as v4_bin_main_dag_smoke_test). Not a P5 violation.

  2. OutOfScopeDependencyKind flattening (13 DependencyKind arms) — Intentional Practice 11 scope-narrowing for this lens; view.kind retains full discrimination. No change.

  3. Reason-symbol equality in status_for_binding_facts — Staged until T-9 resolve→infer bridge; fail-closed today (UnresolvedInferWitness bucket). Inline comment already marks non-load-bearing BindingResolved on Holds.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Follow-up: diagnostic-factory change is on HEAD 46ce7d8b5 (three claim .dag files). Prior comment described the intent; this SHA is what GitHub shows after push.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: cursor APPROVE @ 46ce7d8b5 (exploratory observations)

Verified all three against current code — no changes required:

  1. Five lens_structural_resolution/* _claim_passes scaffolds — Confirmed: binds_to_resolved, facts_lookup_miss, unbound_symbol_at_use, unresolved_infer_witness, module_import_out_of_scope each export a *_claim_passes: Bool wired through LensStructuralResolutionClaim + at/fact_eq; module headers mark 🟡 scaffold with dissolve-on T-13 lens driver / r4-lane-a §3 B2 (same posture as sibling T-13 lens claim dirs). Tracking for testgen pickup is appropriate; not blocking this registry fill.

  2. BindingResolved on infer Holds without resolve stamp — Confirmed staged at structural_resolution.dag:76-79 (inline comment + status_for_binding_facts). Violates-path buckets remain fail-closed; Holds is structural-infer-only until T-9 bridge.

  3. dependency.dag label classifier → Contains default — Confirmed: classify_named_edge_usage returns Contains unless dependency_*_edge markers match (dependency.dag:25, :104-115); non-BindsTo kinds map to OutOfScopeDependencyKind in this lens by design (Wave-2-A staging). Claims that need BindsTo carry dependency_binds_to_edge on the Conj child edge.

No blocking rubric violations on this HEAD.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: claude APPROVE @ f99676586 (minor observations)

1. fact_eq multiset compare (xs: left vs xs: right)

Verified on HEAD — already correct, not a live typo:

      acc && (structural_resolution_dependency_count(xs: left, item: item) == structural_resolution_dependency_count(xs: right, item: item))

structural_resolution_dependency_facts_eq checks equal lengths, then for each element drawn from left compares multiplicity in left vs right (standard multiset equality for this scaffold). The xs: left on both sides regression was fixed in be719894b (fix(v4): single-line multiset eq in structural_resolution fact_eq). Whole helper remains 🟡 gated for B2 dissolution per the file header — no commit.

2. OutOfScopeDependencyKind — 13 explicit arms vs wildcard

Intentional for this staged lens: exhaustive match view.kind forces a compile-time update when DependencyKind grows, instead of silently bucketing new variants to out-of-scope. BindsTo is the only arm with binding semantics today; the rest are explicitly named pending T-9 edge stamping. Wildcard would be reasonable post-T-9 once the closed set stabilizes — tracked with the lens driver / testgen anchor work, not blocking this registry fill.

No blocking rubric violations on this HEAD.

— sent from cool-dove-67

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: 46ce7d8b · Trigger: schedule
  • Thinking: 489s wall

Non-blocking — Strengths

  • src/v4/lens/structural_resolution.dag The lens reads dependency endpoints through DependencyView and per-node facts through InferredTree, which preserves the intended single-authority shape.

ROADMAP — Verified

  • T-13: The TASKS update, registry binding, structural_resolution lens, and staged T-9/B2 triggers align with the T-13 lens-family scope.

✅ No new blocking issues found.

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: codex APPROVE @ 46ce7d8b (non-blocking strengths + ROADMAP T-13)

Verified on current HEAD f99676586 (merge of origin/main after your review SHA):

  • Single-authority shape — unchanged: structural_resolution.dag still projects via dependency_lens → DependencyView + per-node InferredTree.facts.lookup → ClassifiedDependencyView<StructuralResolutionStatus> (no parallel row payload). structural_resolution.dag / registry.dag have zero diff vs 46ce7d8b; post-merge delta is upstream main (runtime Option C, v2, extdeps) only.
  • ROADMAP T-13 — still aligned: TASKS.md lists structural_resolution in the T-13 family; registry binds LensIdV0::StructuralResolution → v4.lens.structural_resolution; staged T-9/B2 markers intact.

Agree: no new blocking issues. CI green on f99676586.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: f9967658 · Trigger: manual
  • Comparison: main @ cce52b4e ... session/cool-dove-67 @ f9967658
  • Conversation: View conversation

1. Story of the diff

This PR fills the previously unbound StructuralResolution lens registry row by binding it to v4.lens.structural_resolution, then adds that lens as a projection over InferredTree plus dependency_lens output. The new lens classifies each DependencyView into StructuralResolutionStatus, treating BindsTo edges as binding-resolution evidence and collapsing all other dependency kinds to OutOfScopeDependencyKind (src/v4/lens/structural_resolution.dag:94). To make that possible, std/dependency.dag grows staged dependency marker symbols and a classifier that maps marked named edges to BindsTo, ModuleDependsOn, or BootstrapDependsOn, with a Bind-parent carve-out so bind-internal edges remain containment (src/v4/std/dependency.dag:25, src/v4/std/dependency.dag:43).

The PR also adds .dag claim fixtures for the intended structural-resolution cases: resolved bind, infer fact lookup miss, unbound symbol, unrelated infer witness violation, and module-import out-of-scope. The v4 lens registry Rust smoke is deliberately downgraded from compile_to_dag to tokenize/parse plus bounded source-text receipts because the registry now imports Symbol/List from v4.std.*, which the single-file M1(2.7) harness cannot lower (src/v3/compiler/tests/integration/v4_lens_registry_dag_smoke_test.rs:6).

2. Invariant categories

  1. LAYER MODEL — Finding. src/v4/test/claim/lens_structural_resolution/claim_carrier.dag:16 makes actual: Witness<StructuralResolutionFact> an authored field beside input and expected. That is a substrate/test-carrier shape, not implementation-only Rust, and it admits the illegal state “claim input X, expected Y, actual computed from Z.” The concrete rows then consume the authored actual field directly (src/v4/test/claim/lens_structural_resolution/binds_to_resolved.dag:127) rather than deriving at(input) inside the predicate, so the carrier is a second authority for the lens result. The fix is to remove actual from LensStructuralResolutionClaim and compute the actual witness from input in the claim predicate or eventual generated runner.
  2. INVARIANTS.md + modeling-discipline.md — Finding. src/v4/lens/structural_resolution.dag:181 introduces structural_resolution_status_eq, a hand-rolled equality match over every StructuralResolutionStatus variant (src/v4/lens/structural_resolution.dag:185). Practice 10 treats hand-written equality / identity as a derived-operation finding, and this file already uses direct equality for the same status carrier at src/v4/lens/structural_resolution.dag:164 and src/v4/lens/structural_resolution.dag:176. This should dissolve to the canonical equality surface, or at minimum a wrapper a == b, rather than a second per-variant equality authority.
  3. CODING.md — Compliant. The changed Rust smoke stays data + free functions: the test entrypoint tokenizes/parses explicit inputs (src/v3/compiler/tests/integration/v4_lens_registry_dag_smoke_test.rs:29) and the AST helper functions are small pure helpers (src/v3/compiler/tests/integration/v4_lens_registry_dag_smoke_test.rs:79).
  4. TESTING.md — Finding. The new .dag claim surface is not yet behavior-driven over the published interface because the carrier stores actual as data (src/v4/test/claim/lens_structural_resolution/claim_carrier.dag:16) and the assertion reads that stored field (src/v4/test/claim/lens_structural_resolution/binds_to_resolved.dag:127). A behavior test for the lens should assert that at(input) produces expected; this shape can pass while input is stale or unrelated, as long as the authored actual remains equal to expected.
  5. LOCKED DESIGN DECISIONS — Compliant. The registry fill is explicit and aligned across the operator pin and substrate: the brief table names v4.lens.structural_resolution for StructuralResolution (docs/briefs/r4-lane-a-lens-interface-freeze-pin.md:55), and the canonical registry row is changed from Unbound to Bound { path: "v4.lens.structural_resolution" } (src/v4/lens/registry.dag:80). I do not see a locked-design divergence.
  6. TRACKED vs UNTRACKED DEBT — Compliant. The new scaffolds name their bounds and dissolution triggers: the test-claim carrier is scoped to the T-13 driver landing (src/v4/test/claim/lens_structural_resolution/claim_carrier.dag:5), and the temporary fact equality scaffold is explicitly gated on canonical/generated lens-claim equality or content_hash (src/v4/lens/structural_resolution.dag:246). The findings above are about the shape of the carrier/equality while present, not an untracked-debt omission.

2.5. Top-down PM intent review

Finding. The thesis-level intent says tests are structural .dag TestClaim data and manual tests are upstream behavioral contracts the code must satisfy (THESIS.md:366, THESIS.md:374). The new claim carrier instead lets the test author provide the observed result as an input field (src/v4/test/claim/lens_structural_resolution/claim_carrier.dag:16), and the claim predicate reads that field rather than deriving it from the claim’s input (src/v4/test/claim/lens_structural_resolution/binds_to_resolved.dag:127). That dilutes the PM intent from “test declares contract; runner/lens computes result” into “test row can carry both contract and result,” which is exactly the kind of parallel authority the structural-test program is trying to retire.

3. Verdict

REQUEST_CHANGES

The core lens direction is sound: it uses ClassifiedDependencyView<StructuralResolutionStatus>, reads InferredTree.facts at classification time, and binds the registry row without inventing a parallel module path authority. The merge blocker is the new claim carrier storing actual as authored data, plus the hand-rolled status equality match; both are small fixes, but both create substrate-pattern debt if they land as-is.

briansrls and others added 2 commits May 21, 2026 21:14
Address openai-pro REQUEST_CHANGES on f996765:
- Remove authored `actual` from LensStructuralResolutionClaim; predicates
  call `lens_structural_resolution_actual(claim)` → `at(claim.input)`.
- Replace hand-rolled StructuralResolutionStatus match with `a == b` for
  classified_dependency_view_eq (Practice 10).

Co-authored-by: Cursor <cursoragent@cursor.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Re: openai-pro REQUEST_CHANGES @ f9967658

Both blocking findings verified and fixed on new HEAD:

1. Claim carrier parallel authority (actual field) — Valid. LensStructuralResolutionClaim no longer carries actual: Witness<…>; rows are { input, expected } only. lens_structural_resolution_actual(claim) in claim_carrier.dag derives at(claim.input); all five *_claim_holds() predicates match on that computed witness (e.g. binds_to_resolved.dag no longer reads a stored actual).

2. Hand-rolled structural_resolution_status_eq — Valid. Replaced per-variant match with a == b (same surface already used at fact_projects_status / fact_single_dependency_projects_status); still passed to classified_dependency_view_eq as the classification hook. Multiset fact_eq scaffold remains 🟡 gated for B2.

v4_lens_registry integration smoke passes locally.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: codex APPROVE @ dd90536e9

Verified on HEAD — agree, no further changes from this review:

  • registry.dag:80 — StructuralResolution → Bound { path: "v4.lens.structural_resolution" }.
  • structural_resolution.dag — projection-only over dependency_lens + InferredTree.facts → ClassifiedDependencyView<StructuralResolutionStatus> (post–openai-pro RC: claim actual derived via lens_structural_resolution_actual(claim) → at(claim.input); status equality uses a == b).
  • Claim fixtures — 🟡 scaffold headers + dissolve-on T-13 driver; not steady-state authority.

No concrete rubric violations in the changed lines.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: dd90536e · Trigger: manual
  • Comparison: main @ cce52b4e ... session/cool-dove-67 @ dd90536e
  • Conversation: View conversation

1. Story of the diff

This PR fills the previously-unbound LensIdV0::StructuralResolution registry entry by binding it to v4.lens.structural_resolution, then adds the new structural-resolution lens itself. The lens reads InferredTree facts at dependency usage sites, projects dependency edges through dependency_lens, and emits a StructuralResolutionFact whose rows are ClassifiedDependencyView<StructuralResolutionStatus> rather than copied endpoint/fact payloads (src/v4/lens/structural_resolution.dag:68-74, src/v4/lens/structural_resolution.dag:117-159). That is paired with a small staged classifier in std/dependency.dag that recognizes explicit dependency edge-label symbols for BindsTo, module imports, and bootstrap dependencies (src/v4/std/dependency.dag:24-28, src/v4/std/dependency.dag:104-123).

The PR also adds .dag claim fixtures for the main structural-resolution outcomes: resolved binding, unbound symbol, infer lookup miss, unrelated infer violation, and an out-of-scope dependency kind. The v3 Rust registry smoke is deliberately narrowed from isolated compile_to_dag to tokenize/parse plus source-shape receipts because the registry now imports Symbol/List from v4 std modules that the single-file harness does not link (src/v3/compiler/tests/integration/v4_lens_registry_dag_smoke_test.rs:3-12, src/v3/compiler/tests/integration/v4_lens_registry_dag_smoke_test.rs:26-83).

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation). Compliant — this does touch substrate/model files, and the main lens output avoids the T-13 parallel-payload failure by storing dependency: DependencyView plus classification, not copied source/dependent/per-node facts (src/v4/lens/structural_resolution.dag:68-70); that matches the ClassifiedDependencyView<C> pattern in the reference discipline. chatgpt-review-a120a342-1176-43…
  2. INVARIANTS.md + modeling-discipline.md. Compliant — fail-closed status projection is explicit: only Holds becomes BindingResolved, known diagnostic reasons become specific statuses, and any other Violates becomes UnresolvedInferWitness rather than a plausible success (src/v4/lens/structural_resolution.dag:80-90). Facts flow forward by lookup at view.usage_site instead of being carried as row payload (src/v4/lens/structural_resolution.dag:117-124).
  3. CODING.md. Compliant — the Rust smoke changes stay as small free helper functions over parsed data (module_path, module_declares_type_sum_named) rather than methods or hidden state (src/v3/compiler/tests/integration/v4_lens_registry_dag_smoke_test.rs:85-110). The comments are mostly load-bearing staging/dissolution boundary notes, not ordinary control-flow explanation.
  4. TESTING.md. Compliant — the PR adds targeted claim fixtures for each material structural-resolution status (binds_to_resolved, facts_lookup_miss, module_import_out_of_scope, unbound_symbol_at_use, unresolved_infer_witness) and keeps the Rust smoke honest about its parse-only boundary. The .dag claim rows are staged, but each file names the same T-13 driver dissolution path, consistent with the .dag-native testing trajectory. chatgpt-review-05b45072-a655-42…
  5. LOCKED DESIGN DECISIONS. Compliant — the operator pin table and substrate registry both move StructuralResolution from TBD/Unbound to the same concrete module path (docs/briefs/r4-lane-a-lens-interface-freeze-pin.md:54, src/v4/lens/registry.dag:78-81), and the registry smoke explicitly preserves P2-staging rather than claiming a generated consumer (src/v3/compiler/tests/integration/v4_lens_registry_dag_smoke_test.rs:3-8).
  6. TRACKED vs UNTRACKED DEBT. Compliant — the new staged surfaces carry bounded triggers: the binding-status bridge dissolves on T-9 resolve→infer witness work (src/v4/lens/structural_resolution.dag:76-79), the equality scaffold dissolves when the T-13 lens driver/generated TestClaim provides canonical equality or content hash (src/v4/lens/structural_resolution.dag:225-230), and the claim carrier files dissolve when the T-13 lens driver executes those rows (src/v4/test/claim/lens_structural_resolution/claim_carrier.dag:1-5).

2.5. Top-down PM intent review

Finding — src/v4/TASKS.md:551: stale T-13 I/O now contradicts the structural-resolution contract. The freeze-pin update says structural_resolution is a T-13 mirror over “InferredTree + dependency projection” (docs/briefs/r4-lane-a-lens-interface-freeze-pin.md:54), and the implementation follows that with witness(tree: InferredTree, dependencies: List<DependencyView>) plus at(tree: InferredTree) (src/v4/lens/structural_resolution.dag:152-159). But this PR also extends the T-13 task header to include structural_resolution (src/v4/TASKS.md:549) while leaving the section’s I/O line as Node -> Witness<...> per lens (src/v4/TASKS.md:551). That planning artifact now tells future workers the wrong contract for this lens; update the T-13 I/O text to carve out structural_resolution’s InferredTree + dependency projection input shape, or restate T-13 as a family whose members may name their own input carrier.

3. Verdict

REQUEST_CHANGES

The code/modeling shape is strong: it uses the intended classified dependency view, reads infer facts by reference, and keeps staged debt named. I would block only on the stale src/v4/TASKS.md contract because it newly applies to structural_resolution and would misdirect future T-13 work if merged as-is.

TASKS.md listed Node -> Witness per lens while the T-13 family (including
structural_resolution) reads InferredTree + dependency_lens output. Align
planning text with the freeze pin and landed lens contracts.

Co-authored-by: Cursor <cursoragent@cursor.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Re: openai-pro REQUEST_CHANGES @ dd90536e9 (TASKS.md T-13 I/O stale)

Valid finding — TASKS.md:551 still said Node -> Witness<...> after this PR added structural_resolution under the T-13 header while the lens contract is InferredTree + dependency_lens projection (same as sibling *_witness(tree, dependencies) lenses; plus at(tree: InferredTree) entry).

Fix: docs: correct T-13 family I/O for InferredTree + dependency projection — T-13 section now documents (InferredTree, List<DependencyView>) -> Witness<...>, Practice 11 lookup posture, and the structural_resolution at entrypoint.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: codex APPROVE @ c43a5b707

Verified on HEAD — agree, no further changes from this review:

  • structural_resolution remains projection-only: ClassifiedDependencyView<StructuralResolutionStatus> over DependencyView + tree.facts.lookup(usage_site) (no parallel row payload).
  • Staged surfaces carry explicit dissolve triggers (T-9 bridge, B2 fact_eq, T-13 claim driver).
  • Registry / pin / TASKS.md T-13 I/O aligned with landed contracts (including post–openai-pro RC: (InferredTree, List<DependencyView>) family I/O + at(tree) entry).

No concrete rubric violations in the changed lines.

— sent from cool-dove-67

@briansrls

Copy link
Copy Markdown
Contributor Author

Re: codex APPROVE @ 4240ee948

Verified on HEAD (includes merge of origin/main after c43a5b707 TASKS I/O fix):

No concrete rubric violations in the changed lines.

— sent from cool-dove-67

@briansrls
briansrls merged commit c0193d2 into main May 22, 2026
7 checks passed

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review metadata

  • Provider / model: codex / unknown
  • Commit: f9967658 · Trigger: schedule
  • Thinking: 388s wall

✅ No new blocking concerns found in the mixed .dag, design, and Rust-test changes.

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