Skip to content

fix(opencode): pass trusted visibility into the private free-model hook - #1046

Draft
cursor[bot] wants to merge 8 commits into
mainfrom
cursor/bc-9fd846c1-0cf0-4d06-9964-ed9b659612f7-f459
Draft

fix(opencode): pass trusted visibility into the private free-model hook#1046
cursor[bot] wants to merge 8 commits into
mainfrom
cursor/bc-9fd846c1-0cf0-4d06-9964-ed9b659612f7-f459

Conversation

@cursor

@cursor cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Problem

#830 adds a fail-closed trusted-base opt-in so a private repository can use governed opencode-free/* review models only after an unchanged base policy classifies the tree as public_equivalent.

The live runner already knows repository privacy from validate-pr-metadata.outputs.is_private, but #830 never exported that signal as OPENCODE_REPOSITORY_IS_PRIVATE. Public eligibility then depended on a credential-free git ls-remote. A timeout or transport failure would strip the free pool from a public repository and send the run down the private policy path.

The hook contract also asserted only that the runner sourced the hook. It did not execute public catalog filtering, private preconfigured-free removal, or trusted-base re-enable.

Solution

  • Pass OPENCODE_REPOSITORY_IS_PRIVATE from the trusted validate-pr-metadata output into the live model-pool runner.
  • Keep the local unit-test escape that omits both visibility and PR_BASE_SHA, and lock the live workflow so that escape cannot fire in production.
  • Add hook-level contracts for public catalog filtering, private fail-closed stripping, eligible-base prepend, and invalid visibility.
  • Protect .github/opencode-private-free-models.json in CODEOWNERS.
  • Record the visibility wire and control-plane flow in AGENTS.md, ARCHITECTURE.md, CHANGELOG.md, and docs/doctoring/opencode-private-free-model-policy.md (APA 7th).

Next action

Land this successor instead of #830 at f449a8de. After merge, a later PR can add the canonical policy on an authoritatively classified private canary (#833). Do not add the policy file on this PR; a head cannot opt itself in.

Verification

  • python3 -m pytest tests/test_opencode_private_free_model_hook_contract.py tests/test_opencode_private_free_model_policy_1.py tests/test_opencode_private_free_model_policy_2.py tests/test_opencode_private_free_model_policy_3.py tests/test_opencode_provider_guard.py tests/test_opencode_agent_contract.py tests/test_required_workflow_queue_contract.py — 151 passed
  • python3 -m pytest tests/test_opencode_model_pool_runner.py::test_free_provider_runtime_cap_preserves_queue_budget tests/test_opencode_model_pool_runner.py::test_nvidia_nim_combined_budget_preserves_fallback_attempt tests/test_opencode_model_pool_runner.py::test_free_provider_gets_one_bounded_schema_repair_attempt — 3 passed
Open in Web View Automation 

@seonghobae

Copy link
Copy Markdown
Contributor

Rebased the private free-model policy/hook series onto current origin/main c47bee5, preserving trusted-base visibility, provider-scoped credentials, CODEOWNERS protection, and the no-Copilot model boundary.

Current HEAD: 6e16e32

Validation on this HEAD:

  • private-free-model and provider-guard pytest: 61 passed
  • interrogate: 100%
  • actionlint, bash -n, new-script shellcheck, compileall, and git diff --check passed

@OpenCode review this exact HEAD after the rebase.

github-actions Bot and others added 2 commits August 20, 2026 14:50
Do not replace the current model-pool implementation. Source a thin
hook that opt-in enables governed anonymous free candidates from an
unchanged trusted-base policy and wraps opencode with a provider
credential guard. Unit tests that pass candidates directly are left
alone unless PR_BASE_SHA or visibility is set.
The live runner already knew repository privacy from validated PR
metadata but never exported it, so public eligibility depended on a
credential-free ls-remote. Wire that signal, lock CODEOWNERS on the
policy path, and add hook-level public/private candidate contracts.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@seonghobae
seonghobae force-pushed the cursor/bc-9fd846c1-0cf0-4d06-9964-ed9b659612f7-f459 branch from 6e16e32 to 7a17f0c Compare August 20, 2026 05:52
@seonghobae

Copy link
Copy Markdown
Contributor

@opencode-agent

Rebased PR #1046 onto current protected main and revalidated trusted repository-visibility propagation.
Exact current head: 7a17f0c

The live runner supplies the trusted is_private signal to the free-model hook; public catalog filtering, private fail-closed stripping, eligible-base prepend, invalid visibility rejection, and CODEOWNERS protection remain covered. No PR-controlled policy file is added.

Proof at this exact head: 154 focused tests passed; opencode_private_free_model_policy interrogate 100%; compileall and git diff --check passed. The broad changed-workflow actionlint invocation exceeded the bounded local window, so hosted workflow Checks remain authoritative and no local actionlint pass is claimed.

The PR remains Draft. Please rerun independent review and protected Checks before readiness or merge; no bypass or merge is claimed.

@seonghobae

Copy link
Copy Markdown
Contributor

Resolved the exact-head reviewer-blob contract after synchronizing with protected main. The independent read-only workflow remains unchanged in behavior and is now pinned to its live blob; targeted contract tests (134) and Ruff pass. The new exact-head Checks are running.

@seonghobae

Copy link
Copy Markdown
Contributor

Correction: resolved the exact-head reviewer-blob contract after synchronizing with protected main. The independent read-only workflow remains unchanged in behavior and is now pinned to its live blob. Targeted contract tests (134) and Ruff pass. New exact-head Checks are running.

Copy link
Copy Markdown
Contributor

Current-head merge repair pushed normally at 8e36fe99 after reconciling the stale main base; the private free-model policy, Rust ownership, and exact-artifact SBOM architecture records are preserved. Please observe Checks for this exact head; no merge bypass is used.

@seonghobae

Copy link
Copy Markdown
Contributor

Strix TOCTOU finding fixed at exact current head e1c7d16. The model-pool hook now requires OPENCODE_TRUSTED_SOURCE_DIR in CI and executes the policy checker/provider guard only from the trusted central checkout; local tests retain a non-CI fallback. The dispatch workflow supplies the trusted workspace explicitly, and 40 policy/hook tests plus bash syntax validation pass locally. Please rerun Strix and all hosted Checks on e1c7d16.

@seonghobae

Copy link
Copy Markdown
Contributor

Reconciled the branch with protected main at exact pre-push head e1c7d16 and pushed merge commit 80746e0. The merge preserves trusted-source execution for private free-model policy and current central LLM evidence publication changes. Fresh verification: 206 focused pytest tests passed and the merge diff is whitespace-clean. Please review/check current head 80746e0; no force-push or protection bypass used.

@seonghobae

Copy link
Copy Markdown
Contributor

Repaired the current-head CI failures after the exact head check of 80746e0. The trusted-source boundary is now injected in the model-pool and private-hook test fixtures under CI=true, and the immutable reviewer-workflow hash is updated to the current main-derived blob after the intended trusted-source environment addition. Fresh verification: 1380 tests passed, 16 subtests passed, compileall passed, Strix quick gate was run, and git diff --check passed. Pushed f053ba8; please rerun and review this exact head. No key-system change, bypass, or merge was performed.

@seonghobae

Copy link
Copy Markdown
Contributor

The branch advanced to f053ba8, which includes the trusted-source test-fixture repair. Exact-head local validation on the predecessor plus this unchanged fixture diff passed: 29 hook/autofix contract tests and 28 model-pool tests. Hosted exact-head checks are still running; the PR remains draft and has no exact-head approval, so it is not merge-eligible.

@seonghobae

Copy link
Copy Markdown
Contributor

@claude Please review exact current head f053ba8. Confirm the trusted-source CI fixture repair preserves the existing read-only review-agent key system and the fail-closed private free-model boundary. Publish a current-head review only; do not self-approve, modify, or merge.

@opencode-agent opencode-agent Bot added priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior labels Aug 22, 2026

Copy link
Copy Markdown
Contributor

Triage (2026-09-02): base history is orphaned, not a resolvable merge conflict

This PR's base commit 0156282022134484ea9d7541d5ba0730ba14fd96 is not an ancestor of current main:

$ git merge-base --is-ancestor 0156282022134484ea9d7541d5ba0730ba14fd96 origin/main && echo yes || echo no
no
$ git merge origin/main --no-edit
fatal: refusing to merge unrelated histories

origin/main now has multiple historical roots (a restructuring/history-splice happened after this branch was cut from an older main), so there is no common ancestor for an ordinary 3-way merge. Forcing --allow-unrelated-histories would diff every shared file against an empty tree and manufacture spurious conflicts across the whole tree — not a real fix, and not something to push through mechanically.

The mergeable_state: dirty GitHub reports here reflects that structural gap, not a normal content conflict this session's usual merge-main-and-resolve recipe can repair.

Next action (needs a human/design call): either (a) reimplement the intent of this PR as a fresh branch cut from current main — the historical commits can't be replayed as-is — or (b) verify whether the underlying gap (OPENCODE_REPOSITORY_IS_PRIVATE wiring) is already closed on current main, since predecessor #830 was itself closed unmerged around the same time this history diverged, and close this as superseded if so. Not closing this myself since I haven't verified a live successor covers it. Leaving open pending that decision.


Generated by Claude Code

Copy link
Copy Markdown
Contributor

Retraction — the "main history splice" diagnosis was wrong.

An earlier comment on this PR claimed main's history was spliced onto new roots around 2026-08-20/21, that this PR's base predates the boundary, and that an ordinary merge would fail with fatal: refusing to merge unrelated histories requiring a from-scratch re-implementation. That diagnosis is incorrect — please disregard it entirely.

Root cause: the analysis was run from a shallow git clone in the analysis sandbox (git rev-parse --is-shallow-repository → true). A shallow clone's truncation boundary commits look exactly like disjoint history roots, and git merge from inside a shallow checkout genuinely does throw fatal: refusing to merge unrelated histories even when the real, full history is perfectly linear and connected. After git fetch --unshallow, origin/main has exactly one root commit, and this PR's base is a completely normal ancestor of current main.

This PR should be triaged the ordinary way: fetch a full (non-shallow) clone, git fetch origin main && git merge origin/main --no-edit, resolve any real content conflicts, run the repo's gates, and push. There is no history-splice blocker and no need to abandon or re-implement this PR's work.

Apologies for the incorrect guidance. See #1722 for the corrected writeup.


Generated by Claude Code

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

Labels

priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants