Repository navigation
feat(ci): track merged core PRs for the opencode v2 rewrite - #15134
Conversation
Kilo v1 fixes and features do not carry over to the opencode v2 rewrite automatically, and the `pr-track-v1` skill that records them only ran when a human remembered to invoke it. This automates that: a merged PR carrying a Kilo-specific change to packages/opencode/ now files its own tracking issue. The gate is deterministic, so upstream merges, formatting, and dependency bumps never reach the model. Only PRs that touch a `kilocode`-named opencode path or add a `kilocode_change` marker line qualify. The agent that writes the issue is steered by untrusted PR text, so it runs with no GitHub token and no shell: the workflow pre-fetches the PR metadata and diff, and a deterministic script performs every GitHub mutation after validating the draft. Permissions are explicit denies rather than `--auto`, because an inherited `ask` default is auto-rejected headlessly and aborts the run, while an explicit `deny` is a recoverable tool error. The skill is vendored into the repo so the interactive command and CI share one source of truth; CI-only differences live in the prompt file.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge The only change since the previous review at Files Reviewed (9 files)
Previous Review Summaries (2 snapshots, latest commit 34daa5c)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 34daa5c)Status: No Issues Found | Recommendation: Merge The three findings from the previous review are resolved at the current HEAD: the Files Reviewed (9 files)
Previous review (commit 71f96c3)Status: 3 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (11 files)
Reviewed by deepseek-v4.1-flash · Input: 45K · Output: 5.5K · Cached: 233.2K Review guidance: REVIEW.md from base branch |
Keep the PR-steered agent away from the workflow token by disabling checkout credential persistence, and provide the complete gh pr view metadata shape the tracking skill expects. Remove the unused docs-sync outDir change and stale artifact claims called out in review.
Issue
No issue. This is internal CI tooling for the opencode v2 rewrite; the tracking issues it creates are the artifacts, not the motivation for this PR.
What Problem This Solves
opencode v2 is a rewrite, so Kilo v1 fixes and features do not carry over automatically. The
pr-track-v1skill records what the behavior was and why it mattered in enough detail that a v2 agent can confirm v2 already covers it or implement it from scratch. The problem is that it only ran when a human remembered to invoke it after a merge, so the v2 port backlog depended on memory.Why This Change Was Made
A merged PR that carries a Kilo-specific change to
packages/opencode/now files its own[v2-port]tracking issue inKilo-Org/kilocode, assigned to the original PR author.The gate is deterministic, so most merges never reach the model: a PR qualifies only when its diff touches a
kilocode-named path underpackages/opencode/, or adds akilocode_changemarker line in apackages/opencode/file. That is the same signal the annotations check already enforces, so upstream merges, formatting, and dependency bumps are excluded for free.The agent that writes the issue is steered by untrusted PR text — titles, bodies, diffs, and review comments from any contributor — while the job holds org secrets. So it runs with no GitHub token and no shell: the workflow pre-fetches the PR metadata and diff, and a deterministic script performs every GitHub mutation after validating the draft. Prompt injection can at worst produce a misleading issue body, which a human reviews.
Changes:
v2-port-tracker.ymlruns onpull_request_target: closed(path-filtered topackages/opencode/**) plusworkflow_dispatchfor replays, and always checks out the base branch tip, never the PR head ref.--auto. An inheritedaskdefault is auto-rejected headlessly and aborts the whole run (run.ts:1032-1039), whereas an explicitdenyreturns a tool error the agent can recover from.bash, network,task,external_directory, and the memory/recall tools are denied, andeditis scoped tov2-port-out/**..kilo/skills/pr-track-v1/SKILL.mdso the interactive/pr-track-v1command and CI share one source of truth; CI-only differences (author assignment, nogh, no interaction) live inprompt.md.<!-- v2-port:pr-<N> -->), so a re-run updates rather than duplicates.::warning::, rather than failing the run.docs-sync/lib.mjsgains an optionaloutDironrunKiloso the two bots do not share an artifact tree.User Impact
No end-user impact; this is CI-only. Reviewers get one
core-v1-changes-portissue per qualifying merge instead of relying on someone remembering to run the skill, and every issue carries a paste-readyPrompt For V2 Agentblock. Merged PRs can opt out with ano-v2-portlabel.Screenshots / Video
N/A - no visual changes. The change is a GitHub Actions workflow and Node scripts.
How to Test
Manual/local verification
Agent-verified:
node .github/v2-port/gate.test.mjs— 25 tests passed. Includes end-to-end runs of the realgate.mjsagainst a stubbedghand a stubbed GitHub API: a qualifying PR writespr.json/pr.diffand reportsqualifies=true; an unmarked shared-file change reportsqualifies=falsewith a reason; a bot-authored PR is skipped before any diff fetch.node .github/v2-port/issue.test.mjs— 22 tests passed. Drives the realissue.mjsagainst a local stub of the GitHub API via theDOCS_SYNC_API_BASEhook, so dedup, label ensure, assignee resolution, and comment idempotency are exercised as real code. Covers: one issue created with label/assignee plus back-link, dedup on re-run, unassignable author left unassigned with a warning, existing comment patched in place,skip.txtshort-circuits without any API call, an invalid draft fails without creating anything, and dry run mutates nothing.node .github/docs-sync/model-config.test.mjsandnode .github/docs-sync/selftest.mjs— all cases passed, confirming therunKilooutDirchange does not regress docs-sync.bun run script/check-workflows.ts— ok (39 workflows).bun run script/check-opencode-annotations.ts --worktree— all shared upstream changes annotated.bun run script/check-md-table-padding.ts— 387 files checked, no padded tables.bunx oxlint .github/v2-port— 0 warnings, 0 errors.Reviewer test steps
packages/opencode/:gh workflow run v2-port-tracker.yml -f pr_number=<N> -f dry_run=truequalifiesor a skip reason, and that the draft is printed without creating anything.dry_run=false, then run it a third time and confirm the second and third runs report the PR as already tracked rather than filing duplicates.Blocked checks and substitute verification
issue.test.mjs, which exercises the real create/dedup/assign/comment code paths, plus the stub-ghend-to-end coverage ingate.test.mjs.Evidence
node .github/v2-port/gate.test.mjs: passed (25 tests) — agent.node .github/v2-port/issue.test.mjs: passed (22 tests) — agent.node .github/docs-sync/model-config.test.mjs: passed — agent.node .github/docs-sync/selftest.mjs: passed, all cases — agent.bun run script/check-workflows.ts: passed — agent.bun run script/check-opencode-annotations.ts --worktree: passed — agent.bun run script/check-md-table-padding.ts: passed — agent.bunx oxlint .github/v2-port: passed, 0 warnings — agent.Dependency
Requires the repo secrets
KILO_API_KEYandKILO_ORG_ID, both already present fordocs-sync.KILO_ORG_IDis required, or the gateway bills the key owner's personal balance. Optional repo variablesV2_PORT_MODEL(defaultkilo/anthropic/claude-sonnet-4.6) andV2_PORT_VARIANT(defaulthigh) override the model.Checklist
Get in Touch
No changeset: CI-only change, nothing user-facing.
Changes
v2-port-trackerworkflow and its.github/v2-port/scripts (gate, prompt, issue writer, tests, README).pr-track-v1skill into.kilo/skills/pr-track-v1/.runKilo's optionaloutDirin.github/docs-sync/lib.mjs.v2-port-tracker.ymlto thescript/check-workflows.tsallowlist.