Date: 2026-07-24
Build the next major version of @marimo-team/codemirror-sql as a performant,
robust, correct, and powerful SQL language service with a first-class
CodeMirror adapter.
This is a breaking overhaul. Compatibility with current implementation classes is not a design constraint. We will still publish a migration guide and use marimo as the reference consumer.
Success means:
- Correct, explicitly bounded dialect support
- Predictable latency and bounded memory
- Honest partial and unsupported results
- Safety under malformed input, rapid edits, cancellation, and hostile metadata
- A small, understandable public API
- High confidence from independent forms of testing
Before implementation, publish a vNext capability charter defining:
- Initial dialects and constructs
- Explicit non-goals and unsupported syntax
- Browser, Node, bundler, and peer-dependency support
- Latency, memory, and bundle envelopes
- Which features require local, native, or remote providers
Do not claim support until a construct passes its conformance corpus. Explicit partial results are better than confident incorrect results.
Prefer small modules, explicit data flow, pure transformations, and narrow interfaces. Optimize from profiles. Every abstraction must enforce an invariant, isolate a dependency, remove duplication, or improve testability.
Names, types, and structure should explain normal behavior. Comments should explain an invariant, external limitation, security boundary, performance tradeoff, or surprising dialect rule. If ordinary flow needs a long comment, first simplify the design. Public APIs and non-obvious algorithms still need useful documentation.
The goal is not just to compile. Revision identity, source coordinates, analysis completeness, catalog loading, cancellation, and provider provenance should be difficult to omit or combine incorrectly.
Coverage, contracts, examples, goldens, browser tests, fuzzing, mutation testing, differential testing, and benchmarks find different failures. No one metric substitutes for the others.
Create dev-refactor as the next-major integration branch. Do not implement
everything directly on it. Use short-lived, focused PR branches:
main
└─ dev-refactor
├─ refactor/analysis-session
├─ refactor/source-mapping
├─ refactor/statement-index
├─ refactor/catalog-provider
└─ refactor/codemirror-adapter
Required practices:
- Every PR into
dev-refactorleaves it green and runnable. - Use a merge queue or serialize merges.
- Open a continuous draft PR from
dev-refactortomain. - Give the branch an owner, a target merge date, and explicit merge/delete criteria.
- Allow no direct commits.
- Forward-merge
mainon a fixed cadence and document hotfix propagation. - Keep a continuously runnable demo and marimo integration fixture.
- Build a canary artifact for every accepted integration commit; publish prereleases only at selected checkpoints after canary gates pass.
- Compare API, coverage, bundle, and performance against both
mainand the previousdev-refactorcommit. - Prefer a sequence of vertical slices to a large rewrite.
The branch is an integration boundary, not permission to accumulate an
unreviewable diff. If its lifetime or divergence becomes excessive, move vNext
development onto main behind an unpublished entry point.
Before branch protection is enabled, update CI triggers to include pushes and
pull requests targeting dev-refactor; the current workflow targets only
main.
Classify every PR before implementation.
Documentation, test data, mechanical renames, or a local fix with no public, semantic, concurrency, or performance effect. One normal review is sufficient.
Any change to:
- A public/provider interface
- Parsing, source mapping, or semantics
- Scheduling, caching, cancellation, or concurrency
- Catalog resolution
- Completion, diagnostics, hover, navigation, formatting, or gutter behavior
- A dialect rule
- More than one architectural layer
Two independent adversarial reviews are required.
Classification is fail-closed. Sensitive paths, public API diffs, dependency changes, concurrency modules, and cross-layer changes automatically make a PR medium or large. A maintainer must approve any downgrade to small.
A cross-cutting architecture change, new semantic subsystem, or new parser or remote/native provider. Split it into an ADR and multiple medium PRs. A large PR is a planning failure unless the change is generated or indivisible.
Do this before changing production architecture.
- Capture public exports and generated declarations.
- Record representative completion, hover, navigation, lint, and gutter output.
- Add characterization tests for critical migration-risk behavior.
- Put every confirmed issue from
SQL_EDITOR_RESEARCH.mdin an owned traceability backlog. An unfixed case may use a commit-bound known-failure fixture with an owner and expiry until its feature slice; the baseline suite must not be permanently red. - Add a marimo fixture for document-level DuckDB validation, connection
changes, schema completion, many editors, and
{...}expressions. - Record demo workflows in browser tests.
Label characterization cases:
preserve intentional behavior
replace behavior intentionally changed in the new major
bug confirmed defect with the desired result documented
unknown needs a semantic or product decision
Characterization tests document behavior; they do not preserve known bugs.
Measure fixed document and catalog sizes:
- Cold load and first parse
- Active-statement edit/reparse
- Completion and hover latency
- Full-document diagnostics
- Rapid-edit and stale-result behavior
- Memory after long edit sequences
- 1, 10, and 50 mounted editors
- Bundle and parser chunk sizes
Store JSON results and raw samples as CI artifacts. Establish budgets from measured baselines and product goals, not arbitrary percentages.
Record:
- Line, statement, function, and branch coverage
- Unsafe assertions and suppression directives
- Public API surface
- Bundle size and dependency inventory
- Test runtime and flake rate
Introduce ratchets from this baseline. Do not hide existing problems simply to make the first gate green.
Targets:
| Metric | Repository | New or changed core code |
|---|---|---|
| Lines | At least 95% | At least 95% per changed file |
| Statements | At least 95% | At least 95% per changed file |
| Functions | At least 95% | At least 95% per changed file |
| Branches | 90%, ratcheting to 95% | At least 95% diff coverage |
Branch coverage matters for failure, cancellation, partial-result, and dialect paths. Coverage exclusions are limited to generated data, type-only code, debug instrumentation, and true exhaustiveness guards. Each exclusion requires a reviewed reason.
Coverage is a floor, not an objective. Do not add tests that execute lines without asserting semantics. Mutation testing must confirm that important assertions detect meaningful faults.
Enforcement must define:
- All production files as the denominator, including files not imported by tests
- Explicit checked-in include/exclude rules
- Repository thresholds for lines, statements, functions, and branches
- Changed executable lines and branches relative to the PR merge base, including renamed files
- Diff coverage for lines and branches; statements and functions are enforced at the changed-file and risk-tier module level rather than inferred unreliably from a textual diff
- Per-module floors for revisions, ranges, source maps, cancellation, and provider policy
Add separate failing test:coverage and coverage:diff commands. Protect
coverage configuration, exclusions, baselines, and generated-code rules with
CODEOWNERS. Baseline reductions or exclusion growth require explicit approval.
Apply strict changed-code gates immediately to vNext modules. The repository target applies to retained/new-major production code by release candidate; do not manufacture low-value tests for legacy modules scheduled for deletion. Named invariant tests and mutation evidence are required for critical logic. Defensive or platform-specific uncovered code needs a narrow reviewed waiver with an owner and expiry.
Use focused, table-driven tests for:
- Range and position primitives
- Identifier normalization and quoting
- Statement boundaries
- Original/rendered source mapping
- Cache identity and invalidation
- Catalog load states and lookup
- Scope and visibility rules
- Provider authority, merge, and ranking policies
- Completion replacement edits
- Cancellation, disposal, and error normalization
Every provider implementation must pass reusable contracts:
- Ranges are absolute UTF-16 half-open ranges inside the document.
- Every request settles, rejects, or is observably aborted.
- Aborted or stale work cannot publish results.
- Results identify revision, provider, authority, and completeness.
- Incomplete catalogs cannot create definite unknown-object diagnostics.
- Document validators are never invoked once per statement.
dispose()prevents callbacks and editor dispatch.- Provider errors degrade according to documented policy.
Use structured, reviewed fixtures for:
- Nested and correlated subqueries
- CTE ordering, recursion, and shadowing
- Derived relations and
LATERAL - Set operations
- Clause-specific alias visibility
- Qualified, unqualified, and ambiguous references
- Search paths and multiple catalogs
- Quoted identifiers and case folding
- Incomplete input at likely cursor positions
- DML and templates/interpolation
Each fixture names its dialect and expected capability. Prefer typed structured outputs to large parser-AST or DOM snapshots.
Use snapshots only for stable, high-dimensional normalized results such as a scope graph or complete feature response. Prefer direct assertions for simple behavior. Never snapshot parser-specific ASTs, unstable ordering, incidental error details, or entire DOM trees. CI must not auto-update snapshots.
Test invariants:
- Statement ranges remain ordered, non-overlapping, and in bounds.
- Template masking preserves length and newline positions.
- Source-map conversion always yields valid ranges.
- Arbitrary edit sequences never publish stale results.
- Completion edits remain inside the document.
- Identifier quote/normalize behavior round-trips where defined.
- Caches stay bounded.
- Arbitrary input terminates within resource budgets.
Run a deterministic short suite on every PR and longer randomized campaigns nightly. Commit a minimal regression fixture and seed for every failure.
Execute parser fuzz cases in disposable workers or processes. A normal Vitest timeout cannot interrupt synchronous code that blocks the event loop. The parent enforces wall-clock and memory limits and records the seed, input, dialect, dependency versions, and operation sequence. Distinguish crash, timeout, OOM, invalid range, unhandled rejection, and stale publication.
Compare supported constructs with:
- SQLGlot for scope and qualification
- DuckDB for DuckDB parsing and selected catalog behavior
node-sql-parserlocation output while it is a backendsqruffif used for formatting or linting
Classify differences as ours-bug, upstream-difference,
dialect-ambiguity, unsupported, or intentional-policy. Another tool is
evidence, not automatically the oracle.
Use deterministic fake providers and schedulers to test:
- Edit → invalidate affected layers → publish current feature result
- Dialect/connection changes without text edits
- Catalog refresh without reparsing
- Remote validation cancellation during rapid typing
- Local/native completion composition
- Disposal with work in flight
- Provider timeout and worker crash recovery
- Partial catalogs
Use fake clocks; do not base correctness assertions on real time.
Inject failures including malformed payloads, repeated callbacks, callback after abort/dispose, synchronous throws before Promise creation, rejection after abort, worker restart, catalog refresh storms, duplicate IDs, out-of-order results, and exceptions from consumer renderers.
Vitest currently includes a Playwright browser project through the aggregate
test configuration, but the documented test:browser script references the
nonexistent vitest.browser.config.ts. Repair that script and give the browser
project a named required CI step so configuration changes cannot silently stop
running it.
Cover:
- Completion opening, filtering, refreshing, and applying the exact edit
- Safe, attributed hover rendering
- Diagnostic movement and removal after edits
- Current-statement gutter and navigation
- Dialect/connection changes without text edits
- Stale slow-provider rejection
- Keyboard and accessibility behavior
Require Chromium on PRs. Run Firefox and WebKit nightly until sufficiently stable and fast. Capture traces and screenshots on failure, not as a broad pixel-snapshot suite.
Maintain a small marimo fixture here and a pinned cross-repository test in
marimo. Cover dynamic context, document validation, many SQL cells, {...}
regions, external completion composition, partial/nested catalogs, and custom
renderers.
Test a packed tarball rather than workspace source. For release candidates:
- Install it in a minimal CodeMirror consumer.
- Import every documented entry point.
- Build with supported bundlers.
- Run in a real browser and in the marimo fixture.
- Verify ESM, declarations, source maps, peer dependencies, and optional providers.
- Verify core-only consumers do not bundle optional integrations.
Test hostile catalog metadata, LSP Markdown/HTML, deeply nested SQL, extremely long identifiers/statements, invalid/cyclic provider data, worker crashes, and pathological regular-expression input. CodeQL and dependency scanning remain required but are not substitutes for behavior tests.
Run mutation tests on ranges, semantics, scheduling, caching, and provider policy. Start nightly. Establish a baseline mutation score, narrowly classify equivalent mutations, and ratchet upward. High coverage with a weak mutation score blocks further work in that subsystem.
Track mutation results per critical module and mutation class. Designated revision, range, source-map, cancellation, and security modules may have no surviving high-risk mutants. Equivalent-mutant exclusions require a reviewed reason and expiry.
Maintain a checked-in invariant registry with stable ID, owner, failure mode, affected modules, required test layers, test references, and applicable performance/security budget. CI fails if an invariant loses all mapped tests.
Fail CI on:
- Zero discovered tests in an expected suite
- Unexpected
.only, skipped, or todo tests - Stale snapshots
- Unhandled rejections
- Leaked timers, handles, workers, listeners, or DOM nodes
- Unexpected browser console errors
- Missing fixture provenance
Print test counts, duration, retry count, and first-attempt failures by category. Retry success must not silently erase a flake; quarantines require an owner and deadline.
Report median, p95, worst observed time, and memory where measurable. Separate:
- Pure core microbenchmarks
- Edit-to-result scenario benchmarks
- Browser/CodeMirror benchmarks
- Bundle-size checks
Exercise 1/10/100/1,000 statements, small/large/partial catalogs, cold/warm completion, 1/10/50 editors, rapid edits with delayed providers, and template-heavy documents.
PR CI runs stable smoke benchmarks and fails only on meaningful regressions beyond agreed budgets. Full performance and leak tests run nightly on controlled runners. Store history to catch gradual degradation.
For every blocking benchmark, define runner class, warmups, sample count, interleaved base/head execution, outlier policy, confidence method, minimum effect size, absolute ceiling, and an inconclusive result for excessive noise. Record hardware and runtime metadata. Use controlled runners for blocking latency and memory gates; hosted runners enforce only gross smoke ceilings and bundle size. Gate tail latency under load and event-loop blocking. Do not use “worst observed” as a statistical gate; use a defined percentile plus a hard timeout.
Memory tests run in isolated processes with fixed edit/mount cycles and explicit GC where supported. Track heap, DOM/listener retention, worker lifecycle, cache size, process RSS, and retained-memory slope separately.
The repo already enables strict, noUncheckedIndexedAccess, and
noUnusedLocals. Keep these and evaluate:
exactOptionalPropertyTypesnoImplicitOverridenoPropertyAccessFromIndexSignatureverbatimModuleSyntax
New-major rules:
- No explicit
any. - No double assertion such as
as unknown as T. - No unchecked casts of parser, provider, JSON, or network data.
- No
@ts-ignore. @ts-expect-erroronly in type tests, with the expected reason.- Use
unknownat boundaries and narrow or decode it. - Use discriminated unions for partial, recovered, failed, and cancelled states.
- Use opaque types where document/revision/range identity can be confused.
- Use exhaustive checks for closed unions.
- Prefer
satisfies; allow useful safe constructs such asas const.
External ASTs are untrusted boundary data. Decode them in one adapter. Feature code must not scatter parser-specific assertions.
Automate this with type-aware lint rules, a forbidden-pattern CI check, type tests, declaration generation, and a public API diff. If a third-party type forces a narrow assertion, isolate and runtime-check it in an adapter and require adversarial review; do not weaken global settings.
The current production tsconfig.json excludes tests and the demo. Add separate
typecheck projects for production, unit tests, browser tests, demo, fixtures,
and public type tests. Validate emitted declarations in a clean consumer with
skipLibCheck: false.
Forbidden assertions apply strictly to production. Tests use typed builders rather than double assertions, but may have a separately audited boundary registry for unavoidable third-party mocks. Decide each proposed compiler option in an early ADR; do not leave “evaluate” as a permanent gate.
Enforce the dependency direction:
core primitives
← document/source mapping
← syntax/statement analysis
← semantic model
← catalog and feature policies
← providers
← CodeMirror adapter
Core cannot import CodeMirror, DOM, remote providers, or parser-specific ASTs. Automate import-boundary and dependency-cycle checks.
Set ratcheted review thresholds for complexity, function/file size, nesting, and parameter count. These are review triggers, not an invitation to split one bad function into many bad functions.
Public API rules:
- Keep the stable surface small.
- Do not export implementation classes for tests.
- Prefer interfaces and factories over subclassing.
- Mark experimental surfaces explicitly.
- Generate and review an API report.
- Require examples and release notes for public behavior changes.
Every runtime dependency needs bundle, license, security, maintenance, and alternatives review, and must remain optional where appropriate.
Every medium change receives two independent reviews before dependent work continues.
Review SQL semantics, Unicode/ranges, partial-result confidence, concurrency, cancellation, disposal, security boundaries, and missing negative/fuzz tests.
Review parsing/allocation cost, cache identity, bounded memory, main-thread work, layer coupling, public API leakage, excessive abstraction, and benchmark evidence.
Both receive the same diff, acceptance criteria, invariants, test results, API diff, and benchmark/bundle deltas. They do not see each other's initial conclusions.
Loop:
- Implement the scoped change and evidence.
- Run automated gates.
- Obtain both reviews.
- Classify findings as blocking correctness, architecture, performance, test gap, documentation gap, justified follow-up, or rejected with evidence.
- Resolve all blocking findings.
- Rerun gates. Each reviewer rechecks unresolved findings and materially changed areas against the new commit.
- Require two full reviews again only when the revision changes public contracts, architecture, concurrency, or benchmark behavior materially.
- After two automated resolution cycles, escalate disputes to a human maintainer rather than looping indefinitely.
- Store reports and the resolution ledger in the PR.
Reviews must be tied to the exact commit; a push invalidates prior attestations. Review agents supplement human maintainers and never authorize a merge. Prefer reviewers with different prompts or models; two identical agents are correlated evidence. Independent downstream work may target an accepted interface contract, but cannot merge until its dependency is accepted.
Keep the rigor at candidate boundaries without paying the full cost after every small edit:
- Combine naturally coupled package-private work into one coherent vertical slice when separate PRs would only create temporary APIs and duplicate review cycles.
- Run focused unit, type, lint, and benchmark checks while developing. Run the complete local gate once at a clean candidate commit and again only after a material fix.
- Start the two independent reviews in parallel against that coherent candidate. A reviewer may recheck a narrow non-architectural amendment without repeating unrelated probes; public-contract, concurrency, or lifecycle changes still require two full exact-head approvals.
- Treat hosted CI as the authoritative cross-platform and package-matrix rerun. Do not duplicate the same unchanged full matrix between every local commit.
- Parallelize independent design, implementation, consumer research, and review work. Time-box exploratory research and record nonblocking ideas as follow-ups instead of expanding the active slice.
- Request Copilot once when the PR first has a coherent reviewable head. Never delay a later exact-head fix solely to obtain another Copilot pass.
Generate one review packet containing:
- Base/head commit and diff
- Changed files and risk classification
- Affected invariants and ADRs
- Test/coverage results
- API, benchmark, and bundle deltas
Add a PR template for change size, risks, evidence, two reports, finding ledger, and rollback/disable strategy. CI should reject a medium PR missing commit-bound review attestations or containing unresolved blockers.
Use independent bot/App identities to create required GitHub checks containing reviewer identity, model/version, packet digest, head SHA, findings, and disposition. Validate them through a protected reusable workflow from the base branch so a PR cannot approve itself. Maintainers approve classification overrides and rejected blocking findings.
Request GitHub Copilot review exactly once on every medium or large PR, after the PR has a coherent head that is ready for review:
gh pr edit <number> --add-reviewer @copilotCopilot is an additional advisory review, not one of the two independent commit-bound adversarial attestations and not a substitute for human approval. Resolve or explicitly disposition its actionable comments in the finding ledger. Do not re-request Copilot after later pushes or material rewrites; the commit-bound adversarial reviewers and required CI provide exact-head revalidation.
Set measured per-job budgets and run independent jobs in parallel. Aim for a useful result within ten minutes without making that aspirational number a correctness constraint:
- Frozen install
- Non-mutating lint
- Strict typecheck and forbidden-practice scan
- Unit, contract, and deterministic short fuzz tests
- Coverage and changed-code coverage
- Build, declarations, and public API diff
- Packed-package validation
- Bundle-size budget
- Required Chromium integration
- Import boundaries and dependency cycles
Cancel superseded runs.
Add a CI self-test before branch protection: deliberately failing fixture PRs must prove every required check appears and blocks merging.
For relevant paths, run full browser tests, marimo fixture, packed consumers, performance smoke tests, and security fixtures. Core, package, TypeScript, lockfile, or CI changes conservatively run everything.
Run randomized fuzzing, mutation tests, the full performance matrix, memory/leak scenarios, Firefox/WebKit, dependency auditing, differential testing, and the dialect conformance matrix.
Nightly failures should open or update a tracking issue with seeds and artifacts. Avoid duplicate issue spam. Maintain a scheduled-health check that records suite, source SHA, configuration digest, completion time, and expiry. Release candidates are blocked by red or stale scheduled health. Define an owner, triage SLA, and maximum quarantine duration.
Run reduced mutation, differential, and leak sentinels in PR CI when critical modules change; nightly evidence alone is too delayed.
Run all scheduled-class suites against the exact tagged SHA.
Build one npm pack artifact from that SHA in a reusable verification workflow
and record its SHA-256 and provenance. Split release evidence:
- Source/configuration gates against the exact tagged SHA: unit, coverage, mutation, fuzz, static analysis, API, source-level benchmarks, and dependency inventory
- Packaging/runtime gates against the exact tarball: minimal consumers, supported bundlers/peers, browser smoke tests, marimo, declarations, source maps, bundle composition, and migration examples
Publishing downloads that immutable artifact and requires successful release checks and scheduled-class evidence for the tagged SHA. Protect the npm environment and reject tags not reachable from the protected release branch. Never rebuild different bits in the publish job.
Checkpoint prereleases publish the verified canary artifact under a next
dist-tag with provenance after their defined subset of source and runtime gates.
Document their versioning and retention policy; ordinary integration commits
remain downloadable CI artifacts rather than permanent npm versions.
Choose explicit supported Node, browser, peer-dependency, bundler, and SSR
versions. Test minimum and latest Node and peer sets against the tarball. Narrow
engines and compatibility claims to what CI continuously validates.
- Coverage cannot decrease for retained/new-major code and reaches the repository target by release candidate; changed-code and invariant floors apply immediately.
- No new unsafe type practice is allowed from the first overhaul commit.
- Existing unsafe practices decrease by milestone.
- Bundle/performance budgets cannot regress without explicit approval.
- Mutation score cannot decrease.
- Flaky tests need an owner and expiry; quarantine is temporary.
- Public API growth requires explicit approval.
Ratchets prevent new debt immediately while allowing deliberate removal of existing debt.
- Acceptance criteria and affected invariants are satisfied.
- Relevant unit, contract, integration, browser, fuzz, and failure tests pass.
- Changed core code meets coverage targets.
- No forbidden type practice is introduced.
- Lint, typecheck, build, package, and API checks pass.
- Performance and bundle budgets pass or their change is approved.
- Fuzz failures have permanent regression fixtures.
- Both independent reviews have no unresolved blocking findings.
- Docs, ADRs, examples, and capability matrices are current.
- The result is simpler or demonstrably more capable than what it replaces.
Deliver branch protection, PR/ADR templates, review automation, behavior/API/ coverage/bundle/performance baselines, confirmed-bug tests, and the marimo fixture.
Exit when every baseline is reproducible in CI.
Deliver enforced coverage, contract/golden organization, fuzz/property harness, mutation pilot, explicit browser CI, package smoke tests, type/import/API checks, and benchmark/bundle budgets.
In parallel, build a deliberately thin walking skeleton:
document revision
→ parser adapter
→ minimal normalized result
→ one completion result
→ CodeMirror presentation
Apply final changed-code gates to this new code immediately. Do not delay architectural feedback while exhaustively testing legacy code scheduled for deletion.
Exit when critical characterization exists, harnesses are reproducible, and CI catches deliberately introduced stale-result, unsafe-cast, range, bundle, and API defects. Repository-wide coverage of retained/new-major code reaches the target by release candidate, not as a waterfall prerequisite.
Deliver revisions, UTF-16 half-open ranges, original/rendered source maps, embedded regions, statement boundaries, disposable sessions, in-flight deduplication, and bounded caches.
Also define the minimum parser, validator, catalog, completion, and provider result contracts now, including capability, authority, load state, document-versus-statement granularity, timeout, cancellation, and provenance. Run early DuckDB, LSP, formatter, and worker feasibility spikes and record go/no-go ADRs. These contracts cannot be deferred until after features that depend on them.
Exit when arbitrary edit properties pass, stale results cannot apply, and unchanged statements are reused.
Deliver the parser contract, measured node-sql-parser adapter, normalized
artifacts, isolated execution, bounded coordination, and authenticated syntax
evidence.
Deliver relation completion independently through a bounded partial-SELECT
query-site recognizer and CTE-visibility recognizer plus one asynchronous,
coverage-aware catalog provider. The host may implement that provider as a
composite; multi-provider arbitration remains a later explicit design.
This path must remain useful for incomplete SQL and must not construct or wait
for the parser worker.
Keep the public provider and completion types provisional until the vertical slice, two provider shapes, packed marimo integration, hostile decoding and lifecycle suites, and declaration snapshots pass.
Then design query blocks, typed visibility, CTE/relation/alias/column bindings, and explicit partial semantic states against materially different dialect corpora before an additional parser-derived scope feature consumes them. The bounded CTE recognizer remains the explicit narrow exception. Flat parser relation lists are not a semantic model.
Exit when relation completion works through the framework-independent session, catalog and parser failures remain independent, semantic goldens pass, parser ASTs do not leak, and dialect differences are classified.
After completion proves the end-to-end model, migrate:
- Statement selection and gutter
- Syntax diagnostics
- Hover
- Navigation
- Semantic diagnostics
Each slice includes CodeMirror integration, browser tests, performance evidence, and the two-reviewer loop. Delete the old slice after acceptance.
Expand the minimal contracts into lazy catalogs, stable
identities/invalidation, production feature-specific authority, native/remote
providers, and the recorded DuckDB/LSP/sqruff decisions.
Exit when optional remote work never delays the local baseline beyond the checked product response budget, incomplete local results remain useful, and all race/failure/partial-catalog contracts pass.
Migrate marimo, publish performance results and a dialect capability matrix, resolve prerelease feedback, remove legacy exports, and finalize migration/API documentation.
Exit when the exact release tarball passes marimo and minimal-consumer smoke tests plus all correctness, quality, security, performance, and review gates.
Before semantic implementation:
- Add
dev-refactorCI triggers and prove required checks fail closed. - Enforce explicit all-file Vitest coverage and per-file changed-code coverage.
- Add explicit Chromium browser script and required CI step.
- Add production/test/demo/fixture/public-consumer typecheck projects.
- Add package tarball, peer-version, bundler, and minimal-consumer tests.
- Add API declaration diffing.
- Add bundle reporting and budgets.
- Add isolated deterministic property/fuzz infrastructure.
- Add JSON benchmarks, base/head comparison, and noise policy.
- Add the hermetic marimo fixture and pinned scheduled canary.
- Add forbidden type-practice, import-boundary, and cycle checks.
- Add the invariant registry and test-suite integrity checks.
- Add PR risk template and review-packet generation.
- Add protected, commit-bound two-reviewer checks.
- Automate one GitHub Copilot review request per medium or large PR.
- Add verified-artifact provenance to release CI.
- Add nightly mutation, fuzz, cross-browser, leak, and performance workflows.
- Add expiring scheduled-health and deduplicated failure issues.
- Define the supported runtime and dependency matrix.
The proposed emphasis on tests, >95% coverage, type safety, simplicity, and adversarial review is right. The important refinements are:
- Use coverage as a ratcheted floor, backed by branch coverage, mutation tests, and semantic corpora so the metric cannot be gamed.
- Establish behavior and performance baselines before replacing code.
- Keep
dev-refactorgreen with small vertical PRs. - Test revisions, provider contracts, partial results, cancellation, and disposal as aggressively as happy-path SQL.
- Make marimo a continuous reference consumer.
- Tie reviews to exact commits and repeat them after changes.
- Gate latency, memory, bundle size, API growth, and correctness with measurable budgets.
Automation should make the demanding path the easiest path while keeping every change small enough for humans and review agents to understand completely.