Initial publish v0.1.0: standalone workflow core (corpus + examples + guards)
This commit is contained in:
@@ -0,0 +1,493 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
# Review Pipeline Phases (Canonical)
|
||||
|
||||
This document is the **single source of truth** for the shared Phase A→E
|
||||
review/audit pipeline flow. Individual review and audit skills bind their own
|
||||
parameters and reference this doc rather than duplicating the shared mechanics.
|
||||
|
||||
**Terminology**: "reviewer" and "auditor" are interchangeable — `audit-process`
|
||||
legitimately uses "auditor"/"Re-audit" terminology. All generic descriptions
|
||||
use `{REVIEWER_OR_AUDITOR}`.
|
||||
|
||||
**Output model — two findings sinks** ([org-internal #1988] Tier 1 migration): raw per-dimension
|
||||
reviewer findings have ONE of two sinks, chosen per skill. The **synthesis**
|
||||
(human gate) and **commit status** are ALWAYS Tier 2 (Gitea) regardless of the
|
||||
findings sink.
|
||||
|
||||
| Sink | Skills | Reviewer writes findings to | Synthesizer reads findings from |
|
||||
|---|---|---|---|
|
||||
| `tier1-local` (migrated) | `review-code`, `review-artifact` (live targets: review-dag, audit-process; the roadmap/design-space/plan targets were archived 2026-08-21, [org-internal #3072] phase 3) | `<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json` (validated by `core/schemas/reviewer-output.schema.json`) | the local finding files (no Gitea call) |
|
||||
| `tier2-comment` (fallback) | _(none — all targets migrated)_ | Gitea PR/issue comment via `工单评论 API(见 TERMINOLOGY)` (Pattern 5) | `工单评论 API(见 TERMINOLOGY)` (Pattern 3) |
|
||||
|
||||
Migration complete — every review/audit skill now outputs `tier1-local`; the
|
||||
`tier2-comment` row remains as the documented fallback (boundary rule:
|
||||
`core/rules/two-tier-artifacts.md`; a skill without `<runs-root>/`
|
||||
write access falls back to comment-based output unchanged). A `tier1-local`
|
||||
reviewer additionally
|
||||
appends an `index.json` row per finding file (Tier 1 manifest, see
|
||||
`core/templates/runs-layout.md`).
|
||||
|
||||
**Tier 2 outputs (always)**: synthesis is posted as a **Gitea PR/issue comment**
|
||||
with a fenced ` ```json ` block — except for the `audit-process` target, which
|
||||
has no source issue and posts the synthesis as a **wiki page**
|
||||
`audit/{date}/round{N}/synthesis` instead (see `review-artifact/SKILL.md` process target
|
||||
Output Artifacts); status tracking uses **REST commit status**
|
||||
(`pipeline/{REVIEW_TYPE}` context). The full Gitea output pattern is documented
|
||||
in `_shared/gitea-write-patterns.md`.
|
||||
|
||||
---
|
||||
|
||||
## Phase A — Parallel {REVIEWER_OR_AUDITOR_NAME}
|
||||
|
||||
**Orchestrator actions**:
|
||||
|
||||
0. **Move the source issue to the `review` column** on the Pipeline Stages
|
||||
board per `_shared/gitea-write-patterns.md` Pattern 7.5. Skip if no
|
||||
source issue exists. The review stage is a single board column covering
|
||||
all review targets (DAG single gate / code review / audit-process).
|
||||
|
||||
0.5. **Initialize the review-status file** (round 1 only). The Orchestrator
|
||||
creates `<runs-root>/{slug}/reviews/{stage}/status.json` before dispatching
|
||||
round 1, with the full schema-required field set
|
||||
(`core/schemas/review-status.schema.json`): `slug`, `started_at`
|
||||
(RFC 3339 timestamp), `current_round: 1`, `max_rounds` (per-skill binding —
|
||||
`review-artifact` = 3, `review-code` = 2 default / 3 high-risk —
|
||||
`<instance-root>/workflow-routing.yaml` `review.max_rounds`), `converged: false`,
|
||||
`history: []`. This
|
||||
step is skipped on rounds ≥ 2 — the file already exists and the Synthesizer
|
||||
appends to it in Phase B. Initialization is the Orchestrator's sole
|
||||
responsibility; the Synthesizer never creates the file. The Orchestrator
|
||||
also appends an `index.json` row for the file (`type` = `review-status`,
|
||||
`stage` = `{REVIEW_TYPE}`, `produced_by` = `Orchestrator`, `schema` = the
|
||||
review-status `$id`).
|
||||
|
||||
1. **Tool-availability probe** (defense-in-depth, [org-internal #2115] RC1 / [org-internal #2126]). Before
|
||||
dispatching any {REVIEWER_OR_AUDITOR}, verify reviewers will be able to read
|
||||
wiki artifacts (requirements / design / plan / prior-review reports). A
|
||||
reviewer that cannot read its inputs aborts or hallucinates — catch this ONCE
|
||||
in the Orchestrator instead of letting {DIMENSION_COUNT} parallel subagents
|
||||
each rediscover the gap:
|
||||
|
||||
- **Primary path**: confirm `gitea_wiki__*` tools are registered (the
|
||||
Orchestrator checks its own tool catalog; these tools are forwarded to
|
||||
reviewer subagents when registered — [org-internal #2116] raised the tool cap 50→100 so
|
||||
they are present in normal runs). If available → continue to step 2.
|
||||
- **Fallback path** (when `gitea_wiki__*` is NOT registered, e.g. a
|
||||
cross-repo scenario [org-internal #2115]): verify the **local wiki clone** at
|
||||
`<wiki-clone-root>/{repo}-wiki/` is readable —
|
||||
`glob(pattern="*.md", path="<wiki-clone-root>/{repo}-wiki/")`. If the clone
|
||||
is readable → continue to step 2; reviewers use the local clone (see
|
||||
`_shared/gitea-read-patterns.md` Pattern 1 fallback note and the "Tool
|
||||
Availability & Path Resolution" section of this skill).
|
||||
- **Both unavailable → FAIL FAST**: post a `failure` commit status (state
|
||||
`"failure"`, context `pipeline/{REVIEW_TYPE}`, description naming the
|
||||
missing capability) and abort — do NOT enter parallel dispatch. Report the
|
||||
gap so the environment can be fixed (register the wiki MCP server, or
|
||||
populate `<wiki-clone-root>/{repo}-wiki/`).
|
||||
|
||||
This probe is belt-and-suspenders: RC1 (tool cap, [org-internal #2116]) already fixed the
|
||||
primary cause of missing `gitea_wiki__*` in subagents. It exists so a future
|
||||
environment regression fails gracefully with one clear message instead of N
|
||||
silent subagent aborts.
|
||||
|
||||
2. Post an initial pending commit status via REST:
|
||||
|
||||
```
|
||||
POST /api/v1/repos/Octopus/octopus/statuses/{SHA}
|
||||
state: "pending"
|
||||
context: "pipeline/{REVIEW_TYPE}"
|
||||
description: "Round {N}: {DIMENSION_COUNT} reviewers dispatched"
|
||||
```
|
||||
|
||||
(See `_shared/gitea-write-patterns.md` Pattern 8.)
|
||||
|
||||
3. Spawn **all {DIMENSION_COUNT} {REVIEWER_OR_AUDITOR}s in parallel**. Each
|
||||
receives:
|
||||
- The standardized prompt with dimension-specific values filled in.
|
||||
- Agent type: Explorer.
|
||||
- Permission: Explorer read-only (see
|
||||
`core/skills/_shared/review-orchestrator-rules.md` — Default
|
||||
Explorer Permissions).
|
||||
- Temperature: 0.1 (deterministic output).
|
||||
|
||||
4. Wait for all {REVIEWER_OR_AUDITOR}s to complete. Each reviewer writes its
|
||||
dimension result to the skill's configured findings sink:
|
||||
- `tier1-local` (e.g. `review-code`, `review-artifact`, `audit-process`): write the JSON to
|
||||
`<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`
|
||||
(validated by `core/schemas/reviewer-output.schema.json`). The reviewer
|
||||
is granted scoped write to `<runs-root>/**` (read-only everywhere else —
|
||||
this emits the reviewer's OWN output, it does not touch the artifact under
|
||||
review, so it does not violate rule #7 auditor independence).
|
||||
- `tier2-comment` (fallback): post an issue comment via
|
||||
`工单评论 API(见 TERMINOLOGY)` (Pattern 5, `_shared/gitea-write-patterns.md`)
|
||||
with a fenced ` ```json ` block on the target PR (pipeline mode) or issue
|
||||
(standalone mode). The comment is labeled `**{DIMENSION_CODE} review — round {N}**`.
|
||||
After all reviewers complete, for `tier1-local` the Orchestrator appends one
|
||||
`index.json` row per finding file (type `review-findings`, stage
|
||||
`{REVIEW_TYPE}`, produced_by `Reviewer`, schema = the reviewer-output `$id`).
|
||||
|
||||
5. If a {REVIEWER_OR_AUDITOR} fails (crash / timeout), retry once. If still
|
||||
failed, mark that dimension as `UNRESOLVED` in the synthesis and continue.
|
||||
Record it for deferred retry at the start of the next round.
|
||||
|
||||
---
|
||||
|
||||
## Phase B — Synthesis (Delegated)
|
||||
|
||||
> **Context optimization**: Phase B is delegated to a Synthesizer (Worker) to
|
||||
> prevent the Orchestrator's context from accumulating N dimension finding
|
||||
> Read results (up to N × 50KB per round). The Synthesizer reads all dimension
|
||||
> findings in its own context, posts the synthesis comment + commit status,
|
||||
> and returns a compact summary (≤ 2KB). The Orchestrator never reads
|
||||
> dimension findings directly.
|
||||
|
||||
**Orchestrator actions**:
|
||||
|
||||
1. Fill the synthesis task template
|
||||
(`core/skills/_shared/synthesis_task.md`) with:
|
||||
- Round number. A round-1 dispatch carries the template's step-8
|
||||
"Round-1 only — findings digest" duty (the Synthesizer writes
|
||||
`round1/findings-summary.md`, consumed verbatim at Phase E — see the
|
||||
digest bullet in step 3 below); verify it is present in the filled
|
||||
template.
|
||||
- Target PR number (pipeline mode) or issue number (standalone mode).
|
||||
- List of UNRESOLVED dimensions (reviewers that crashed/timed out).
|
||||
- Commit SHA and review type.
|
||||
- For `tier1-local` skills (all review/audit): write the filled template to
|
||||
`<runs-root>/{slug}/reviews/{stage}/round{N}/task-synthesizer.md` (Tier 1
|
||||
synthesis prompt; append an `index.json` row, type `synthesis-prompt`). The
|
||||
`/tmp/octopus/` embryo is NOT used — Tier 1 owns the prompt.
|
||||
- For `tier2-comment` skills: write the filled template to
|
||||
`/tmp/octopus/synthesis_task_{slug}_round{N}.md` for `prompt_file` use; the
|
||||
authoritative copy is published as a Gitea wiki page at
|
||||
`{slug}/reviews/{stage}/round{N}/task-synthesizer`.
|
||||
|
||||
2. Dispatch the **Synthesizer** (Worker) via the `task` tool:
|
||||
- `role`: `Synthesizer`
|
||||
- `subagent_type`: `worker`
|
||||
- `prompt_file`: the synthesis-prompt path from step 1 (Tier 1 local path for
|
||||
`tier1-local` skills; `/tmp/octopus/...` for `tier2-comment` skills)
|
||||
- `permissions`: read + write + edit + bash + glob + grep (all allow)
|
||||
- `temperature`: 0.1
|
||||
- Foreground (the Orchestrator waits for completion).
|
||||
|
||||
3. The Synthesizer:
|
||||
- Reads all dimension findings from the skill's configured sink:
|
||||
- `tier1-local`: read the finding files at
|
||||
`<runs-root>/{slug}/reviews/{stage}/round{N}/findings-*.json` (in its
|
||||
OWN context, not the Orchestrator's — no Gitea call).
|
||||
- `tier2-comment`: read all dimension comments via `工单评论 API(见 TERMINOLOGY)`
|
||||
(Pattern 3, `_shared/gitea-read-patterns.md`) on the target PR/issue.
|
||||
- **Post-check finding-id uniqueness (MANDATORY)**: verifies that `id`
|
||||
values are unique across ALL findings files of the round (including
|
||||
every `-r{k}` slot file) — the schema's `uniqueItems` does NOT enforce
|
||||
this. On a duplicate id, keeps both findings, notes the collision in
|
||||
the digest and marks the affected dimension WARN (per step 1b of
|
||||
`_shared/synthesis_task.md`).
|
||||
- Computes synthesis following `core/schemas/synthesis.schema.json`.
|
||||
- Posts synthesis as a PR/issue comment via `工单评论 API(见 TERMINOLOGY)`
|
||||
(Pattern 5, `_shared/gitea-write-patterns.md`) — markdown summary + fenced
|
||||
` ```json ` block matching `core/schemas/synthesis.schema.json`. (This
|
||||
is the Tier 2 human-gate output — it stays on Gitea for both sinks.) For
|
||||
the `audit-process` target (no source issue), post the synthesis as a wiki
|
||||
page `audit/{date}/round{N}/synthesis` instead of a PR/issue comment.
|
||||
- Posts a commit status via REST with context
|
||||
`pipeline/{REVIEW_TYPE}` (Pattern 8, `_shared/gitea-write-patterns.md`):
|
||||
`state: "success"` for PASS/WARN, `"failure"` for FAIL.
|
||||
- Appends one `history[]` entry for this round to the run's review-status
|
||||
file `<runs-root>/{slug}/reviews/{stage}/status.json` (validated by
|
||||
`core/schemas/review-status.schema.json`) — `round`,
|
||||
`overall_verdict`, `blockers`, `majors`, `minors` — the durable per-round
|
||||
audit history (defined by `core/schemas/review-status.schema.json`
|
||||
`history[]`; mirrors the audit-process checklist TRC 10.4), and updates
|
||||
the file's `current_round` to this round number. (The Orchestrator initializes `status.json` before
|
||||
round 1 — see Phase A step 0.5 — with the full required field set `slug` /
|
||||
`started_at` / `current_round` / `max_rounds` / `converged` / `history`.
|
||||
The Synthesizer only appends `history[]` and updates `current_round`; it
|
||||
never re-creates the file.)
|
||||
- **Round-1 findings digest (round 1 only)**: for skills whose final report
|
||||
carries a Round-1 Findings Summary (`review-code` Phase E step 2.55 and
|
||||
any target adopting the template section), the round-1 Synthesizer is the
|
||||
PRODUCER of that table: it writes
|
||||
`<runs-root>/{slug}/reviews/{stage}/round1/findings-summary.md` — the
|
||||
rendered `## Round-1 Findings Summary` table (columns
|
||||
`| Dim | Finding ID | Severity | Summary |`, one row per round-1 finding;
|
||||
Summary = one-line 摘由/root cause) — distilled from the round-1 findings
|
||||
it just read in its own context (append an `index.json` row, type
|
||||
`review-synthesis` — Synthesizer-produced synthesis artifacts; the
|
||||
round-verdict return summary `synthesis-return.md` keeps the generic
|
||||
worker-report type `other` per
|
||||
`_shared/worker-report-persistence.md`). This duty is wired into the
|
||||
Synthesizer's operative prompt as step 8 of
|
||||
`_shared/synthesis_task.md` ("Round 1 only — findings digest"). The
|
||||
Orchestrator at Phase E copies this file
|
||||
verbatim into the final report; it does NOT read the findings JSONs
|
||||
(step 4 below) — the digest file is the wired producer→consumer path.
|
||||
- Returns a compact summary (≤ 2KB) with verdict, per-dimension results,
|
||||
and re-audit targets.
|
||||
|
||||
4. The Orchestrator receives the summary and proceeds to Phase C or Phase E
|
||||
based on `overall_verdict`. The Orchestrator does NOT read dimension
|
||||
comments or the synthesis comment directly — all decision-relevant data
|
||||
is in the Synthesizer's return summary.
|
||||
|
||||
5. Present the Synthesizer's return summary to the user in chat.
|
||||
|
||||
---
|
||||
|
||||
## Phase C — {REVISION_ROLE} Revision
|
||||
|
||||
If `overall_verdict` is PASS, skip to Phase E.
|
||||
|
||||
Otherwise:
|
||||
|
||||
**Orchestrator actions**:
|
||||
|
||||
1. Prepare the {REVISION_ROLE}'s input as a structured task, published as a
|
||||
Gitea wiki page at `{slug}/reviews/{stage}/round{N}/task-{ROLE}` (Pattern 1,
|
||||
`_shared/gitea-write-patterns.md`). For the `audit-process` target, the
|
||||
process target's Phase Bindings override the wiki namespace to
|
||||
`audit/{date}/` — publish to `audit/{date}/round{N}/task-{ROLE}` instead
|
||||
(see `review-artifact/SKILL.md` process target).
|
||||
|
||||
This must contain:
|
||||
- Paths to all files that need revision.
|
||||
- Reference to the synthesis comment on the PR/issue (posted in Phase B).
|
||||
- References to the dimensions that have open BLOCKER, MAJOR, or MINOR
|
||||
findings, via the skill's findings sink:
|
||||
- `tier1-local`: paths to the Tier 1 finding files
|
||||
(`<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`).
|
||||
- `tier2-comment`: references to the individual dimension issue comments.
|
||||
Dimensions whose only findings are INFO are excluded — INFO is
|
||||
dispositioned at synthesis and never revised (see the "Severity handling —
|
||||
INFO disposition" rule in Phase D).
|
||||
- The {REVISION_ROLE} MUST NOT receive the full text of all findings inline —
|
||||
use finding-file path / comment references only to avoid context explosion.
|
||||
- Convergence status: blockers/majors remaining vs. previous round.
|
||||
- **Revision survival ([org-internal #2601]) — primary path**: the task tool's completion
|
||||
output includes a `task_id`; passing it back resumes the SAME
|
||||
{REVISION_ROLE} subagent session instead of creating a fresh one. Round 1:
|
||||
persist the returned `task_id` with the round's working-notes entry (it
|
||||
must survive round-boundary compaction). Round ≥ 2: dispatch with
|
||||
`task_id` set to the previous revision round's — the reviser continues
|
||||
in-session with its prior context. {REVIEWER_OR_AUDITOR}s are NEVER
|
||||
resumed — per-round freshness is their independence.
|
||||
- **Revision survival — fallback** (task_id lost to compaction before it
|
||||
was persisted): for round ≥ 2, include the current
|
||||
`<runs-root>/{slug}/working-notes.md` content (run narrative memory:
|
||||
prior decisions, dead ends, earlier reviewer feedback) and a reference to
|
||||
the previous round's revision summary. State explicitly that this revises
|
||||
work a prior round already produced — re-derive from upstream artifacts
|
||||
ONLY when a finding requires it.
|
||||
|
||||
2. Spawn the {REVISION_ROLE} (Worker) with revision instructions from
|
||||
`core/skills/_shared/review-revision-prompt.md`. For round ≥ 2, pass
|
||||
the previous reviser `task_id` to resume the same session (see Revision
|
||||
survival above); reviewer/auditor dispatches are always fresh.
|
||||
|
||||
---
|
||||
|
||||
## Phase D — {REVIEWER_OR_AUDIT_LOOP} Loop
|
||||
|
||||
After the {REVISION_ROLE} completes revision:
|
||||
|
||||
1. Increment the round counter, and update `current_round` in
|
||||
`<runs-root>/{slug}/reviews/{stage}/status.json` to match. Post the round
|
||||
transition as a progress update to the commit status (Pattern 8):
|
||||
```
|
||||
state: "pending"
|
||||
context: "pipeline/{REVIEW_TYPE}"
|
||||
description: "Round {N+1}: re-reviewing after {REVISION_ROLE} revision"
|
||||
```
|
||||
2. Go back to Phase A (spawn a new round against the revised files).
|
||||
|
||||
**Convergence criteria** (stop the loop when ANY of these is true):
|
||||
|
||||
| Condition | Action |
|
||||
| -------------------------------------- | ---------------------------------------------- |
|
||||
| `overall_verdict` = PASS | Stop. Proceed to Phase E. |
|
||||
| `current_round` > `{MAX_ROUNDS}` | Stop. Proceed to Phase E with final status. |
|
||||
| No improvement in 2 consecutive rounds | Stop. (Same blocker count AND same major count |
|
||||
| (compared to 2 rounds ago) | without reduction). Proceed to Phase E. |
|
||||
| User explicitly approves current state | Stop. Proceed to Phase E. |
|
||||
|
||||
**`{MAX_ROUNDS}` binding** (per skill):
|
||||
- `review-artifact` skill (process target): **3**.
|
||||
- `review-artifact` skill (`review-dag` single-gate target): **per depth** from
|
||||
`dag_metrics.review_depth` — D1 ≤2, D2 ≤3, D3 ≤3, D4 ≤4 (D4 reaches round 4,
|
||||
exceeding the shared `review-artifact` default; the per-depth cap takes precedence —
|
||||
see `review-artifact/SKILL.md` review-dag Phase D and
|
||||
`core/schemas/review-status.schema.json`).
|
||||
- `review-code` skill: **2** default / **3** high-risk (a BLOCKER survived a
|
||||
round, or the diff touches a frozen cross-session contract) —
|
||||
`<instance-root>/workflow-routing.yaml` `review.max_rounds` ([org-internal #3567], process-diet
|
||||
P0b). At budget without convergence: STOP, register the remaining
|
||||
BLOCKER/MAJOR findings as TD registry rows, verdict FAIL if any BLOCKER
|
||||
remains else PASS — the debt is carried by those TD registry rows
|
||||
(see `review-code/SKILL.md` Phase D). This
|
||||
supersedes the 2026-08-25 [org-internal #3380] calibration (p50=2, p95=5, n=66): the runs
|
||||
past round 3 are the marathon tail this budget exists to cut; their residue
|
||||
flows to the TD registry instead of reviewer rounds. Ledger:
|
||||
`docs/workflow-refactor/thresholds-ledger.md`.
|
||||
|
||||
Rationale for `review-artifact` = 3 (evaluated in [org-internal #1969], replacing the prior blanket
|
||||
default of 5): (1) the Round-3 Escalation Guardrail below already detects
|
||||
non-convergence at the start of round 3; (2) the INFO-disposition rule below
|
||||
removes spurious WARN rounds previously caused by non-blocking INFO findings;
|
||||
(3) the "no improvement in 2 consecutive rounds" stop condition naturally
|
||||
fires by round 3; (4) the marginal value of rounds 4-5 is low once the
|
||||
guardrail has fired and they burn reviewer budget. (`review-code` no longer
|
||||
reaches round 4 — its round budget is 2/3, see the binding above.)
|
||||
|
||||
**Provisional, not empirically validated**: the four safeguards make `review-artifact`=3
|
||||
defensible, but it has no fresh run-data yet. Treat it as a hypothesis to
|
||||
confirm via the retrospective signal ([org-internal #1834]; gate-trim's landing machinery was
|
||||
retired, [org-internal #3072] phase 3 — the check is observational, not a trim proposal): if
|
||||
live `review-artifact` runs frequently hit round 3 still improving yet are
|
||||
forced to stop at WARN/FAIL, bump it back to 4.
|
||||
|
||||
**Severity handling — INFO disposition** (non-blocking, non-revising): INFO
|
||||
findings are observations/recommendations beyond the checklist. They NEVER
|
||||
block convergence and NEVER drive a reviser round.
|
||||
- A dimension whose ONLY open findings are INFO has effective verdict **PASS**
|
||||
— INFO does not reduce `pass_rate` and does not cause WARN/FAIL (see
|
||||
orchestrator rule #3). Such a dimension does NOT count against
|
||||
`overall_verdict`.
|
||||
- At synthesis, the Synthesizer dispositions EVERY INFO finding as one of:
|
||||
- `TD-candidate` — actionable observation worth a tech-debt item; record a
|
||||
suggested REGISTRY ROW (one-line summary + reactivation trigger,
|
||||
`core/rules/ticket-lifecycle.md`). Actual `TD-NNN` registration is
|
||||
deferred to the `verify` skill's Phase 5.5 registry filing — a
|
||||
TD-candidate does NOT open an independent ticket at review time
|
||||
(consistent with how `review-code` Accepted Risks flow to verify).
|
||||
- `DISCARDED` — not worth tracking; record a one-line reason.
|
||||
Dispositions are listed in the synthesis comment (markdown). INFO counts
|
||||
carry in `info_count` / `infos` for reporting only.
|
||||
- Phase C reviser task (step 1 above) references ONLY dimensions with open
|
||||
BLOCKER/MAJOR/MINOR findings. INFO findings are NEVER passed to the
|
||||
{REVISION_ROLE}.
|
||||
|
||||
**Round-3 Escalation Guardrail** (applies to the `review-artifact` skill's
|
||||
live targets — the process audit target AND the review-dag single-gate
|
||||
target; the roadmap / design / plan targets were archived 2026-08-21,
|
||||
[org-internal #3072] phase 3). `review-code` does NOT use this guardrail; it uses its round
|
||||
budget ([org-internal #3567], see the `{MAX_ROUNDS}` binding above).
|
||||
|
||||
At the start of round 3, if the combined blocker+major count is still >50% of
|
||||
round 1's count, STOP the loop and surface to the user:
|
||||
|
||||
> Review not converging: round 1 had {N1} blockers+majors, round 2 still has
|
||||
> {N2} ({pct}% of round 1). This suggests the artifact under review needs a
|
||||
> substantive rewrite, not incremental patching. Options:
|
||||
> (a) Return to upstream — for the `process` audit target, escalate to the
|
||||
> octopus maintainer for a process-level redesign (the legacy producer skills
|
||||
> `roadmap` / `requirements-elicitation` / `design` / `plan-iterations` were
|
||||
> archived 2026-08-21, [org-internal #3072] phase 3 — `<instance-root>/archive/`), then restart this
|
||||
> review at round 1.
|
||||
> (b) Continue iterating — accept that more rounds may be needed (capped by
|
||||
> `{MAX_ROUNDS}`).
|
||||
|
||||
Choosing (a) returns control to the upstream skill (or maintainer); the
|
||||
review's commit status is marked with description `"escalated"` and
|
||||
`converged: false`.
|
||||
|
||||
**Round-4 user-choice escalation point (shared)**: a multi-round review skill
|
||||
MUST offer the user an explicit choice before entering round 4 — (a) stop the
|
||||
review and escalate to a human, or (b) continue into round 4 — via the
|
||||
`question` tool. The guard means "escalate with a choice", NOT "force-stop".
|
||||
The choice is UNCONDITIONAL at the round-3→4 transition — instance skills may
|
||||
narrow when an escalation *variant* (e.g. a design-level decision) fires, but
|
||||
never narrow the choice gate itself. The call MUST be optionized ([org-internal #3378]):
|
||||
two options — `Stop & escalate to a human` (first, when recommended) /
|
||||
`Continue into round 4` — with `stage` set to the running skill's stage so
|
||||
auto-approval applies in autonomous mode; free-text asking is a spec
|
||||
violation.
|
||||
Instance: review-dag D4 option-b (`review-artifact/SKILL.md` §"Round-3
|
||||
Escalation Guardrail interaction") — the sole live instance, its D4 round cap
|
||||
(≤4) being the only budget that reaches round 4 (`review-code` is capped 2/3,
|
||||
[org-internal #3567]).
|
||||
Rationale (retro 2026-08-21 / [org-internal #3050]): unattended late-round loops drift into
|
||||
review marathons — the choice forces the design-level stall to surface to a
|
||||
human at round 4 instead of round 6.
|
||||
|
||||
**Efficiency optimization**: From round 2 onward ([org-internal #2598]), only spawn
|
||||
{REVIEWER_OR_AUDITOR}s for dimensions that had FAIL, WARN, or UNRESOLVED in
|
||||
the previous round. Every 2 rounds, run a full {DIMENSION_COUNT}-reviewer
|
||||
sweep to catch regressions. From round 2 onward reviewer input is also
|
||||
delta-scoped: the file list handed to each reviewer covers only the files
|
||||
changed since the previous round plus their convention-comparison neighbors,
|
||||
not the round-1 full set.
|
||||
|
||||
---
|
||||
|
||||
## Phase E — Final Report
|
||||
|
||||
**Orchestrator actions**:
|
||||
|
||||
1. Write the final report as a Gitea wiki page at
|
||||
`{slug}/reviews/{stage}/final/report` (Pattern 1,
|
||||
`_shared/gitea-write-patterns.md`), using the template at
|
||||
`core/skills/_shared/review-final-report-template.md`. For the
|
||||
`audit-process` target, write to `audit/{date}/final/report` instead (wiki
|
||||
namespace override `audit/{date}/`). Also set the lifecycle `converged` flag
|
||||
in `<runs-root>/{slug}/reviews/{stage}/status.json`: `true` when the final
|
||||
verdict is PASS (or WARN with no unresolved BLOCKERs), else `false`. This is
|
||||
the ONLY place `converged` is written — the Orchestrator at Phase E; the
|
||||
Synthesizer never sets it.
|
||||
|
||||
2. Update the `## 工件索引` comment on the source issue per
|
||||
`_shared/gitea-write-patterns.md` Pattern 10: add/update the
|
||||
`REVIEW-{stage}` row (位置 = the final report page, 重读 = CORE —
|
||||
review conclusions are part of the compaction re-read set).
|
||||
Skip if no source issue exists (Pattern 10 step 1).
|
||||
|
||||
2.5. **Inline-ization (skills that bind it)** — when the review target is a
|
||||
PR and the skill's Phase E binds the inline-comment step (currently
|
||||
`review-code` only, as its Phase E step 2.56), execute it now: post the
|
||||
final round's findings as PR inline comments via
|
||||
`<harness-package>/script/post-inline-comments.ts` (consumer of frozen
|
||||
contract `shared/review-inline-v1`): noise findings (INFO / DISCARDED /
|
||||
`WAIVED-{id}`) are never inlined (contract behavior 2), multi-round
|
||||
posts delete the identity's previous inline comments first (behavior 5),
|
||||
stale lines degrade to the file's first diff hunk (behavior 4; caveat:
|
||||
this server build returns HTTP 500 rather than the contract's 422 for
|
||||
stale lines — TD-611 — so stale items currently surface under `failed`
|
||||
with `fallback` empty), and partial failures are accounted — never
|
||||
blocking the verdict (behavior 6) — in the synthesis comment and final
|
||||
report's `inline: X posted / Y file-level / Z fallback / W failed` line.
|
||||
Skills whose target has no PR (e.g. `audit-process`) skip this step. The
|
||||
skill-specific binding (runner invocation, findings paths, identity,
|
||||
cleanup) is normative in the binding skill's own Phase E section.
|
||||
|
||||
3. Post final commit status via REST:
|
||||
|
||||
```
|
||||
POST /api/v1/repos/Octopus/octopus/statuses/{SHA}
|
||||
state: "success"|"failure"
|
||||
context: "pipeline/{REVIEW_TYPE}"
|
||||
description: "Final: {PASS|WARN|FAIL} after {N} rounds — converged: {true|false}"
|
||||
target_url: "{wiki page link}"
|
||||
```
|
||||
|
||||
3.5. **Gitea approval timing (mandatory when the PR needs a human approval
|
||||
gate)**: if the flow requests approval from a human reviewer on Gitea,
|
||||
register the reviewer FIRST via `gitea_pull__add_reviewer`, wait for the
|
||||
`REQUEST_REVIEW` registration to be recorded, and only THEN ask the human
|
||||
to approve. Approving before the reviewer is registered produces
|
||||
`official: false` on the approval — the gate treats the PR as unapproved
|
||||
and the approval must be re-done. ([org-internal #1931]: audit R2→R3 re-loop + re-approve,
|
||||
~30min wasted on exactly this ordering.)
|
||||
|
||||
4. Present the final report to the user and obtain approval via the `question`
|
||||
tool, passing `stage: "{STAGE}"`.
|
||||
|
||||
The `question` tool auto-approves per `core/rules/auto-approve.md` (stage `"{STAGE}"`).
|
||||
|
||||
Do NOT advance without approval (auto or explicit).
|
||||
|
||||
---
|
||||
|
||||
## Orchestrator Rules (Mandatory)
|
||||
|
||||
See `core/skills/_shared/review-orchestrator-rules.md` for the mandatory
|
||||
Orchestrator behavior rules. Substitute `{REVISION_ROLE}`: {REVISION_ROLE}.
|
||||
Reference in New Issue
Block a user