Skip to content

refactor(arch): make runtime.NewExecutor a strong invariant boundary — no post-construction mutation#118

Merged
matdev83 merged 1 commit into
mainfrom
pr2/runtimebundle-no-post-construction-mutation
Jul 8, 2026
Merged

refactor(arch): make runtime.NewExecutor a strong invariant boundary — no post-construction mutation#118
matdev83 merged 1 commit into
mainfrom
pr2/runtimebundle-no-post-construction-mutation

Conversation

@matdev83

@matdev83 matdev83 commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Hardens the runtimebundle executor construction so runtime.NewExecutor becomes a strong invariant boundary: all Executor fields are computed before construction and passed through ExecutorConfig, with no post-construction field mutation.

What changed

  • Delete runtimebundle.BuildExecutor (last thin wrapper around Build); switch the one remaining stdhttp test caller to runtimebundle.Build.
  • build_executor.go: compute interleaved / accounting / security / observability / routing runtimes (including model-catalog resolver attachment) before constructing the executor; NewExecutor receives them all via ExecutorConfig.
  • interleaved.go: applyInterleavedToExecutorinterleavedExecutorRuntime (returns runtime.InterleavedRuntime instead of mutating *Executor).
  • secure_session.go: applySecureSessionToExecutorsecurityRuntimeFromSecureSession (returns runtime.SecurityRuntime instead of mutating *Executor).
  • modelcatalog_attach.go: attachModelCatalog now takes/returns a runtime.RoutingRuntime (enriches routing before construction) instead of mutating *Executor.
  • build_test.go: rename TestBuildExecutor_*TestBuild_*.
  • built.go / doc.go: correct BuildOptions doc references to the grouped sub-struct paths (Infra.HTTPClient, Diagnostics.SecureSessionStore).
  • stdhttp/route.go: comment follow-on — DefaultWireModel now lives in standardplugins (relocated by the standardplugins split in refactor(arch): finish standardplugins split — remove pluginreg/standardbundle shim and types.go alias #117).
  • New internal/archtest/executor_invariant_test.go: AST-based archtest that rejects any assignment to runtime.Executor fields after a NewExecutor call in internal/infra/runtimebundle, locking the invariant against regressions.
  • critical_files.go: update budget comment to reflect BuildExecutor removal.

Verification (PR scoped, in isolation)

  • go build ./... — passes.
  • go test ./internal/archtest/... ./internal/infra/runtimebundle/... ./internal/stdhttp/... — passes.
  • go vet ./internal/archtest/... ./internal/infra/runtimebundle/... ./internal/stdhttp/... — clean.
  • TestExecutorConstructionNoPostConstructionMutation — passes.

No behavior change; construction is now data-in / config-out.

Second of the PRs splitting the post-review cleanup changes on the local working tree.

…— no post-construction mutation

Harden the runtimebundle executor construction so all Executor fields are
computed before runtime.NewExecutor and passed through ExecutorConfig.
NewExecutor is now a strong invariant boundary with no post-construction
field mutation.

- Delete runtimebundle.BuildExecutor (the last thin wrapper around Build);
  switch the one remaining stdhttp test caller to runtimebundle.Build.
- build_executor.go: compute interleaved/accounting/security/observability/
  routing runtimes (including model-catalog resolver attachment) before
  constructing the executor; NewExecutor receives them via ExecutorConfig.
- interleaved.go: applyInterleavedToExecutor -> interleavedExecutorRuntime
  (returns runtime.InterleavedRuntime instead of mutating *Executor).
- secure_session.go: applySecureSessionToExecutor -> securityRuntimeFromSecureSession
  (returns runtime.SecurityRuntime instead of mutating *Executor).
- modelcatalog_attach.go: attachModelCatalog now takes/returns a
  runtime.RoutingRuntime (enriches routing before construction) instead of
  mutating *Executor.
- build_test.go: rename TestBuildExecutor_* -> TestBuild_*.
- built.go / doc.go: correct BuildOptions doc references to the grouped
  sub-struct paths (Infra.HTTPClient, Diagnostics.SecureSessionStore).
- stdhttp/route.go: comment follow-on — DefaultWireModel now lives in
  standardplugins (relocated by the standardplugins split).
- Add internal/archtest/executor_invariant_test.go: AST-based archtest that
  rejects any assignment to runtime.Executor fields after a NewExecutor call
  in internal/infra/runtimebundle, locking the invariant.
- Update critical_files.go budget comment to reflect BuildExecutor removal.

No behavior change; construction is now data-in/config-out.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@matdev83, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 96766478-f23e-4317-9b9b-bb1b03e58329

📥 Commits

Reviewing files that changed from the base of the PR and between 69941c1 and 17d30bf.

📒 Files selected for processing (12)
  • internal/archtest/critical_files.go
  • internal/archtest/executor_invariant_test.go
  • internal/infra/runtimebundle/build.go
  • internal/infra/runtimebundle/build_executor.go
  • internal/infra/runtimebundle/build_test.go
  • internal/infra/runtimebundle/built.go
  • internal/infra/runtimebundle/doc.go
  • internal/infra/runtimebundle/interleaved.go
  • internal/infra/runtimebundle/modelcatalog_attach.go
  • internal/infra/runtimebundle/secure_session.go
  • internal/stdhttp/default_route_frontends_test.go
  • internal/stdhttp/route.go

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@matdev83 matdev83 merged commit 3a434f7 into main Jul 8, 2026
2 checks passed
matdev83 pushed a commit that referenced this pull request Jul 8, 2026
…rdrails, EchoesVault

Documentation closure for the go-llm-interactive-proxy architecture
de-slopification effort. Updates the spec docs and project knowledge
base to reflect the end state of the refactor.

- specs/go_llm_proxy_arch_review/resolution-plan.md: mark all phases
  complete; rewrite the plan as the final closure record.
- specs/go_llm_proxy_arch_review/{architecture-review,findings-register,
  source-index}.md: update to reflect deleted BuildExecutor wrappers,
  moved standard_table.go, and the feature merge surface.
- docs/adr/0001-registry-driven-composition.md: registry is now the
  registry type only; standard tables live in standardplugins; add a
  dated update entry for the standardbundle/types.go/BuildExecutor
  cleanup.
- docs/architecture-guardrails.md: document the bootstrap_plan.go
  composition-root exemption, the role metadata in the hexagonal
  baseline, and the standardplugins.DefaultWireModel rename.
- docs/architecture.md: note the MergeBundles/Append merge-surface
  simplification.
- internal/plugins/features/README.md: wiring location corrected from
  internal/pluginreg to internal/standardplugins.
- EchoesVault/pages/{plugin-system,testing-strategy}.md and
  EchoesVault/daily/2026-07-08.md: compiled knowledge base updated.

Docs only; no code or test changes.

Note: this PR describes the end state of the cleanup, which is delivered
across #118 (runtimebundle invariant boundary), #119 (baseline role),
and #120 (merge surface). It should merge after those three to keep
docs and code consistent.

Co-authored-by: Cursor <cursoragent@cursor.com>
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