Skip to content

feat: broker OpenCode Go API keys to Boat OMP homes - #260

Merged
dnth merged 6 commits into
mainfrom
fm/fm-boat-opencode-go-vend
Oct 19, 2026
Merged

dnth merged 6 commits into
mainfrom
fm/fm-boat-opencode-go-vend

Conversation

@dnth

@dnth dnth commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Intent

Implement brokered in-memory delivery of API keys for opencode-go-dnth, opencode-go-dnth-1, opencode-go-neuralengine, and opencode-go-neuralengine-1 to Boat-hosted OMP homes (the Boat secondmate and its workers). The existing per-lease credential broker is the only key path; OMP provider blocks and model configuration on Boat must reference the broker, never a key file. The workstation must stay online while a lease is live. vend() accepts api_key credentials only for allowlisted Boat providers and returns the minimum OMP shape; non-allowlisted API keys are refused and OAuth behavior stays unchanged. Follow the existing owner of the provider allowlist. Boat lane selection must not claim quota-informed choices for these accounts because quota-axi reads only the workstation auth.json; document how the main home supplies account choice at routing time. Docs must state the brokered credential path, keys in Boat memory only per lease and never at rest, workstation-online dependency, and key rotation as revocation. AC1 uses fake-key automated tests. AC2 requires real OMP calls through the broker on all four providers on a throwaway large Boat box plus a check for no auth.json and no OpenCode key in any file, models config, or environment; the box must be deleted under the $0.30 cap. Existing live evidence records four calls passed, 60,279 files scanned without key matches, box deleted, cost $0.01115. AC3 is the quota and documentation behavior. AC4 is proven only by green GitHub CI lanes on the PR; do not mark it accepted-blocked. Local suite context is attached in ~/Desktop/firstmate/data/fm-boat-opencode-go-vend/artifacts/baseline-classification.md: 25 failures reproduced at base with the same failure, 4 flaky failures passed on serial branch repeat, 0 branch-only. Include the classification summary/table and live-smoke cost/deletion in PR context. If a PR CI lane fails, report it before changing anything outside this task surface. Do not broaden scope: no Boat keys in argv, logs, commits, or disk; tests use fake keys; do not touch boatmate bx_cbbk3thq; out of scope are GitHub/Codex/Claude logins on the box, Boat API key, box size, Discord, and scope policy.

What Changed

  • Add lease-scoped API-key delivery through the workstation broker for all four OpenCode Go providers, preserving OAuth behavior and restricting API-key egress by provider and credential ID.
  • Install broker-backed OMP model entries on Boat, disable disk snapshot caching, and require credential-lease markers for launches and relaunches.
  • Add fake-key coverage for credential delivery, rotation, model configuration, and launch guards; document workstation connectivity, revocation, and main-home account routing.

Risk Assessment

✅ Low: Credential delivery is explicitly scoped, Boat launch settings remain bounded, and configuration changes are validated before atomic replacement.

Testing

Real local broker/consumer, configuration, and marker checks passed. Focused simulated launch coverage passed but is not live, so Boat launch emission is untested live. Temporary-home setup errors were resolved; the broader launch file was stopped after an unrelated recovery stall. Real Boat inference, remote scanning, and cost/deletion remain untested because isolated authentication is unavailable. This CLI-only change needs no screenshot; CI remains with the outer executor.

  • Live validation: ⚠️ inconclusive - 7 of 9 scenarios driven live against the product
Scenario Result Live Evidence
Resolve all four Go accounts through the real local OMP broker, facade, helper, and OMP token consumer ✅ pass live live-broker.log
Exclude nonallowlisted and unselected account credentials, minimize OAuth output, and refuse remote mutation ✅ pass live live-broker.log
Rotate an account key for the next lease and revoke facade access by deleting its token ✅ pass live live-broker.log
Consume brokered fake keys without persisting them in the disposable remote files or environment ✅ pass live live-broker.log; generated-models.yml
Replace a Go provider while preserving the following private provider and byte-identical reinstall ✅ pass live config-product.log
Refuse inline, unsupported-indentation, duplicate-key, and invalid YAML without changing original bytes ✅ pass live config-product.log
Install the Boat marker and refuse a relaunch after that marker is removed ✅ pass live marker-product.log
Emit Boat launch and relaunch broker settings while preserving generic broker snapshot-cache behavior ⏸️ untested no The prior payload did not establish a live result: only automated checks with simulated launch backends passed (config-launch-tests.log, boat-launch-focused.log). No running Boat OMP process was launc…
Run real inference on all four providers on a disposable large Boat box, scan remote storage, and delete it below $0.30 ⏸️ untested no The Boat CLI was tried with an isolated empty home and returned HTTP 401. No isolated authenticated Boat session or authorized real-provider broker lease was supplied, and operator credentials/configu…
Evidence: Real OMP broker, facade, and consumer transcript
Real OMP canonical broker started on isolated loopback port
Lease synchronization imported all four fake account keys into real broker
HTTP snapshot: four scoped API keys, nonallowlisted key excluded, OAuth sanitized unchanged
Remote broker resolver returned expected fake key in memory: opencode-go-dnth
Real OMP token consumer read brokered credential: opencode-go-dnth
Remote broker resolver returned expected fake key in memory: opencode-go-dnth-1
Real OMP token consumer read brokered credential: opencode-go-dnth-1
Remote broker resolver returned expected fake key in memory: opencode-go-neuralengine
Real OMP token consumer read brokered credential: opencode-go-neuralengine
Remote broker resolver returned expected fake key in memory: opencode-go-neuralengine-1
Real OMP token consumer read brokered credential: opencode-go-neuralengine-1
Remote generated files scanned: 7; no fake API key at rest or in environment
Remote mutation and API-key refresh refused with HTTP 403
Next lease imported rotated key and disabled previous owned broker credential
Deleting lease token immediately revoked facade access: HTTP 401
Resolver refused revoked lease without returning a credential
All disposable broker/facade processes stopped
Evidence: Configuration preservation and refusal transcript
install-models: exit 0
Installed provider names: ["private-provider", "opencode-go-dnth", "opencode-go-dnth-1", "opencode-go-neuralengine", "opencode-go-neuralengine-1"]
Preserved private-provider: {"baseUrl": "https://private.example/v1"}
check-models: exit 0
install-models: exit 0
Reinstallation byte-identical: true
Input representation: inline
install-models: exit 1 error: Boat OMP model config install failed
check-models: exit 1 error: Boat OMP model config check failed
Original bytes preserved: true
Input representation: four-space
install-models: exit 1 error: Boat OMP model config install failed
check-models: exit 1 error: Boat OMP model config check failed
Original bytes preserved: true
Input representation: duplicate
install-models: exit 1 error: Boat OMP model config install failed
check-models: exit 1 error: Boat OMP model config check failed
Original bytes preserved: true
Input representation: invalid
install-models: exit 1 error: Boat OMP model config install failed
check-models: exit 1 error: Boat OMP model config check failed
Original bytes preserved: true
Evidence: Real missing-marker relaunch refusal
Real auth installer created boat-auth.marker and keyless model configuration
Real relaunch exit: 1
error: Boat OMP auth marker is missing or unsafe; restore the Boat credential lease before launching
Missing-marker relaunch refused before starting OMP; no mocked commands used
Evidence: Generated keyless OMP models configuration
providers:
  # firstmate-opencode-go-brokered: begin
  opencode-go-dnth:
    baseUrl: https://opencode.ai/zen/go/v1
    headers:
      x-opencode-session: "!cat /proc/sys/kernel/random/uuid"
    apiKey: "!python3 ~/.no-mistakes/worktrees/dd71c22cc6d7/01M58ECA5XZB22RG1DG2KGBSFE/.test-boat/live/remote/boat-omp-remote.py api-key opencode-go-dnth"
    compat:
      whenThinking:
        requiresReasoningContentForToolCalls: true
        allowsSyntheticReasoningContentForToolCalls: false
        reasoningContentField: reasoning_content
    models:
      - id: deepseek-v4.1-flash
        name: DeepSeek V4.1 Flash
        api: openai-completions
        reasoning: true
        thinking:
          mode: effort
          efforts: [low, high, max]
        input: [text, image]
        cost: {input: 0.15, output: 0.6, cacheRead: 0.003, cacheWrite: 0}
        contextWindow: 1000000
        maxTokens: 384000
      - id: muse-spark-1.3-contributor
        name: Muse Spark 1.3 Contributor
        api: openai-responses
        reasoning: true
        thinking:
          mode: effort
          efforts: [minimal, low, medium, high, xhigh, max]
        input: [text, image]
        cost: {input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0}
        contextWindow: 1048576
        maxTokens: 131072
  opencode-go-dnth-1:
    baseUrl: https://opencode.ai/zen/go/v1
    headers:
      x-opencode-session: "!cat /proc/sys/kernel/random/uuid"
    apiKey: "!python3 ~/.no-mistakes/worktrees/dd71c22cc6d7/01M58ECA5XZB22RG1DG2KGBSFE/.test-boat/live/remote/boat-omp-remote.py api-key opencode-go-dnth-1"
    compat:
      whenThinking:
        requiresReasoningContentForToolCalls: true
        allowsSyntheticReasoningContentForToolCalls: false
        reasoningContentField: reasoning_content
    models:
      - id: deepseek-v4.1-flash
        name: DeepSeek V4.1 Flash
        api: openai-completions
        reasoning: true
        thinking:
          mode: effort
          efforts: [low, high, max]
        input: [text, image]
        cost: {input: 0.15, output: 0.6, cacheRead: 0.003, cacheWrite: 0}
        contextWindow: 1000000
        maxTokens: 384000
      - id: muse-spark-1.3-contributor
        name: Muse Spark 1.3 Contributor
        api: openai-responses
        reasoning: true
        thinking:
          mode: effort
          efforts: [minimal, low, medium, high, xhigh, max]
        input: [text, image]
        cost: {input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0}
        contextWindow: 1048576
        maxTokens: 131072
  opencode-go-neuralengine:
    baseUrl: https://opencode.ai/zen/go/v1
    headers:
      x-opencode-session: "!cat /proc/sys/kernel/random/uuid"
    apiKey: "!python3 ~/.no-mistakes/worktrees/dd71c22cc6d7/01M58ECA5XZB22RG1DG2KGBSFE/.test-boat/live/remote/boat-omp-remote.py api-key opencode-go-neuralengine"
    compat:
      whenThinking:
        requiresReasoningContentForToolCalls: true
        allowsSyntheticReasoningContentForToolCalls: false
        reasoningContentField: reasoning_content
    models:
      - id: deepseek-v4.1-flash
        name: DeepSeek V4.1 Flash
        api: openai-completions
        reasoning: true
        thinking:
          mode: effort
          efforts: [low, high, max]
        input: [text, image]
        cost: {input: 0.15, output: 0.6, cacheRead: 0.003, cacheWrite: 0}
        contextWindow: 1000000
        maxTokens: 384000
      - id: muse-spark-1.3-contributor
        name: Muse Spark 1.3 Contributor
        api: openai-responses
        reasoning: true
        thinking:
          mode: effort
          efforts: [minimal, low, medium, high, xhigh, max]
        input: [text, image]
        cost: {input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0}
        contextWindow: 1048576
        maxTokens: 131072
  opencode-go-neuralengine-1:
    baseUrl: https://opencode.ai/zen/go/v1
    headers:
      x-opencode-session: "!cat /proc/sys/kernel/random/uuid"
    apiKey: "!python3 ~/.no-mistakes/worktrees/dd71c22cc6d7/01M58ECA5XZB22RG1DG2KGBSFE/.test-boat/live/remote/boat-omp-remote.py api-key opencode-go-neuralengine-1"
    compat:
      whenThinking:
        requiresReasoningContentForToolCalls: true
        allowsSyntheticReasoningContentForToolCalls: false
        reasoningContentField: reasoning_content
    models:
      - id: deepseek-v4.1-flash
        name: DeepSeek V4.1 Flash
        api: openai-completions
        reasoning: true
        thinking:
          mode: effort
          efforts: [low, high, max]
        input: [text, image]
        cost: {input: 0.15, output: 0.6, cacheRead: 0.003, cacheWrite: 0}
        contextWindow: 1000000
        maxTokens: 384000
      - id: muse-spark-1.3-contributor
        name: Muse Spark 1.3 Contributor
        api: openai-responses
        reasoning: true
        thinking:
          mode: effort
          efforts: [minimal, low, medium, high, xhigh, max]
        input: [text, image]
        cost: {input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0}
        contextWindow: 1048576
        maxTokens: 131072
  # firstmate-opencode-go-brokered: end
Evidence: Isolated Boat access unavailable

{"code":"unauthorized","error":"not signed in, or your session expired. run boat onboard","event":"error","status":401}

{"code":"unauthorized","error":"not signed in, or your session expired. run `boat onboard`","event":"error","status":401}
- Outcome: ⚠️ 1 warning across 2 runs (24m8s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed (3) ✅
  • 🚨 bin/fm-boat-remote-omp.py:151 - Replacing an existing Go provider deletes unrelated providers that follow it. For example, with opencode-go-dnth followed by private-provider, _provider_key() recognizes only the Go entry, so its deletion range extends through private-provider to the end of the mapping. Preserve every sibling boundary when calculating replacement ranges. Related sites: bin/fm-boat-remote-omp.py:86 recognizes only target providers; :151 filters sibling boundaries; :155 calculates the oversized range; :165 deletes it.
  • ⚠️ bin/fm-spawn.sh:5288 - The unconditional snapshot-cache override also changes RunPod and other broker-backed OMP launches: fm-remote-secondmate-control.sh exports the same broker variables for RunPod, reaching this branch. No Boat requirement needs that additional behavior. Remove the override for non-Boat launches and retain a Boat-specific form. Related changed assertion: tests/fm-omp-secondmate.test.sh:560 requires the override for a generic broker launch.

🔧 Fix applied.
2 errors still open:

  • 🚨 bin/fm-boat-remote-omp.py:151 - Replacing an existing Go provider deletes unrelated providers that follow it. For example, with opencode-go-dnth followed by private-provider, _provider_key() recognizes only the Go entry, so its deletion range extends through private-provider to the end of the mapping. Preserve every sibling boundary when calculating replacement ranges. Related sites: bin/fm-boat-remote-omp.py:86 recognizes only target providers; :151 filters sibling boundaries; :155 calculates the oversized range; :165 deletes it.
  • 🚨 bin/fm-boat-remote-omp.py:94 - A valid existing config such as providers: {private-provider: {baseUrl: https://private.example/v1}} is treated as having no providers mapping. Installation then appends a second providers: key, hiding existing providers or causing YAML rejection. Round 1 fixed sibling preservation for two-space block mappings but left this preservation failure reachable. Related sites: bin/fm-boat-remote-omp.py:94 recognizes only block headers; :103 accepts the inline header; :128 appends the duplicate mapping; :218 checks only the generated block and accepts the corrupted result. Recognize existing mappings semantically, or reject unsupported representations before writing; preserve the original file on refusal.

🔧 Fix applied.
4 issues (3 errors, 1 warning) still open:

  • 🚨 bin/fm-boat-remote-omp.py:151 - Replacing an existing Go provider deletes unrelated providers that follow it. For example, with opencode-go-dnth followed by private-provider, _provider_key() recognizes only the Go entry, so its deletion range extends through private-provider to the end of the mapping. Preserve every sibling boundary when calculating replacement ranges. Related sites: bin/fm-boat-remote-omp.py:86 recognizes only target providers; :151 filters sibling boundaries; :155 calculates the oversized range; :165 deletes it.
  • 🚨 bin/fm-boat-remote-omp.py:94 - A valid existing config such as providers: {private-provider: {baseUrl: https://private.example/v1}} is treated as having no providers mapping. Installation then appends a second providers: key, hiding existing providers or causing YAML rejection. Round 1 fixed sibling preservation for two-space block mappings but left this preservation failure reachable. Related sites: bin/fm-boat-remote-omp.py:94 recognizes only block headers; :103 accepts the inline header; :128 appends the duplicate mapping; :218 checks only the generated block and accepts the corrupted result. Recognize existing mappings semantically, or reject unsupported representations before writing; preserve the original file on refusal.
  • 🚨 bin/fm-boat-remote-omp.py:170 - Rounds 1/2 left another provider-preservation failure reachable. A valid models.yml containing providers:\n private-provider:\n baseUrl: https://private.example/v1\n passes admission, but installation appends two-space provider entries beneath the existing four-space mapping, producing invalid YAML while install-models and check-models succeed. Recognize the existing indentation or refuse unsupported representations before writing, preserving the original bytes. Related sites: bin/fm-boat-remote-omp.py:87 assumes two-space sibling keys; :107 accepts the mapping without validating its children; :170 appends the incompatible block; :219 and :221 validate the header and generated substring rather than YAML meaning.
  • ⚠️ tests/boat-auth-cases.py:166 - New generated-configuration assertions check provider-name substrings and counts without validating YAML meaning, contrary to the test-quality rule for machine-consumed declarative artifacts. These checks can accept malformed configuration or names appearing outside the providers mapping. Parse the generated YAML with duplicate-key rejection and assert provider values and broker commands semantically; retain byte comparisons for preservation and idempotence. Sites: tests/boat-auth-cases.py:161-166, :483, :486-491. The replacement assertions were added or extended by the previous fix rounds.

🔧 Fix applied.
✅ Re-checked - no issues remain.

⚠️ **Test** - 1 warning
  • ⚠️ live validation verdict: inconclusive (5 of 6 scenarios were driven live against the product); untested: Run real OMP inference on all four providers on a disposable large Boat box, scan for persisted keys, and delete it below $0.30
  • Live validation: ⚠️ inconclusive - 5 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Resolve all four Go accounts through the real local OMP broker, facade, and remote helper without persisting keys in the disposable remote home ✅ pass live Real broker and remote-helper transcript
Reject non-allowlisted accounts and unrelated credential IDs while retaining the minimum API-key and OAuth response shapes ✅ pass live Provider admission transcript; Real broker and remote-helper transcript
Rotate an imported key, remove lease authorization, and stop the workstation broker; old or unavailable credentials cannot be resolved ✅ pass live Real broker and remote-helper transcript
Replace Go configuration while preserving sibling providers and idempotence; reject unsupported or invalid YAML without modifying its bytes ✅ pass live Configuration preservation and refusal transcript; OMP-consumed model catalog
Generate launch commands with snapshot caching disabled only for Boat ✅ pass live Generated Boat launch command; Generated generic broker launch command; secondmate-regressions.log
Run real OMP inference on all four providers on a disposable large Boat box, scan for persisted keys, and delete it below $0.30 ⏸️ untested no Built and exercised a disposable local environment with real OMP and fake keys. Real provider inference requires genuine OpenCode credentials and Boat provisioning authority. Operator credentials are…
  • TMPDIR="$PWD/.local-test/tmp" PYTHONDONTWRITEBYTECODE=1 python3 tests/boat-auth-cases.py "$PWD" ModelConfigTests -v
  • PYTHONDONTWRITEBYTECODE=1 python3 .local-test/live-drive.py using real OMP 18.10.1 broker, Node facade, and remote helper with fake credentials
  • PYTHONDONTWRITEBYTECODE=1 python3 .local-test/config-drive.py
  • omp models --json with isolated HOME and PI_CODING_AGENT_DIR
  • node bin/fm-boat-policy.mjs --model <provider/model> with default and explicit allowlists for all four accounts
  • FM_HOME="$PWD/.local-test/primary" TMPDIR="$PWD/.local-test/tmp" bash .local-test/product/tests/fm-omp-secondmate.test.sh against a disposable archive of HEAD; passed after resolving nested-home setup refusals
  • Captured generated Boat and generic launch scripts with a targeted disposable test driver
  • Reviewed credential, quota-routing, workstation-online, and revocation documentation; removed disposable files and confirmed a clean working tree

🔧 Fix applied.
1 warning still open:

  • ⚠️ live validation verdict: inconclusive (7 of 9 scenarios were driven live against the product); untested: Emit Boat launch and relaunch broker settings while preserving generic broker snapshot-cache behavior, Run real inference on all four providers on a disposable large Boat box, scan remote storage, and delete it below $0.30
  • Live validation: ⚠️ inconclusive - 7 of 9 scenarios driven live against the product
Scenario Result Live Evidence
Resolve all four Go accounts through the real local OMP broker, facade, helper, and OMP token consumer ✅ pass live live-broker.log
Exclude nonallowlisted and unselected account credentials, minimize OAuth output, and refuse remote mutation ✅ pass live live-broker.log
Rotate an account key for the next lease and revoke facade access by deleting its token ✅ pass live live-broker.log
Consume brokered fake keys without persisting them in the disposable remote files or environment ✅ pass live live-broker.log; generated-models.yml
Replace a Go provider while preserving the following private provider and byte-identical reinstall ✅ pass live config-product.log
Refuse inline, unsupported-indentation, duplicate-key, and invalid YAML without changing original bytes ✅ pass live config-product.log
Install the Boat marker and refuse a relaunch after that marker is removed ✅ pass live marker-product.log
Emit Boat launch and relaunch broker settings while preserving generic broker snapshot-cache behavior ⏸️ untested no The prior payload did not establish a live result: only automated checks with simulated launch backends passed (config-launch-tests.log, boat-launch-focused.log). No running Boat OMP process was launc…
Run real inference on all four providers on a disposable large Boat box, scan remote storage, and delete it below $0.30 ⏸️ untested no The Boat CLI was tried with an isolated empty home and returned HTTP 401. No isolated authenticated Boat session or authorized real-provider broker lease was supplied, and operator credentials/configu…
  • TMPDIR="$PWD/.test-boat/tmp" PYTHONDONTWRITEBYTECODE=1 python3 tests/boat-auth-cases.py "$PWD" ModelConfigTests LaunchAuthTests -v
  • PYTHONDONTWRITEBYTECODE=1 python3 .test-boat/live.py — real isolated OMP broker, facade, credential synchronization, four OMP token consumers, rotation, revocation, and remote-file scan
  • PYTHONDONTWRITEBYTECODE=1 python3 .test-boat/config-probe.py — real install-models/check-models CLI preservation and refusal checks
  • PYTHONDONTWRITEBYTECODE=1 python3 .test-boat/marker-probe.py — real auth installation and missing-marker relaunch refusal
  • bash tests/fm-omp-secondmate.test.sh — two temporary-home setup refusals; default-temp retry passed launch checks but was stopped after a later recovery case stalled
  • env -u TMPDIR FM_HOME="$PWD/.test-boat/main" PYTHONDONTWRITEBYTECODE=1 bash tests/.boat-launch-phase.test.sh — existing launch function selected alone; passed
  • env -i PATH="$PATH" HOME="$PWD/.test-boat/boat-home" XDG_CONFIG_HOME="$PWD/.test-boat/boat-home/config" boat list — HTTP 401
  • Reviewed the changed quota-routing and credential documentation; removed disposable files and verified a clean working tree and stopped test processes
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Post-test-gate live evidence

This section supersedes the earlier live-validation status for current-head relaunch behavior; the preceding pipeline snapshot remains historical.

  • Live relaunch-path check: the actual fm-remote-secondmate-control.sh relaunch path called configure_compute_omp_auth_launch. A downstream stub on the disposable box prevented any Herdr or pane operation and launched OMP 18.10.1 directly with the secondmate environment composed by fm-spawn.sh. opencode-go-neuralengine/deepseek-v4.1-flash returned exactly OK (assistant_reply_seen=true, reply_ok=true, timed_out=false). The test driver terminated OMP after recording the reply (process_exit=143); no HTTP status or request host/path was captured.
  • Missing-marker check: after removing /home/user/.fm/boat-auth.marker, the same relaunch path exited 1 with Boat OMP auth marker is missing or unsafe; restore the Boat credential lease before launching. The stub call count stayed at one, so OMP did not start on the second attempt.
  • Herdr limitation: no end-to-end relaunch through a live Herdr pane was exercised. The captain's instruction in inbox 011 explicitly prohibited driving Herdr and regenerating the brief; the real relaunch setup helper ran, while a test stub intercepted the pane handoff.
  • Box and cost: boat usage before deletion reported 660 seconds and $0.0066. The box was deleted and boat info returned 404. Total task spend upper bound is $0.15507 against the $0.30 cap. Decision 009 contains the four-provider live smoke and full key scan; this box added one current-head provider call and marker-refusal check, not another storage scan.
  • Test exception: the test gate was approved per the captain's explicit instruction after both live checks passed. No-Mistakes records live validation verdict: inconclusive and Test exception approved: no operator reason supplied; this is not a clean test pass. CI passed.

@dnth
dnth merged commit 338a7ac into main Oct 19, 2026
19 checks passed
@dnth
dnth deleted the fm/fm-boat-opencode-go-vend branch October 19, 2026 03:49
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