Skip to content

Variant collision diagnostic + factor algebra_templates_for_profile into std/algebra.dag - #279

Merged
briansrls merged 6 commits into
mainfrom
cursor/variant-collision-type-enrichment-66aa
Apr 1, 2026
Merged

briansrls merged 6 commits into
mainfrom
cursor/variant-collision-type-enrichment-66aa

Conversation

@briansrls

@briansrls briansrls commented Apr 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Variant collision diagnostic, algebra enrichment factoring, warning infrastructure removal, review violation fixes, and doc updates.

1. Variant collision diagnostic (Stream 1, violation #1)

Adds a VariantCollision error diagnostic when two explicitly imported enums collide on a variant name. On collision, the ambiguous binding is removed from locals (fail-closed) — later phases see an unresolved variant rather than a fabricated winner.

  • 00_core.dag: new VariantCollision { variant, enum1, enum2, span } variant in CompilerDiagnostic
  • 04_infer.dag: VariantFoldState accumulator with pre-computed imported_enum_names index (FF-compliant); collision removes binding instead of overwriting
  • Stage0 Rust mirrors (v2_std_core.rs, v2_compiler_infer.rs)

2. L1 Tier 2 — factor enrich_kernel_type to call .dag functions in std/algebra.dag

Moves algebra_templates_for_profile from 04_types.dag into std/algebra.dag, co-locating the dispatcher with the data table and per-profile template functions.

  • dsl/std/algebra.dag: adds algebra_templates_for_profile function
  • src/v2/04_types.dag: imports dispatcher from std.algebra, removes local definition
  • v2_compiler_infer_types.rs: adds BooleanAlgebraCollectionProfile variant + templates, fixes Set/NonEmptySet profile mapping

3. Warning infrastructure removal (INVARIANTS.md C-8)

Per INVARIANTS.md: "no warning severity for semantic errors." Promotes all warnings to errors and eliminates the warning concept.

  • OwnershipWarning → OwnershipViolation; VariantCollisionWarning → VariantCollision
  • is_error_diagnostic → always returns true
  • Removed "error"/"warning" severity branching
  • dsl/std/symbols.dag: renamed SymbolId variants to fix real collision with SemanticColor

4. Review violation fixes (3 violations resolved)

Violation 1 — No fallbacks that fabricate: On variant collision between two explicitly imported enums, the binding is now removed from locals instead of fabricating a winner. Later phases see an unresolved variant.

Violation 2 — Facts Flow Forward: Pre-computed imported_enum_names as a Map<String, Bool> from resolved_imports before the variant fold. Inner fold performs O(1) map lookups instead of rescanning the import list per variant.

Violation 3 — Early Detection (ownership→emit boundary): Added a gate after ownership analysis in compile.dag and stage0 Rust. If ownership_diagnostics produces errors, the pipeline returns early with empty files instead of proceeding to emit.

5. Documentation updates

  • INVARIANTS.md: Marked escape hatch C-8 as FIXED
  • ROADMAP.md: Checked off enrich_kernel_type Tier 2, per-profile field builders Tier 1, Set/NonEmptySet profile Tier 2.5
  • docs/bootstrap-b-and-lane-work-plan.md: Added DONE status banners to sections 1 and 2

Testing

  • cargo clippy --all-targets -- -D warnings — clean
  • cargo test --workspace --exclude v2-compiler-tests — 12 passed
  • cargo test -p v2-compiler-tests — 282 passed
  • cargo test -p v2-compiler-tests full_dsl_compiles -- --ignored — passed
  • cargo test -p v2-compiler-tests strict_compile_diagnostic_count -- --ignored — ratchet holds at 0
Open in Web Open in Cursor 

cursoragent and others added 2 commits April 1, 2026 15:41
… collisions

When two explicitly imported enums both define the same variant name,
emit a warning diagnostic. The existing disambiguation logic (prefer
the explicitly imported enum) still applies — this adds visibility
into the collision without changing resolution behavior.

Changes:
- 00_core.dag: add VariantCollisionWarning variant to CompilerDiagnostic,
  wire into diagnostic_to_span, diagnostic_to_message, is_error_diagnostic
- 04_infer.dag: add VariantFoldState type, refactor imported_variant_locals
  fold to track collision warnings, thread into ModuleContext diagnostics
- v2_std_core.rs: mirror VariantCollisionWarning in stage0 Rust
- v2_compiler_infer.rs: mirror VariantFoldState and collision detection

Co-authored-by: Brian Searls <briansrls@users.noreply.github.com>
…nAlgebraCollectionProfile

Move the AlgebraProfile->templates dispatch function from 04_types.dag
to std/algebra.dag so the profile-to-template mapping lives with the
data table and template functions it dispatches to. This reduces
04_types.dag to importing the dispatch function rather than defining it.

Also adds BooleanAlgebraCollectionProfile (set algebra with union,
intersect, diff, member) to stage0 Rust, aligning the Rust enum and
data table with the .dag source.

Changes:
- dsl/std/algebra.dag: add algebra_templates_for_profile dispatcher
- src/v2/04_types.dag: import algebra_templates_for_profile from
  std.algebra, remove local definition and per-profile fn imports
- v2_compiler_infer_types.rs: add BooleanAlgebraCollectionProfile
  variant, boolean_algebra_collection_templates(), update KERNEL_ALGEBRA_PROFILE
  for Set/NonEmptySet, add arm in algebra_templates_for_profile

Co-authored-by: Brian Searls <briansrls@users.noreply.github.com>
@briansrls
briansrls marked this pull request as ready for review April 1, 2026 15:49
cursoragent and others added 2 commits April 1, 2026 15:52
The test counted all diagnostics including warnings, but
VariantCollisionWarning is a warning (not an error). Filter using
is_error_diagnostic so only errors cause test failure.

Co-authored-by: Brian Searls <briansrls@users.noreply.github.com>
Per INVARIANTS.md (escape hatch C-8): no warning severity in the
compiler. All diagnostics are errors.

- Rename OwnershipWarning → OwnershipViolation (00_core.dag, compile.dag,
  v2_std_core.rs, v2_compiler_compile.rs)
- Rename VariantCollisionWarning → VariantCollision (00_core.dag,
  04_infer.dag, v2_std_core.rs, v2_compiler_infer.rs)
- Make is_error_diagnostic always return true (00_core.dag, v2_std_core.rs)
- Remove warning/error severity branching in serialize_diagnostic
  (compile.dag, v2_compiler_compile.rs, main.rs)
- Rename VariantFoldState.warnings → collision_errors
- Revert pipeline.rs test to count all diagnostics (no filter)
- Fix DSL collision: rename SymbolId variants Success/Failure/Warning/Info
  → StatusSuccess/StatusFailure/StatusWarning/StatusInfo to avoid collision
  with SemanticColor variants

Co-authored-by: Brian Searls <briansrls@users.noreply.github.com>

@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 (2 violations, 2 good, 1 improve)

Invariant violations (2)

Modeling (good)

  • dsl/std/algebra.dag Moving the profile-to-template dispatch into std.algebra keeps the algebra witness as the single authority for which operations a kernel type inhabits, which is the right compositional layer.
  • src/v2/04_types.dag Deleting the local algebra_templates_for_profile helper and importing the algebra authority removes a duplicate representation and improves harmony with the existing kernel_algebra_profile model.

Modeling (improve)

  • src/v2/00_core.dag VariantCollisionWarning models namespace ambiguity as advisory lint, but the domain fact is an unresolved ambiguity and would be more faithful as an error or explicit ambiguous-binding state.

The algebra helper extraction is a compositional improvement, but the new variant-collision handling is not fail-closed and introduces a fresh repeated-scan regression.

Comment thread src/v2/04_infer.dag
})
} else { vacc }
VariantFoldState {
locals: map_insert(vacc.locals, child.name, TypeBinding { name: child.name, resolved: binding.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.

Invariant violation: When two explicitly imported enums share a variant name, this code still overwrites locals with one enum after only emitting VariantCollisionWarning, fabricating a winner for an ambiguous reference and violating No fallbacks that fabricate / Explicit boundary contracts.

Comment thread src/v2/04_infer.dag Outdated
let curr_is_imported = resolved_imports |> any(imp =>
imp.specific_names |> any(n => n == binding.resolved.name)
)
let prev_is_imported = resolved_imports |> any(imp =>

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.

Invariant violation: The new prev_is_imported check rescans resolved_imports inside the inner variant fold instead of carrying an indexed import-membership fact forward, violating the Performance invariant's Facts Flow Forward rule.

@briansrls

Copy link
Copy Markdown
Contributor Author

Invariant review (6d2716a8)

Violations (2):

  • src/v2/04_infer.dag:2524 When two explicitly imported enums share a variant name, this code still overwrites locals with one enum after only emitting VariantCollisionWarning, fabricating a winner for an ambiguous reference and violating No fallbacks that fabricate / Explicit boundary contracts.
  • src/v2/04_infer.dag:2516 The new prev_is_imported check rescans resolved_imports inside the inner variant fold instead of carrying an indexed import-membership fact forward, violating the Performance invariant's Facts Flow Forward rule.

Improve:

  • src/v2/00_core.dag VariantCollisionWarning models namespace ambiguity as advisory lint, but the domain fact is an unresolved ambiguity and would be more faithful as an error or explicit ambiguous-binding state.

The algebra helper extraction is a compositional improvement, but the new variant-collision handling is not fail-closed and introduces a fresh repeated-scan regression.

@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 (1 violations, 3 good, 3 improve)

Invariant violations (1)

Modeling (good)

  • src/v2/00_core.dag Adding VariantCollision to the closed CompilerDiagnostic sum is the right core-layer model because ambiguity becomes a typed compiler fact instead of an ad-hoc message.
  • src/v2/04_infer.dag VariantFoldState is a coherent infer-local product type because it threads both chosen locals and accumulated collision diagnostics through one fold state.
  • dsl/std/symbols.dag The Status* rename cleanly separates symbol identity from SemanticColor, which is a faithful std-layer distinction.

Modeling (improve)

  • src/v2/00_core.dag Now that every CompilerDiagnostic is effectively an error, the boundary would compose more cleanly if severity disappeared structurally instead of being represented by a degenerate classifier.
  • src/v2/04_infer.dag A more compositional model would represent ambiguous variant lookup as its own binding shape instead of winner-plus-error, so later phases cannot consume a fabricated enum choice.
  • dsl/std/symbols.dag If the symbol vocabulary keeps growing, compose standard_symbols from per-domain tables so the flat list stays derived instead of hand-expanded.

The PR improves the diagnostic and symbol models, but fail-closed handling is still incomplete and the previously flagged variant-collision issues remain unresolved.

Comment thread src/v2/compile.dag
match decision {
SharedError { binding: binding, consumer_count: count, sites: sites } =>
[make_error_node(diagnostic: OwnershipWarning { binding: binding, fn_name: proof.func_name, consumers: count, span: no_span() }, module_name: proof.func_name)]
[make_error_node(diagnostic: OwnershipViolation { binding: binding, fn_name: proof.func_name, consumers: count, span: no_span() }, module_name: proof.func_name)]

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.

Invariant violation: Stage 6 now emits OwnershipViolation diagnostics here, but the pipeline still proceeds through artifact planning and emit without gating on ownership_diags, so a known error crosses the ownership→emit boundary in violation of the Early Detection invariant.

@briansrls

Copy link
Copy Markdown
Contributor Author

Invariant review (0cecc3e0)

Violations (1):

  • src/v2/compile.dag:122 Stage 6 now emits OwnershipViolation diagnostics here, but the pipeline still proceeds through artifact planning and emit without gating on ownership_diags, so a known error crosses the ownership→emit boundary in violation of the Early Detection invariant.

Improve:

  • src/v2/00_core.dag Now that every CompilerDiagnostic is effectively an error, the boundary would compose more cleanly if severity disappeared structurally instead of being represented by a degenerate classifier.
  • src/v2/04_infer.dag A more compositional model would represent ambiguous variant lookup as its own binding shape instead of winner-plus-error, so later phases cannot consume a fabricated enum choice.
  • dsl/std/symbols.dag If the symbol vocabulary keeps growing, compose standard_symbols from per-domain tables so the flat list stays derived instead of hand-expanded.

The PR improves the diagnostic and symbol models, but fail-closed handling is still incomplete and the previously flagged variant-collision issues remain unresolved.

cursoragent and others added 2 commits April 1, 2026 17:53
INVARIANTS.md:
- Mark C-8 (Warning severity for semantic errors) as FIXED
- Strikethrough stale warning prose, add fix dates
- Update Root Cause C bullet and design-decision bullet

ROADMAP.md:
- Check off 'enrich_kernel_type calls .dag function in std/algebra.dag'
- Check off 'Convert per-profile field builders to .dag functions'
- Check off 'Fix Set/NonEmptySet profile' (Tier 2.5)
- Update ownership violation prose (no longer deferred)

docs/bootstrap-b-and-lane-work-plan.md:
- Add DONE status banners to sections 1 and 2

pipeline.rs:
- Fix stale comment ('not downgraded to warnings' → 'all diagnostics are errors')

Co-authored-by: Brian Searls <briansrls@users.noreply.github.com>
…ownership gate

Violation 1 — No fallbacks that fabricate:
When two explicitly imported enums collide on a variant name, the
ambiguous binding is now REMOVED from locals instead of fabricating
a winner. Later phases will see an unresolved variant and produce a
proper error rather than silently using one enum's binding.

Violation 2 — Facts Flow Forward:
Pre-compute imported_enum_names as a Map<String, Bool> from
resolved_imports BEFORE the variant fold. The inner fold performs
O(1) map lookups instead of rescanning the import list for every
variant of every enum.

Violation 3 — Early Detection (ownership→emit boundary):
Added a gate after ownership analysis in compile.dag and stage0 Rust.
If ownership_diagnostics produces errors, the pipeline returns early
with empty files instead of proceeding to artifact planning and emit.

Co-authored-by: Brian Searls <briansrls@users.noreply.github.com>
@briansrls
briansrls merged commit d8f2c04 into main Apr 1, 2026
1 check passed
briansrls added a commit that referenced this pull request Apr 1, 2026
Merged main (coercion design #278, variant collision #279, etc.)
Resolved ROADMAP.md conflict: kept implemented TypeRendering struct,
merged coercion dissolution notes.

Reviewer fixes:
- Removed orphaned Char type_map entry (chars() now returns List<Int>,
  no Char producer exists — reviewer correctly flagged inconsistency)
- Updated ROADMAP E0c acceptance to reflect current implemented state

Reviewer items deferred to follow-up (need design/modeling):
- find_struct_by_fields heuristic → needs record literal inference to
  carry struct name (boundary sufficiency)
- Fold refinement magic name checks → needs bidirectional inference
- with() string-keyed branch → needs algebra operation registry
- TypeRendering concern mixing → dissolves into coercion (M5)
- Codepoint carrier modeling → algebra design work

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@briansrls
briansrls deleted the cursor/variant-collision-type-enrichment-66aa 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.

2 participants