Skip to content

fix(#6471): validate config-driven runtimes against ValidRuntimes() - #6472

Merged
waynesun09 merged 1 commit into
mainfrom
agent/6471-validate-config-runtimes
Aug 23, 2026
Merged

fix(#6471): validate config-driven runtimes against ValidRuntimes()#6472
waynesun09 merged 1 commit into
mainfrom
agent/6471-validate-config-runtimes

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Summary

Add a ValidRuntimes() guard to config-driven runtime resolution so that stub runtimes (e.g. opencode) registered in Resolve() for dev/testing are rejected before sandbox bootstrap when selected through org or per-repo config. Previously, resolveBackendFromConfigData() skipped .Validate() and passed parsed config straight to Resolve(), which accepted stub runtimes and let the run proceed through sandbox creation before failing in Bootstrap().

Changes

  • Add validateConfigRuntime() helper in internal/runtime/registry.go that checks the runtime name against config.ValidRuntimes() before resolution
  • Call validateConfigRuntime() in both ResolveFromConfig() and ResolveFromPerRepoConfig()
  • Direct Resolve() calls remain unaffected — stub runtimes are still accessible for dev/testing
  • Update registry_test.go: replace test asserting opencode resolves via config with tests verifying stub runtimes are rejected through config paths while remaining accessible via direct Resolve()

Testing

  • New test TestResolveFromPerRepoConfig_RejectsStubRuntimes verifies stub runtimes are rejected via per-repo config and still resolvable via direct Resolve()
  • New test TestResolveFromConfig_RejectsStubRuntimes verifies stub runtimes are rejected via org config
  • All existing tests pass (go test -race ./internal/runtime/...)
  • 100% function coverage on all changed functions in registry.go
  • go vet passes

Note: golangci-lint was not available in the sandbox environment. pre-commit could not initialize due to network restrictions. Manual verification of these is required.


Closes #6471

Post-script verification

  • Branch is not main/master (agent/6471-validate-config-runtimes)
  • Secret scan passed (gitleaks — 6fa6cb907b700abaace905bf2cfd8ffb5693dc71..HEAD)
  • PR body secret scan passed (gitleaks — no-git)

@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner August 22, 2026 00:40
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Triggers review agent dispatch label Aug 22, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:42 AM UTC · Completed 12:54 AM UTC

Commit: 38a5330 · View workflow run →

@codecov

codecov Bot commented Aug 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review

Copy link
Copy Markdown

Looks good to me

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Aug 22, 2026
resolveBackendFromConfigData() passes parsed config straight into
ResolveFromConfig/ResolveFromPerRepoConfig → Resolve() without
checking ValidRuntimes(). This allows stub runtimes like "opencode"
(registered in Resolve() for dev/testing but absent from
ValidRuntimes()) to pass through config-driven resolution, burning
sandbox/bootstrap side effects before failing in Bootstrap().

Add a validateConfigRuntime() guard in both ResolveFromConfig() and
ResolveFromPerRepoConfig() that checks the runtime name against
config.ValidRuntimes() before calling Resolve(). Direct Resolve()
calls remain unaffected, preserving dev/testing access to stubs.

Update registry_test.go: the existing test asserting opencode
resolves via config is replaced with tests verifying stub runtimes
are rejected through config paths while remaining accessible via
direct Resolve().

Closes #6471
@waynesun09
waynesun09 force-pushed the agent/6471-validate-config-runtimes branch from 38a5330 to f047ad7 Compare August 23, 2026 00:44
@waynesun09

Copy link
Copy Markdown
Member

Rebased onto 9a184a9e (current main) and reviewed. CONFLICTINGMERGEABLE; head is now f047ad71.

The conflict, and how I resolved it

The conflict was in TestResolveFromPerRepoConfig, and it was a meaningful one rather than a textual clash. Main had gained this block from #6467:

// opencode is not in ValidRuntimes() but is resolvable via Resolve().
// A hand-written config bypassing validation can reach the stub.
ocCfg.SetRuntime("opencode")
ocBackend, err := ResolveFromPerRepoConfig(ocCfg)
require.NoError(t, err)
assert.Equal(t, "opencode", ocBackend.Runtime.Name())

// pi is user-selectable (#6464).
piCfg.SetRuntime("pi")
...

The first half asserts exactly the behaviour this PR removes — it pinned the bug #6471 describes — so it had to go; your TestResolveFromPerRepoConfig_RejectsStubRuntimes replaces it and asserts the opposite. The second half (pi resolving via per-repo config) is unrelated, still true, and worth keeping, so I kept it. Taking your side of the conflict wholesale would have silently dropped that pi coverage.

Review

The change is correct and minimal: validateConfigRuntime gates both config entry points against config.ValidRuntimes() while direct Resolve() keeps stub access for dev/testing, which is the right split. gofmt/go vet clean; internal/runtime (except two host-only DummyRuntime failures that fail identically on unmodified main here, because openshell is installed on this machine), internal/config and internal/cli all pass.

One correction to the framing, not the code. The PR body and #6471 both say an invalid runtime currently burns "sandbox/bootstrap side effects" before failing. Half of that stays true after this fix: runtime resolution happens at internal/cli/run.go:1202, but the sandbox is created at line 1045 — before it. Confirmed in a real run:

• Creating sandbox: fs-pis-6ace8a7df740
✓ Sandbox created (3.7s)
runtime: selected "pi" from .../config.yaml
• Bootstrapping sandbox

So this correctly prevents the wasted Bootstrap (the expensive part — image work, uploads, preflight) and gives a clear "invalid runtime" error instead of a late failure, but a typo'd runtime: still creates and tears down a sandbox first. Moving resolution above CreateWithRetry would close that, and is a separate change with its own risk (resolution currently sits after several things the sandbox path computes) — worth a follow-up issue rather than expanding this PR.

Ready for approval and the merge queue; say the word and I will take it the rest of the way.

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Rebased onto 9a184a9e by me; the conflict was in TestResolveFromPerRepoConfig, where main had gained an assertion that opencode resolves through per-repo config — the exact behaviour this PR removes — next to an unrelated pi assertion. I dropped the first (superseded by the new …_RejectsStubRuntimes tests) and kept the second, so pi coverage survives the rebase.

The change itself is correct and minimal: validateConfigRuntime gates both config entry points against config.ValidRuntimes() while direct Resolve() keeps stub runtimes available for dev and tests. gofmt/go vet clean; internal/config and internal/cli pass in full, internal/runtime passes apart from two DummyRuntime tests that fail on this machine regardless of branch (a real openshell is installed here, so their "call against a nonexistent sandbox must fail" assertion does not hold).

No blocking findings. The one correction — recorded in the thread above rather than as a change here — is that this stops the wasted Bootstrap, not the wasted sandbox: runtime resolution runs at run.go:1202 while CreateWithRetry is at 1045, so a typo'd runtime: still creates and deletes a sandbox before failing. Follow-up material, not a reason to hold this.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 23, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:46 AM UTC · Completed 12:57 AM UTC

Commit: f047ad7 · View workflow run →

@waynesun09
waynesun09 added this pull request to the merge queue Aug 23, 2026
Merged via the queue into main with commit d31168a Aug 23, 2026
31 checks passed
@waynesun09
waynesun09 deleted the agent/6471-validate-config-runtimes branch August 23, 2026 00:54
@fullsend-ai-retro

fullsend-ai-retro Bot commented Aug 23, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 12:56 AM UTC · Completed 1:08 AM UTC

Commit: f047ad7 · View workflow run →

@fullsend-ai-review

Copy link
Copy Markdown

Review skipped — this PR is already merged.

The /fs-review command only reviews open PRs/MRs.

Posted by fullsend post-review check

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #6472 — validate config-driven runtimes against ValidRuntimes()

Workflow outcome: Successful. The code agent produced correct, minimal code in one shot (zero rework), tests achieved 100% function coverage on changed functions, and the PR merged cleanly after human review.

Timeline: Issue #6471 opened → triage (~6 min) → code agent (~11 min) → review agent approved (~14 min, $2.99) → human rebased and reviewed (~24h later) → second review agent ran post-merge (~13 min, $2.56) → merged.

Key human reviewer contribution: Wayne resolved a meaningful merge conflict (main had gained a test asserting the exact behavior this PR removes, alongside an unrelated pi assertion — he kept the latter and dropped the former) and identified a factual inaccuracy in the PR body: the fix prevents wasted Bootstrap() calls but does NOT prevent sandbox creation, because runtime resolution (run.go:1202) happens after CreateWithRetry (line 1045). The reviewer flagged this as follow-up material.

Evidence for existing open issues

What went well

  • Code agent produced correct code in a single iteration with comprehensive tests
  • Triage was fast, accurate, and provided a useful test sketch the code agent could reference
  • The challenger sub-agent correctly removed a false-positive correctness finding about the if parseErr == nil guard
  • Codecov confirmed 100% patch coverage
  • The agents repo was correctly resolved from fullsend-ai/agents at runtime

Proposals filed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-merge All reviewers approved — ready to merge ready-for-review Triggers review agent dispatch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Config-driven runtime selection doesn't validate against ValidRuntimes() before sandbox bootstrap

1 participant