Skip to content

Spec amendment 3 — full carrier dissolution + pragma plugin contract (Phase P, load-bearing)#84

Merged
StarGazerM merged 1 commit into
feat/spec-amendment-2-no-context-principlefrom
feat/spec-amendment-3-full-context-dissolution
May 20, 2026
Merged

Spec amendment 3 — full carrier dissolution + pragma plugin contract (Phase P, load-bearing)#84
StarGazerM merged 1 commit into
feat/spec-amendment-2-no-context-principlefrom
feat/spec-amendment-3-full-context-dissolution

Conversation

@StarGazerM

Copy link
Copy Markdown
Collaborator

Summary

Three big additions + an entropy retrospective. Headline finding: today's pragma surface is not a plugin, and without fixing that, every other phase of the redesign is shuffling code without changing the extensibility surface. Phase P (pragma plugin contract) becomes the new top priority, ahead of Phase R / T / B2.

Builds on PR #83 (Amendment 2). Merge order: #83 → this PR.

What changes

§ 3.2.1.1 — Full carrier dissolution scope

The audit revealed the dissolution scope is broader than LoweringCtx alone. The entire src/srdatalog/ir/codegen/cuda/context.py (543 LOC) dissolves under the no-context principle. Field-by-field bucket assignment for CodeGenContext (38 fields), CodeGenHooks (10 callable slots), RunnerGenState (14 fields), + 30+ ctx-taking helpers.

§ 3.2.1.2 — Self-audit on the proposed solution

Five risks that would have rebuilt the anti-pattern one layer up:

Risk Fix
1. Services becomes a named-field carrier Typed-key dict: services.get[T](T) → T
2. IR op classes grow per-feature with named binding fields MLIR-style op.attributes[T] typed attribute dict
3. Bucket-2 **scope kwargs become stack-allocated context Sharpened boundary: single-render scope only; multi-render = bucket 1 (IR)
4. @register_X decorators are module-global mutable state Per-Compiler registries; decorators are sugar
5. Op classes themselves carry fixed schemas Ops are typed shells; per-feature data in attributes

§ 3.2.1.3 — The pragma plugin contract (Phase P, LOAD-BEARING)

Today's @pragma_handler is a constrained materialization-handler primitive, NOT a plugin. A pragma cannot:

  1. Contribute its own IR ops
  2. Run as a general program pass
  3. Bring its own lowerings + renders
  4. Express dependencies
  5. Bundle as one plugin package

The four built-in pragmas (BlockGroup, WorkStealing, DedupHash, FanOut) work today only by leaking knowledge into the framework. Without fixing this, every other phase shuffles code without changing the contract.

Specifies the PragmaPlugin schema (typed Pragma + new_ops + new_attributes + passes + lowerings + renders + requires_services + produces_ops + consumes_ops + preserves) and the atomic compiler.register_pragma_plugin(plugin) API.

§ 6.0 — PR-P series (highest priority)

PR Concern Est. size Sequence
PR-P0 Framework primitives ~2500 LOC serial, blocks P1-P4
PR-P1 BlockGroup migration ~1500 LOC parallel with P2-P4
PR-P2 WorkStealing migration ~1500 LOC parallel
PR-P3 DedupHash migration ~1000 LOC parallel
PR-P4 FanOut migration ~1000 LOC parallel
PR-P5 Context cleanup (consequence) ~800 LOC serial, last

After PR-P series lands, the existing PR-2/3/4/5/6 plan re-applies with reduced scope — most dissolution work is already done as Phase P consequences.

§ 11 — Architectural precedent

The shape has 40 years of validation across 4 domains: relational query compilation (Volcano 1993 → Cascades → Calcite → DuckDB), MLIR, LLVM, FRP UI (React/Solid). Per-domain mapping table. Future contributors can pattern-match against existing literature rather than re-derive design choices.

§ 10.3 — Amendment log + entropy retrospective

Of PR work to date:

  • ~10% was entropy (reverted PR-1d)
  • ~30% was useful-but-out-of-order (B-series, A3-series — useful as inputs to Phase P)
  • ~60% was load-bearing (PR-1a/b foundation, C-pragma typed classes, declarative kernel-body lowerings)

The original PR-2/3/4 (RIR) plan is NOT entropy but is BLOCKED by Phase P — running it first would design RIR ops around the wrong plugin contract.

Test plan

Spec-only, no code changes. Reviewers focus:

  • Does Phase P (§ 3.2.1.3) capture what's missing from today's pragma surface?
  • Does the PragmaPlugin schema cover every "feature" that a pragma plugin might want to ship?
  • Are the 5 self-audit risks (§ 3.2.1.2) actually fixed by the proposed shape?
  • Is the PR-P series sequencing correct (P0 serial, P1-4 parallel, P5 serial)?
  • Is the precedent mapping in § 11 accurate enough to ground design decisions?

PR #68 jaccard demo audit (included in this amendment)

Concurrent audit found PASS-WITH-CAVEATS: zero edits to existing files (ACID-test letter satisfied), but the demo uses ctx.dedup_hash bool-field flip + imports private _lower_insert_into. Cannot yet be cited as proof of the additive contract. Four follow-ups identified. Phase P cleans up the framework side; the demo updates separately.

🤖 Generated with Claude Code

…+ architectural precedent

§ 3.2.1.1 — Full carrier dissolution scope: context.py (543 LOC)
dissolves entirely. Field-by-field bucket assignment for
CodeGenContext (38 fields), CodeGenHooks (10 callable slots),
RunnerGenState (14 fields), plus 30+ ctx-taking helpers.

§ 3.2.1.2 — Self-audit on the proposed solution. 5 risks that would
have rebuilt the anti-pattern one layer up + their fixes: typed-key
Services dict, MLIR-style attribute dict on Ops, sharpened
bucket-2 boundary, per-Compiler registries, Ops as typed shells.

§ 3.2.1.3 — The pragma plugin contract (Phase P, load-bearing).
Today's @pragma_handler is a constrained materialization-handler,
NOT a plugin. A pragma cannot contribute IR ops, run as a general
pass, bundle lowerings + renders, or declare dependencies. Without
a real pragma plugin contract, every other phase shuffles code
without changing the extensibility surface. Specifies the
PragmaPlugin schema (typed Pragma + new_ops + new_attributes +
passes + lowerings + renders + requires_services + produces_ops +
consumes_ops + preserves) and the atomic
compiler.register_pragma_plugin(plugin) API.

§ 6.0 — PR-P series (highest priority, ahead of PR-2/3/4):
- PR-P0: framework primitives (~2500 LOC, serial, blocks P1-P4)
- PR-P1/P2/P3/P4: per-pragma migrations (BG, WS, DedupHash, FanOut)
  ~1000-1500 LOC each, parallel + file-disjoint
- PR-P5: context cleanup as consequence (~800 LOC, mostly deletion)

§ 11 — Architectural precedent. The shape we are converging on has
40 years of validation: relational query compilation (Volcano
1993 → Cascades → Calcite → DuckDB 2024); MLIR (dialects + typed
Op attributes + conversion patterns); LLVM (analyses via
getAnalysis<T>()); FRP UI (React/Solid components as data, hooks
lexical, Context Providers carry services not feature accumulators).

§ 10.3 — Amendment log entry. Includes entropy retrospective: ~10%
of work to date was entropy (reverted PR-1d), ~30% was
useful-but-out-of-order (B/A3 series — useful as inputs to Phase
P), ~60% was load-bearing (PR-1a/b foundation, C-pragma typed
classes, declarative kernel-body lowerings).

Triggered by user review of the design after PR-1d revert + the
anti-pattern audit findings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@StarGazerM
StarGazerM merged commit 71c05e4 into feat/spec-amendment-2-no-context-principle May 20, 2026
3 checks passed
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