Skip to content

docs(r4-wishlist): affected-set lens design + worked examples (R4.B addendum) - #2700

Merged
briansrls merged 8 commits into
mainfrom
docs/design-affected-set-lens
May 11, 2026
Merged

briansrls merged 8 commits into
mainfrom
docs/design-affected-set-lens

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

Summary

PM-authored design doc + WISHLIST addition for the affected-set lens — buck2/bazel-style fine-grained build system for .dag, with the structural argument that pure-substrate gives strictly narrower than transitive-downstream semantics for free.

Per operator directive at gunbc#846 (2026-05-11):

"I want a build system (for .dag) that recursively/finely manages dependencies — it should be very easy to see/query (trivial) — i changed this code, so i should change Y code (downstream of this code, affected) — i.e. not just downstream, but actually 'affected' at an atomic level — since everything is pure, changing upstream usually doesn't matter too much; it usually changes interfaces or certain edge cases."

Paired with prototype worker dispatch at gunbc#2699.

What's in this PR

docs/design-affected-set-lens.md new design doc:

  • §1 problem framing: Bazel serial-analysis bottleneck; Buck2 parallel-analysis fix; gunbc's structural-substrate leverage past both (analysis IS the substrate)
  • §2 affected-set definition: structurally checkable predicate; strictly narrower than transitive-downstream because pure functions don't have hidden state
  • §3 substrate composition: DescentEvidence (gate Ir graph and components #72 CONSUMER_LANDED) + SubValueRelation (gate Replace port-type heuristics with NodeKind classification #78 in-flight) + Cardinality lens + cross_target_coverage + TestClaim DB-15 + apply_lens framework — no new substrate required
  • §4 five worked examples (the core deliverable):
    • Case A function body change identical signature → {fn} only
    • Case B signature change → all binders affected
    • Case C algebra carrier change → all walkers affected
    • Case D test-only change → {test} only, no production propagation
    • Case E refinement type tightening → only consumers flowing through refined port
  • §5 CI integration sketch (deferred to R4 full delivery)
  • §6 coupling to R4.B queries-as-data family (refactor / coverage / effect-shape / bottleneck all use same substrate)
  • §7 prototype scope (worker at gunbc#2699)
  • §8 WISHLIST cross-link

WISHLIST.md addition under R4.B as stress-test use case #5.

Scope discipline

Test plan

Companion

Prototype worker dispatch at gunbc#2699 — concrete lens implementation + 5 example outputs + real-PR test against recently-merged PRs (#2693 v2 delete / #2679 gate #4 / #2647 quantifier substrate). Worker auto-spawn ETA ~5 min from issue creation.

🤖 Generated with Claude Code

…ddendum)

Per operator directive at gunbc#846 (2026-05-11): buck2/bazel-style
fine-grained build system for `.dag`, with pre-R3-close working prototype
+ R4.B WISHLIST entry for full delivery.

Two deliverables, paired:

1. **WISHLIST.md** addition under R4.B as stress-test use case #5
   "Affected-set lens (fine-grained build system)" with cross-link to
   design doc + prototype worker

2. **docs/design-affected-set-lens.md** new design doc:
   - §1 problem framing (Bazel serial / Buck2 parallel / gunbc structural)
   - §2 affected-set definition (strictly narrower than transitive-down)
   - §3 substrate composition (DescentEvidence + SubValueRelation +
     Cardinality lens + cross_target_coverage; no new substrate)
   - §4 five worked examples:
     - Case A: function body change, identical signature → {fn} only
     - Case B: signature change → all binders affected
     - Case C: algebra carrier change → all walkers affected
     - Case D: test-only change → {test} only, no production propagation
     - Case E: refinement type tightening → only consumers flowing
       through refined port
   - §5 CI integration sketch (deferred to R4 full delivery)
   - §6 coupling to R4.B queries-as-data family (refactor / coverage /
     effect / bottleneck use same substrate)
   - §7 pre-R3-close prototype scope (worker at gunbc#2699)
   - §8 WISHLIST cross-link

Companion prototype dispatched at gunbc#2699 (PM sub-issue; auto-spawn
ETA ~5 min from issue creation). Worker will produce concrete lens
implementation + real-PR test against recently-merged PRs.

PM-tier scope: design doc + WISHLIST addition only; no §1.8 gate
addition (not Director-tier ratified as R4 lane; landing as wishlist
+ prototype investigation; Director ratifies formal R4.B lane at R4
boundary).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-pro
  • Commit: 580f40d3 · Trigger: manual
  • Comparison: main @ a4152472 ... docs/design-affected-set-lens @ 580f40d3
  • Conversation: View conversation

1. Story of the diff

This PR adds an R4.B wishlist entry for a fine-grained “affected-set” lens and introduces docs/design-affected-set-lens.md as the working design artifact. The new design frames affected-set as stricter than transitive downstream: compare Dag_before and Dag_after, find structurally changed nodes, then traverse only consumers that structurally depend on the changed fact. The doc anchors the lens in existing substrate/lens machinery, gives five worked examples, and scopes a pre-R3-close prototype worker while deferring CI/IDE integration to later R4 delivery.

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Finding — BLOCKING. docs/design-affected-set-lens.md:89 says structural_dependency(M, N) is “a fold over the edge types — Conj / Disj / Cardinality / Bit (the only types the compiler knows...)”. That imports the PB runtime kernel vocabulary into a substrate-level query and omits the locked two-substrate shape: THESIS.md:198-201 says the type substrate has Atom | Conj | Disj | Arrow | Cardinality | Instantiation, while computation is Value | Transform | Branch | Loop | Bind, with Transform referring to Arrow.body. A worker following line 89 literally could under-model call/signature/refinement dependencies that require Arrow/Instantiation and L1 behavior edges. Rephrase this as a fold over the declared substrate/query surface, or explicitly distinguish “runtime kernel primitives” from the full affected-set dependency surface.

  1. INVARIANTS.md + modeling-discipline.md.

Finding — BLOCKING. docs/design-affected-set-lens.md:24 says “A function whose internal cost changes but whose I/O behavior is unchanged has no consumers in the affected set — only the function itself.” That drops a structured dimension fact at the lens boundary. THESIS.md:87-89 makes complexity/cost a structural correctness dimension carried by the program model, and modeling-discipline.md:69-75 says structured facts must flow forward unless explicitly justified. If a callee’s cost changes, callers with cost/complexity claims, memoization decisions, or bottleneck lenses can be affected even when return values are unchanged. The affected-set predicate needs to be dimension-aware: value-equivalence is only one projection, not the whole affectedness contract.

  1. CODING.md.

N/A — this is a documentation/design PR; it does not add Rust functions, helpers, APIs, error shapes, or method surfaces governed by CODING.md.

  1. TESTING.md.

Finding — BLOCKING for the proposed CI semantics, not because this docs PR needed tests. docs/design-affected-set-lens.md:266-269 sketches CI selection by intersecting affected-set with TestClaim references and says function-body PRs “would run a single TestClaim.” Combined with the I/O-only Case A at docs/design-affected-set-lens.md:121-125, that can skip downstream structural tests whose behavior is cost/effect/dimension output rather than returned value. TESTING.md:37-48 treats tests as behavior contracts, and cost behavior is explicitly a valid contract surface. Before the doc can safely dispatch implementation, Case A needs to say downstream value tests may skip, but downstream dimension consumers must run when the changed dimension fact flows to them.

  1. LOCKED DESIGN DECISIONS.

Finding — BLOCKING. Same locked-design issue as the layer-model finding: docs/design-affected-set-lens.md:89 cites the substrate-shape thesis while naming only Conj / Disj / Cardinality / Bit. The locked authority is broader: THESIS.md:198-201 requires six type connectives plus five L1 behaviors. If the intent is to cite the PB runtime bounded-kernel rule, align it with docs/design-pure-bootstrap-zero.md:118-119 and do not present that kernel as the full dependency model for the affected-set lens.

  1. TRACKED vs UNTRACKED DEBT.

Compliant. The doc bounds the prototype and deferral: docs/design-affected-set-lens.md:261-271 explicitly defers CI integration to R4 full delivery, and docs/design-affected-set-lens.md:292-304 lists worker deliverables and non-deliverables. That is a tracked planning bridge, not open-ended implementation scaffolding.

2.5. Top-down PM intent review

Finding — BLOCKING. The highest-level intent is not merely “skip tests when return values are unchanged”; gunbc’s thesis makes correctness dimensions structural, including complexity/cost (THESIS.md:87-89), and even names suboptimal-complexity contract violations as compile-time obligations (THESIS.md:374-376). The diff narrows affectedness to I/O in Case A: docs/design-affected-set-lens.md:24 says internal cost changes have no consumers, docs/design-affected-set-lens.md:125 says downstream tests skip, and docs/design-affected-set-lens.md:269 says function-body PRs run a single TestClaim. That would cause a faithful worker to under-select dimension consumers and build a lens that preserves ordinary build-system intuition while diluting gunbc’s structural-correctness promise. The fix is to define affectedness over changed structural dimensions, not just changed returned values or signatures.

3. Verdict

REQUEST_CHANGES. The PR is a useful R4.B design artifact, but two load-bearing semantics need correction before it dispatches implementation: the substrate basis at docs/design-affected-set-lens.md:89 must not flatten/omit the locked substrate shape, and Case A must propagate cost/complexity/effect dimension changes to structural consumers.

Exploratory observations

WISHLIST.md:82 appears to link to (design-affected-set-lens.md) from the repo root, while the new file is under docs/; the link target likely wants (docs/design-affected-set-lens.md).

@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: 580f40d3 · Trigger: schedule
  • Thinking: 241s wall

BLOCKING (1)

Root Cause

  • docs/design-affected-set-lens.md Structural identity, semantic value, and interface shape are conflated into one "changed" fact → define one typed delta/equivalence source and make unknown equivalence propagate as affected.

Non-blocking — Improvements (fix in-PR if easy, else defer to roadmap)

  • docs/design-affected-set-lens.md Lines 70-71 point to non-existent files src/v3/std/descent_evidence.dag and src/v3/std/sub_value_relation.dag; git ls-tree origin/main for those paths returned no blobs, while the live R4.B targets are src/v3/std/termination.dag and src/v3/std/induction.dag.

ROADMAP — Verified

  • R4.B affected-set lens: The WISHLIST addition is scoped as wish-tier/prototype work and does not add an R3 gate.

⚠️ One blocking definition gap needs reconciliation before the design can safely guide the prototype.

Comment thread docs/design-affected-set-lens.md Outdated
N has different structural identity in before vs after
OR
// Case B: N consumes the change through a typed edge
∃ edge (M → N) such that M.identity changed AND

This comment was marked as resolved.

Three BLOCKING findings from openai-pro review, with two distinct root
issues + one path typo. All valid:

ROOT ISSUE 1 — substrate-shape mis-citation (§3 line 89, locked design):
   Said "fold over Conj/Disj/Cardinality/Bit" but that's the PB-runtime
   bounded kernel (per design-pure-bootstrap-zero.md:118-119), NOT the
   full substrate-level query surface. Per THESIS.md:198-201, substrate
   is two parallel surfaces:
   - Type substrate: Atom | Conj | Disj | Arrow | Cardinality |
     Instantiation (6 type connectives)
   - Computation: Value | Transform | Branch | Loop | Bind (5 L1
     behaviors; Transform refers to Arrow.body)
   structural_dependency is a fold over BOTH surfaces; conflating them
   under-models call/signature/refinement/algebra-walk dependencies that
   need Arrow/Instantiation/Branch.

   Fix §3 line 89: cite full 6+5 substrate; enumerate per-edge-type
   dependency kinds; explicitly distinguish from PB kernel.

ROOT ISSUE 2 — dimension-collapse in affected-set predicate (§1 line 24,
§4 Case A, §5 CI sketch):
   Said "internal cost change → no consumers affected; downstream tests
   skip; function-body PRs run single TestClaim." But cost/complexity/
   effect are STRUCTURAL DIMENSIONS per THESIS.md:87-89 +
   modeling-discipline.md:69-75. Consumers carrying cost-claims,
   memoization decisions, or bottleneck-lens claims ARE affected when
   the changed function's cost shape changes — even when I/O is
   identical.

   Per THESIS.md:374-376, suboptimal-complexity contract violations are
   compile-time obligations. A build system that silently skips
   downstream cost-contract tests when only cost changed would dilute
   that structural-correctness promise.

   Fix §1: affected-set is "did ANY structural dimension the consumer
   reads change?" not "did return-value behavior change?"; value-
   equivalence is one projection among cost/complexity/effect/etc.; full
   affected-set is the union across per-dimension affected-sets.

   Fix §4 Case A: show per-dimension affected-sets (value / cost /
   effect); aggregate is union; test selection composes per-dimension ×
   per-TestClaim-asserted-dimensions intersection.

   Fix §5 CI sketch: dimension-aware selection; explicit warning against
   defaulting to value-equivalence only.

EXPLORATORY — WISHLIST.md:82 link typo:
   Was `(design-affected-set-lens.md)` (treats as repo-root); fixed to
   `(docs/design-affected-set-lens.md)` (correct relative path from
   WISHLIST.md at repo root).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed openai-pro REQUEST_CHANGES in commit ac4f12caf — all 3 BLOCKING findings + 1 exploratory addressed.

# Finding Root Fix
1 §3 line 89 cites "Conj/Disj/Cardinality/Bit" — that's PB-runtime kernel, not full substrate-level query surface Substrate-shape mis-citation Rewrote §3 to cite full THESIS.md:198-201 substrate: Type (6 connectives) + Computation (5 L1 behaviors). Enumerated per-edge-type dependency kinds (Arrow→Bind / Cardinality→Branch / Conj/Disj / Loop / Instantiation). Explicitly distinguished from PB kernel per design-pure-bootstrap-zero.md:118-119.
2 §1 + §4 Case A + §5 narrow affected-set to I/O-only — cost/complexity/effect are structural dimensions per THESIS.md:87-89 + modeling-discipline.md:69-75 Dimension-collapse Rewrote §1: "did ANY structural dimension the consumer reads change?" — value-equivalence is one projection; union across dimensions. Rewrote §4 Case A with per-dimension affected-sets + aggregate union. Rewrote §5 CI sketch: dimension-aware selection; explicit warning against value-equivalence default.
3 (locked design) Same as #1 Same Same fix; both findings collapse to one citation correction
Exploratory WISHLIST.md:82 link path was (design-affected-set-lens.md) (repo-root); should be (docs/design-affected-set-lens.md) Path typo Fixed

Key conceptual reframe: per THESIS.md:374-376, suboptimal-complexity contract violations are compile-time obligations. A build system that defaults to value-equivalence-only affected-set would silently skip downstream cost-contract tests when only cost changed — diluting the structural-correctness promise. The lens is now dimension-aware: per-dimension affected-set × per-TestClaim asserted-dimensions intersection.

This reframe also strengthens the worker's prototype scope (gunbc#2699): silent-bat-152 should now produce per-dimension lens output in the 5 worked examples, not just value-projection output.

— sent from deep-wolf-155

CODEX BLOCKING — structural identity / semantic value / interface
shape conflated into one "changed" fact; needed typed delta/equivalence
source + unknown-equivalence-propagates-as-affected (fail-closed).

Fix at §2: rewrote affected-set definition as **dimension-parameterized**
with explicit "PROVEN delta in dimension" semantics. Propagation
predicate is no longer "M.identity changed" — it's "M has PROVEN delta
in dimension dim_M AND N reads dim_M via the edge."

Fail-closed discipline added (per INVARIANTS P1/P3):
- delta(M, dim_M) PROVEN empty → consumer N excluded for that dimension
- delta(M, dim_M) NOT proven empty (unknown / unbounded / lens lacks
  substrate) → consumer N INCLUDED by default
- Lens MUST emit per-dimension proof receipt for each excluded consumer
  (similar to TestClaim fail-closed receipts per verification.dag)
- No silent exclusions

Aggregate affected-set is union across dimensions.

CODEX NON-BLOCKING (path corrections):
- `DescentEvidence` is in `src/v3/std/termination.dag:17`, not
  `descent_evidence.dag` (which doesn't exist on main)
- `SubValueRelation` is in `src/v3/std/induction.dag:207`, not
  `sub_value_relation.dag` (which doesn't exist on main)

Fixed §3 substrate-composition table with correct paths + line
references + cross-link to consumers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed codex BLOCKING + non-blocking in commit c2f1200ed.

# Finding Root Fix
BLOCKING Structural identity / semantic value / interface shape conflated into one "changed" fact; need typed delta source + fail-closed for unknown equivalence Propagation trigger over-loose Rewrote §2 as dimension-parameterized affected-set: trigger is "PROVEN delta in dimension dim_M AND N reads dim_M via edge", not bare "M.identity changed". Added INVARIANTS P1/P3 fail-closed discipline: unproven-empty deltas default-include; per-dimension proof receipts required for exclusions; no silent skips.
Non-blocking (paths) DescentEvidence cited at src/v3/std/descent_evidence.dag (doesn't exist); actual is src/v3/std/termination.dag:17 Path typo Fixed §3 substrate table with correct paths + line refs + consumer cross-link
Non-blocking (paths) SubValueRelation cited at src/v3/std/sub_value_relation.dag (doesn't exist); actual is src/v3/std/induction.dag:207 Path typo Same fix

Worker scope ripple (gunbc#2699): the §2 dimension-parameterized framing further reinforces the per-dimension prototype output requirement I noted at gunbc#2699 c#4423318123. silent-bat-152 should produce per-dimension lens output AND per-dimension proof receipts for each excluded consumer in the worked examples.

Also posting path-correction comment on gunbc#2699 since the charter body cites the same stale paths.

— sent from deep-wolf-155

briansrls and others added 2 commits May 11, 2026 17:51
…ursor APPROVE exploratory)

Cursor APPROVE on commit ac4f12c flagged optional clarity polish: the
"Strictly excluded" list lumped together (a) nodes not in affected-set
and (b) nodes in affected-set but not propagating-through. Reframed as
"Strictly excluded from PROPAGATION" with explicit per-bullet
disambiguation:

- Transitive non-readers: not propagated through
- Test nodes: IN the affected-set themselves (test runs), but no
  downstream production consumers exist so propagation doesn't expand
- Documentation / comments / non-structural metadata: NOT in affected-
  set at all

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

Codex BLOCKING on PR #2700: §3 algorithm sketch (line 110) seeded
propagation from `nodes_with_different_identity` while §2 established
that identity change alone isn't sufficient — propagation must be
triggered by a proven per-dimension delta. Inconsistency would brief
the worker toward a broader changed-node closure than the design wants.

Fix: rewrote §3 algorithm sketch as dimension-parameterized:
- Seed = nodes_with_proven_delta_in_dimension ∪
         nodes_with_unknown_delta_in_dimension (fail-closed for unknowns
         per §2 INVARIANTS P1/P3)
- Propagation predicate renamed from `structural_dependency(M, N)` to
  `dim_delta_propagates_through_edge(M, dim, edge, N)` to match the
  dimension-aware framing
- Aggregate across dimensions is the union (consistent with §2)

Internal consistency now intact: §2 dimension-parameterized definition,
§3 algorithm seed, and §4/§5 per-dimension worked-example/CI framing
all aligned.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed codex BLOCKING in commit ef3d990e7 — valid finding; §3 algorithm seed was inconsistent with §2 dimension-delta trigger.

Fix: rewrote §3 algorithm as dimension-parameterized lens:

  • Seed = nodes_with_proven_delta_in_dimension ∪ nodes_with_unknown_delta_in_dimension (fail-closed for unknowns per §2 INVARIANTS P1/P3 discipline)
  • Propagation predicate renamed structural_dependency(M, N) → dim_delta_propagates_through_edge(M, dim, edge, N) to match dimension-aware framing
  • Aggregate across dimensions = union (consistent with §2 closing)

Internal consistency now intact: §2 definition ↔ §3 algorithm seed ↔ §4 per-dimension worked examples ↔ §5 dimension-aware CI selection all aligned.

— sent from deep-wolf-155

Operator ratification at gunbc#846 (2026-05-11): "query" is user-surface
terminology for invoking an Introspect-config lens via tooling (CLI /
agent / IDE / build system). There is NO separate `Query<Input, Output>`
substrate carrier alongside `Lens<Input, Output>`. The substrate stays
unified: `apply_lens(L, S, IntrospectApplication{Output})`.

Why locked: avoids the coproduct-dissolution trap (per
feedback_coproduct_dissolution) of nicknaming similar concepts into
parallel branches. If we kept `Query` and `Lens` as parallel substrate
types, every composition step where they meet would force match-arms
(if-it's-a-query-do-X / if-it's-a-lens-do-Y). The unified frame avoids
that: every step is `apply_lens(...)`; composition is graph topology
over a single substrate.

Changes:

1. `docs/design-affected-set-lens.md`:
   - Title rename: "Affected-Set Lens" → "Affected-Set Introspect-Lens"
   - New §0: LOCKED terminology section explicitly stating no `Query`
     substrate type; "query" is user-facing nickname only; R4.B is
     Introspect-lens saturation NOT new substrate
   - Status header updated to "R4.B Introspect-lens saturation lane"
   - §6 rewritten: R4.B family table reframed as Introspect-config lens
     variants (refactor-impact, coverage-gap, effect-shape, bottleneck,
     affected-set are all the same substrate); closing sentence
     explicitly notes lens-vs-query is user-surface, not substrate

2. `WISHLIST.md` R4.B section:
   - Section title updated: "Queries-as-data" → "Introspect-lens
     saturation + tooling-consumer adapters (user-facing: queries-as-
     data)"
   - Top-of-section LOCKED note explicitly stating no `Query` substrate
     carrier; cross-links to design doc §0 and feedback memory
   - "Sequencing" question resolution updated: the open question about
     "query may be expressible as lens" is now RESOLVED (yes, it is)

3. Memory entry `feedback_query_is_lens_no_coproduct.md` written +
   indexed in MEMORY.md so future sessions don't re-litigate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Hardened lens-vs-query decision in commit beeae61b2 — operator ratification at gunbc#846 (2026-05-11): LOCK that "query" is user-surface terminology for Introspect-config lens; no parallel Query<Input, Output> substrate carrier.

Why locked: avoids coproduct-dissolution trap (per feedback_coproduct_dissolution). Parallel Query + Lens carriers would force match-arms wherever they compose. Unified substrate: every step is apply_lens(L, S, IntrospectApplication{Output}); "query" is just the user gesture when tooling invokes it.

Three artifacts updated:

  1. docs/design-affected-set-lens.md — new §0 "Substrate-vs-user-surface terminology (LOCKED)"; title rename to "Affected-Set Introspect-Lens"; §6 R4.B coupling rewritten as Introspect-lens family table
  2. WISHLIST.md R4.B — section title reframed to "Introspect-lens saturation + tooling-consumer adapters (user-facing: queries-as-data)"; LOCKED note + sequencing-question resolution
  3. Memory entry feedback_query_is_lens_no_coproduct.md indexed — so future sessions don't re-litigate

The substantive shape of affected-set is unchanged; only the framing is hardened. The §2/§3/§4/§5 dimension-aware + fail-closed work from prior commits stays.

— sent from deep-wolf-155

…(cursor non-blocking)

Cursor APPROVE_WITH_COMMENTS on commit beeae61: §0 LOCKED section
framed `config` as "disjoint sum EnforcedApplication ∪
IntrospectApplication" but per design-lens-application-surface.md §2
(lines 141-159), those are TWO SEPARATE TOP-LEVEL CARRIERS, NOT
variants of a single sum — v3 `.dag` substrate cannot currently
express that sum with per-variant generics.

Fix §0: reframed as "config chooses one of two separate top-level
carriers" + cross-cite that "SectionedLensApplication" names the pair
of carriers taken together, not a sum-type declaration. Maintains §0
LOCK intent (no parallel Query substrate) while aligning with the
locked LAS substrate shape.

INVARIANTS P2 (boundary / single structural story) preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed cursor non-blocking in commit d1a6c10b4 — valid NON-BLOCKING per design-lens-application-surface.md:141-159.

§0 LOCKED section said "disjoint sum EnforcedApplication ∪ IntrospectApplication" — but per LAS authority, those are two separate top-level carriers, NOT variants of a single sum (v3 substrate cannot currently express that sum with per-variant generics). "SectionedLensApplication" names the pair taken together, not a sum-type declaration.

Fixed §0 wording to: "config chooses one of two separate top-level carriers" + cross-cite that they are not a sum type. §0 LOCK intent (no parallel Query substrate) is preserved; only the LAS-shape framing was wrong.

— sent from deep-wolf-155

@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: beeae61b · Trigger: schedule
  • Thinking: 240s wall

BLOCKING (2)

Root Cause

  • docs/design-affected-set-lens.md User-surface apply_lens(..., config) shorthand is being described as substrate shape → say the parser/user surface selects one of the existing EnforcedApplication or IntrospectApplication carriers, with no config substrate sum.
  • docs/design-affected-set-lens.md Tool-facing rendering is conflated with substrate output → make the lens output structural (Set<NodeRef> or a NodeRef-keyed affected record) and leave {file, span} to CLI/IDE adapters.

ROADMAP — Verified

  • R4.B affected-set lens: The WISHLIST entry is wish-tier/prototype scoped and does not add an R3 §1.8 gate.

⚠️ The delta framing is fixed, but the design still needs these two substrate-vs-user-surface corrections before it can safely guide the prototype.

Comment thread docs/design-affected-set-lens.md Outdated

## §0. Substrate-vs-user-surface terminology (LOCKED — operator ratification gunbc#846 2026-05-11)

**Internal substrate**: there is only **lens** as a substrate type. `apply_lens(L, section, config)` is the singular declaration mechanism. `config` is the disjoint sum `EnforcedApplication<Output, Budget>` (compile-time obligation) ∪ `IntrospectApplication<Output>` (read-only fact emission). Per design-lens-application-surface.md §2.

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.

BLOCKING: This restates the locked lens-application surface as a single config disjoint sum, but docs/design-lens-application-surface.md and src/v3/std/lens_application.dag deliberately use two top-level carriers to avoid the illegal-state/per-variant-generic shape (P2).

Comment thread docs/design-affected-set-lens.md Outdated
**No "Query" substrate type, ever** (per `feedback_coproduct_dissolution` + operator coproduct-dissolution discipline). Creating parallel `Query<Input, Output>` vs `Lens<Input, Output>` carriers would force match-arms wherever they compose. The unified frame is: every step is `apply_lens(L, S, IntrospectApplication{...})`; composition is graph topology over a single substrate.

**This means**:
- The affected-set is an **Introspect-config lens** with output `Set<{file, span}>` (or richer per-dimension structure)

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.

BLOCKING: Making the Introspect lens output Set<{file, span}> conflicts with the later Set<NodeRef> definition and turns source location into canonical identity instead of a tooling projection, violating P2 single-authority/structural-reference discipline.

+#2)

Two valid BLOCKING findings from codex on prior sha beeae61:

#1 — `apply_lens(..., config)` shorthand framed as substrate sum, but
per design-lens-application-surface.md §2 + src/v3/std/lens_application
.dag, EnforcedApplication and IntrospectApplication are TWO SEPARATE
TOP-LEVEL CARRIERS, not variants of a single `Config<...>` sum (v3
substrate cannot currently express per-variant generics; P2 illegal-
state shape).

#2 — Lens output `Set<{file, span}>` conflated substrate (NodeRef
structural identity) with tooling rendering (file/span source-locations).
Per P2 single-authority/structural-reference discipline, substrate
output must be `Set<NodeRef>` (or NodeRef-keyed record); {file, span}
rendering is an adapter step at the tooling-consumer boundary, not lens
substrate output.

Fix at §0 (LOCKED terminology section):
- Reframed "config is disjoint sum" → "user-surface shorthand selects
  one of two separate top-level carriers; no `Config<...>` substrate sum"
- Added explicit "lens substrate output is structural" paragraph
  stating output is `Set<NodeRef>`; {file, span} rendering is adapter
  step
- Updated "This means" bullets: affected-set output is `Set<NodeRef>`
  (substrate) + CLI/IDE adapters render to user shapes
- §6 R4.B family table: affected-set Output column corrected to
  `Set<NodeRef>` (substrate); CLI/IDE adapter framing added

Substrate-vs-user-surface boundary now explicit + load-bearing.
INVARIANTS P2 (single-authority / structural-reference) preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-thinking
  • Commit: d1a6c10b · Trigger: manual
  • Comparison: main @ a4152472 ... docs/design-affected-set-lens @ d1a6c10b
  • Conversation: View conversation

1. Story of the diff

This PR turns R4.B from a vague “queries-as-data” wishlist item into a locked lens-based design direction. WISHLIST.md:68-86 now says “query” is user-facing terminology only: internally, R4.B is Introspect-config lens saturation plus tooling adapters, with no new Query substrate carrier. The new docs/design-affected-set-lens.md then works that decision through a concrete affected-set lens: it defines affectedness as a dimension-parameterized delta over two Dag states, makes exclusion fail-closed via proof receipts, composes the design over the existing 6 type-connectives + 5 behavior substrate, and gives five worked examples that distinguish value, cost/complexity, effect, test-only, algebra, and refinement changes.

The load-bearing move is that the design avoids both over-broad transitive downstream rebuilds and under-broad value-only selection: docs/design-affected-set-lens.md:49-51 explicitly says affectedness is the union of every structural dimension the consumer reads, while docs/design-affected-set-lens.md:84-97 requires default-inclusion unless a per-dimension empty-delta proof exists. That lines up with the thesis framing that correctness dimensions are structural facts, not behavioral afterthoughts, and that tests are structurally derived from TestClaim data. chatgpt-review-7bb7be96-61ed-43…

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Compliant — this is documentation/planning only, and where it does discuss substrate it explicitly rejects a new Query substrate carrier: docs/design-affected-set-lens.md:13-17 says the substrate remains lens plus EnforcedApplication / IntrospectApplication, and WISHLIST.md:70 mirrors that lock.

  1. INVARIANTS.md + modeling-discipline.md.

Compliant — single-authority / coproduct dissolution is handled by refusing parallel Query<Input, Output> vs Lens<Input, Output> carriers at docs/design-affected-set-lens.md:17, while fail-closed is handled by default-including unknown deltas and requiring proof receipts for excluded consumers at docs/design-affected-set-lens.md:84-97. This matches the invariant bar against parallel authority and fabricated success paths. chatgpt-review-972cb057-530c-43…

  1. CODING.md.

N/A — diff is docs-only; it adds no Rust implementation, functions, methods, result shapes, helpers, builders, or impurity surfaces.

  1. TESTING.md.

Compliant — no implementation or behavioral claim is promoted to landed/completed status, so no same-PR test is required. The prototype scope is explicitly future worker output at docs/design-affected-set-lens.md:387-392, while the CI integration is explicitly deferred at docs/design-affected-set-lens.md:351-363. The doc’s test-selection model also stays aligned with .dag TestClaim direction by intersecting affected-set output with TestClaim references at docs/design-affected-set-lens.md:355-356. chatgpt-review-8668975d-3733-4f…

  1. LOCKED DESIGN DECISIONS.

Compliant — the PR introduces a new locked R4.B terminology decision rather than diverging from an existing lock: docs/design-affected-set-lens.md:11-17 locks “query is user-surface, lens is substrate,” and docs/design-affected-set-lens.md:159 explicitly avoids conflating the PB-runtime bounded kernel with the full substrate query surface.

  1. TRACKED vs UNTRACKED DEBT.

Compliant — the only scaffold-like work is bounded as prototype/R4 delivery, not silently made permanent: prototype deliverables are named at docs/design-affected-set-lens.md:387-392, non-deliverables are bounded at docs/design-affected-set-lens.md:394-401, and CI integration is separately deferred to R4 full delivery at docs/design-affected-set-lens.md:351-363.

2.5. Top-down PM intent review

Compliant. The highest-level intent is preserved: gunbc’s correctness dimensions should be structural, lens-readable facts, and user/tooling queries should not create a second substrate authority. The diff reinforces that by treating “affected-set” as an Introspect-config lens (docs/design-affected-set-lens.md:20-24), by making the affected set dimension-aware rather than value-only (docs/design-affected-set-lens.md:43-51), and by requiring fail-closed inclusion when an empty delta cannot be proven (docs/design-affected-set-lens.md:84-97). It also preserves the locked two-surface substrate shape instead of narrowing the query surface to the PB runtime kernel (docs/design-affected-set-lens.md:146-159). chatgpt-review-7bb7be96-61ed-43…

3. Verdict

APPROVE — I found no diff-cited invariant violation. The PR is docs-only, but it is doing real design work: it locks the query/lens terminology split, avoids new substrate duplication, and carries the affected-set idea through fail-closed dimension-aware examples without prematurely claiming implementation delivery.

@briansrls

Copy link
Copy Markdown
Contributor Author

Addressed codex BLOCKING #1+#2 in commit 2882168e7 — both valid; substrate-vs-user-surface boundary now explicit.

# Finding Root Fix
1 §0 framed apply_lens(..., config) shorthand as substrate config sum, but per design-lens-application-surface.md §2 + src/v3/std/lens_application.dag, EnforcedApplication and IntrospectApplication are TWO SEPARATE TOP-LEVEL CARRIERS (P2 illegal-state-avoidance; v3 substrate can't express per-variant generics) Substrate sum-type wording where there's no substrate sum Reframed: "user-surface shorthand selects one of two separate top-level carriers; no Config<...> substrate sum"
2 Output Set<{file, span}> conflated substrate (NodeRef structural identity) with tooling rendering (source location) — P2 single-authority/structural-reference violation Substrate output shape ≠ user-rendering shape Added explicit "lens substrate output is structural" paragraph + updated all output references to Set<NodeRef> (substrate); {file, span} framed as adapter step at tooling-consumer boundary

§6 R4.B family table also corrected (affected-set Output: Set<{file, span}> → Set<NodeRef> substrate + CLI/IDE adapter note).

The substrate-vs-user-surface boundary is now load-bearing in §0 — workers reading this for prototype scope should emit Set<NodeRef> (with NodeRef-keyed dimension/provenance metadata); adapters render to user shapes. This will also flow back to silent-bat-152's prototype review at PR #2701 (which currently emits something — need to verify against this corrected substrate framing on next review pass).

— sent from deep-wolf-155

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: openai-pro / gpt-5-5-thinking
  • Commit: 2882168e · Trigger: manual
  • Comparison: main @ a4152472 ... docs/design-affected-set-lens @ 2882168e
  • Conversation: View conversation

1. Story of the diff

This PR reframes R4.B from a possible “queries-as-data” substrate into an Introspect-lens saturation lane: “query” becomes user-facing terminology, while substrate authority remains Lens plus EnforcedApplication / IntrospectApplication carriers. The WISHLIST lock at WISHLIST.md:70 is the top-level contract: no separate Query substrate carrier, and R4.B is tooling adapters over Introspect-config lenses.

The new design doc then works that contract through one concrete R4.B use case: an affected-set lens for fine-grained build/test selection. The load-bearing mechanism is dimension-aware propagation: affectedness is not just value behavior, but the union of dimensions a consumer reads — value, cost, complexity, effect, refinement, etc. (docs/design-affected-set-lens.md:46-54, docs/design-affected-set-lens.md:79-84). The doc also gives the fail-closed rule for unknown deltas (docs/design-affected-set-lens.md:122-127) and keeps rendering concerns at the tooling boundary rather than inside the lens substrate (docs/design-affected-set-lens.md:15-25).

2. Invariant categories

  1. LAYER MODEL (substrate vs implementation).

Compliant — the diff explicitly keeps this as design/user-surface work rather than ratifying a new substrate shape: docs/design-affected-set-lens.md:7 says “Not a substrate-shape ratification,” and docs/design-affected-set-lens.md:19 says “No ‘Query’ substrate type, ever.” This aligns with the thesis’s two coordinated substrate shapes and avoids inventing a seventh connective / sixth behavior without stop-signal evidence. chatgpt-review-28bd590b-f7d3-41…

  1. INVARIANTS.md + modeling-discipline.md.

Compliant — Boundary Discipline / single authority is handled by making query a surface nickname over the existing lens mechanism: WISHLIST.md:70 says “There is only lens as a substrate type,” and docs/design-affected-set-lens.md:17 says query maps to the same substrate mechanism, not a separate type. Fail-closed is also explicit: docs/design-affected-set-lens.md:124-125 excludes only proven-empty deltas and includes unknown deltas by default. This matches P2/P3’s single-authority and fail-closed requirements. chatgpt-review-33acd20b-9515-4c…

  1. CODING.md.

N/A — diff is documentation only; no Rust implementation, helpers, APIs, method placement, panic surface, or error/result shape is changed.

  1. TESTING.md.

Compliant for this doc-only scope — no implementation is added, so no test is required in this PR. The design preserves test selection as structural data rather than hand-maintained behavior: docs/design-affected-set-lens.md:358-364 requires per-dimension affected-set intersection with TestClaim references and explicitly rejects value-only selection. That is consistent with TESTING.md’s .dag-native TestClaim trajectory. chatgpt-review-64b35285-0f54-42…

  1. LOCKED DESIGN DECISIONS.

Compliant — the PR is itself locking the query-is-lens decision rather than diverging from it: docs/design-affected-set-lens.md:11 marks §0 locked, docs/design-affected-set-lens.md:13 names the two top-level carriers, and WISHLIST.md:86 resolves the prior “confirm via stress test” language to “query IS lens.” I do not see an unreconciled divergence from the uploaded locked Pure Bootstrap / thesis constraints.

  1. TRACKED vs UNTRACKED DEBT.

Compliant — the prototype bridge is bounded and named: docs/design-affected-set-lens.md:390-395 lists the worker deliverables, and docs/design-affected-set-lens.md:397-404 names what the worker is not delivering and says R4 full delivery operationalizes the prototype. That gives documentation, bounds, and a dissolution/continuation trigger; I don’t see an untracked TODO or permanent scaffold.

2.5. Top-down PM intent review

Compliant. The highest-level intent is preserved: correctness dimensions remain structural facts/lenses, not a parallel query subsystem, and user-facing “queries” are tooling invocations over Introspect lenses. The doc is especially careful not to dilute structural correctness into value-only change detection: docs/design-affected-set-lens.md:52-54 and docs/design-affected-set-lens.md:364 both require dimension-aware propagation, including cost/effect/complexity consumers. That preserves the thesis claim that dimensions are structural and lens-readable rather than test-time annotations. chatgpt-review-28bd590b-f7d3-41…

3. Verdict

APPROVE. The PR is doc-only, but it does real architectural cleanup: it locks “query” as user-surface terminology, keeps substrate authority on lenses, defines affected-set propagation fail-closed, and bounds the prototype work without introducing untracked scaffolding.

@briansrls
briansrls merged commit 4086185 into main May 11, 2026
3 checks passed
@briansrls
briansrls deleted the docs/design-affected-set-lens branch June 1, 2026 18:41
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