Skip to content

Commit 9ff8bc0

Browse files
authored
Merge branch 'main' into opencode/issue10-20260723203408
2 parents 2775253 + a64a3be commit 9ff8bc0

3 files changed

Lines changed: 24 additions & 16 deletions

File tree

.github/scripts/opencode-target.mjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { appendFileSync, readFileSync } from "node:fs"
22
import { randomUUID } from "node:crypto"
33
import { pathToFileURL } from "node:url"
44

5-
export const MAX_THREAD_COMMENTS = 10
5+
export const MAX_THREAD_ITEMS = 50
66
export const MAX_THREAD_CONTEXT_CHARACTERS = 60_000
77
export const MAX_PULL_REQUEST_FILES = 100
88
const CONTEXT_FORMAT_OVERHEAD = 10_000
@@ -56,7 +56,7 @@ async function fetchTargetData({ apiUrl, repository, endpoint, token, fetchImpl
5656
async function assertBoundedThread(target, options) {
5757
const issueComments = await fetchTargetData({
5858
...options,
59-
endpoint: `issues/${target.number}/comments?per_page=${MAX_THREAD_COMMENTS + 1}`,
59+
endpoint: `issues/${target.number}/comments?per_page=${MAX_THREAD_ITEMS + 1}`,
6060
})
6161
const context = [
6262
options.subject.title,
@@ -70,15 +70,15 @@ async function assertBoundedThread(target, options) {
7070
if (target.type === "pull_request") {
7171
const reviews = await fetchTargetData({
7272
...options,
73-
endpoint: `pulls/${target.number}/reviews?per_page=${MAX_THREAD_COMMENTS + 1}`,
73+
endpoint: `pulls/${target.number}/reviews?per_page=${MAX_THREAD_ITEMS + 1}`,
7474
})
7575
itemCount += reviews.value.length
7676
context.push(...reviews.value.flatMap((review) => [review.user?.login, review.submitted_at, review.state, review.body]))
7777
const reviewComments = await Promise.all(
7878
reviews.value.map((review) =>
7979
fetchTargetData({
8080
...options,
81-
endpoint: `pulls/${target.number}/reviews/${review.id}/comments?per_page=${MAX_THREAD_COMMENTS + 1}`,
81+
endpoint: `pulls/${target.number}/reviews/${review.id}/comments?per_page=${MAX_THREAD_ITEMS + 1}`,
8282
}),
8383
),
8484
)
@@ -93,10 +93,10 @@ async function assertBoundedThread(target, options) {
9393
throw new Error(`OpenCode limits pull requests to ${MAX_PULL_REQUEST_FILES} changed files.`)
9494
}
9595
context.push(...files.value.flatMap((file) => [file.filename, file.status, file.additions, file.deletions]))
96-
if (reviews.hasNextPage || reviewComments.some((result) => result.hasNextPage)) itemCount = MAX_THREAD_COMMENTS + 1
96+
if (reviews.hasNextPage || reviewComments.some((result) => result.hasNextPage)) itemCount = MAX_THREAD_ITEMS + 1
9797
}
98-
if (itemCount > MAX_THREAD_COMMENTS || issueComments.hasNextPage) {
99-
throw new Error(`OpenCode limits issue and pull request threads to ${MAX_THREAD_COMMENTS} comments.`)
98+
if (itemCount > MAX_THREAD_ITEMS || issueComments.hasNextPage) {
99+
throw new Error(`OpenCode limits issue and pull request threads to ${MAX_THREAD_ITEMS} items.`)
100100
}
101101

102102
const text = context.filter((value) => typeof value === "string" || typeof value === "number")

.github/scripts/opencode-target.test.mjs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import assert from "node:assert/strict"
22
import test from "node:test"
33

4-
import { MAX_PULL_REQUEST_FILES, MAX_THREAD_COMMENTS, classifyTarget, inspectTarget } from "./opencode-target.mjs"
4+
import { MAX_PULL_REQUEST_FILES, MAX_THREAD_ITEMS, classifyTarget, inspectTarget } from "./opencode-target.mjs"
55

66
const repository = "owner/repo"
77
const pull = {
@@ -92,26 +92,31 @@ test("plan permits fork pull requests", async () => {
9292
assert.equal(result.head_repo, "fork/repo")
9393
})
9494

95+
test("accepts a thread at the item limit", async () => {
96+
const comments = Array.from({ length: MAX_THREAD_ITEMS }, () => ({ body: "comment" }))
97+
await assert.doesNotReject(() => inspectTarget({ issue: { number: 8 } }, "plan", { ...options, fetchImpl: response({ issueComments: comments }) }))
98+
})
99+
95100
test("rejects oversized thread context before model access", async () => {
96-
const comments = Array.from({ length: MAX_THREAD_COMMENTS + 1 }, () => ({ body: "comment" }))
101+
const comments = Array.from({ length: MAX_THREAD_ITEMS + 1 }, () => ({ body: "comment" }))
97102
await assert.rejects(
98103
() => inspectTarget({ issue: { number: 8 } }, "plan", { ...options, fetchImpl: response({ issueComments: comments }) }),
99-
/limits issue and pull request threads/,
104+
/limits issue and pull request threads to 50 items/,
100105
)
101106
})
102107

103108
test("counts PR reviews and nested review comments in the context limit", async () => {
104-
const reviews = Array.from({ length: MAX_THREAD_COMMENTS + 1 }, (_, id) => ({ id, body: "review" }))
109+
const reviews = Array.from({ length: MAX_THREAD_ITEMS + 1 }, (_, id) => ({ id, body: "review" }))
105110
await assert.rejects(
106111
() => inspectTarget({ pull_request: { number: 9 } }, "plan", { ...options, fetchImpl: response({ reviews }) }),
107-
/limits issue and pull request threads/,
112+
/limits issue and pull request threads to 50 items/,
108113
)
109114
await assert.rejects(
110115
() => inspectTarget({ pull_request: { number: 9 } }, "plan", {
111116
...options,
112-
fetchImpl: response({ reviews: [{ id: 1, body: "review" }], reviewComments: Array.from({ length: MAX_THREAD_COMMENTS }, () => ({ body: "comment" })) }),
117+
fetchImpl: response({ reviews: [{ id: 1, body: "review" }], reviewComments: Array.from({ length: MAX_THREAD_ITEMS }, () => ({ body: "comment" })) }),
113118
}),
114-
/limits issue and pull request threads/,
119+
/limits issue and pull request threads to 50 items/,
115120
)
116121
})
117122

docs/opencode-github.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ OpenCode responds to explicit commands in GitHub issue comments, pull request co
66

77
- Only the repository owner can invoke unapproved plan runs. Build requests require repository write/admin permission and the build-environment approval.
88
- Commands must start at the first character of a comment and use an allowlisted mode and model. Requests are limited to 8,000 characters; CRLF is normalized, and unsupported control characters are rejected.
9-
- Both plan and build runs exchange GitHub OIDC for the installed OpenCode App token, so visible reactions, comments, branches, commits, and pull requests are authored by `opencode-agent[bot]`. The authorization and post-approval verification steps alone use scoped `GITHUB_TOKEN` credentials for invisible read-only checks.
9+
- Both plan and build runs exchange GitHub OIDC for the installed OpenCode App token, so visible reactions, comments, branches, commits, and pull requests are authored by `opencode-agent[bot]`. The authorization and post-approval verification steps use scoped `GITHUB_TOKEN` credentials for invisible read-only checks; an accepted build also uses a narrowly scoped notification job to add or update its approval comment.
1010
- Build runs require approval through the `opencode-build` environment. Fork PRs, non-open PRs, and PRs whose head is the default branch are rejected.
11+
- An accepted build request adds an idempotent issue or PR comment linking to the pending workflow. The `opencode-build` deployment approval links back to the authorized source issue or PR, so reviewers can identify the affected request from either location.
1112
- The build agent statically denies edits. A trusted startup plugin enables edits only for ordinary repository files and retains canonical and symlink path checks. If the plugin or config hook fails, editing stays denied.
1213
- The build agent has no shell, network, subagent, external-directory, or merge access. It cannot edit `.github/`, `.opencode/`, `.git/`, `opencode.json`, `AGENTS.md`, `vault_pass.sh`, `.env`, or `.env.*` files.
1314
- Comment workflows start from the trusted default branch before OpenCode processes PR content.
14-
- Authorization bounds the repository-collected issue and pull-request context to ten issue/review/review-thread comments, 100 changed files, and 60,000 characters before OAuth is exposed. Native OpenCode may independently fetch additional GitHub context. GitHub attachment URLs are rejected rather than downloaded. Authorization captures current target state, `updated_at`, PR base branch, head branch, head SHA, and head repository. After environment approval, build mode rechecks the commenter's permission and fetches the target again immediately before OpenCode, rejecting any relevant change.
15+
- Authorization bounds the repository-collected issue and pull-request context to 50 combined conversation comments, reviews, and inline review comments, 100 changed files, and 60,000 characters before OAuth is exposed. Native OpenCode may independently fetch additional GitHub context. GitHub attachment URLs are rejected rather than downloaded. Authorization captures current target state, `updated_at`, PR base branch, head branch, head SHA, and head repository. After environment approval, build mode rechecks the commenter's permission and fetches the target again immediately before OpenCode, rejecting any relevant change.
1516
- Builds may update any same-repository, non-default-branch PR head. A residual race remains: OpenCode v1.18.4 ultimately fetches and pushes by mutable branch name, so a branch can theoretically move after verification and before fetch or push. Execution is not immutable by SHA unless upstream changes this behavior; all such branches need equivalent protection where appropriate, and final human diff review remains mandatory.
1617
- OpenCode sessions are never shared. The workflow downloads OpenCode v1.18.4 and verifies its pinned SHA-256 digest.
1718
- OpenCode can create or update a branch and pull request but has no merge operation in its configured toolset. Protected branch rules provide the final merge boundary.
@@ -89,6 +90,8 @@ Model names map to `openai/gpt-5.6-sol`, `openai/gpt-5.6-terra`, and `openai/gpt
8990

9091
Use `plan` first for non-trivial work. Review the result in the GitHub thread, then issue a separate `build` command. Inspect the complete generated PR diff and wait for required CI before human approval.
9192

93+
When an authorized `/oc build` request is awaiting `opencode-build` approval, OpenCode adds or updates a comment on its source issue or pull request with a link to that workflow run. The deployment approval page also links back to the same authorized issue or pull request.
94+
9295
## Updating OpenCode
9396

9497
OpenCode is deliberately pinned by version and digest. To update it:

0 commit comments

Comments
 (0)