Skip to content

[GEN-E3] operations bind through returned facet results; one inventory refuses every type-name collision (PR 2/3, #414) - #437

Merged
Blind-Striker merged 1 commit into
masterfrom
feat/gen-e3-operations
Oct 17, 2026
Merged

Blind-Striker merged 1 commit into
masterfrom
feat/gen-e3-operations

Conversation

@Blind-Striker

@Blind-Striker Blind-Striker commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Operation binding becomes named collaborators that return what they decide. One generated-type-name inventory refuses every collision. Generated output is byte-identical.

Closes: P42, P46, P31, P43, #414. This is GEN-E3 PR 2 of 3, following the approved plan (faz4/GEN-E3/plan.md, amendments included). PR 1 is #425. PR 3 (graph and statics) waits for TST-E3's first half.

What changes

  • The operation binders move out. SingleOperationBinder and ErrorMapBinder leave OperationPlanBinder, which goes from 593 to 254 lines.
  • P42 (a characterization): each facet returns FacetResult<T>. A facet is bound, or refused with its own errors:
    • What it replaces: the shared error-count window and the partial-plan convention.
    • Independent facets stay independent. A refused query still feeds pagination and request-merge diagnostics, through its classified properties. A facet refusal still rejects the operation, MissingRow included.
  • P46: ErrorMapBinder reuses the error union's verdicts. It does so only for closure members. ErrorStyle.None objects and stream causes still resolve directly. An error schema with no unique C# name reports once, from the error union.
  • P31: a cursor list keeps its method and loses only the pagination companion when it declares a header, has a required member, or has an incompatible signature. Before, the whole operation refused.
  • P43: one GeneratedTypeNameInventory, built once after the last declaring pass, feeds one collision wall. This is the lead's "deferred single wall" (plan amendment A.5).
    • Coverage: every generated name.
      • schema names, seeded from the same type-name map as before;
      • models;
      • unions, with their Kind and Unknown names;
      • hoisted interfaces;
      • clients;
      • envelopes;
      • streams.
    • The hoist composer records claims. It keeps only a structural first-claim guard on its own interfaces.
    • A hoisted name refused against another declaration never reaches placement. Before the fix-up review, it crashed in ModelOwnershipPolicy.
    • First claim wins: of two hoisted claimants, the first keeps its name and only the second reports, as on master.
    • Two derived names are now refused (for example a union's Unknown name equal to another union's Kind name). The old wall missed that.
  • Generator: an invalid curated method name also reports a misleading 'does not pluralize naively' error #414: an invalid curated list method name reports once, by its own rule. The misleading "the group does not pluralize naively" error is gone.

Tests

  • Red then green: every behaviour change.

    • P31: two expectation flips and three signature rows.
    • Generator: an invalid curated method name also reports a misleading 'does not pluralize naively' error #414: its two-row whole-list test (amendment F6).
    • P46: the unnamed-error regression.
    • P43's missed-collision rows:
      • hoisted against a client and against a Kind name, each exactly one refusal with the hoist's literal (the lead's A.5 condition);
      • hoisted against a placed model and against a placed union, through the full pipeline, red with ArgumentException;
      • hoist against hoist;
      • derived against derived;
      • a curated spine name on a non-emitted alias.
    • The generic model-collision message: four rows, proven by a mutation that deletes the branch (185/4 → restored with cmp → 189/0).
  • Restored-behaviour rows: the fix-up derived each oracle from git show 04f18994:<file> and pins it as the full ordered Errors list:

    • the enumeration-name error behind a refused query;
    • the mixed body/query diagnostic;
    • a closure member's marker error;
    • a duplicate-tag error union that no longer drops its operations.
  • Existing-test edits:

    • the plan's §9 PR 2 rows: P31's two expectations, Generator: an invalid curated method name also reports a misleading 'does not pluralize naively' error #414's two rows, and inventory argument wiring;
    • assertions strengthened from Contains or a category filter to the full ordered list: Bind_Should_Refuse_A_Tag_Owned_By_Two_Closure_Schemas and the mixed body/query row;
    • compile-forced arrange-only edits (lead's blanket rule): InternalNameCollisionCheckTests.Check, OperationPlanBinderTests.Bind_Should_Preserve_Type_Name_Claim_Order, UnionHoistPlanData.CheckNames, and P31's arrange moved into one CursorQuery helper.

    No existing expected error list was reordered.

  • E0 guards:

    • full ordered lists with CollectionOrdering.Matching;
    • no Contains, and no IsTrue over Any/All;
    • both TST-E1 site lists stay empty.
  • Found and kept as on master: A duplicate-tag error union refusal cascades into misleading 'absent union' membership errors #436. A duplicate-tag error union refusal still cascades into two "absent union 'IOpenCodeError'" errors. That is base behaviour, which this PR restored exactly and now pins. The fix is the same claim-drop PR 1 used for P36, and it lands in GEN-E3 PR 3, with a deliberate red-first change to this row.

Clone baseline (proven)

tests.baseline.json: −3 / +1, two fewer clones.

Budget (against the merge-base)

  • Hand-written tools: +647 / −535, +112 net, against a cap of +120.
  • Tests: 537 added (−50). PR 2's own work was 348, against a cap of 350. The rest is the review fix-up's rows, and the spec says caps bound scope, not review fixes.

Local check and review

  • Local check at this head, on dev-01, after a root Release build: slopwatch 0 issues; the Release build with 0 warnings; both format passes; verify-clones passing; --help; generate --verify current; the whole Tools.Tests project (guards included) at 2033/0. Bun 1.4.3, off the 1.4.2 pin. CI is the full gate.

  • verify.log: for both runs, the harness ran the guards, 13 touched classes, the whole Tools.Tests project (failing only on the 14 packaging rows that need a root build; manual §5.3) and generate --verify.

  • Review: the coordinator's Claude review and a fresh cross-family review, each comparing old against new code behaviour by behaviour. They found six behaviour changes that generate --verify could not see at the pin, all fixed here:

    • the placement crash;
    • the double hoist report;
    • missed derived collisions;
    • a narrowed claim set;
    • hidden independent diagnostics;
    • dropped operations.

    The fix-up rule was "restore 04f1899 exactly unless the plan lists the change; finish what is deliberate".

Provenance: Generator lane / opencode dispatch harness (openai/gpt-6.1-sol-1m) for the implementation and the fix-up, coordinated, reviewed and finished in Claude Code.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…and one inventory refuses every type-name collision

SingleOperationBinder and ErrorMapBinder move out of OperationPlanBinder (593 -> 230 lines). Each
facet returns a FacetResult (bound or refused with its own errors), which replaces the shared
error-count window, and an independent facet still reports when another refused. ErrorMapBinder
reuses the error union's per-target verdicts and resolves the rest directly.

- P43: one GeneratedTypeNameInventory, built once after the last declaring pass, feeds one
  collision wall over every generated name: models and schema names, unions with their Kind and
  Unknown names, hoisted interfaces, clients, envelopes and streams. The hoist composer records
  claims; a hoisted name refused against another declaration never reaches placement, and the
  first of two hoisted claimants keeps its name.
- P31: a cursor list that declares a header, a required member or an incompatible signature
  keeps its method and loses only the pagination companion.
- P46: an error schema with no unique C# name reports once, from the error union.
- #414: an invalid curated list method name reports once, by its own rule, without the
  misleading plural error.

Generated output is byte-identical.
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