Initial publish v0.1.0: standalone workflow core (corpus + examples + guards)
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
# Shared Rule — Round-Boundary Context Compaction
|
||||
|
||||
> **Canonical source of truth.** This file is the single authoritative copy of
|
||||
> the round-boundary compaction rule. It is injected **directly** (via
|
||||
> `<!-- inject -->`) by two skills:
|
||||
>
|
||||
> - `review-code/SKILL.md`
|
||||
> - `review-artifact/SKILL.md`
|
||||
>
|
||||
> Both inject tags are resolved by `injectShared`
|
||||
> (`<harness-package>/src/tool/skill.ts`) at skill-load time. Do not place this
|
||||
> inject inside a file that is *itself* injected (a nested inject) —
|
||||
> `injectShared` is single-pass and does not resolve nested inject tags; they
|
||||
> survive as literal `<!-- inject -->` comments and the procedure is silently
|
||||
> lost.
|
||||
>
|
||||
> **When editing:** update this file only. Every consumer picks up the change
|
||||
> automatically at load time — do not copy the text into any skill.
|
||||
>
|
||||
> This is a reference document, not a skill (no `SKILL.md` frontmatter), so the
|
||||
> skill loader does not register it. It exists purely so maintainers have one
|
||||
> place to edit.
|
||||
|
||||
## Why a canonical copy exists
|
||||
|
||||
Every multi-round review skill (`review-artifact`, `review-code`) needs the model to
|
||||
read this rule inline at the point it dispatches rounds — a cross-file
|
||||
reference would not be loaded into the model's context. So the text is
|
||||
injected directly into both skills at load time. The injection is intentional;
|
||||
this file exists to keep the two consumers on identical wording without a
|
||||
copy-paste mirror.
|
||||
|
||||
## Canonical text
|
||||
|
||||
The block below is what each consumer receives at the inject site. The guard
|
||||
referenced is the agent-initiated `compact` tool's minimum-turns guard,
|
||||
configured at `compaction.agent.min_turns_since_compaction` (default **3**).
|
||||
|
||||
> **Context compaction (round ≥ 2)**: The Orchestrator is the only long-lived
|
||||
> context across rounds; per-round dimension outputs, synthesis, and
|
||||
> convergence tracking must not accumulate unbounded. Once Phase B has posted
|
||||
> the commit status (all round state persisted in the synthesis comment + commit status)
|
||||
> and before dispatching the next
|
||||
> round in Phase A, the Orchestrator MUST run `compact` to summarize the
|
||||
> conversation through the current round, then re-read
|
||||
> the latest synthesis comment via `工单评论 API(见 TERMINOLOGY)` to restore
|
||||
> `current_round` and convergence tracking. The
|
||||
> Synthesizer's return summary (verdict, per-dimension results, re-audit
|
||||
> targets) is carried in the compacted conversation; if it was lost, re-read
|
||||
> the synthesis comment's fenced JSON block as fallback before proceeding.
|
||||
> Skip on round 1
|
||||
> (single-pass reviews never loop). Each round then starts from a bounded
|
||||
> context anchored on file state, not conversation memory.
|
||||
>
|
||||
> This round-boundary compaction is mandatory, but it is NOT exempt from the
|
||||
> `compact` tool's `min_turns_since_compaction` guard
|
||||
> (`compaction.agent.min_turns_since_compaction`, default 3): no such exemption
|
||||
> exists in the tool implementation. If the tool rejects with
|
||||
> `insufficient_turns`, accept the rejection and continue into the next round
|
||||
> without compacting — do NOT retry or work around the guard. A round with too
|
||||
> few turns since the last compaction simply keeps its context; the synthesis
|
||||
> comment + commit status still bound what accumulates.
|
||||
|
||||
## Canonical note line
|
||||
|
||||
There is no `*(Shared rule …)*` italic note line in any consumer — the inject
|
||||
directive resolves to this file's full content (this header included) at load
|
||||
time. Older revisions of this document described a two-step "copy the
|
||||
canonical text into each mirror" sync procedure; that procedure no longer
|
||||
exists and must not be reintroduced.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Shared Rule — Large Prompts via `prompt_file`
|
||||
|
||||
> **Canonical source of truth.** This file is the single authoritative copy of
|
||||
> the large-prompts-via-prompt_file rule. The following skills reference this
|
||||
> rule via an `<!-- inject -->` comment and MUST NOT maintain their own copies:
|
||||
>
|
||||
> - `review-code/SKILL.md`
|
||||
> - `implement/SKILL.md`
|
||||
> - `frontend/SKILL.md`
|
||||
>
|
||||
> (The `roadmap`, `requirements-elicitation`, `design`, and `plan-iterations`
|
||||
> referencing skills were archived 2026-08-21, [org-internal #3072] phase 3 — see
|
||||
> `.octopus/archive/skills/`; their copies of this directive moved with them.)
|
||||
>
|
||||
> **When editing:** update this file only. Each skill references this file via a
|
||||
> one-line `<!-- inject -->` directive — there are no verbatim mirrors to sync.
|
||||
>
|
||||
> This is a reference document, not a skill (no `SKILL.md` frontmatter), so the
|
||||
> skill loader does not register it.
|
||||
|
||||
## Why a canonical copy exists
|
||||
|
||||
The `task-tool-discipline` rule in `AGENTS.md` requires large prompts to be
|
||||
written to a file and passed via `prompt_file`. This guidance applies to every
|
||||
skill that dispatches sub-agents with potentially large prompts. A single
|
||||
canonical source prevents drift and ensures the rule, file path convention
|
||||
(`/tmp/octopus/<slug>.md`), and justification stay consistent.
|
||||
|
||||
## Canonical text
|
||||
|
||||
> **Large Prompts via `prompt_file`**
|
||||
>
|
||||
> Follow the `task-tool-discipline` rule in `AGENTS.md`: any prompt expected to
|
||||
> exceed ~1 KB MUST be written to a file first and passed via the `task` tool's
|
||||
> `prompt_file` parameter (e.g. `/tmp/octopus/<slug>.md`), never inlined.
|
||||
@@ -0,0 +1,75 @@
|
||||
# Shared Final Report Template
|
||||
|
||||
> Canonical final-report markdown template shared across review skills. Read
|
||||
> on-demand by the Orchestrator when writing the final report in Phase E.
|
||||
|
||||
```markdown
|
||||
# {REVIEW_TYPE} Final Report
|
||||
|
||||
- **Project**: {slug}
|
||||
- **Rounds completed**: {N}
|
||||
- **Final verdict**: {PASS | WARN | FAIL}
|
||||
- **Converged**: {true | false — reason}
|
||||
|
||||
## Dimension Summary
|
||||
|
||||
| Dimension | Final Verdict | Pass Rate | R1→RN |
|
||||
| --------- | ------------- | --------- | ----- |
|
||||
| ... | | | |
|
||||
|
||||
## Outstanding Findings
|
||||
|
||||
### Accepted Risks (for tech-debt issue creation in verify Phase 5.5)
|
||||
|
||||
> verify Phase 5.5 会将下表每项 Accepted Risk 创建为 Gitea issue
|
||||
> (label `tech-debt`,标题含 `TD-NNN`)。issue 集即技术债登记表——
|
||||
> 不再有 `tech-debt.md` 文件或 `{slug}/tech-debt` wiki 页。
|
||||
|
||||
| Finding ID | Severity | Description | Recommended Reactivation Trigger |
|
||||
|-----------|----------|-------------|--------------------------------|
|
||||
| {ID} | HIGH/MEDIUM/LOW | {描述} | {可客观判断的条件} |
|
||||
|
||||
> Note: the Severity column uses the **TD-registry severity scale**
|
||||
> (HIGH/MEDIUM/LOW → Priority/High|Medium|Low labels, feeding verify Phase
|
||||
> 5.5's `## TD 登记` rows and promotion labels), NOT the review-finding
|
||||
> severity scale (BLOCKER/MAJOR/MINOR/INFO) — reviewers assign the TD
|
||||
> severity directly when accepting a risk.
|
||||
|
||||
### Other Open Items
|
||||
|
||||
...
|
||||
|
||||
## Review History
|
||||
|
||||
| Round | Verdict | Blockers | Majors | Minors |
|
||||
| ----- | ------- | -------- | ------ | ------ |
|
||||
| ... | | | | |
|
||||
|
||||
## Round-1 Findings Summary
|
||||
|
||||
> Mandatory for `review-code` (Phase E step 2.55): one row per round-1
|
||||
> finding, produced by the round-1 Synthesizer as
|
||||
> `.octopus/runs/{slug}/reviews/{stage}/round1/findings-summary.md`
|
||||
> (`_shared/review-pipeline-phases.md` Phase B step 3 "Round-1 findings
|
||||
> digest") and copied verbatim by the Orchestrator — the Orchestrator does
|
||||
> NOT read the findings JSONs — before they are deleted at archive-at-close.
|
||||
> This table is the durable record retro M7 reads. Other targets MAY include
|
||||
> it when round-1 findings data exists.
|
||||
|
||||
| Dim | Finding ID | Severity | Summary |
|
||||
| --- | ---------- | -------- | ------- |
|
||||
| ... | | | |
|
||||
```
|
||||
|
||||
## Placeholders
|
||||
|
||||
- `{REVIEW_TYPE}` — the value the skill's Phase Bindings declares, used
|
||||
verbatim in the title (`# {REVIEW_TYPE} Final Report`): "Code Review"
|
||||
(review-code — human label; its commit-status context is separately fixed
|
||||
to `pipeline/review-code`), or the machine ids `audit-process` /
|
||||
`review-dag` (review-artifact targets — same id feeds the
|
||||
`pipeline/{REVIEW_TYPE}` commit-status context; see review-artifact Phase
|
||||
Bindings). (The design-space/plan targets were archived 2026-08-21,
|
||||
[org-internal #3072] phase 3.)
|
||||
- `{DIMENSION_COUNT}` — 10 (code review; 9 in standalone-bugfix mode), 3 (review-dag single gate), or 10 (process audit); used in
|
||||
the skill's SKILL.md reference text, not inside this template body
|
||||
@@ -0,0 +1,168 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
# Shared Orchestrator Rules (Mandatory)
|
||||
|
||||
> Canonical Orchestrator behavior rules shared across review skills. Read
|
||||
> on-demand by the Orchestrator. These rules constrain the Orchestrator's behavior;
|
||||
> violating any of them invalidates the review.
|
||||
|
||||
1. **No scope narrowing**: The Orchestrator MUST NOT add qualifiers to the
|
||||
reviewer prompt that discourage thoroughness. Forbidden phrases include:
|
||||
"Focus on the most important issues", "Prioritize critical findings",
|
||||
"Limit to top N items", "Be concise", or any wording that suggests the
|
||||
reviewer should self-censor.
|
||||
|
||||
2. **Standardized prompts only**: Every reviewer receives the prompt from the
|
||||
template field-for-field. The Orchestrator MUST NOT modify the template
|
||||
structure, add constraints, or remove required sections.
|
||||
|
||||
3. **Quantitative verdicts only**: A PASS verdict REQUIRES pass_rate = 1.0
|
||||
with quantitative_summary populated. The Orchestrator MUST NOT promote a
|
||||
WARN to PASS based on subjective judgment. If pass_rate < 1.0, the
|
||||
dimension is at best WARN; if pass_rate < 0.7 or any BLOCKER finding exists,
|
||||
the dimension MUST be FAIL. INFO findings do NOT reduce `pass_rate` and do
|
||||
NOT affect the dimension verdict — a dimension whose only findings are INFO
|
||||
is PASS. INFO is dispositioned (`TD-candidate` / `DISCARDED`) at synthesis
|
||||
and never enters the revision loop (see
|
||||
`_shared/review-pipeline-phases.md` Phase D, "Severity handling — INFO
|
||||
disposition").
|
||||
|
||||
4. **Synthesis is aggregation, not reinterpretation**: The Orchestrator MUST NOT
|
||||
soften, rephrase, or downgrade reviewer findings during synthesis.
|
||||
If a reviewer writes "BLOCKER", it stays "BLOCKER" in synthesis.
|
||||
|
||||
5. **Anonymous findings preservation**: If two reviewers independently flag
|
||||
the same issue from different dimensions, preserve both entries. Do not
|
||||
deduplicate by discarding one — cross-dimension agreement is itself a
|
||||
signal.
|
||||
|
||||
6. **File-based communication**: Do not inline large text blocks in prompts.
|
||||
Use wiki page paths. Reviewer output goes to the skill's configured findings
|
||||
sink (see `_shared/review-pipeline-phases.md` "Output model — two findings
|
||||
sinks"): either a Tier 1 local file
|
||||
`<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`
|
||||
(validated by `reviewer-output.schema.json`) for migrated skills like
|
||||
`review-code`, or an issue comment via `工单评论 API(见 TERMINOLOGY)` (Pattern
|
||||
5) for unmigrated skills. Tier boundary: `core/rules/two-tier-artifacts.md`.
|
||||
Either way, reviewer output does NOT travel as agent reply text.
|
||||
|
||||
7. **Auditor independence**: Reviewers are read-only Explorers. Only the
|
||||
{REVISION_ROLE} (a separate Worker, run in a different phase) may edit files.
|
||||
The Orchestrator MUST NOT let a reviewer both judge and fix.
|
||||
|
||||
8. **Subagent dispatch contract** (binding — omitting `subagent_type` is the
|
||||
#1 review-skill dispatch failure): every `task` tool call MUST resolve an
|
||||
agent type. The skill prose uses role names ("Orchestrator", "Architect",
|
||||
"Reviewer", "Developer", "Analyst", "Planner", "Verifier", "Remediator", "Synthesizer") — those are
|
||||
`role` values, NOT agent types. Map them to the `task` tool parameters as
|
||||
follows:
|
||||
|
||||
| Skill role | `role` param | `subagent_type` param |
|
||||
| ----------------- | -------------- | --------------------- |
|
||||
| Reviewer | `Reviewer` | `explorer` |
|
||||
| Orchestrator | `Orchestrator` | `worker` |
|
||||
| Architect | `Architect` | `worker` |
|
||||
| Developer / Tester| `Developer` | `worker` |
|
||||
| Analyst | `Analyst` | `worker` |
|
||||
| Planner | `Planner` | `worker` |
|
||||
| Verifier | `Verifier` | `worker` |
|
||||
| Remediator | `Remediator` | `worker` |
|
||||
| Synthesizer | `Synthesizer` | `worker` |
|
||||
|
||||
The `agent` type is declared in `roles/*.yaml` for the five roles that
|
||||
have a role YAML — `producer.yaml` (worker), `reviewer.yaml` (explorer),
|
||||
`tool.yaml` (explorer), `verifier.yaml` (worker), and `coordinator.yaml`
|
||||
(worker; the pool coordinator session — not a task-dispatch role, so it
|
||||
does not appear in the table above). The task tool derives
|
||||
`subagent_type` from `role` automatically when `subagent_type` is omitted
|
||||
AND the role's `agent` field is defined. All other roles in the table above
|
||||
(Orchestrator, Architect, Developer, Analyst, Planner, Remediator,
|
||||
Synthesizer) have NO role YAML and therefore MUST pass `subagent_type`
|
||||
explicitly — never pass only `role` + `description` and assume a default.
|
||||
|
||||
Concrete example (dispatching a reviewer):
|
||||
|
||||
```
|
||||
task(
|
||||
description: "Review CMP dimension",
|
||||
role: "Reviewer",
|
||||
subagent_type: "explorer", // optional here (derivable from role), shown for clarity
|
||||
permissions: [{ permission: "read", pattern: "*", action: "allow" }, ...],
|
||||
temperature: 0.1,
|
||||
prompt: <filled reviewer template>
|
||||
)
|
||||
```
|
||||
|
||||
Forbidden: a `task` call that names the role in prose ("Spawn the
|
||||
Architect") but omits BOTH `subagent_type` and a defined-`agent` `role` —
|
||||
it fails with `TaskMissingSubagentType`.
|
||||
|
||||
## Default Explorer Permissions
|
||||
|
||||
All review and audit skills that spawn Explorer sub-agents use the same
|
||||
read-only BASE permission set. The canonical base template is:
|
||||
|
||||
```
|
||||
permissions: [
|
||||
{ permission: "read", pattern: "*", action: "allow" },
|
||||
{ permission: "glob", pattern: "*", action: "allow" },
|
||||
{ permission: "grep", pattern: "*", action: "allow" }
|
||||
]
|
||||
```
|
||||
|
||||
Each skill references this base template via `core/skills/_shared/review-orchestrator-rules.md`
|
||||
rather than inlining the JSON array. This centralization ensures the base
|
||||
permission surface stays consistent across all review/audit skills.
|
||||
|
||||
**Tier-1 local exception** ([org-internal #1988]): migrated skills that write raw per-dimension
|
||||
findings to `<runs-root>/**` (e.g. `review-code`) add ONE scoped `edit` allow
|
||||
to the base set — `{ permission: "edit", pattern: "<runs-root>/**", action:
|
||||
"allow" }` — so the reviewer can write its OWN finding file. This is a
|
||||
documented exception to the read-only base, not a divergence: it does NOT grant
|
||||
edit on the code under review, so rule #7 (auditor independence) holds. See
|
||||
`_shared/review-pipeline-phases.md` Phase A step 4 and `review-code/SKILL.md`
|
||||
Phase A step 3 for the inline extended array.
|
||||
|
||||
Residual risk — accepted trade-off (TD/STD-F004, [org-internal #2688]): the grant is scoped
|
||||
to `<runs-root>/**`, wider than the reviewer's own findings file. Per-file
|
||||
narrowing was considered and rejected: findings paths are round- and
|
||||
dimension-dependent (`{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`),
|
||||
which makes per-file permission patterns brittle at spawn time, and `runs/**`
|
||||
holds only transient Tier 1 artifacts (digest-summarized at archive). The
|
||||
residual exposure — a misbehaving reviewer could overwrite a sibling stage's
|
||||
Tier 1 files — is recorded here as accepted; auditor independence is
|
||||
unaffected (code under review lives outside `runs/`).
|
||||
|
||||
### No bash for Explorer sub-agents (deliberate boundary, [org-internal #2115] RC4 / [org-internal #2126])
|
||||
|
||||
Explorer sub-agents (Reviewer / auditor / Tool roles) have **no bash**. The
|
||||
`explorer` agent is built deny-by-default at
|
||||
`<harness-package>/src/agent/agent.ts` (`"*": "deny"` + explicit `read`/`glob`/
|
||||
`grep` allows + `bash: "deny"`), so the `permissions` array above is read-only
|
||||
by construction — a reviewer cannot run commands, mutate state, or escape its
|
||||
read surface even if a prompt tried to grant bash. This is a deliberate
|
||||
security boundary that upholds rule #7 (auditor independence): a reviewer must
|
||||
never alter the artifact under review or its environment.
|
||||
|
||||
**Reviewer guidance**: do everything with `read`, `glob`, `grep`, and the
|
||||
`gitea-rest` skill (curl against `/api/v1`; `gitea-mcp` is retired). If a
|
||||
review dimension seems to require running a command
|
||||
(executing a build, running a test, computing a metric), that is the
|
||||
Synthesizer / Verifier's job (Worker sub-agents, which DO have bash via the
|
||||
`worker` agent defaults) — not the Reviewer's. Report the need in findings
|
||||
instead of attempting bash.
|
||||
|
||||
> **[org-internal #2126] Task 2 conclusion — keep + document.** The `deny **` pushed per-tool
|
||||
> at `<harness-package>/src/session/prompt.ts` is the **session tool-enable /
|
||||
> disable map** (it disables `todowrite` / `task` / `experimental.primary_tools`
|
||||
> for subagents and allows forwarded MCP tools). It is NOT the source of the
|
||||
> Explorer bash deny — that comes from the `explorer` agent config above, which
|
||||
> is the correct place. Relaxing it would break auditor independence; worker-
|
||||
> class sub-agents already have bash wherever the pipeline needs to run
|
||||
> commands. Decision: **keep the deny, document it here** (this section).
|
||||
|
||||
## Placeholder
|
||||
|
||||
- `{REVISION_ROLE}` — "Developer" (code review), "Analyst" (review-dag single
|
||||
gate), or "Remediator" (process audit). The Worker role that revises
|
||||
artifacts between rounds. (The Architect/Planner revision roles belonged to
|
||||
the archived design-space / iteration-plan targets, [org-internal #3072] phase 3.)
|
||||
@@ -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}.
|
||||
@@ -0,0 +1,135 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
# Shared Reviewer Prompt Template
|
||||
|
||||
> Canonical template for spawning parallel Explorer reviewers. Read on-demand
|
||||
> by the Orchestrator when dispatching reviewers. The Orchestrator substitutes
|
||||
> skill-level constants (fixed per skill, documented in the skill's SKILL.md)
|
||||
> and per-dimension values (filled from the skill's dimension mapping table).
|
||||
|
||||
The prompt text below is sent to each reviewer. Substitute all `{PLACEHOLDER}`
|
||||
values before dispatch.
|
||||
|
||||
```
|
||||
You are a {REVIEWER_ROLE}. Your responsibility is exactly the dimension(s)
|
||||
assigned to you — one dimension in the standard dispatch, or the named group
|
||||
of dimensions in a risk-tier grouped dispatch (review-code S/M tiers). Do NOT
|
||||
expand or narrow your scope beyond the assignment. Examine every file
|
||||
assigned to you and flag every issue you find, regardless of perceived
|
||||
importance.
|
||||
|
||||
{BASELINE_SECTION}
|
||||
|
||||
## Your Dimension(s)
|
||||
|
||||
Code: {DIMENSION_CODE}
|
||||
Label: {DIMENSION_NAME}
|
||||
|
||||
## Checklist Items You Must Verify
|
||||
|
||||
{CHECKLIST_ITEMS}
|
||||
|
||||
{FILE_SECTIONS}
|
||||
|
||||
## Instructions
|
||||
|
||||
{READ_FIRST_STEPS}
|
||||
4. For each checklist item, determine whether the {ARTIFACT_NOUN} satisfies it.
|
||||
Every checklist item must receive a PASS or FAIL verdict.
|
||||
Items that are genuinely not applicable must be marked NA with a reason.
|
||||
5. For every FAIL, produce a finding with: a unique id (pattern {FINDING_ID_PREFIX}-F{NNN},
|
||||
e.g. {FINDING_ID_EXAMPLE}), severity, checklist ref, {FINDING_DETAILS}, and a concrete
|
||||
suggestion for how to fix it. {FINDING_ID_PREFIX} is the finding's OWN
|
||||
dimension code — equal to {DIMENSION_CODE} in the standard single-dimension
|
||||
dispatch; for a grouped dispatch each finding's id uses its own dimension
|
||||
code (e.g. COR-F001, TST-F001), NOT the joined group code
|
||||
(never `COR+TST+DBT-F001`). When your dispatch is multi-slot
|
||||
(reviewer_count > 1), use the slot-prefixed form {DIM}R{k}-F{NNN} with your
|
||||
1-based slot k (e.g. TOPOR1-F001) so parallel slot files never collide on id.
|
||||
{CONTRADICTION_RULE}
|
||||
7. Assign severity strictly:
|
||||
{SEVERITY_DEFINITIONS}
|
||||
8. Count every PASS and FAIL. Compute pass_rate = passed / total_checks.
|
||||
Verdict rules:
|
||||
- PASS: pass_rate = 1.0 (no failed checks)
|
||||
- WARN: pass_rate >= 0.7 and no BLOCKER findings
|
||||
- FAIL: any BLOCKER finding OR pass_rate < 0.7
|
||||
9. Place the computed counts in a `quantitative_summary` object with fields
|
||||
`total_checks`, `passed`, `failed`, `pass_rate`, `na_count` (if any items were marked NA),
|
||||
and the four severity counts `blocker_count`, `major_count`, `minor_count`,
|
||||
`info_count` (count the BLOCKER/MAJOR/MINOR/INFO findings you produced —
|
||||
the Synthesizer consumes these for aggregation).
|
||||
10. Write findings to `{OUTPUT_FILE}`
|
||||
using the JSON Schema defined at `core/schemas/reviewer-output.schema.json`.
|
||||
Populate `reviewed_files` with the list of file paths you actually read
|
||||
during review.
|
||||
|
||||
## What You Must NOT Do
|
||||
|
||||
- Do NOT fabricate results. If a tool you need (e.g. `gitea_wiki__get_page`,
|
||||
`read`, `codegraph_*`) is unavailable, errors, or returns empty, report the
|
||||
failure honestly — emit a finding stating the dimension could not be
|
||||
reviewed due to the missing tool. NEVER invent findings, severities, or
|
||||
file references you did not derive from a successful tool call. Fabricated
|
||||
review output is a critical defect (per `core/rules/claim-discipline.md`
|
||||
§ "Tool-failure honesty").
|
||||
- Do NOT narrow your scope because "this seems minor".
|
||||
- Do NOT skip checklist items because "{LOOKS_FINE_PHRASE}".
|
||||
- Do NOT produce a PASS verdict to save effort. Base verdicts on data.
|
||||
- Do NOT add findings for dimensions you are not assigned to.
|
||||
- Do NOT read files outside your assigned list.
|
||||
- Do NOT edit any file EXCEPT your own findings file at `{OUTPUT_FILE}`. You are read-only for all other files.
|
||||
```
|
||||
|
||||
## Placeholders
|
||||
|
||||
### Skill-level constants (fixed per skill — see the skill's SKILL.md)
|
||||
|
||||
- `{REVIEWER_ROLE}` — reviewer identity (e.g. "code reviewer", "DAG reviewer", "process auditor")
|
||||
- `{BASELINE_SECTION}` — the full baseline section heading + body (differs structurally
|
||||
per skill: single design baseline vs. dual requirements+design baselines)
|
||||
- `{READ_FIRST_STEPS}` — instruction steps 1–3 (what to read first; includes the `1.` `2.`
|
||||
`3.` prefixes)
|
||||
- `{ARTIFACT_NOUN}` — "code" or "artifact" (used in step 4)
|
||||
- `{FINDING_DETAILS}` — the location/evidence phrase in step 5 (e.g. "file path and line
|
||||
number, a summary, detailed explanation, quoted code evidence")
|
||||
- `{FINDING_ID_EXAMPLE}` — example finding id (e.g. COR-F001, CMP-F001)
|
||||
- `{FINDING_ID_PREFIX}` — the id prefix for findings: the finding's own
|
||||
dimension code (equal to `{DIMENSION_CODE}` in the standard dispatch; the
|
||||
own-code of each finding inside a group in a grouped dispatch; see step 5's
|
||||
per-finding rule and the multi-slot `{DIM}R{k}-F{NNN}` form)
|
||||
- `{CONTRADICTION_RULE}` — step 6 in full (includes the `6.` prefix); the rule for when
|
||||
an artifact contradicts its baseline
|
||||
- `{SEVERITY_DEFINITIONS}` — the four severity bullets (BLOCKER/MAJOR/MINOR/INFO) with
|
||||
leading indentation matching step 7's sub-items
|
||||
- `{LOOKS_FINE_PHRASE}` — "the code looks fine" / "the artifacts look fine"
|
||||
|
||||
### Per-dimension values (filled by the Orchestrator from the dimension mapping table)
|
||||
|
||||
- `{DIMENSION_CODE}` — the dimension code (e.g. COR, ARCH). For a grouped
|
||||
dispatch (review-code S/M risk tiers, where one reviewer covers several
|
||||
dimensions), fill with the joined group, e.g. `COR+TST+DBT` — the reviewer
|
||||
then emits one findings file for the group with per-finding ids prefixed by
|
||||
each finding's own dimension code.
|
||||
- `{DIMENSION_NAME}` — the dimension label (e.g. Correctness, Architecture);
|
||||
for a grouped dispatch, the joined labels of the group.
|
||||
- `{CHECKLIST_ITEMS}` — the inline checklist items text for this dimension (read from
|
||||
the checklist file; inlined so the reviewer does not need to open the checklist)
|
||||
- `{FILE_SECTIONS}` — the file sections block (skill-specific section headers + the
|
||||
dimension's assigned file paths; include the "(none)" note where applicable)
|
||||
- `{OUTPUT_FILE}` — the output target for this reviewer's findings. The skill
|
||||
picks the findings sink (see `_shared/review-pipeline-phases.md` "Output model
|
||||
— two findings sinks"):
|
||||
- Tier 1 local (migrated skills, e.g. `review-code`): the absolute path inside
|
||||
the worktree, e.g.
|
||||
`<worktrees-root>/<repo>-<slug>/<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`
|
||||
— a JSON file validated by `core/schemas/reviewer-output.schema.json`.
|
||||
The reviewer is granted scoped write to `<runs-root>/**` for this.
|
||||
When the dispatch assigns MORE THAN ONE reviewer to this dimension
|
||||
(dim_split > 1), each reviewer writes its OWN slot file
|
||||
`findings-{DIMENSION_CODE}-r{k}.json` (k = its 1-based slot) with
|
||||
`reviewer_slot` / `reviewer_count` set — parallel reviewers never share
|
||||
one file.
|
||||
- Tier 2 comment (unmigrated fallback): post an issue comment via
|
||||
`工单评论 API(见 TERMINOLOGY)` (Pattern 5) with a fenced ` ```json ` block,
|
||||
labeled `{DIMENSION_CODE} review — round {N}` (multi-slot reviewers append
|
||||
` · r{k}` to the label).
|
||||
@@ -0,0 +1,57 @@
|
||||
# Shared Revision Prompt Template
|
||||
|
||||
> Canonical prompt for spawning the {ROLE} (Worker) that revises artifacts
|
||||
> between review rounds. Read on-demand by the Orchestrator in Phase C. The
|
||||
> Orchestrator substitutes skill-level constants before dispatch.
|
||||
|
||||
```
|
||||
Read `{TASK_FILE}` for your input files. {REVISION_SCOPE}
|
||||
|
||||
{RESOLUTION_RULE}
|
||||
|
||||
Your task file references ONLY dimensions with open BLOCKER, MAJOR, or MINOR
|
||||
findings. INFO findings are NEVER in your scope — they are dispositioned
|
||||
(`TD-candidate` or `DISCARDED`) at synthesis and excluded from revision (see
|
||||
`.octopus/skills/_shared/review-pipeline-phases.md` Phase D, "Severity
|
||||
handling — INFO disposition"). Do NOT act on or chase INFO observations.
|
||||
|
||||
From round 2 onward, every remaining purely cosmetic MINOR finding
|
||||
({COSMETIC_MINOR_EXAMPLES} — per the severity definition above) MUST be explicitly
|
||||
dispositioned: either fix it and mark it resolved, or waive it by recording
|
||||
`WAIVED-{finding-id}` (e.g. `{WAIVED_EXAMPLE}`) with a one-line reason and setting
|
||||
the finding's status to `WAIVED`. Cosmetic MINORs MUST NOT carry forward as open
|
||||
items beyond round 2 — an unresolved cosmetic MINOR is itself a process violation.
|
||||
This is the canonical definition of the `WAIVED-{id}` convention referenced in
|
||||
`{CHECKLIST_REF}`.
|
||||
|
||||
After revising, report a summary of changes made:
|
||||
- Files modified: {FILES_MODIFIED_LINE}
|
||||
- Findings addressed: {counts by severity}
|
||||
- Findings deferred with justification: {list}
|
||||
- Findings waived as cosmetic MINOR (round 2+): {WAIVED-{id} → reason}
|
||||
|
||||
Persist that summary to `{RETURN_FILE}` as your LAST action, BEFORE
|
||||
returning it — worker-report persistence ([org-internal #2847], see
|
||||
`.octopus/skills/_shared/worker-report-persistence.md`). The persisted copy
|
||||
is the report of record; if your completion notification is lost, the
|
||||
Orchestrator recovers the revision outcome from this file.
|
||||
```
|
||||
|
||||
## Placeholders
|
||||
|
||||
### Skill-level constants (fixed per skill — see the skill's SKILL.md)
|
||||
|
||||
- `{ROLE}` — "Developer" (code review), "Analyst" (review-dag single gate), or "Remediator" (process audit)
|
||||
- `{TASK_FILE}` — `task-developer`, `task-architect`, `task-analyst`, `task-planner`, or `task-remediator` (wiki page name under `{slug}/reviews/{stage}/round{N}/`)
|
||||
- `{REVISION_SCOPE}` — the opening paragraph: what to revise and the
|
||||
minimal/surgical constraint
|
||||
- `{RESOLUTION_RULE}` — the design-deviation / resolution-comment rule
|
||||
- `{COSMETIC_MINOR_EXAMPLES}` — the parenthetical examples of cosmetic MINORs
|
||||
- `{WAIVED_EXAMPLE}` — example waived id (e.g. `WAIVED-COR-R2-001`)
|
||||
- `{CHECKLIST_REF}` — the checklist file(s) the WAIVED convention is defined in
|
||||
- `{FILES_MODIFIED_LINE}` — `{list}` or `{list by artifact type}`
|
||||
- `{RETURN_FILE}` — the Tier 1 return-persistence target for this dispatch,
|
||||
following the skill's canonical stage path (e.g. review-code:
|
||||
`.octopus/runs/{slug}/reviews/code/round{N}/revision-return.md`); default
|
||||
per convention: `.octopus/runs/{slug}/workers/{chunk-id}-worker-{seq}.md`,
|
||||
lightweight fallback `/tmp/octopus/{chunk-id}-worker-{seq}.md`
|
||||
@@ -0,0 +1,86 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
name: Coordinator
|
||||
purpose: >
|
||||
Pool dispatch coordinator (billing-v2 [org-internal #4041] §7, REQ-F-012): a wake-driven,
|
||||
STATELESS decision-maker session living in the pool pod alongside workers.
|
||||
List eligible issues (Gitea API, scoped token) → produce DAG-aware dispatch
|
||||
proposals → commit each dispatch through the N-16 assignment API
|
||||
(POST /api/pools/:repo/assignments). The coordinator decides; the
|
||||
control-plane dumbwaiters make the commit atomic. It never holds wallet
|
||||
internals, never bypasses the central ledger, and never merges (E-4).
|
||||
|
||||
# Layer 5 — Executable
|
||||
agent: worker
|
||||
model: null
|
||||
agents_md:
|
||||
- workflow-routing
|
||||
- claim-discipline
|
||||
- code-graph
|
||||
- compact
|
||||
|
||||
# Stateless iron rule (§7.1): the coordinator's ENTIRE dispatch state is the
|
||||
# work_order_assignments table. After any wake (first start, re-wake after
|
||||
# idle, or takeover after the previous coordinator died) the first action is
|
||||
# ALWAYS: GET /api/pools/:repo/assignments?state=assigned — rebuild the
|
||||
# in-flight view from the table, never from memory or notes. Dying costs
|
||||
# nothing; the pool reconciler migrates the role to the earliest surviving
|
||||
# member by convention (no election).
|
||||
#
|
||||
# Decision procedure (AC-1) — full text: docs/runbooks/pool-coordinator.md.
|
||||
# 1. recover — read the assignment table (state=assigned) + org
|
||||
# notifications (pools.assignment.expired = re-dispatch inbox)
|
||||
# 2. list — eligible issues via Gitea API (scoped token): labeled
|
||||
# Kind/* and unassigned/without active assignment row
|
||||
# 3. propose — DAG-aware: respect blockedBy edges (epic DAG / node deps),
|
||||
# sibling load (least-loaded member first), and the N>1
|
||||
# self-assign constraints below; fast path (AC-1 简单场景):
|
||||
# exactly one eligible issue and one available member →
|
||||
# deterministic pick, no elaborate deliberation needed
|
||||
# 4. commit — one POST per dispatch; proposal payload carries the audit
|
||||
# trace (§audit contract below); 409/403 envelopes are
|
||||
# terminal outcomes, not retried blindly
|
||||
#
|
||||
# Self-assign constraints (AC-2, §7.2 N>1) — the ledger is identity-blind, so
|
||||
# the constraints live HERE and are enforced by convention + audited via the
|
||||
# trace: least-loaded ordering puts self LAST (self-assign only when no other
|
||||
# member is available); the coordinator holds at most 1 active assignment at
|
||||
# a time, same cap as any worker; self-dispatch still goes through the same
|
||||
# POST (铁律 — never "start working because I am the coordinator"). N=1:
|
||||
# self-dispatch is the only form and is NOT a special branch.
|
||||
#
|
||||
# Audit contract (AC-4/AC-6): every POST carries proposal =
|
||||
# { version: 1,
|
||||
# decision: { coordinator, self_position: "last"|"n/a", held_active,
|
||||
# cap: 1, fast_path: boolean, reason },
|
||||
# eligible: [{ issue, blockedBy: [issue,...] }...],
|
||||
# chosen: { issue, member } }
|
||||
# The trace lands verbatim on the assignment row (jsonb proposal_payload),
|
||||
# is queryable via GET /api/pools/:repo/assignments, and is exported in the
|
||||
# assignmentAuditRecord shape (runs archive / pool-drill.sh). LLM decisions
|
||||
# are not replayable — the recorded decision + the deterministic commit is
|
||||
# the audit story.
|
||||
#
|
||||
# Security posture (AC-5, see docs/security/threat-model.md §自治批处理):
|
||||
# the coordinator authenticates with a workspace-level API token
|
||||
# (TD-687/[org-internal #3898] owner-minted, jti-revocable, role claim org_role). TODAY'S
|
||||
# mint shape hardcodes org_role=viewer — read-capable only (assignment table
|
||||
# + pool surfaces); the editor-capable mint needed for dispatch submission is
|
||||
# an explicit deployment-time decision on the [org-internal #3898] channel (not landed with
|
||||
# N-19). Either way the token can NOT mint tokens, touch wallet internals, or
|
||||
# merge PRs — the merge gate stays human (E-4).
|
||||
#
|
||||
# Worker-report persistence ([org-internal #2847] — see
|
||||
# core/skills/_shared/worker-report-persistence.md): a Coordinator
|
||||
# sub-agent persists its FINAL RETURN REPORT to disk as its LAST action,
|
||||
# before returning — <runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md
|
||||
# (Tier 1 preferred; else /tmp/octopus/{chunk-id}-worker-{seq}.md), and
|
||||
# appends its working-notes entry at stage exit per
|
||||
# core/templates/runs-layout.md. The persisted copy is the report of
|
||||
# record; re-read persisted artifacts after any compaction, never rely on
|
||||
# conversation memory.
|
||||
compact:
|
||||
preserve:
|
||||
- "docs/runbooks/pool-coordinator.md — the decision procedure is file-driven, never memory-driven; re-read after any compaction"
|
||||
- "the recovered in-flight view (GET /api/pools/:repo/assignments?state=assigned) — the coordinator holds NO dispatch state in memory; re-read the table first after every wake/compaction"
|
||||
- "the audit trace schema (decision.self_position / decision.held_active / decision.cap / eligible[].blockedBy) — drift here breaks AC-6 auditability"
|
||||
- "self-assign constraints: self LAST in least-loaded order, active-assignment cap 1, self-dispatch goes through the same POST — never a special branch (§7.2 铁律)"
|
||||
@@ -0,0 +1,41 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
name: Producer
|
||||
purpose: >
|
||||
Write production artifacts — requirements, design, plans, code, fixes,
|
||||
refactors, releases, retrospectives. The specific task, its checklist, and
|
||||
the current pipeline stage are injected by the calling skill.
|
||||
|
||||
# Layer 5 — Executable
|
||||
agent: worker
|
||||
model: null
|
||||
agents_md:
|
||||
- code-graph
|
||||
- testing
|
||||
- type-checking
|
||||
- claim-discipline
|
||||
- compact
|
||||
|
||||
# Worker-report persistence ([org-internal #2847], retro-2696 AI#2 — see
|
||||
# core/skills/_shared/worker-report-persistence.md): every Producer
|
||||
# sub-agent persists its FINAL RETURN REPORT to disk as its LAST action,
|
||||
# before returning — <runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md
|
||||
# (Tier 1 preferred; skill-canonical stage path when the skill defines one),
|
||||
# else /tmp/octopus/{chunk-id}-worker-{seq}.md. The persisted copy is the
|
||||
# report of record; the task notification is a convenience copy.
|
||||
#
|
||||
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md §
|
||||
# working-notes.md): at stage exit the Producer appends ONE entry (≤30 lines:
|
||||
# decisions and why, dead ends, reviewer feedback that changed the work, hints
|
||||
# for the next stage) to <runs-root>/{slug}/working-notes.md, and registers
|
||||
# its index.json row (type working-notes) once if absent.
|
||||
#
|
||||
# Role-level compaction contract (harness-enforced — see core/rules/compact.md
|
||||
# § "Role-level re-read set"). After any compaction, a Producer sub-agent re-reads
|
||||
# these persisted artifacts before continuing; it never relies on conversation
|
||||
# memory for them.
|
||||
compact:
|
||||
preserve:
|
||||
- "<runs-root>/{slug}/working-notes.md (re-read FIRST, before formal artifacts — carries prior stages' tacit context: decisions, dead ends, reviewer feedback)"
|
||||
- "the work item / node spec being implemented (issue body or the frozen DAG copy {epic-slug}/dag + {epic-slug}/dag-nodes/{node-id} subpages)"
|
||||
- "the node's design baseline: node spec + cross-session edge contracts in {epic-slug}/dag (design detail is folded into node AC + contracts)"
|
||||
- "the acceptance criteria for the current node (node acceptance_criteria in {epic-slug}/dag, or the task ticket body)"
|
||||
@@ -0,0 +1,30 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
name: Reviewer
|
||||
purpose: >
|
||||
Review one dimension of an artifact against its checklist, read-only.
|
||||
Find issues that would block merge. One reviewer per dimension, all
|
||||
running in parallel.
|
||||
|
||||
# Layer 5 — Executable
|
||||
agent: explorer
|
||||
model: null
|
||||
agents_md:
|
||||
- code-graph
|
||||
- claim-discipline
|
||||
- ticket-lifecycle
|
||||
- compact
|
||||
|
||||
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md §
|
||||
# working-notes.md): the Reviewer side appends ONE distilled entry via the
|
||||
# Synthesizer at review convergence — never per dimension dispatch (9
|
||||
# dimension dispatches = 1 entry) — to <runs-root>/{slug}/working-notes.md.
|
||||
#
|
||||
# Role-level compaction contract (harness-enforced — see core/rules/compact.md
|
||||
# §"Role-level re-read set"). A Reviewer is read-only and short-lived (one
|
||||
# dimension per dispatch); after any compaction it re-reads its checklist and
|
||||
# the artifact under review, never conversation memory.
|
||||
compact:
|
||||
preserve:
|
||||
- "<runs-root>/{slug}/working-notes.md (re-read FIRST — prior stages' tacit context; also the file the Synthesizer's convergence entry appends to)"
|
||||
- "the dimension checklist being applied (core/checklists/*.md)"
|
||||
- "the artifact under review ({slug}/ wiki page or PR diff)"
|
||||
@@ -0,0 +1,26 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
name: Tool
|
||||
purpose: >
|
||||
Specialized tool agent for image interpretation and other vision/utility
|
||||
tasks that require a specific model.
|
||||
|
||||
# Layer 5 — Executable
|
||||
agent: explorer
|
||||
model: opencode/claude-haiku-4-5
|
||||
agents_md:
|
||||
- code-graph
|
||||
- claim-discipline
|
||||
- compact
|
||||
|
||||
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md §
|
||||
# working-notes.md): Tool agents append to <runs-root>/{slug}/working-notes.md
|
||||
# ONLY when the task produced a load-bearing finding (e.g. image evidence that
|
||||
# changed a decision) — not for routine single-shot output.
|
||||
#
|
||||
# Role-level compaction contract (harness-enforced — see core/rules/compact.md
|
||||
# §"Role-level re-read set"). Tool agents are single-shot; after any compaction
|
||||
# they re-read the task prompt's input artifact, never conversation memory.
|
||||
compact:
|
||||
preserve:
|
||||
- "<runs-root>/{slug}/working-notes.md (re-read FIRST — prior stages' tacit context)"
|
||||
- "the input artifact named in the task prompt (image path, file, or URL)"
|
||||
@@ -0,0 +1,40 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
name: Verifier
|
||||
purpose: >
|
||||
Run the iteration's DoD matrix, integration tests, NFR validation, and
|
||||
regression checks. The iteration is not Done until all DoD items pass.
|
||||
|
||||
# Layer 5 — Executable
|
||||
agent: worker
|
||||
model: null
|
||||
agents_md:
|
||||
- code-graph
|
||||
- testing
|
||||
- ticket-lifecycle
|
||||
- type-checking
|
||||
- claim-discipline
|
||||
- compact
|
||||
|
||||
# Worker-report persistence ([org-internal #2847], retro-2696 AI#2 — see
|
||||
# core/skills/_shared/worker-report-persistence.md): the Verifier
|
||||
# persists its FINAL RETURN REPORT (DoD verdict + evidence pointers) to disk
|
||||
# as its LAST action, before returning —
|
||||
# <runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md (Tier 1 preferred),
|
||||
# else /tmp/octopus/{chunk-id}-worker-{seq}.md. The persisted copy is the
|
||||
# report of record; the task notification is a convenience copy.
|
||||
#
|
||||
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md §
|
||||
# working-notes.md): the Verifier appends ONE entry at verify exit (what the
|
||||
# DoD sweep caught, flaky/deferral context the next run should know). The
|
||||
# Phase 5.5 archive step additionally inlines the final working-notes.md
|
||||
# content into the archive bundle's working_notes field.
|
||||
#
|
||||
# Role-level compaction contract (harness-enforced — see core/rules/compact.md
|
||||
# §"Role-level re-read set"). After any compaction, a Verifier re-reads these
|
||||
# persisted artifacts before continuing; it never relies on conversation memory.
|
||||
compact:
|
||||
preserve:
|
||||
- "<runs-root>/{slug}/working-notes.md (re-read FIRST, before formal artifacts — carries prior stages' tacit context: decisions, dead ends, reviewer feedback)"
|
||||
- "the DoD matrix for the current iteration ({slug}/05-verify-*)"
|
||||
- "the acceptance criteria (node acceptance_criteria in the frozen DAG copy {epic-slug}/dag, or the task ticket body)"
|
||||
- "the final code-review report ({slug}/reviews/code/final/report)"
|
||||
@@ -0,0 +1,236 @@
|
||||
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
|
||||
# Synthesis Task — Round {ROUND_NUMBER}
|
||||
|
||||
> Shared template filled by the Orchestrator and dispatched to the Synthesizer
|
||||
> (Worker) during Phase B of all review and audit skills. The Orchestrator
|
||||
> writes this template to the skill's configured prompt location (Tier 1 local
|
||||
> `<runs-root>/{slug}/reviews/{stage}/round{N}/task-synthesizer.md` for
|
||||
> `tier1-local` skills like `review-code`; `/tmp/octopus/synthesis_task_{slug}_round{N}.md`
|
||||
> + a Gitea wiki page for `tier2-comment` skills) for `prompt_file` dispatch.
|
||||
>
|
||||
> The Synthesizer reads all dimension findings from the skill's findings sink
|
||||
> (local files or issue comments), posts the synthesis to the pipeline PR /
|
||||
> source issue comment — for audit-process runs, the wiki page
|
||||
> `audit/{date}/round{N}/synthesis` — with a fenced JSON block (Tier 2 human
|
||||
> gate — always Gitea), updates the commit status, and returns a compact
|
||||
> summary (≤ 2KB).
|
||||
|
||||
## Input
|
||||
|
||||
- **Target**: PR #{PR_NUMBER} (pipeline mode) or issue #{ISSUE_NUMBER} (standalone mode)
|
||||
— for audit-process runs, the wiki page `audit/{date}/round{N}/synthesis`.
|
||||
Post the synthesis to this target.
|
||||
- **Findings sink**: `{FINDINGS_SINK}` — `tier1-local` or `tier2-comment`
|
||||
(set by the skill; see `_shared/review-pipeline-phases.md`).
|
||||
- **Dimension findings** — already produced by individual reviewers:
|
||||
- `tier1-local`: read the finding files at
|
||||
`<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`,
|
||||
each a JSON document matching `core/schemas/reviewer-output.schema.json`.
|
||||
Read every `findings-*.json` in that round directory. A dimension with
|
||||
multiple reviewer slots (dim_split > 1) contributes several files
|
||||
(`findings-{DIM}-r1.json`, `-r2.json`, …) — aggregate them as ONE
|
||||
dimension's findings (union of findings; worst verdict wins).
|
||||
- `tier2-comment`: read the dimension issue comments via
|
||||
`工单评论 API(见 TERMINOLOGY)` (Pattern 3, `_shared/gitea-read-patterns.md`).
|
||||
Each comment body contains a `**{DIMENSION_CODE} review — round {N}**` header
|
||||
followed by a fenced ` ```json ` block matching
|
||||
`core/schemas/reviewer-output.schema.json`.
|
||||
- **Dimensions marked UNRESOLVED** (reviewer crashed/timed out, no finding exists):
|
||||
`{UNRESOLVED_DIMENSIONS}`
|
||||
Exclude these from aggregation.
|
||||
- **Synthesis schema**: `core/schemas/synthesis.schema.json`
|
||||
- **Commit SHA**: `{SHA}` (the HEAD commit being reviewed).
|
||||
- **Review type**: `{REVIEW_TYPE}` — one of `review-code`, `review-dag`,
|
||||
`audit-process` (the `review-design-space` / `review-iteration-plan` /
|
||||
`review-roadmap` targets were archived 2026-08-21, [org-internal #3072] phase 3 — their
|
||||
historical synthesis data remains readable).
|
||||
|
||||
## Your Job
|
||||
|
||||
1. Read all dimension findings from the configured sink. For each dimension,
|
||||
extract:
|
||||
- `verdict` (PASS / WARN / FAIL / UNRESOLVED)
|
||||
- `pass_rate`
|
||||
- `blocker_count`, `major_count`, `minor_count`, `info_count`
|
||||
- `findings` array (each finding has: id, severity, checklist_ref, summary)
|
||||
|
||||
1b. **Finding-id uniqueness post-check (MANDATORY)**: after reading ALL
|
||||
findings files of the round (including every `-r{k}` slot file), verify
|
||||
that `id` values are unique across the whole round. The reviewer-output
|
||||
schema's `uniqueItems` compares whole objects and does NOT enforce id
|
||||
uniqueness — this step is the enforcement. On a duplicate id: do NOT
|
||||
silently drop or renumber it; keep both findings in the raw files, note
|
||||
the collision in the synthesis digest, and mark the affected dimension
|
||||
WARN with the collision listed (the dispatch/prompt defect that produced
|
||||
it — e.g. a missing slot prefix — is the fix target).
|
||||
|
||||
2. Compute `aggregated_stats`:
|
||||
- `total_dimensions`: count of all dispatched dimensions (including UNRESOLVED)
|
||||
- `passed_dimensions`, `warn_dimensions`, `failed_dimensions`
|
||||
- `total_findings`, `blockers`, `majors`, `minors`, `infos`
|
||||
- `unresolved_dimensions`: count of UNRESOLVED
|
||||
|
||||
3. Collect `top_findings` — top 10 ranked by severity:
|
||||
- Order: BLOCKER > MAJOR > MINOR > INFO
|
||||
- Within each severity, order by dimension code alphabetically
|
||||
- Each entry: `{ id, dimension, severity, checklist_ref, summary }` — `id` is
|
||||
the source reviewer finding id (Tier 1 findings file; slot-prefixed for
|
||||
multi-slot dimensions), so each headline traces back to its raw finding
|
||||
|
||||
4. Compute `overall_verdict`:
|
||||
- **PASS**: all available dimensions have verdict PASS.
|
||||
- **WARN**: no FAIL dimensions AND no BLOCKER findings.
|
||||
- **FAIL**: any FAIL dimension OR any BLOCKER finding.
|
||||
|
||||
5. Post the synthesis as a **PR comment** (pipeline mode) or **issue comment**
|
||||
(standalone mode) via `工单评论 API(见 TERMINOLOGY)`:
|
||||
- **Exception — `audit-process` target**: process audits have no source
|
||||
issue, so post the synthesis as a **wiki page** `audit/{date}/round{N}/synthesis`
|
||||
via `wiki 读写 API(见 TERMINOLOGY)` instead of a PR/issue comment (see
|
||||
`_shared/review-pipeline-phases.md` Phase B step 3 and review-artifact/SKILL.md
|
||||
process target Output Artifacts). The commit-status `target_url` then
|
||||
carries that wiki page's `html_url`.
|
||||
- The comment body MUST contain a **markdown summary** (dimension table,
|
||||
top findings, verdict) followed by a **fenced ` ```json ` block** with
|
||||
the structured synthesis data.
|
||||
- Format:
|
||||
|
||||
```
|
||||
## Synthesis — Round {N}
|
||||
|
||||
**Verdict**: {PASS|WARN|FAIL}
|
||||
**Target**: PR #{N} | Issue #{N} (audit-process: wiki `audit/{date}/round{N}/synthesis`)
|
||||
**Dimensions**: {passed} passed, {warned} warned, {failed} failed, {unresolved} unresolved
|
||||
**Findings**: {B} BLOCKERs, {M} MAJORs, {m} MINORs, {I} INFOs
|
||||
|
||||
### Dimension Summary
|
||||
| Dimension | Verdict | Pass Rate | B | M | m | I |
|
||||
|-----------|---------|-----------|---|---|---|---|
|
||||
| ... | ... | ... | | | | |
|
||||
|
||||
### Top Findings
|
||||
1. [{DIM_CODE}] [{SEVERITY}] {checklist_ref}: {summary}
|
||||
2. ...
|
||||
|
||||
```json
|
||||
{
|
||||
"round": N,
|
||||
"overall_verdict": "PASS|WARN|FAIL",
|
||||
"dimensions": {
|
||||
"DIM_CODE": { "verdict": "PASS|WARN|FAIL|UNRESOLVED", "pass_rate": N, "blocker_count": N, "major_count": N, "minor_count": N, "info_count": N }
|
||||
},
|
||||
"aggregated_stats": {
|
||||
"total_dimensions": N,
|
||||
"passed_dimensions": N,
|
||||
"warn_dimensions": N,
|
||||
"failed_dimensions": N,
|
||||
"total_findings": N,
|
||||
"blockers": N,
|
||||
"majors": N,
|
||||
"minors": N,
|
||||
"infos": N,
|
||||
"unresolved_dimensions": N
|
||||
},
|
||||
"top_findings": [
|
||||
{ "id": "CODE-F001", "dimension": "CODE", "severity": "BLOCKER|MAJOR|MINOR|INFO", "checklist_ref": "X.Y", "summary": "..." }
|
||||
]
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
6. Post a **commit status** via REST:
|
||||
|
||||
```
|
||||
POST /api/v1/repos/Octopus/octopus/statuses/{SHA}
|
||||
Authorization: token {GITEA_TOKEN}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"state": "success"|"failure",
|
||||
"context": "pipeline/{REVIEW_TYPE}",
|
||||
"description": "Round {N}: {PASS|WARN|FAIL} — {passed}/{total} dims passed, {B}B {M}M",
|
||||
"target_url": "{link to synthesis comment}"
|
||||
}
|
||||
```
|
||||
|
||||
- `state` is `"success"` for PASS or WARN, `"failure"` for FAIL (any BLOCKER).
|
||||
- `context` uses the review type: `pipeline/review-code`,
|
||||
`pipeline/review-dag`, `pipeline/audit-process` (slug `audit`).
|
||||
|
||||
(See `_shared/gitea-write-patterns.md` Pattern 8 for the full commit-status recipe.)
|
||||
|
||||
7. Append 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`, and update the file's
|
||||
top-level `current_round` to this round number. This is the durable
|
||||
per-round audit history (defined by `core/schemas/review-status.schema.json`
|
||||
`history[]`; mirrors the audit-process checklist TRC 10.4). Initialization is the **Orchestrator**'s
|
||||
job (Phase A step 0.5 of `_shared/review-pipeline-phases.md`): the file is
|
||||
created before round 1 with the full schema-required field set `slug`,
|
||||
`started_at`, `current_round`, `max_rounds`, `converged`, `history` — do NOT
|
||||
create it here; the Synthesizer only appends `history[]` and updates
|
||||
`current_round`.
|
||||
|
||||
8. **Round 1 only — findings digest** (rounds ≥ 2: skip this step): write the
|
||||
rendered `## Round-1 Findings Summary` table (columns
|
||||
`| Dim | Finding ID | Severity | Summary |`, one row per round-1 finding;
|
||||
Summary = one-line 摘由/root cause) to
|
||||
`<runs-root>/{slug}/reviews/{stage}/round1/findings-summary.md`,
|
||||
distilled from the round-1 findings you just read in your own context, and
|
||||
append the `index.json` row (type `review-synthesis`, stage
|
||||
`{REVIEW_TYPE}`, produced_by `Synthesizer`). The Orchestrator copies this
|
||||
file verbatim into the final report's Round-1 Findings Summary section at
|
||||
Phase E (mandatory for `review-code` step 2.55; other targets MAY include
|
||||
it — `_shared/review-final-report-template.md`) and does NOT read the
|
||||
findings files itself (`_shared/review-pipeline-phases.md` Phase B step 3
|
||||
"Round-1 findings digest").
|
||||
|
||||
9. Persist your return summary (the exact text from the Return Format
|
||||
below) to `<runs-root>/{slug}/reviews/{stage}/round{N}/synthesis-return.md`
|
||||
(Tier 1) as your LAST action, BEFORE returning it — worker-report
|
||||
persistence ([org-internal #2847], `_shared/worker-report-persistence.md`). The persisted
|
||||
copy is the report of record; if your completion notification is lost, the
|
||||
Orchestrator recovers the round verdict from this file.
|
||||
|
||||
## Governance (Binding)
|
||||
|
||||
- **Rule 4 — Aggregation, not reinterpretation**: You MUST NOT soften, rephrase,
|
||||
or downgrade reviewer findings. If a reviewer writes "BLOCKER", it stays
|
||||
"BLOCKER" in synthesis.
|
||||
- **Rule 5 — Anonymous findings preservation**: If two reviewers independently
|
||||
flag the same issue from different dimensions, preserve both entries. Do not
|
||||
deduplicate by discarding one — cross-dimension agreement is itself a signal.
|
||||
- **Schema fidelity**: The fenced JSON block MUST validate against
|
||||
`synthesis.schema.json`. Read the schema file first if unsure of field names.
|
||||
|
||||
## Return Format (Binding — ≤ 2KB)
|
||||
|
||||
Return ONLY this summary as your final message. Do NOT include the full
|
||||
synthesis JSON — it is already posted to the pipeline PR / source issue
|
||||
comment (for audit-process runs, the wiki page `audit/{date}/round{N}/synthesis`).
|
||||
Persist this summary verbatim to
|
||||
`<runs-root>/{slug}/reviews/{stage}/round{N}/synthesis-return.md` before
|
||||
returning (step 9 above — worker-report persistence [org-internal #2847]).
|
||||
|
||||
```
|
||||
## Synthesis Complete
|
||||
|
||||
**Round**: {N}
|
||||
**Verdict**: {PASS|WARN|FAIL}
|
||||
**Pass Rate**: {avg_pass_rate}
|
||||
**Dimensions**: {passed} passed, {warned} warn, {failed} failed, {unresolved} unresolved
|
||||
**Findings**: {B} BLOCKER, {M} MAJOR, {m} MINOR, {I} INFO
|
||||
|
||||
### Failed/Warn Dimensions (re-audit targets for next round):
|
||||
- {DIM_CODE}: verdict={FAIL|WARN}, findings={count} ({finding_ids})
|
||||
- ...
|
||||
|
||||
### Top Findings (for revision task):
|
||||
1. [{DIM_CODE}] [{SEVERITY}] {checklist_ref}: {summary}
|
||||
2. ...
|
||||
|
||||
### Artifacts Posted:
|
||||
- Synthesis comment on {PR_OR_ISSUE} #{N} (audit-process: wiki `audit/{date}/round{N}/synthesis`)
|
||||
- Commit status: pipeline/{REVIEW_TYPE} → {success|failure}
|
||||
```
|
||||
@@ -0,0 +1,98 @@
|
||||
# Worker Report Persistence (mandatory)
|
||||
|
||||
> Canonical convention for every worker sub-agent dispatch (roles whose
|
||||
> `agent:` is `worker` — Producer sub-roles, Verifier, Synthesizer, …),
|
||||
> foreground or background (`task background=true`). Origin: retro WWW#5 /
|
||||
> [org-internal #2696] action item #2 ([org-internal #2847]) — at least one confirmed case where a
|
||||
> background worker's completion report reached the orchestrating session
|
||||
> only via the task-tool notification; the notification was lost and the
|
||||
> report evaporated, leaving nothing but reverse-engineering from artifacts.
|
||||
|
||||
## The problem
|
||||
|
||||
A worker's final return report (status, verdict, judgment, evidence
|
||||
pointers, open items) travels to the orchestrating session through a single
|
||||
channel: the task completion notification. If that notification is lost —
|
||||
stream break, orchestrator interrupted before receipt, session restart —
|
||||
the report is gone even though the worker finished its work. Conclusions
|
||||
that exist only in a notification are not durable.
|
||||
|
||||
## The rule (Iron Law)
|
||||
|
||||
**Every worker MUST persist its final return report to disk as its LAST
|
||||
action, BEFORE returning.** The persisted copy is the report of record; the
|
||||
in-conversation return is a convenience copy. No worker return may exist
|
||||
only in the task notification.
|
||||
|
||||
## Where to persist (path selection, in order)
|
||||
|
||||
1. **Tier 1 run workspace (preferred when it exists)** — if
|
||||
`.octopus/runs/{slug}/` exists (see `.octopus/templates/runs-layout.md`),
|
||||
write the report to:
|
||||
- Default: `.octopus/runs/{slug}/workers/{chunk-id}-worker-{seq}.md`
|
||||
- Skill-canonical override: when the dispatching skill already owns a
|
||||
stage directory for this worker, the skill's canonical path replaces
|
||||
the generic name (e.g. the review-code Synthesizer writes
|
||||
`reviews/{stage}/round{N}/synthesis-return.md` next to its task file).
|
||||
- Register one `index.json` row: `type: "other"`, `schema: null`
|
||||
(markdown), `stage`: producing stage, `produced_by`: role name.
|
||||
2. **Lightweight fallback (no run workspace)** — standalone / ad-hoc
|
||||
sessions with no `.octopus/runs/{slug}/`: write to
|
||||
`/tmp/octopus/{chunk-id}-worker-{seq}.md`. Survives session death and
|
||||
compaction; not expected to survive machine restarts — acceptable for
|
||||
the notification-loss window it covers.
|
||||
|
||||
### Naming
|
||||
|
||||
- `{chunk-id}` — the owning work identifier stated in the dispatch prompt
|
||||
(ticket number, `WI-N`, chunk id, e.g. `2847`, `WI-3`).
|
||||
- `{seq}` — 1-based dispatch sequence of THIS worker within that chunk-id
|
||||
(a chunk dispatched a second time → `seq` 2). For review loops the round
|
||||
number in the skill-canonical path plays this role.
|
||||
- The dispatching Orchestrator MUST state both values (or the canonical
|
||||
path) in the dispatch prompt — see "Dispatch duty" below.
|
||||
|
||||
## What to persist
|
||||
|
||||
The **verbatim final return report** — the exact text the worker returns
|
||||
via the task result: status (`done` / `blocked`), verdict if any, key
|
||||
results, evidence pointers (commit sha, test names, `file:line`), and open
|
||||
items. Markdown, no schema. Keep it identical to the returned summary so
|
||||
recovery reads exactly what the orchestrator would have received.
|
||||
|
||||
## Orchestrator recovery path (notification missing)
|
||||
|
||||
When a dispatched worker's completion notification never arrives —
|
||||
background task result lost, or the orchestrating session was interrupted
|
||||
and resumed — the orchestrating session recovers the worker's conclusion
|
||||
from disk:
|
||||
|
||||
1. Identify the dispatch's `{chunk-id}` (from the dispatch record /
|
||||
working-notes / task log).
|
||||
2. Read, in order, the newest match by `{seq}` / mtime:
|
||||
- `.octopus/runs/{slug}/workers/{chunk-id}-worker-*.md`
|
||||
- the skill-canonical return file when the dispatch named one (e.g.
|
||||
`reviews/{stage}/round{N}/synthesis-return.md`)
|
||||
- `/tmp/octopus/{chunk-id}-worker-*.md`
|
||||
3. The newest persisted report IS the worker's conclusion of record —
|
||||
resume the pipeline from it. Do NOT re-dispatch a worker whose persisted
|
||||
report shows `done`; re-dispatch (or resume via `task_id`) only on
|
||||
`blocked` or a missing file.
|
||||
|
||||
## Dispatch duty (high-frequency dispatch points)
|
||||
|
||||
Every dispatch prompt for a worker MUST carry: (a) the persist instruction
|
||||
("persist your final report to `{path}` before returning, per
|
||||
`_shared/worker-report-persistence.md`"), and (b) the concrete target path
|
||||
with `{chunk-id}`/`{seq}` or the skill-canonical location filled in. The
|
||||
high-frequency templates carry it inline:
|
||||
|
||||
- `implement/SKILL.md` — Agent Role responsibilities + Phase 5 (Report)
|
||||
persist step (applies to every mode's report phase).
|
||||
- `review-code/SKILL.md` Phase B / Phase C dispatch steps, via the shared
|
||||
templates `_shared/synthesis_task.md` and
|
||||
`_shared/review-revision-prompt.md`.
|
||||
|
||||
Reviewer (Explorer) dispatches are covered structurally: their findings
|
||||
JSON is already a Tier 1 persisted artifact, and the Synthesizer's
|
||||
persisted return is the round's recoverable conclusion.
|
||||
Reference in New Issue
Block a user