Skip to content

De-fork grounding keystone: fix v2 generic type-alias instantiation so FreeMonoid aliases resolve - brief in docs plans dsl-v2-defork-audit section 3b - #5552

Merged
briansrls merged 12 commits into
mainfrom
session/bright-deer-111
Jun 23, 2026
Merged

briansrls merged 12 commits into
mainfrom
session/bright-deer-111

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jun 22, 2026 •

Copy link
Copy Markdown
Contributor

De-fork grounding keystone — generic type-alias instantiation for coproduct aliases

Brief: docs/plans/dsl-v2-defork-audit.md §3b (operator ruling), phase 1 — the keystone. Also docs/plans/fold-ergonomics.md Root B #1 / dissolve-on feature:free-monoid-entry-generic-inference. Scope = keystone only; def-unification (phase 2), repoints (phase 3) and 🟡-marker dissolution (phase 4) are later PRs.

The bug

A non-parametric alias whose RHS is an applied generic coproduct — type QualifiedName = FreeMonoid<Symbol> — did not expand to its underlying coproduct, so the FreeMonoid variants (Empty | Cons) were unreachable through the alias name. This forced consumers (qualified_name.dag, catalog.dag fold_list, ParseTable) to hand-roll a parallel coproduct + eq/for_all.

Before (match on an alias-typed value):

type QName = FreeMonoid<Symbol>
fn qname_len(qn: QName) -> Int {
  match qn { Empty => 0  Cons { head: _, tail: t } => 1 + qname_len(qn: t) }
}
error: variant 'Empty' not found in type 'QName'
error: variant 'Cons'  not found in type 'QName'

The same value typed directly as FreeMonoid<Symbol> matched fine — the bug was purely the alias indirection.

After: resolves and runs (qname_len over a 3-element path returns 3; length, field-binding and the Empty variant all work through the alias).

Root cause & fix

In src/v1/04_resolve.dag resolve_node_bounded, a bare alias reference followed one level of .inferred to the un-instantiated applied-generic node (FreeMonoid<Symbol>, NoConnective with type-arg children) but never ran the generic instantiation that the direct-use branch (is_user_generic_use_site) already performs. The fix runs that same instantiation one pass when the alias target is an applied generic.

  • Falls out of the existing model — reuses resolve_generic_use_decl + resolve_node_bounded; no special-case patch, no substrate change.
  • Gated to Disj (coproduct) decls — principled and found by execution: leaving it ungated instantiated record aliases too (Nat = CommutativeSemiring<Magnitude>), breaking Optional<alias> Present/Absent synthesis (17 dsl errors). Records must stay the bare applied node; the gate is the §5 fail-closed boundary.
  • Emitted seed (v1_compiler_infer_resolve.rs) hand-synced to the .dag.

Verification (green by execution)

  • CI floor discovery corpus: 694/694 PASS (zero type-resolution regressions tree-wide).
  • dsl whole-tree compile --target rust: 0 diagnostics.
  • Durable RED-on-revert witness: src/v2/test/claim/algebra/generic_alias_coproduct_instantiation_test.dag — constructs, matches and recurses through type SymbolPath = FreeMonoid<Symbol>; reverting the fix makes it fail to typecheck (a wall, not a passive assertion).
  • cargo fmt --all --check clean; cargo clippy -p v1-compiler --all-targets -- -D warnings clean. (The floor's rust_monolith_gate flagged during the run was sccache infra flakiness, not this change.)

🤖 Generated with Claude Code

@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 22, 2026 20:26
briansrls added a commit that referenced this pull request Jun 22, 2026
…stones

Surgical ROADMAP.md updates from the 2026-06-22 session (short lines, density in
docs per the roadmap's own no-dual-rep rule):
- §5 de-fork: grounding cluster UNPARKED (operator ruled FreeMonoid/algebra single
  authority — coproduct structural authority, record-surface derived, grounded-
  realization wins); de-fork + self-host fused into one grounding lane (Root A
  emit-seam / Root B keystone), v1-coupled coercion/node fenced to v1-delete.
- ✦ ergonomics: generic-inference keystone landed (#5552, green-by-execution).
- §1 CI: rust-gate run-all at nextest speed CI-green-proven (#5427).
- §1 G2: cross-host placement dispatched (proud-tern-439), live apply fenced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jun 22, 2026
…content review; re-homes into .dag after #5535] (#5560)

* WIP: ROADMAP planning

* docs(roadmap): reflect FreeMonoid grounding ruling + keystone/CI milestones

Surgical ROADMAP.md updates from the 2026-06-22 session (short lines, density in
docs per the roadmap's own no-dual-rep rule):
- §5 de-fork: grounding cluster UNPARKED (operator ruled FreeMonoid/algebra single
  authority — coproduct structural authority, record-surface derived, grounded-
  realization wins); de-fork + self-host fused into one grounding lane (Root A
  emit-seam / Root B keystone), v1-coupled coercion/node fenced to v1-delete.
- ✦ ergonomics: generic-inference keystone landed (#5552, green-by-execution).
- §1 CI: rust-gate run-all at nextest speed CI-green-proven (#5427).
- §1 G2: cross-host placement dispatched (proud-tern-439), live apply fenced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
briansrls and others added 3 commits June 22, 2026 21:05
An isolation test reverted 04_resolve.dag + the .rs seed to origin/main to
prove the dsl_compile_clean fixture errors are pre-existing (they are —
identical 2 errors with the fix reverted). The auto-committer captured the
reverted state mid-test; this restores the real fix (the let-bound
target_is_coproduct_use coproduct-alias instantiation).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Jun 22, 2026
#5535)

#5560 hand-edited ROADMAP.md on main (FreeMonoid grounding ruling + keystone/CI
milestones) with intent to "re-home into .dag after #5535" — but it landed BEFORE
#5535, so transcribe its content into the authority now or the generated ROADMAP.md
would drop/drift it (zero-content-loss). Folded all 5 edits:
- §0 rust-gate: run-all-at-nextest-speed CI-green line (#5427)
- ✦ Milestones + generic-inference fix: #5552 keystone green
- §1 G2: + cross-host placement (proud-tern-439)
- §5 de-fork restructure: grounding cluster UNPARKED → Root A / Root B / v1-coupled

All 8 #5560 phrases present + matching; 2 superseded items removed; whole-doc audit
zero missing refs/paths; 5 witnesses green; gate drift-clean + red-receipt intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@briansrls briansrls closed this in 06aff7d Jun 22, 2026
@gunbai-bot gunbai-bot Bot reopened this Jun 22, 2026
briansrls added a commit that referenced this pull request Jun 23, 2026
…vec![]) value-seed paired to rust_seed_host_container_base (independent slice, does NOT require the #5552 generic-alias keystone), per docs/plans/dsl-v2-defork-audit.md section 3b (#5575)

* WIP: Self-host Lane 1 value-grounding in 05_emit_rust single owner, per docs/

* WIP: Self-host Lane 1 value-grounding in 05_emit_rust single owner, per docs/

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
@briansrls
briansrls merged commit ec8d429 into main Jun 23, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/bright-deer-111 branch June 23, 2026 00:56
briansrls added a commit that referenced this pull request Jul 3, 2026
…oupling

- Dissolved type QualifiedName = FreeMonoid<Symbol>; deleted qualified_name_eq/for_all/singleton.
- Migrated ~22 consumers (imports, QnEmpty/QnCons→Empty/Cons, eq→==, for_all→for_all).
- == gate PROVEN green (freemonoid_eq_witness_test): structural == matches old qualified_name_eq, no straddle.
- Rewrote 2 FreeMonoid raw-tail-match sites (qn_fold_step, layer_prefix) to list_head idiom
  (recursive tail raw-match still hits the #5552 'variant not found in type FreeMonoid' resolver gap).

BLOCKER: brief's 'QualifiedName is v2-ONLY' premise is FALSE. v1 Rust seed hardcodes QnEmpty/QnCons
tags in host builtins (cli_run.rs qualified_name_value_{from_dotted_string,to_module_path},
v1_interpreter.rs, external_authority_project.rs x7, emit_qualified_name_dag). Runtime produces
QnCons Values → .dag now expects Empty/Cons → non-exhaustive crash. Completing needs lockstep seed
edits (cli_run.rs is #6046-gated). Reported to operator; not touching seed unilaterally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jul 3, 2026
… over FreeMonoid<Symbol>)

Per operator re-scope (v2-only premise was false; this is a v2-authority + v1-seed-realization de-fork):

Seed (src/v1/stage0/src/): the three QualifiedName-specific host builtins are now GENERIC
FreeMonoid<Symbol> marshaling — seed no longer knows QualifiedName/QnEmpty/QnCons as a domain:
- qualified_name_value_from_dotted_string -> free_monoid_symbol_value_from_dotted_string
  (type_name FreeMonoid, variants Empty/Cons)
- qualified_name_value_to_module_path     -> free_monoid_symbol_value_to_dotted_string (matches Empty/Cons)
- emit_qualified_name_dag                 -> free_monoid_symbol_emit_dag (emits Empty/Cons + algebra import)
  all callers (coproduct_reflection, external_authority_project x7, v1_interpreter) updated.
  Bounded: no resolver changes, no broad cli_run cleanup. .dag-facing std fn name kept.

Verified by execution (rebuilt seed): == gate green; dotted-string round-trip green through the
generic bridge; layer_prefix green; external-authority corpus witnesses green; Rust manifest
host emit round-trip test green (3/3).

Docs corrected (§8): fold-ergonomics.md, dag-v2-defork-audit.md + .dag twin now state #5552 fixed
SIMPLE generic-alias instantiation; recursive-tail raw-match remains a resolver gap avoided via
the list_head/algebra idiom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jul 3, 2026
…idge made generic (#6195)

* WIP: roadmap hosting work

* WIP: roadmap hosting work

* WIP QualifiedName→FreeMonoid: v2 .dag half done, BLOCKED on v1-seed coupling

- Dissolved type QualifiedName = FreeMonoid<Symbol>; deleted qualified_name_eq/for_all/singleton.
- Migrated ~22 consumers (imports, QnEmpty/QnCons→Empty/Cons, eq→==, for_all→for_all).
- == gate PROVEN green (freemonoid_eq_witness_test): structural == matches old qualified_name_eq, no straddle.
- Rewrote 2 FreeMonoid raw-tail-match sites (qn_fold_step, layer_prefix) to list_head idiom
  (recursive tail raw-match still hits the #5552 'variant not found in type FreeMonoid' resolver gap).

BLOCKER: brief's 'QualifiedName is v2-ONLY' premise is FALSE. v1 Rust seed hardcodes QnEmpty/QnCons
tags in host builtins (cli_run.rs qualified_name_value_{from_dotted_string,to_module_path},
v1_interpreter.rs, external_authority_project.rs x7, emit_qualified_name_dag). Runtime produces
QnCons Values → .dag now expects Empty/Cons → non-exhaustive crash. Completing needs lockstep seed
edits (cli_run.rs is #6046-gated). Reported to operator; not touching seed unilaterally.

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

* WIP: roadmap hosting work

* WIP: roadmap hosting work

* QualifiedName seed de-fork: v1 host-builtins made generic (Empty/Cons over FreeMonoid<Symbol>)

Per operator re-scope (v2-only premise was false; this is a v2-authority + v1-seed-realization de-fork):

Seed (src/v1/stage0/src/): the three QualifiedName-specific host builtins are now GENERIC
FreeMonoid<Symbol> marshaling — seed no longer knows QualifiedName/QnEmpty/QnCons as a domain:
- qualified_name_value_from_dotted_string -> free_monoid_symbol_value_from_dotted_string
  (type_name FreeMonoid, variants Empty/Cons)
- qualified_name_value_to_module_path     -> free_monoid_symbol_value_to_dotted_string (matches Empty/Cons)
- emit_qualified_name_dag                 -> free_monoid_symbol_emit_dag (emits Empty/Cons + algebra import)
  all callers (coproduct_reflection, external_authority_project x7, v1_interpreter) updated.
  Bounded: no resolver changes, no broad cli_run cleanup. .dag-facing std fn name kept.

Verified by execution (rebuilt seed): == gate green; dotted-string round-trip green through the
generic bridge; layer_prefix green; external-authority corpus witnesses green; Rust manifest
host emit round-trip test green (3/3).

Docs corrected (§8): fold-ergonomics.md, dag-v2-defork-audit.md + .dag twin now state #5552 fixed
SIMPLE generic-alias instantiation; recursive-tail raw-match remains a resolver gap avoided via
the list_head/algebra idiom.

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

* WIP: roadmap hosting work

* WIP: roadmap hosting work

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jul 5, 2026
…r (QualifiedName, structural ==) + last dsl stragglers (E0 / PR-0b)

The fired subject_roster_string_dissolution_trigger (vocab.dag), executed:
SubjectRoster carried BOTH filesystem scope roots and declaration names as one
List<String> - a state-space conflation with two different comparison
semantics (path-literal vs segment-structural) in one representation.

- vocab.dag: SubjectRoster.entries -> List<QualifiedName> (v2.std.qualified_name
  authority; compared via structural ==, qualified_name_eq); new ScopeRoster
  { roots: List<String> } for tree roots; ScopeNarrowed.missing -> ScopeRoster;
  scope_roster_covers/subject_roster_covers now two fns with the right
  semantics each; trigger row deleted, split note left on the carrier.
- standing_intent: desired_scope -> ScopeRoster; required_subjects grounds
  v1.compiler.infer.build_type_env via qualified_name_from_dotted_string.
- contract/receipts/gate/enforcement_live: claimed_scope -> ScopeRoster;
  discovered_fn_subjects converts at the decl_facts boundary (subject_qn_of,
  same single pass, linear); self_application_for now reads facts directly
  (String prefix pre-conversion, fn-like only - TypeItem no longer counts
  toward self-application, a small honesty gain).
- NEW RED control: permuted_segment_subject_does_not_cover - a QualifiedName
  with the same segments in a different order must NOT satisfy the subjects
  leg (the discriminator List<String> equality could not express).
- self_application_liveness_discriminates gains a TypeItem-prefix control
  (kind filter proven, not just prefix).
- dsl stragglers renamed (operator ask): phase_profile_proof_plan.dag
  dsl/tools -> dag/tools AND phase_profile_claim_executor.rs --source-root
  dsl -> dag. The Rust consumer test was failing on main since #6165
  (source root does not exist: dsl); it now PASSES by execution - the only
  .rs change is that one literal.

Receipts by execution (2026-07-05): 11/11 gate_test (incl. new permuted
control), 10/10 enforcement_live witnesses; enrolled pair 40s/39s (QualifiedName
interning over 14,283 facts is in the noise); pinned 3-red/3-green verdict
unchanged (representation-only, zero leg flips - as planned);
phase_profile_claim_executor 1 passed.

Typechecker note: QualifiedName alias vs FreeMonoid<Symbol> does not unify in
an if-branch JOIN (nominal expectation flows from a record-field into fold
init while the then-branch expands structurally) - worked around by hoisting
the fold out of the record construction; assignment-position coercion is fine.
Same #5552 alias-instantiation residue family.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jul 5, 2026
…tructural subjects + last dsl stragglers (E0 PR-0b) (#6256)

* WIP: complexity lens enforcement

* WIP: complexity lens enforcement

* Enforcement rosters: split ScopeRoster (tree roots) from SubjectRoster (QualifiedName, structural ==) + last dsl stragglers (E0 / PR-0b)

The fired subject_roster_string_dissolution_trigger (vocab.dag), executed:
SubjectRoster carried BOTH filesystem scope roots and declaration names as one
List<String> - a state-space conflation with two different comparison
semantics (path-literal vs segment-structural) in one representation.

- vocab.dag: SubjectRoster.entries -> List<QualifiedName> (v2.std.qualified_name
  authority; compared via structural ==, qualified_name_eq); new ScopeRoster
  { roots: List<String> } for tree roots; ScopeNarrowed.missing -> ScopeRoster;
  scope_roster_covers/subject_roster_covers now two fns with the right
  semantics each; trigger row deleted, split note left on the carrier.
- standing_intent: desired_scope -> ScopeRoster; required_subjects grounds
  v1.compiler.infer.build_type_env via qualified_name_from_dotted_string.
- contract/receipts/gate/enforcement_live: claimed_scope -> ScopeRoster;
  discovered_fn_subjects converts at the decl_facts boundary (subject_qn_of,
  same single pass, linear); self_application_for now reads facts directly
  (String prefix pre-conversion, fn-like only - TypeItem no longer counts
  toward self-application, a small honesty gain).
- NEW RED control: permuted_segment_subject_does_not_cover - a QualifiedName
  with the same segments in a different order must NOT satisfy the subjects
  leg (the discriminator List<String> equality could not express).
- self_application_liveness_discriminates gains a TypeItem-prefix control
  (kind filter proven, not just prefix).
- dsl stragglers renamed (operator ask): phase_profile_proof_plan.dag
  dsl/tools -> dag/tools AND phase_profile_claim_executor.rs --source-root
  dsl -> dag. The Rust consumer test was failing on main since #6165
  (source root does not exist: dsl); it now PASSES by execution - the only
  .rs change is that one literal.

Receipts by execution (2026-07-05): 11/11 gate_test (incl. new permuted
control), 10/10 enforcement_live witnesses; enrolled pair 40s/39s (QualifiedName
interning over 14,283 facts is in the noise); pinned 3-red/3-green verdict
unchanged (representation-only, zero leg flips - as planned);
phase_profile_claim_executor 1 passed.

Typechecker note: QualifiedName alias vs FreeMonoid<Symbol> does not unify in
an if-branch JOIN (nominal expectation flows from a record-field into fold
init while the then-branch expands structurally) - worked around by hoisting
the fold out of the record construction; assignment-position coercion is fine.
Same #5552 alias-instantiation residue family.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant