Pre-Publish Review — 16-Agent Release Gate
Three-layer review before publishing to npm. Every layer covers a different angle — together they catch what no single reviewer could.
| Layer | Agents | Type | What They Check |
|---|---|---|---|
| Per-Change Deep Dive | up to 10 | ultrabrain | Each logical change group individually — correctness, edge cases, pattern adherence |
| Holistic Review | 5 | review-work | Goal compliance, QA execution, code quality, security, context mining across full changeset |
| Release Synthesis | 1 | oracle | Overall release readiness, version bump, breaking changes, deployment risk |
Phase 0: Detect Unpublished Changes
Run /get-unpublished-changes FIRST. This is the single source of truth for what changed.
skill(name="get-unpublished-changes")
This command automatically:
- Detects published npm version vs local version
- Lists all commits since last release
- Reads actual diffs (not just commit messages) to describe REAL changes
- Groups changes by type (feat/fix/refactor/docs) with scope
- Identifies breaking changes
- Recommends version bump (patch/minor/major)
Save the full output — it feeds directly into Phase 1 grouping and all agent prompts.
Then capture raw data needed by agent prompts:
# Extract versions (already in /get-unpublished-changes output)
PUBLISHED=$(npm view oh-my-opencode version 2>/dev/null || echo "not published")
LOCAL=$(node -p "require('./package.json').version" 2>/dev/null || echo "unknown")
# Raw data for agents (diffs, file lists)
COMMITS=$(git log "v${PUBLISHED}"..HEAD --oneline 2>/dev/null || echo "no commits")
COMMIT_COUNT=$(echo "$COMMITS" | wc -l | tr -d ' ')
DIFF_STAT=$(git diff "v${PUBLISHED}"..HEAD --stat 2>/dev/null || echo "no diff")
CHANGED_FILES=$(git diff --name-only "v${PUBLISHED}"..HEAD 2>/dev/null || echo "none")
FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ')
If PUBLISHED is "not published", this is a first release — use the full git history instead.
Phase 1: Parse Changes into Groups
Use the /get-unpublished-changes output as the starting point — it already groups by scope and type.
Grouping strategy:
- Start from the
/get-unpublished-changesanalysis which already categorizes by feat/fix/refactor/docs with scope - Further split by module/area — changes touching the same module or feature area belong together
- Target up to 10 groups. If fewer than 10 commits, each commit is its own group. If more than 10 logical areas, merge the smallest groups.
- For each group, extract:
- Group name: Short descriptive label (e.g., "agent-model-resolution", "hook-system-refactor")
- Commits: List of commit hashes and messages
- Files: Changed files in this group
- Diff: The relevant portion of the full diff (
git diff v${PUBLISHED}..HEAD -- {group files})
Phase 2: Spawn All Agents
Launch ALL agents in a single turn. Every agent uses run_in_background=true. No sequential launches.
Layer 1: Ultrabrain Per-Change Analysis (up to 10)
For each change group, spawn one ultrabrain agent. Each gets only its portion of the diff — not the full changeset.
task(
category="ultrabrain",
run_in_background=true,
load_skills=[],
description="Deep analysis: {GROUP_NAME}",
prompt="""
<review_type>PER-CHANGE DEEP ANALYSIS</review_type>
<change_group>{GROUP_NAME}</change_group>
<project>oh-my-opencode (npm package)</project>
<published_version>{PUBLISHED}</published_version>
<target_version>{LOCAL}</target_version>
<commits>
{GROUP_COMMITS — hash and message for each commit in this group}
</commits>
<changed_files>
{GROUP_FILES — files changed in this group}
</changed_files>
<diff>
{GROUP_DIFF — only the diff for this group's files}
</diff>
<file_contents>
{Read and include full content of each changed file in this group}
</file_contents>
You are reviewing a specific subset of changes heading into an npm release. Focus exclusively on THIS change group. Other groups are reviewed by parallel agents.
ANALYSIS CHECKLIST:
1. **Intent Clarity**: What is this change trying to do? Is the intent clear from the code and commit messages? If you have to guess, that's a finding.
2. **Correctness**: Trace through the logic for 3+ scenarios. Does the code actually do what it claims? Off-by-one errors, null handling, async edge cases, resource cleanup.
3. **Breaking Changes**: Does this change alter any public API, config format, CLI behavior, or hook contract? If yes, is it backward compatible? Would existing users be surprised?
4. **Pattern Adherence**: Does the new code follow the established patterns visible in the existing file contents? New patterns where old ones exist = finding.
5. **Edge Cases**: What inputs or conditions would break this? Empty arrays, undefined values, concurrent calls, very large inputs, missing config fields.
6. **Error Handling**: Are errors properly caught and propagated? No empty catch blocks? No swallowed promises?
7. **Type Safety**: Any `as any`, `@ts-ignore`, `@ts-expect-error`? Loose typing where strict is possible?
8. **Test Coverage**: Are the behavioral changes covered by tests? Are the tests meaningful or just coverage padding?
9. **Side Effects**: Could this change break something in a different module? Check imports and exports — who depends on what changed?
10. **Release Risk**: On a scale of SAFE / CAUTION / RISKY — how confident are you this change won't cause issues in production?
OUTPUT FORMAT:
<group_name>{GROUP_NAME}</group_name>
<verdict>PASS or FAIL</verdict>
<risk>SAFE / CAUTION / RISKY</risk>
<summary>2-3 sentence assessment of this change group</summary>
<has_breaking_changes>YES or NO</has_breaking_changes>
<breaking_change_details>If YES, describe what breaks and for whom</breaking_change_details>
<findings>
For each finding:
- [CRITICAL/MAJOR/MINOR] Category: Description
- File: path (line range)
- Evidence: specific code reference
- Suggestion: how to fix
</findings>
<blocking_issues>Issues that MUST be fixed before publish. Empty if PASS.</blocking_issues>
""")
Layer 2: Holistic Review via /review-work (5 agents)
Spawn a sub-agent that loads the /review-work skill. The review-work skill internally launches 5 parallel agents: Oracle (goal verification), unspecified-high (QA execution), Oracle (code quality), Oracle (security), unspecified-high (context mining). All 5 must pass for the review to pass.
task(
category="unspecified-high",
run_in_background=true,
load_skills=["review-work"],
description="Run /review-work on all unpublished changes",
prompt="""
Run /review-work on the unpublished changes between v{PUBLISHED} and HEAD.
GOAL: Review all changes heading into npm publish of oh-my-opencode. These changes span {COMMIT_COUNT} commits across {FILE_COUNT} files.
CONSTRAINTS:
- This is a plugin published to npm — public API stability matters
- TypeScript strict mode, Bun runtime
- No `as any`, `@ts-ignore`, `@ts-expect-error`
- Factory pattern (createXXX) for tools, hooks, agents
- kebab-case files, barrel exports, no catch-all files
BACKGROUND: Pre-publish review of oh-my-opencode, an OpenCode plugin with 1268 TypeScript files, 160k LOC. Changes since v{PUBLISHED} are about to be published.
The diff base is: git diff v{PUBLISHED}..HEAD
Follow the /review-work skill flow exactly — launch all 5 review agents and collect results. Do NOT skip any of the 5 agents.
""")
Layer 3: Oracle Release Synthesis (1 agent)
The oracle gets the full picture — all commits, full diff stat, and changed file list. It provides the final release readiness assessment.
task(
subagent_type="oracle",
run_in_background=true,
load_skills=[],
description="Oracle: overall release synthesis and version bump recommendation",
prompt="""
<review_type>RELEASE SYNTHESIS — OVERALL ASSESSMENT</review_type>
<project>oh-my-opencode (npm package)</proje