Files
open-multi-agent/packages/release-bot/README.md
T
Jack Chen d52380a0a7 fix(release-bot): request DeepSeek JSON output mode for every role (#601)
Two roles failed in 2026-09 with STRUCTURED_OUTPUT_VALIDATION_FAILED on
bracket mismatches deep inside long nested output, and the in-run
correction failed the same way. #599 moved the nested object to the end of
each schema so the model has no boundary to hold, which works around the
symptom without changing what the provider guarantees.

Set `response_format: { type: 'json_object' }` on the shared role config
through `extraBody`. DeepSeek then guarantees that the answer parses as
JSON, so the syntax failure class goes away at the source. A direct API
probe with the pre-#599 planner schema, thinking at max effort, and a tool
turn confirmed that DeepSeek accepts the mode in that combination and
returned strict JSON on every run. OMA still validates the answer against
the role's schema, so the in-run correction keeps handling schema
mismatches.

The scripted adapter test asserts that every role carries the mode, and
the README documents it next to the shared output ceiling.
2026-09-12 02:14:44 +08:00

4.5 KiB

OMA Release Bot

This private workspace dogfoods @open-multi-agent/core to prepare OMA releases. It is repository-local automation, not a published npm package.

Responsibility boundary

The bot deliberately separates judgment from authority:

  1. An explicit runTasks() DAG runs two independent DeepSeek V4 Flash reviews in parallel: change classification and compatibility analysis.
  2. A planner produces a bounded structured proposal. It can choose only none, patch, minor, or major for each package and concise changelog entries.
  3. An independent reviewer approves or rejects that proposal.
  4. Deterministic TypeScript calculates versions, updates the known manifests and template pins, regenerates the lockfile, runs validation, and creates a ready pull request.
  5. A maintainer reviews and merges the PR. Only then can the deterministic publish workflow run after CI succeeds on the exact merged release commit.

Every role thinks at DeepSeek's max effort and shares one 64,000-token output ceiling. Reasoning and the answer are billed against that same ceiling, so it is sized for both: a ceiling that only fits the answer leaves a role emitting reasoning and no JSON, which surfaces as a schema failure rather than as the truncation it is. The evidence roles have five turns and the planner and reviewer three. Every DAG task has maxRetries: 0, so a failed role is not silently rerun as a whole new analysis (OMA's one in-run structured-output correction still applies). The complete planning DAG has a thirty-minute wall-clock deadline. Every request also sets DeepSeek's JSON output mode (response_format: json_object), so the provider guarantees that the answer parses as JSON. OMA still validates the answer against the role's schema, so the in-run correction only has to handle a schema mismatch, not a bracket error in several thousand characters of nested output.

Repository diffs are untrusted evidence. The analyst and compatibility auditor receive only three custom read-only tools: immutable release evidence, a deterministic risk-ranked and size-bounded review bundle, and the release contract. The model cannot supply repository paths to the bundle. The planner and reviewer consume the immutable summary and structured dependency reports without repository tools. No agent receives bash, filesystem write tools, GitHub credentials, npm credentials, or publication tools.

Concrete package versions remain deterministic. In particular, every core release increments create-oma-app; when no scaffolder files changed since the last core tag, the bot forces a patch bump because the only release change is the exact core template pin. A model-proposed larger scaffolder bump is used only when the scaffolder workspace itself changed. This normalization happens before the independent reviewer receives the proposal.

Commands

Run from the repository root after building the workspace:

npm run build -w @open-multi-agent/release-bot

# Read-only: calls DeepSeek and prints the structured result.
DEEPSEEK_API_KEY=... node packages/release-bot/dist/cli.js plan

# Mutating: intended for release-bot.yml with a GitHub App token.
node packages/release-bot/dist/cli.js prepare-pr

# Consequential: intended only for publish.yml with npm trusted publishing.
node packages/release-bot/dist/cli.js publish

prepare-pr validates the complete repository before it commits or pushes. It refuses a dirty worktree, an advanced HEAD, unexpected file changes, duplicate release PRs, and conflicting remote release branches.

publish is idempotent at package boundaries. It checks the public registry before each package, publishes in the fixed core → otel → create-oma-app order, waits for registry visibility, then creates the lightweight core tag and GitHub Release. A rerun resumes missing stages. A tag that exists before every expected package is visible fails closed.

Activation

The workflows are inert until maintainers configure the GitHub App, DeepSeek secret, npm-release environment, and npm trusted publishers described in .github/RELEASING.md. No long-lived npm token is supported.

The GitHub App is intentional. GitHub documents that pull requests or releases created with the repository GITHUB_TOKEN do not trigger downstream workflows normally; an installation token lets PR CI and release-smoke.yml start without a second manual workflow approval.