Skip to content

[semantic-reference-resolution] Patch 9: Unify shell-to-core linkage onto qualifiedReferences#17

Merged
subsetpark merged 3 commits into
masterfrom
semantic-reference-resolution/patch-9
Jun 8, 2026
Merged

[semantic-reference-resolution] Patch 9: Unify shell-to-core linkage onto qualifiedReferences#17
subsetpark merged 3 commits into
masterfrom
semantic-reference-resolution/patch-9

Conversation

@subsetpark

@subsetpark subsetpark commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Patch 9: Unify shell-to-core linkage onto qualifiedReferences

  • In evaluate_shell_modules, build core_handler_references_by_domain as the set of f'{core.module_name}.{s}' for s in (decision_surface | decision_products) over core files with a module_name.
  • Flag a shell module when its qualified_references does NOT intersect that same-domain qualified surface (mirroring rule 15's surface construction, but as a positive requirement).
  • Leave evaluate_core_modules and evaluate_state_modules unchanged (they match propertyChecks/operation-sequence evidence emitted bare).
  • Update evaluate_test.py shell-linkage cases to the qualified surface; add a regression test where a shell shares a bare name with core but holds no qualified reference and is therefore (correctly) flagged, and a positive case where a qualified core reference satisfies the rule.

Changes

  • In evaluate_shell_modules, build core_handler_references_by_domain as the set of f'{core.module_name}.{s}' for s in (decision_surface | decision_products) over core files with a module_name.
  • Flag a shell module when its qualified_references does NOT intersect that same-domain qualified surface (mirroring rule 15's surface construction, but as a positive requirement).
  • Leave evaluate_core_modules and evaluate_state_modules unchanged (they match propertyChecks/operation-sequence evidence emitted bare).
  • Update evaluate_test.py shell-linkage cases to the qualified surface; add a regression test where a shell shares a bare name with core but holds no qualified reference and is therefore (correctly) flagged, and a positive case where a qualified core reference satisfies the rule.

Files to Modify

  • evaluate.py (modify): Change evaluate_shell_modules to build the core handler surface as {core.module_name}.{decision_surface|decision_products} and intersect it with the shell file's qualified_references instead of bare api_references.
  • evaluate_test.py (modify): Update the shell-linkage tests to the qualified form and add a case proving an unrelated same-named bare function no longer satisfies the rule while a qualified core call does.

Gameplan Specification

module SEMANTIC_REFERENCE_RESOLUTION.

> ══════════════════════════════════════════
> THE GUARANTEE
> ══════════════════════════════════════════
> After this gameplan all four adapters (Go, OCaml, TypeScript,
> Swift) resolve references semantically. Every reference to a
> symbol owned by another module in the same language universe is
> emitted in qualifiedReferences as "owner-module.symbol", including
> uses written bare after open/import or within the same package.
> The dependency-direction rule (rule 15) therefore fires for a
> genuine cross-module reach in every adapter, not only OCaml, and
> never fires on an incidental shared bare name.

SourceFile.
Module.
Symbol.
ModuleType.
Domain.

module-name f: SourceFile => Module.
module-type f: SourceFile => ModuleType.
domain f: SourceFile => Domain.
owner s: Symbol => Module.
references f: SourceFile, s: Symbol => Bool.
qualified-reference f: SourceFile, m: Module, s: Symbol => Bool.
decision-reference f: SourceFile, s: Symbol => Bool.
---
> Semantic completeness: a reference to a symbol owned by a foreign
> module is always emitted qualified by that owner, even when the
> source writes it bare (after open / import / same package). This
> closes the syntactic hole described in issue 6.
all f: SourceFile, s: Symbol, references f s and owner s ~= module-name f | qualified-reference f (owner s) s.

> Prefix consistency: the qualifier on any emitted qualified
> reference is exactly the owner module's own module-name. Without
> this, rule 15's intersection silently never matches.
all f: SourceFile, m: Module, s: Symbol, qualified-reference f m s | m = owner s.

where

> ══════════════════════════════════════════
> RULE 15 (dependency direction) effectiveness
> ══════════════════════════════════════════
> A core or value module is flagged exactly when it holds a
> qualified reference to a same-domain implementation module's
> declared decision reference. reaches-implementation c holds when
> some same-domain shell/state/exempt file i declares a symbol s
> with qualified-reference c (module-name i) s. Incidental bare
> name collisions never flag because they are not emitted as
> qualified references.

implementation? mt: ModuleType => Bool.
core-or-value? mt: ModuleType => Bool.
reaches-implementation? c: SourceFile => Bool.
flagged? c: SourceFile => Bool.

core => ModuleType.
value => ModuleType.
shell => ModuleType.
state => ModuleType.
exempt => ModuleType.
---
all mt: ModuleType | implementation? mt = (mt = shell or mt = state or mt = exempt).
all mt: ModuleType | core-or-value? mt = (mt = core or mt = value).

> The flag fires iff a core/value file actually reaches a same-domain
> implementation surface via a qualified reference.
all c: SourceFile, core-or-value? (module-type c) | flagged? c = reaches-implementation? c.

> Soundness of the prohibition: a flag implies a real qualified
> cross-module reach into a same-domain implementation decision
> reference.
all c: SourceFile, reaches-implementation? c | some i: SourceFile | implementation? (module-type i) and domain i = domain c.

Patch Specification

module SEMANTIC_REFERENCE_RESOLUTION_PATCH_9.

> Patch 9 unifies the shell-to-core linkage rule onto qualifiedReferences:
> a shell module satisfies the linkage requirement only via a qualified
> reference to a same-domain core module's declared decision surface, so an
> unrelated same-named bare function no longer satisfies it. It depends on
> every adapter's semantic BEHAVIOR patch so a legitimately-linked shell
> (calling a core API via open / import / cross-package) is not regressed.

SourceFile.
Module.
Symbol.
ModuleType.
Domain.

module-name f: SourceFile => Module.
module-type f: SourceFile => ModuleType.
domain f: SourceFile => Domain.
owner s: Symbol => Module.
references f: SourceFile, s: Symbol => Bool.
qualified-reference f: SourceFile, m: Module, s: Symbol => Bool.
decision-reference f: SourceFile, s: Symbol => Bool.
decision-surface? f: SourceFile, s: Symbol => Bool.
shell? f: SourceFile => Bool.
core? f: SourceFile => Bool.
shell-linked? f: SourceFile => Bool.
---
> A shell module is linked iff it qualified-references a same-domain core
> module's declared decision surface.
all f: SourceFile, shell? f and shell-linked? f | some c: SourceFile, s: Symbol | core? c and domain c = domain f and decision-surface? c s and qualified-reference f (module-name c) s.

Implementation Notes

  • evaluate_shell_modules now mirrors rule 15's qualified surface shape exactly, but for core linkage: it skips core files without moduleName and builds {core.module_name}.{decision_surface|decision_products} before intersecting with each shell file's qualified_references.
  • I intentionally left evaluate_core_modules and evaluate_state_modules untouched. Their evidence still comes from bare property-check and operation-sequence reference sets, so moving them would require schema/adapter work outside Patch 9.
  • In addition to evaluate_test.py, I updated two Go integration fixtures and one Swift fixture so the adapter suites reflect the qualified-linkage contract instead of old syntactic/bare behavior. The Go passing shell fixtures now import a separate decision package because the Go adapter deliberately excludes same-package references from qualifiedReferences. The Swift enum-case fixture is now a negative collision regression: a shell method named add no longer satisfies linkage just because a same-domain core enum has a bare .add case.
  • I also broadened Swift semantic occurrence filtering to treat IndexStore .call roles as reference candidates in addition to .reference. This keeps the extraction semantic/USR-backed while tolerating toolchains that index function calls without setting both bits.
  • No evaluator API or schema shape changed; the behavior change is only which existing SourceFile field the shell positive rule consumes.

Spec/Evidence Mapping:

  • Patch clause "shell-linked iff it qualified-references a same-domain core module's declared decision surface" maps to evaluate.py:evaluate_shell_modules, where the same-domain lookup is keyed by metadata.domain and the match is source_file.qualified_references.intersection(core_references).
  • Bare-name spoof rejection is covered by EvaluateTests.test_shell_module_does_not_accept_same_named_bare_core_reference.
  • Qualified positive linkage is covered by EvaluateTests.test_shell_module_accepts_qualified_core_decision_reference, the Swift passing fixture, and the updated Go passing fixtures.
  • Required context consulted: evaluate.py, evaluate_test.py, and go/main_test.go for the existing rule 15/qualified-reference contract and adapter expectations.
  • Validation run: uv run --project . python evaluate_test.py, cd go && go test ., sh swift/test.sh, and sh typescript/test.sh passed. sh ocaml/test.sh could not run in this environment because the local OCaml switch/library setup is missing yojson.

Base automatically changed from semantic-reference-resolution/patch-8 to master June 8, 2026 19:09
@subsetpark subsetpark force-pushed the semantic-reference-resolution/patch-9 branch from ea1f289 to 64d44a1 Compare June 8, 2026 19:14
@subsetpark subsetpark marked this pull request as ready for review June 8, 2026 19:20
@flowglad-review-service

Copy link
Copy Markdown

Review Summary

I did not find any in-scope defects in this patch. The evaluator change, updated tests, and fixture adjustments appear consistent with the new qualified-reference shell-linkage contract described in the PR and patch spec.

Severity Count
Must-fix 0
Should-fix 0
Note 0

Variant: convergence-v2

Candidates: 0 | Posted: 0 | Suppressed: 0


0 comments posted · Model: gpt-5.4 (sonnet) · Tokens: 104876 in / 178 out · Cache: 0 created / 63744 read · Context: 44 items · Review mode: agentic · Turns: 4 · Tool calls: 0

@subsetpark subsetpark merged commit 1fe2b74 into master Jun 8, 2026
7 checks passed
@subsetpark subsetpark deleted the semantic-reference-resolution/patch-9 branch June 8, 2026 19:27
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