Skip to content

Simplify PR review to a thin orchestrator and dynamic worker - #101

Merged
dceoy merged 12 commits into
mainfrom
agent/validate-pr-review-findings
Aug 18, 2026
Merged

Simplify PR review to a thin orchestrator and dynamic worker#101
dceoy merged 12 commits into
mainfrom
agent/validate-pr-review-findings

Conversation

@dceoy

@dceoy dceoy commented Aug 18, 2026

Copy link
Copy Markdown
Owner

What changed

  • replace the fixed PR specialist subagents with one hidden, strictly read-only review-worker
  • derive review roles, risk hypotheses, and lenses dynamically from each PR instead of encoding specialties in separate agent definitions
  • use fresh review-worker child sessions for both discovery and independent candidate validation
  • retain explicit review aspects (code, performance, security, tests, docs, comments, errors, types, simplify) as lens constraints rather than agent routing
  • make review-pr-orchestrator a thin primary-agent permission profile; all review behavior lives in pr-review/SKILL.md
  • keep /review-pr as the supported entrypoint and mark the internal pr-review skill non-slash/non-autoinvokable for OpenCode v2 discovery
  • remove trusted review helper/state external_directory allowances from global opencode.jsonc; only the dedicated orchestrator grants them
  • slim review-worker to the read-only boundary and task contract instead of duplicating review policy
  • update README, review documentation, and contract tests for the dynamic-worker architecture
  • preserve the trusted-context, stale-head, App-token, sealed-payload, permission-sandbox, and constrained GitHub submission helpers

Architecture

/review-pr remains bound to the dedicated review-pr-orchestrator primary agent instead of the general main agent. This keeps the GitHub review path fail-closed: the primary agent may load only pr-review, invoke only the review worker, write only the two review-state payloads, execute only the fixed trusted helper commands, and access only the trusted helper/state external paths.

The orchestrator itself contains no review procedure beyond following the skill. Discovery, dynamic task decomposition, candidate arbitration, independent validation, anchoring, and submission sequencing are defined once in pr-review/SKILL.md.

review-worker is the current-runtime read-only child-session boundary. It has only read/glob/grep permissions and cannot edit files, run shell commands, launch subagents, or mutate GitHub state. Its prompt now describes only that boundary and the generic discovery/validation contract; detailed review policy remains in the skill.

OpenCode v2 direction

OpenCode v2 defines a built-in read-only explore subagent and a parent-side subagent permission model suitable for this workflow. Once the action moves to a v2 runtime with those guarantees, review-worker can be removed and fresh built-in explore sessions can perform discovery and validation. The dedicated primary-agent permission profile and /review-pr command binding should remain because the generic main agent has broader mutation capabilities than PR review requires.

The internal pr-review skill carries opencode/slash: "false" and opencode/autoinvoke: "false" metadata so V2 does not expose it as an alternate user/model entrypoint. V1 accepts this metadata as portable skill metadata and continues to use the explicit /review-pr command path.

Why

The previous fixed reviewer files duplicated review policy and coupled coverage to a static set of agent identities. A single bounded worker plus dynamic task packets keeps the adapter smaller and allows concerns such as migrations, concurrency, infrastructure, compatibility, and observability without adding more agents.

Keeping orchestration policy in the skill avoids duplication, while moving trusted external-path allowances out of global config ensures ordinary agents do not inherit review-specific capabilities.

Impact

  • substantially less duplicated prompt content
  • risk-driven review coverage instead of a fixed specialist set
  • independent validation in fresh child sessions
  • trusted review paths available only to the dedicated review primary agent
  • no V2 slash/model discovery path that bypasses /review-pr agent binding
  • strict least-privilege separation between the review primary agent, read-only analysis workers, and trusted GitHub submission helpers
  • straightforward future migration from the compatibility review-worker to OpenCode v2 built-in explore

Validation

  • review-pr-orchestrator is mode: primary, selected explicitly by /review-pr, and acts only as a permission-constrained wrapper around pr-review
  • review-worker is mode: subagent, hidden, and limited to read/glob/grep permissions
  • review-pr-orchestrator permits only review-worker through permission.task
  • global opencode.jsonc no longer grants trusted review external paths
  • contract tests require the legacy fixed reviewer definitions to be absent, explicit aspects to map to lenses, the internal skill metadata to be present, and trusted external paths to be agent-scoped
  • README and review docs describe the dynamic discovery/validation model rather than fixed reviewers

CI/CD run #487 is queued for head 4a73cbac7ed0ae835642a820d11835d67081d89b.

@dceoy dceoy changed the title Add independent PR finding validation Replace fixed PR reviewers with one dynamic worker Aug 18, 2026
@dceoy dceoy changed the title Replace fixed PR reviewers with one dynamic worker Simplify PR review to a thin orchestrator and dynamic worker Aug 18, 2026

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

No actionable issues found. I reviewed the dynamic review-worker architecture, the thin orchestrator permission boundary, aspect-to-lens routing, independent validation flow, OpenCode v1 compatibility assumptions, agent-scoped trusted-path permissions, documentation updates, and contract-test coverage. The current head is internally consistent, and CI/CD run #487 passed for 4a73cbac7ed0ae835642a820d11835d67081d89b.

@dceoy
dceoy marked this pull request as ready for review August 18, 2026 16:32
@dceoy dceoy self-assigned this Aug 18, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a73cbac7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .opencode/opencode.jsonc
@opencode-agent

Copy link
Copy Markdown

The review identified 7 validated inline findings across the orchestrator permission boundary, the skill procedure contract, and the contract tests. However, structured submission failed:

gh: Unprocessable Entity (HTTP 422)

Per the pr-review submission rules, I am not retrying the submission and not emitting the findings as an unstructured fallback comment. The run should fail here.

New%20session%20-%202026-08-18T16%3A33%3A04.832Z
opencode session  |  github run

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Reviewed the current head with a focus on correctness and KISS/DRY/YAGNI.

I found one actionable authorization regression: the PR removes the global external_directory deny boundary together with the trusted-path allowlist. That broadens the policy for every non-orchestrator agent instead of limiting the exception to review-pr-orchestrator.

The smallest coherent fix is to keep a global wildcard deny for external_directory and let only review-pr-orchestrator.md add the trusted-path overrides it requires. I found no additional actionable maintainability findings beyond this authorization issue.

Comment thread .opencode/opencode.jsonc

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Reviewed head 4a73cbac7ed0ae835642a820d11835d67081d89b with a focus on correctness, permission boundaries, and KISS/DRY/YAGNI.

One actionable issue remains on the current head and is already covered by the unresolved inline feedback on .opencode/opencode.jsonc: removing the global permission.external_directory."*": "deny" rule makes non-orchestrator agents fall back to OpenCode's default ask behavior for external paths. In a headless GitHub Actions run, that can wait indefinitely for interactive approval. The smallest coherent fix is to retain the global wildcard deny while keeping only the narrowly required trusted-path allows in review-pr-orchestrator.md.

I found no additional actionable issues in the dynamic review-worker architecture, thin orchestrator, pr-review discovery/validation flow, or updated contract tests. I am not duplicating the existing inline thread for the same root cause.

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Reviewed current head 4a73cbac7ed0ae835642a820d11835d67081d89b with a focus on correctness, permission boundaries, and KISS/DRY/YAGNI.

One actionable issue remains: removing the global permission.external_directory."*": "deny" rule makes non-orchestrator agents fall back to OpenCode's default ask behavior for external paths. In a headless GitHub Actions run, that can wait for interactive approval instead of failing closed. The smallest coherent fix is to retain the global wildcard deny while keeping the narrowly required trusted-path allows scoped to review-pr-orchestrator.

This root cause is already covered by the unresolved inline feedback on .opencode/opencode.jsonc, so I am not duplicating the same line-specific finding with another inline comment. I found no additional actionable issues in the dynamic review-worker architecture, the thin orchestrator, independent discovery/validation flow, or the updated contract tests.

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Independent review pass at head b5c898e42eaf0b88133cd22a290ed24a0f812d72, run via three independent lenses (correctness, tests/docs, security/performance).

The previously-flagged authorization regression (global external_directory deny removal) is confirmed fixed on this head: .opencode/opencode.jsonc retains "*": "deny", and trusted-path overrides are scoped solely to review-pr-orchestrator. No other agent config carries stray elevated permissions, and review-worker.md has no bash/edit/task grants.

One actionable regression found in the test that guards that fix, plus two smaller test-coverage gaps and one dead-config note. Full findings below (inline comments on anchorable ones); unanchorable notes summarized here.

Unanchorable note — SKILL.md frontmatter metadata keys don't match a recognized OpenCode schema field (low severity): .opencode/skills/pr-review/SKILL.md sets metadata: {opencode/slash: "false", opencode/autoinvoke: "false"}. The installed OpenCode v1 runtime's skill-frontmatter decoder recognizes only a flat name/description/slash struct — no metadata wrapper and no autoinvoke concept. This is likely inert (the actual /review-pr invocation path doesn't depend on it), but the docs' claim that the skill is "marked non-slash and non-autoinvokable" isn't enforced by this frontmatter on the current runtime. If suppressing auto-registration is intended, use the real top-level slash: false field instead.

No other actionable correctness, security, or performance issues were found in the dynamic review-worker architecture, the thin orchestrator, permission scoping, or documentation.

Comment thread tests/validate-opencode.bats
Comment thread .opencode/agents/review-worker.md
Comment thread tests/validate-opencode.bats
- restore the global external_directory allow-list check that was
  silently overwritten before it ran
- assert review-worker denies bash/edit/task and only allows read/glob/grep
- assert routed aspects map to the correct lens body, not just any bullet

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Independent review pass at head 2f670c3348408bf6c020311a8db71ce31a0af3e5, run via the same three lenses (correctness, tests/docs, security/performance). This head only added test coverage (tests/validate-opencode.bats) fixing the previous round's findings; those fixes were independently re-verified as correct and effective by all three lenses.

Two smaller, corroborated refinements to that new test coverage found below (inline). No other actionable issues.

Comment thread tests/validate-opencode.bats Outdated
Comment thread tests/validate-opencode.bats
- assert review-worker's frontmatter has exactly the expected
  top-level permission keys instead of only denylisting three
- add an explicit failing default case to the aspect-to-lens
  keyword check so an unmapped aspect can't silently reuse the
  previous iteration's keyword

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Independent review pass at head 68cca3018c06cd5dd89339d7fa16bc04c10b5c91, run via the same three lenses. The two prior-round test-hardening fixes were re-verified as correct.

Three more test-coverage gaps found (inline below), all in the same "assert the exact allow-list/key-set instead of a partial denylist" family as the fixes already applied this loop.

Two lower-priority items from this round's lenses were considered and not carried forward: (1) a suggestion to add an explicit hard cap on discovery/validation Task fan-out in SKILL.md — flagged at only medium-low confidence and explicitly not a regression from main, so left as an optional future hardening rather than a blocking finding; (2) a suggestion to add a *) fallback to an unrelated case in the variant-validation test — lower risk than the aspect-routing case (that loop variable is a fixed, hardcoded list with one arm per value), so also left as optional polish rather than a finding.

Unanchorable finding — orchestrator's edit permission block is untested (high confidence): .opencode/agents/review-pr-orchestrator.md's edit block restricts writes to exactly two review-state payload files (plus their ../* relative variants) — the mechanism preventing arbitrary file writes. Unlike task, skill, bash, and external_directory, no test in tests/validate-opencode.bats asserts this allow-list, so a regression broadening it to "*": allow or dropping a required relative-path variant would pass every current test. Suggested fix: add a test asserting permission_allow_keys(orchestrator, edit) equals exactly the four expected state-file paths, mirroring the existing task/skill/bash/external_directory tests. (This line isn't in the diff hunks for this head, so it can't be anchored inline.)

Comment thread tests/validate-opencode.bats Outdated
Comment thread tests/validate-opencode.bats Outdated
- assert the agents_dir file set equals exactly the two current
  agents instead of denylisting nine legacy names
- extend the review-worker key-extraction regex to also match
  single-quoted and hyphenated/digit permission keys
- add a test asserting the orchestrator's edit allow-list is
  exactly the four review-state payload paths

@dceoy dceoy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Independent review pass at head c29f3a201514fa75439648026ba55769b784a863, run via the same three lenses (correctness, tests/docs, security/performance), framed explicitly as a convergence check after three prior hardening rounds on this branch.

No new actionable findings were found in this review pass. All three lenses independently confirmed: the permission boundaries (global external_directory deny-by-default, review-worker's read/glob/grep-only profile, and the orchestrator's task/skill/bash/edit/external_directory allow-lists) are each now backed by an exact allow-set/key-set assertion in tests/validate-opencode.bats rather than a partial denylist; the aspect-to-lens routing test has a failing default case; and docs remain consistent with the two-agent architecture. This does not imply prior feedback on this PR has been newly cleared beyond what earlier rounds already resolved — it reflects that this pass, on this exact head, surfaced nothing further.

@dceoy
dceoy merged commit 0e064bc into main Aug 18, 2026
21 checks passed
@dceoy
dceoy deleted the agent/validate-pr-review-findings branch August 18, 2026 19:06
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.

2 participants