Skip to content

refactor phase 6: extras boundaries + the layer contract - #303

Merged
hussainsultan merged 3 commits into
mainfrom
refactor/phase6-boundaries
Aug 19, 2026
Merged

refactor phase 6: extras boundaries + the layer contract#303
hussainsultan merged 3 commits into
mainfrom
refactor/phase6-boundaries

Conversation

@hussainsultan

Copy link
Copy Markdown
Collaborator

Phase 6 — the final planned phase of the refactor, stacked on #302. The structural rules the whole stack worked toward are now machine-enforced, and the optional extras stand on the public surface. Full suite: 1745 passed, exit 0; make examples-core green.

Extras stand on the public surface

  • server no longer imports agents: the chart endpoints resolve the agents chart generator at call time and answer HTTP 501 with an install hint when the agent extra is absent — pip install 'boring-semantic-layer[server]' gives you a server that works, not an ImportError.
  • query.find_time_dimension is public — the server and the MCP backend were importing the underscore name.
  • chart/utils uses the op metadata protocol (source.get_dimensions()) instead of reaching into ops privates. That forced the protocol to be complete: SemanticGroupByOp/SemanticProjectOp join the pass-through mixin — a real regression (time-series charts rendering as bars because GroupBy lacked get_dimensions) was caught by the chart suites mid-change and drove the fix.

The layer contract, enforced

The SCC ratchet graduates into the full structural contract in test_import_graph.py:

  • test_layer_contract — every import edge (lazy included) must point to an equal or lower layer: primitives → analysis → compilers → ops → expr/format → api/query/yaml → serialization → extras + root facade. A new top-level module must declare its layer; the test refuses to guess.
  • test_extras_do_not_import_core_privates — chart/agents/server may import only public core names and modules (the _xorq flavor shim is the one documented exception).

Both pass on the current graph with zero allowlisted violations — the contract describes what the stack built, not an aspiration.

Dependency posture

ibis-framework capped <12 (core subclasses Relation and walks Deferred internals; a new major gets matrix-tested by the weekly IBIS_VERSION=all job before the cap moves). Lockfiles regenerated.

Housekeeping

A broad git add briefly swept local working files (CLAUDE.md, a CSV, an embedded repo, three WIP example scripts — one of which imports the malloy package that only exists on feat/malloy-interop and would have broken make examples in CI). All un-committed in a follow-up; git-catalogs/ and flights.csv are now gitignored so it can't recur.

Where the plan stands

This completes the six planned phases (#295#303): CI safety net → dead code + SCC rim → primitives + typed errors → DAG → ops split → preagg decomposition → serialization consolidation → API surface → boundaries + contract. Remaining named follow-ups, none blocking: phase-4-interior decomposition of the per-source preagg loop, ~40 broad handlers in the preagg path, fluent time_grain/having methods, the index() wrapper, the drifted twin test files, and the expr.py docstring pass.

🤖 Generated with Claude Code

@hussainsultan
hussainsultan force-pushed the refactor/phase5-api-surface branch from 6d6792e to e352f20 Compare August 18, 2026 23:15
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch from 0300119 to 4034b5d Compare August 18, 2026 23:15
@hussainsultan
hussainsultan force-pushed the refactor/phase5-api-surface branch from e352f20 to 0ebde8b Compare August 18, 2026 23:27
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch from 4034b5d to 79e0de8 Compare August 18, 2026 23:27
@hussainsultan
hussainsultan force-pushed the refactor/phase5-api-surface branch from 0ebde8b to 893448d Compare August 18, 2026 23:37
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch from 79e0de8 to 215684f Compare August 18, 2026 23:37
@hussainsultan
hussainsultan force-pushed the refactor/phase5-api-surface branch from 893448d to 1e14d07 Compare August 18, 2026 23:44
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch from 215684f to 4821c9b Compare August 18, 2026 23:44
@hussainsultan
hussainsultan force-pushed the refactor/phase5-api-surface branch from 1e14d07 to 1fb09b6 Compare August 18, 2026 23:50
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch from 4821c9b to 043655a Compare August 18, 2026 23:50
@hussainsultan
hussainsultan force-pushed the refactor/phase5-api-surface branch from 1fb09b6 to 4e40e80 Compare August 19, 2026 00:05
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch from 043655a to 3b7cf68 Compare August 19, 2026 00:05
@hussainsultan
hussainsultan force-pushed the refactor/phase5-api-surface branch from 4e40e80 to f5cdede Compare August 19, 2026 00:34
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch 2 times, most recently from d49de04 to f996d6e Compare August 19, 2026 00:39
hussainsultan and others added 3 commits August 18, 2026 20:44
… agents

- query.find_time_dimension is public (server and the MCP backend were
  importing the underscore name)
- server's chart endpoints resolve the agents chart generator at call
  time and answer 501 with an install hint when the agent extra is
  missing — pip install 'boring-semantic-layer[server]' no longer
  drags in the agents package
- chart/utils uses the op metadata protocol (source.get_dimensions())
  instead of reaching into ops privates; SemanticGroupByOp and
  SemanticProjectOp join the pass-through protocol so the metadata
  surface is complete on every op (a chart time-axis regression caught
  by the chart suites forced exactly this completion)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The SCC ratchet graduates into the full structural contract:

- test_layer_contract: every import edge must point to an equal or
  lower layer (primitives -> analysis -> compilers -> ops -> expr ->
  api/query/yaml -> serialization -> extras/facade); a new top-level
  module must declare its layer or the test refuses to guess
- test_extras_do_not_import_core_privates: chart/agents/server may
  import only the core public surface (the _xorq flavor shim is the
  one documented exception)

Both pass on the current graph with zero allowlisted violations.

ibis-framework capped <12: BSL subclasses Relation and reaches into
Deferred internals, so a new major gets matrix-tested (the weekly
IBIS_VERSION=all job) before the cap moves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CLAUDE.md, flights.csv, the git-catalogs/worldcup embedded repo, and
the three WIP example scripts (malloy_interop.py imports the malloy
package that only exists on feat/malloy-interop and would break
'make examples' in CI) return to untracked working-tree files.
git-catalogs/ and flights.csv are gitignored so this can't recur.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hussainsultan
hussainsultan force-pushed the refactor/phase6-boundaries branch from f996d6e to e458c81 Compare August 19, 2026 00:44
@hussainsultan
hussainsultan changed the base branch from refactor/phase5-api-surface to main August 19, 2026 00:44
@hussainsultan hussainsultan reopened this Aug 19, 2026
@hussainsultan
hussainsultan marked this pull request as ready for review August 19, 2026 00:49
@hussainsultan
hussainsultan merged commit 4981c36 into main Aug 19, 2026
10 of 18 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