ELNOR REPO READER TEXT MIRROR Original path: Active Working and Red Team/DOC23 Working/DOC23 Non Operative Proposals/DOC23 Add B Review Studio D1.md Source repo: /Users/OpenClaw1/Elnor/Elnor Specs Git branch: main Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331 Generated: 2026-06-09T01:23:58.539Z --- ```` # DOC23 Addenda B — Review Studio (Human Review & Agent-Assisted Revision) **Type:** Design spec unit (draft, pending architect review + multi-LLM red-team). **Target home:** `Current Specs/DOC23/DOC23 Addenda B/` (new module). Liftable into the consolidated adjudication card as a section; the card otherwise carries a one-line pointer. **Module type id:** `step.review_studio` **Status of dependencies:** A-01 finding model (event/record/view + `EvaluationAuthorityBasis`) is summarized in §2 at the level Review Studio relies on; its full adjudication remains a card Layer-1 item. The Gemini math/C-cluster audit is unrelated and remains a card row. **Grounding rule (no phantom features):** every contract below traces to a cited section in DOC23 R3.1, Outcome Evaluator-Revisor V3.3.1, DOC20 R4.3, or DOC23 Addenda B Core R0.7.1 — or is explicitly flagged `OPEN_FOR_ARCHITECT_REVIEW`. Citations are inline. Appendix B is the consolidated operative-vs-net-new log. --- ## 0. Scope and non-goals ### 0.1 In scope - The `step.review_studio` module (placeable form) and the intrinsic evaluate-revise gate (policy-toggled form). - The complete human-review **input model** (`HumanReviewResult`, defined as a superset of DOC20's `DocumentReviewRequest`). - **Materialization** of human comments into lifecycle-tracked objects (findings / run-scoped criteria) so they resurface across re-evaluation. - The **agent-collaboration** layer: session continuity to the producing agent + the agent-selection ladder + agent-assisted in-place revision. - The **output/routing** model and how it decomposes into the existing Feedback Interpreter pipeline (V3.3.1 §14). - **Versioning / provenance / revalidation** wiring for human and co-authored edits. - The **exposure** primitives: `LifecycleActorEnvelope`, the per-owner read contract, the gated (reserved) write capability. ### 0.2 Non-goals (explicit `slice.negative_space`) - **NOT** redoing the automated Revisor's graph orchestration (V3.3.1 §6–§11). Review Studio does not plan or dispatch across the task graph (§1.2). - **NOT** rewriting DOC20 UI mechanics beyond the review surface. DOC20-owned changes are collected, clearly labeled and liftable, in Appendix A. UI here is specified to **mockup-ready** depth (contracts tight, UI light). - **NOT** building the Human-Review→Orchestrator engine or the review-gate learning-reasoner. Both are reserved (§11). - This unit does **not** touch the memory-spec flatten. DOC23 is outside the flatten scope (Flatten plan §1.2); findings/comments/revisions remain DOC23/DOC20-owned task-system truth, not memory-system truth. --- ## 1. The module, and the boundary against the automated Revisor ### 1.1 One paragraph Review Studio is a task-graph checkpoint where the human (a) reviews an output, (b) optionally **collaborates with the agent that produced it** — its working session resumed — to revise the artifact **in place** or get advice, and (c) **routes** the (possibly revised) version onward. It is the interactive, collaborative form of the current `step.user_review_gate` (DOC23 R3.1 §3.2.3): same "pause the run, human decides" spine, but with the DOC20 Document Viewer as the review surface and an agent-assist channel attached. ### 1.2 Boundary vs the automated Revisor (load-bearing — prevents two orchestrators) | | Automated Revisor (V3.3.1 §6–§11) | Review Studio (this unit) | |---|---|---| | Driver | Agent-automated | Human-driven, agent-assisted | | Operates on | The **task graph** (re-runs modules, escalates to Task Agent §6.9, forks) | **One artifact, in place** | | Trigger | Findings / outcomes (revalidation cascade) | Human at a checkpoint | | Output | Repaired graph state + new artifact version | Revised artifact version + a routing decision | | Orchestration | Yes (RevisionPlan, RevisionDispatcher §11.1) | **No** — it co-edits one output, then hands off | They **compose**: Review Studio's revised version can be routed into the automated loop, and the automated loop's output can land at a Review Studio checkpoint. The agent-assist inside Review Studio is a **scoped single-artifact edit** the human directs (the producing agent makes the changes), producing a new co-authored version — it is explicitly *not* a graph redo. This boundary is the reason the two do not collide. ### 1.3 Relationship to the other checkpoints Review Studio is the **human-driven** checkpoint; it does not replace the other DOC23 review constructs: - `step.agent_review_gate` (R3.1 §3.2.4) remains the **agent-reviews-agent** checkpoint. - `step.panel` (R3.1 §3.2.5), a pointer to a DOC12 room, is the **forum** rung of the assist ladder (§6.1), used for multi-agent collaborative review. - The `human_review_gate` experiment-winner **routing disposition** (Addenda A R227) opens a Review Studio surface when an experiment routes to human review. --- ## 2. Foundational dependency — the finding model (A-01), as relied on here Review Studio renders Evaluator findings as anchored comments and lets the human dispose them; it also creates human-authored findings. It therefore depends on the A-01 finding model. The elements relied on (full definition and adjudication: card Layer 1): ```ts // Immutable audit record of a finding as first observed in a given evaluation round. interface EvaluationFindingEvent { finding_event_id: string outcome_id: string target_artifact_ref: string target_version_ref: string // findings are version-pinned (V3.3.1 §5.7) target_scope_ref: TargetScopeRef | null // the anchor; maps to a DOC20 CommentAnchor (§3.6) detected_at: string severity: FindingSeverity // IMPORTANCE, never a halt (§2.1) assurance_basis: AssuranceBasis[] // how much trust the finding carries authority_basis: EvaluationAuthorityBasis[] // who/what authorizes it (9-value FD enum) body: string schema_version: 1 } // Mutable lifecycle row keyed to the event; carries current state. interface EvaluationFindingRecord { finding_id: string origin_event_id: string state: FindingState // V3.3.1 §5.7 / §0.4.4 target_version_ref: string actor: LifecycleActorEnvelope // §9.1 — who created/last-changed it superseded_by_finding_id: string | null resolved_by_receipt_ref: string | null // only Revisor receipts mark `resolved` (§5.7.2) schema_version: 1 } // Read-only projection the UI renders (the "copy"). No new truth store. interface FeedbackFindingView { finding_id: string display_state: FindingState anchor: TargetScopeRef | null severity: FindingSeverity body: string history: FindingStateTransition[] // per-round snapshots → cross-round drift view schema_version: 1 } ``` ### 2.1 Severity is importance, not a halt (propagated decision) `FindingSeverity` drives revision priority and human-review surfacing. It **never halts** the run. Only mechanical/system errors halt execution (`StepExecutionFailureKind`, DOC23 R3.1). An output is not auto-"passed" while serious findings are unresolved; it stays in the revision loop, and if unresolvable the termination logic (V3.3.1 §6.7.3) **escalates** (Gate-4 human review or "rely with limitations") rather than halting. Irreversible external actions (filing, sending) remain gated by an action permission — that is an action gate, not a finding block. --- ## 3. Input model — everything the user can submit at a Review Studio checkpoint ### 3.1 Complete input taxonomy (grounded in the current modules) From the DOC23 gate (R3.1 §3.2.3 / §6.5.4) and the DOC20 review surface (§6.6.2, §6.10.4, §6.16.8): 1. **Decision** — Approve / Reject / Revise (incl. email APPROVE/REJECT/REVISE). [DOC23 §3.2.3] 2. **Rejection reason** (free text). [DOC23 §6.5.4] 3. **General instruction** (free text). [DOC23 textarea; DOC20 Send-to-Agent `instruction`] 4. **Attachments** (FileRef[]). [DOC23 revision payload; DOC20 §7.18] 5. **Anchored in-line comment** — `CommentAnchor` (text/page/line) + body + threaded replies. [DOC20 §6.6.2/§6.6.3] 6. **General / unanchored comment** — `UnanchoredAnchor`. [DOC20 §6.6.2] 7. **Comment status change** — open/resolved/deleted. [DOC20 §6.6.2] 8. **Per-tracked-change accept/reject** (+ Accept/Reject All). [DOC20 §6.10.4/§6.10.5] 9. **Direct document edit** → new version. [DOC20 §6.16.9/§6.16.11] 10. **Per-finding disposition** — Accept / Reject / Reject-with-modification + comment (this unit, built on DOC20 comment affordances + A-01). 11. **Send-to-Agent controls** — `context_scope`, `output_mode` (respond_in_chat | send_with_instructions), `result_format` (revise_artifact | convert_to_note | respond_in_comments), `agent_id`, `chat_id`. [DOC20 §6.16.8] ### 3.2 `HumanReviewResult` — defined as a superset of DOC20 `DocumentReviewRequest` DOC20 already owns the human-review→agent request/response contract (`DocumentReviewRequest` / `DocumentReviewResultEvent`, §6.16.8). Review Studio does **not** create a parallel request schema; it **extends** that contract with the evaluate-loop layer. (Owner-boundary note → OP-A, §12.) ```ts // Reuses DOC20 DocumentReviewRequest fields (agent_id, chat_id, context_scope, // selected_comment_ids, comments[], instruction, output_mode, result_format) // and adds the evaluate-loop fields below. interface HumanReviewResult extends DocumentReviewRequest { review_id: string task_id: string run_id: string gate_id: string // placeable module id OR intrinsic gate id (§4) // --- interaction axis (ADD #1; closes the advise-vs-revise gap) --- interaction_mode: "revise" | "advise" // advise = no document mutation; answer in chat/comments // --- top-level decision (only meaningful for interaction_mode = "revise") --- decision: "approve" | "send_for_revision" | "reject" // terminal; see §5.4 action model rejection_reason: string | null // + honors DOC23 on_reject_action (pause|redirect|abort) redirect_target_ref: string | null // when on_reject_action = redirect (R3.1 §3.2.3) // --- structured dispositions --- finding_dispositions: FindingDisposition[] // per-finding accept/reject/modify + comment + anchor general_directives: GeneralDirective[] // unanchored comments/instructions → run-scoped criteria tracked_change_dispositions: TrackedChangeDisposition[] | null // ADD #5 (signal of which Revisor edits were rejected) // --- artifact + provenance --- reviewed_artifact_version_ref: string // NEW version if edited, else the reviewed version artifact_edited_by_human: boolean edit_provenance: "none" | "human_direct" | "human_directed_agent" // co-authored when agent assisted (§6.3) // --- routing + follow-up --- routing: ReviewRoutingDecision // §7 requested_followup: FollowupIntent[] | null // multi-step intent captured as data (reserved engine, §11) // --- attachments (ADD #6) --- attachments: AttachmentRef[] // review-global; per-disposition attachments live on the disposition actor: LifecycleActorEnvelope // §9.1 ui_source: ReviewUiSource // ADD #8 created_at: string schema_version: 1 } type ReviewUiSource = // extends DOC20/V3.3.1 ui_source enums | "review_studio_card" | "document_viewer" | "email_reply" | "api" interface FindingDisposition { finding_id: string | null // null => a NEW anchored comment that becomes a finding (§3.5) anchor: TargetScopeRef | null // DOC20 CommentAnchor (§3.6) disposition: "accept" | "reject" | "reject_with_modification" comment: string | null // the modification / rationale authority_class: HumanFeedbackAuthorityClass // V3.3.1 §14.6 (controlling vs advisory) research_request: ResearchNeedRef | null // optional (Grok §5.9 import) attachments: AttachmentRef[] | null } interface GeneralDirective { directive_id: string text: string scope: "this_artifact_goal" | "this_outcome" | "this_run" authority_class: HumanFeedbackAuthorityClass attachments: AttachmentRef[] | null } interface TrackedChangeDisposition { // DOC20 §6.10.5 produces tracked_change_accept/reject change_id: string decision: "accept" | "reject" } ``` ### 3.3 `requested_result_format` (ADD #2) The DOC20 `result_format` field (`revise_artifact` | `convert_to_note` | `respond_in_comments`) sets the downstream output contract. It is carried on `HumanReviewResult` (inherited from `DocumentReviewRequest`) and is authoritative for what the assisting agent returns. `respond_in_comments` / `respond_in_chat` imply `interaction_mode = "advise"`. ### 3.4 `context_scope` and agent/chat targeting (ADD #3, #4) `context_scope` (`full` | `comments_only` | `selected_comments`) and `agent_id` / `chat_id` are inherited from `DocumentReviewRequest`. `agent_id` lets the human **re-target** which agent handles the assist — this is the user-facing override of the routing in §6. Default resolution is the producing agent's session (§6.2). **Channel limits:** the email-reply channel (R3.1 §3.2.3) carries only the coarse decision (APPROVE/REJECT/REVISE) plus free-text revision and attachments; anchored per-finding dispositions and in-place edits require the Document Viewer surface (§5). ### 3.5 Materialization — the mechanism that makes comments persist across re-evaluation The Feedback Interpreter (V3.3.1 §14.3) is a one-shot intake service; resurfacing comes from the **finding/outcome lifecycle**, not from the Interpreter. Review Studio therefore materializes inputs into lifecycle objects at intake: - **Anchored comment / per-finding modification → a human-authored `EvaluationFindingEvent`** (`assurance_basis` includes `human_label`; `target_version_ref` pinned; `target_scope_ref` = the anchor). It then rides `findings_to_address` (V3.3.1 §7.1), the Revision Compiler routes it to a module (§6.4), and the finding lifecycle resurfaces it every re-evaluation until `resolved` / `superseded_by_revision` / `unrecoverable` (§5.7). Finding creation by a human actor is authorized via §9.1 (`author_kind = "human"`). - **General directive → a run-scoped `Criterion`** on the run's `EvaluationOutcomeDefinition` (V3.3.1 §5.1.1), minted by the Outcome Compiler from the directive text. The Evaluator then re-checks it on every re-evaluation, version-independently, until satisfied; a failing criterion yields a finding (outcome-level, `target_criterion_id = null`) that routes like any other. Extend `InterpretedOutcomeFeedback` (V3.3.1 §14.3.1) output accordingly: ```ts interface InterpretedOutcomeFeedback { // existing: proposed_revision_request?: RevisionRequest // V3.3.1 §14.4 (current run) proposed_durable_candidate?: DirectInstructionCandidate // V3.3.1 §14.7 (teaching) // ADD: proposed_findings?: EvaluationFindingEvent[] // span corrections (anchored) proposed_run_criteria?: RunScopedCriterion[] // goal corrections (general) } ``` #### 3.5.1 Governance guardrails on run-scoped criteria - Human-authored, **scoped to this run only** — never raises the pass bar for any other run. - **Inspector-visible** with provenance ("added from your review comment"). - Outcome-set mutation in the revision path is already contemplated (`added_outcome_id`, V3.3.1 §11 status model), so this is not a foreign construct. ### 3.6 Comment ↔ finding reconciliation (ADD #7) - A finding's `target_scope_ref` maps onto a DOC20 `CommentAnchor` (text/page/line/unanchored). Click-finding→highlight is the existing click-comment→highlight behavior (DOC20 §6.6.7). - Map comment-status ↔ finding-state: DOC20 `orphaned` ↔ A-01 `superseded_by_revision`; `resolved` ↔ the finding's resolved/dismissed state. The conversational thread (DOC20 §6.6.3, event-sourced) stays DOC20-owned; dispositions carry `thread_root_id` so the exchange is linked, not duplicated. --- ## 4. The hybrid gate — placeable module + intrinsic loop gate ### 4.1 Placeable module `step.review_studio` A drop-in checkpoint for arbitrary points in a graph. Superset of `step.user_review_gate` (R3.1 §3.2.3). ``` Config (adds to user_review_gate config): review_instructions: string surface: "review_studio" // opens the DOC20 Document Viewer in review mode (§5) load_findings: boolean // load Evaluator findings as anchored finding-comments allow_agent_assist: boolean // enable the collaboration channel (§6); default true default_assist_target: "producing_agent" | "task_agent" | "none" // default producing_agent (§6.2) interaction_modes_allowed: ("revise" | "advise")[] // default both on_reject_action: "pause" | "redirect" | "abort" // R3.1 §3.2.3 redirect_target / max_redirects / max_revisions // R3.1 §3.2.3 revision_delivery: "wired_target" | "to_revisor" | "to_producing_module" | "auto_previous" | "smart" Ports: data_in (Input) — content to review findings_in (Input, optional) — A-01 finding views; presence => load as finding-comments plan_in (Input, optional) — a Revisor RevisionPlan; presence => plan-review layout approved_out (Output) — fires with the (possibly revised) version on Approve / proceed rejected_out (Output) — fires with rejection_reason + payload revision_out (Output) — fires with the full HumanReviewResult (decomposed downstream, §7) feedback_out (Output, optional) — teaching feedback (HumanOutcomeFeedbackEvent) only signal_out (Output) — "decision made" (fires regardless) error_out (Output) — notification-delivery failure only ``` Typed `findings_in` / `plan_in` make the graph self-documenting and let the surface adapt (§5.2). ### 4.2 Intrinsic gate (no wiring, no Loop Controller) The evaluate-revise loop raises a Review Studio gate automatically at its natural points, toggled by per-task/outcome policy — same Review Card, no module wiring, and **no Loop Controller** (avoids the R3.1 §6.2 re-activation wart, since the loop owns re-activation): ```ts type IntrinsicGatePoint = | "post_evaluation" // after Evaluator, BEFORE Revisor plans (findings review) | "post_revision_plan" // review the Revisor's plan before execution | "post_revision_exec" // review a produced revision | "pre_final_acceptance" // final-pass review before reliance interface IntrinsicReviewGatePolicy { enabled_points: IntrinsicGatePoint[] // defaults: post_evaluation/plan/exec OFF; pre_final_acceptance ON (Gate-4) default_assist_target: "producing_agent" | "task_agent" | "none" schema_version: 1 } ``` Timing correction: findings review is **after the Evaluator / before the Revisor**, not "when the task finishes." --- ## 5. The review surface (review mode over the DOC20 Document Viewer) ### 5.1 Reuse, don't rebuild The gate opens the **DOC20 Document Viewer** (§6.16) in a `doc` tab in "review mode" rather than rendering a minimal Review Card body. This reuses the Word (mammoth.js), PDF (PDF.js), Markdown/code renderers, the tabbed right panel `[Comments][Send to Agent]` (§6.16.6/§6.16.8), anchored comments (§6.6.2), tracked changes (§6.10), and Convert-to-Note editing (§6.16.9). Findings load into the Comments panel as a **`finding` comment kind**, anchored via `target_scope_ref` → `CommentAnchor`. The legacy Review Card (R3.1 §13.9) remains the lightweight fallback for text-only review. ### 5.2 Surface adapts to inputs (per the typed ports, §4.1) | Inputs present | Surface | |---|---| | `data_in` only | Document preview; Comments panel empty/closed | | `data_in` + `findings_in` | Findings as anchored finding-comments; per-finding actions (§5.3) | | `findings_in`, no doc focus | Finding list / chat-style review | | `plan_in` | Plan-review layout: plan steps as side-panel items with approve / drop / modify | `RendererCapabilities` (DOC20) hides actions a renderer cannot support (e.g., inline editing on a preview-only DOCX). UI depth here is **mockup-ready**; pixel/interaction detail and all new DOC20 surfaces are in Appendix A. ### 5.3 Per-finding actions Accept / Reject / Reject-with-modification, each with an optional comment box (Word-comment ergonomics). Maps to `FindingDisposition` (§3.2). Reject-with-modification supplies the corrective instruction that the assist agent or Revisor consumes. ### 5.4 Action model — three layers, and what "Revise" means Actions at the surface fall into three distinct layers; conflating them is what made "Revise" ambiguous. **Layer 1 — Per-finding / per-comment actions** (Comments panel): Accept / Reject / Reject-with-modification + comment (§5.3). These dispose individual items; they do not end the checkpoint. **Layer 2 — In-Studio collaboration** (chat / assist / edit), which loops and does **not** end the checkpoint: - **Discuss** — advise mode (`interaction_mode = "advise"`): ask the assist agent, no document mutation. - **Revise with Agent** — the agent edits the artifact in place (`AssistRevisionRequest`, §6.3) -> new version, addressing your comments/instructions **here, now**. - **Edit** — you edit directly -> new version (§8.1). **Layer 3 — Terminal decision** (ends the checkpoint, fires a port + routing, §7.1): **Approve / Proceed**, **Send for Revision**, **Reject**. **The two meanings of "revise":** the terminal **Send for Revision** routes the artifact **plus your dispositions/directives** to a revision *target* (Revisor / producing module / wired target / next step) to be addressed *elsewhere* — the original `revision_out` semantics, with your comments/instructions as the payload. Layer-2 **Revise with Agent** addresses the same comments/instructions *in place*. Both "address comments and instructions"; the difference is **where**. **After an in-place revision** no new terminal button is needed — Approve/Proceed, Send for Revision, Reject still cover "what next." Refinements: the **Approve** label is context-aware ("Approve" for review-only; "Accept revision & continue" after an in-place revision); **Send for Revision** carries a target picker (next step · Revisor · specific module · Task Agent · forum). The genuinely new controls are the Layer-2 affordances (Discuss / Revise with Agent / Edit) — what was missing, not a fourth terminal button. --- ## 6. Agent collaboration — session continuity and the agent-selection ladder ### 6.1 The ladder (all rungs map to operative primitives) | Rung | Mechanism | Citation | |---|---|---| | Producing agent, **same session** (default) | Module session continuation via `TaskModuleSessionRef` + `session_persist` | Core R0.7.1 §3170/§3449/§10363; Reprompt §7.1 → Addenda A §A9 | | Producing agent, **new scoped thread** | Module follow-up session (`followup_session_id`) | Core R0.7.1 §261/§9397 | | **Another module's** agent | Select by `module_ref` → its session | Core R0.7.1 §10363 | | **Task Agent** | Task Agent contextual side-panel chat (task/run/module/artifact scope, attachments) | Core R0.7.1 §260/§9604 | | **Forum** | DOC12 room (Plan Review Forum / role-scoped critique) | V3.3.1 §14.9 | | **Branch the run** | `TaskRunFork` | Core R0.7.1 §8622 | ### 6.2 Default target resolution The default assist target is the **producing agent, session resumed**, resolved from the artifact's provenance: the module/run that produced `reviewed_artifact_version_ref` → its `TaskModuleSessionRef`. The picker's candidate list = "agents involved in this task" (derivable from the run graph) + Task Agent + forum, with the producer pre-selected. `agent_id` on `HumanReviewResult` (§3.4) is the explicit override. If the producing module is not an agent (a deterministic module) or has no resumable session, the default falls back to the Task Agent — or to `none` (review-only) when `allow_agent_assist = false`. ### 6.3 Agent-assisted in-place revision (the scoped op) When the human asks the assist agent to make a change, the agent — its session resumed so it knows how the output was produced — edits **this artifact only** as directed, producing a new version with `edit_provenance = "human_directed_agent"` and a co-authored `LifecycleActorEnvelope` (`author_kind = "module"`, with the directing human recorded). This is **not** the automated Revisor's graph plan (§1.2); it is a single-artifact edit. The resulting version triggers the same revalidation cascade as a human edit (§8.2). ```ts interface AssistRevisionRequest { // thin wrapper over DOC20 DocumentReviewRequest review_id: string assist_target: AssistTargetRef // resolved per §6.1/§6.2 session_ref: TaskModuleSessionRef | FollowupSessionRef | null // null => fresh session directive: string // the in-place change requested scope_ref: TargetScopeRef | null // optional span result_format: "revise_artifact" | "convert_to_note" | "respond_in_comments" schema_version: 1 } ``` ### 6.4 Operative vs net-new here Operative: session continuation/follow-up, Task Agent chat, fork, forum, and the `DocumentReviewRequest` request/response. Net-new: (a) defaulting the assist target to the producing agent's session; (b) the in-place assist op as a scoped single-artifact edit distinct from the Revisor; (c) the checkpoint chat UI — which the reprompt/chat/continuation addendum already proposes (ModuleActivationChat: inspect/advise/branch), so it slots in rather than starting cold. The architect has elected to **adopt** the ModuleActivationChat surface, so the checkpoint chat UI is in scope here; its detailed spec lands when that addendum is folded in (OBL-RS-08). ### 6.5 Assist result handling and iteration An assist action returns a DOC20 `DocumentReviewResultEvent` (disposition `revised_artifact` | `chat_response` | `note_created` | `comments_replied`, §6.16.8) **back to the review surface**, not straight onward: - `revised_artifact` / `note_created` -> a new version loaded into the viewer for the human to review. - `comments_replied` -> threaded replies appear under the relevant finding-comments. - `chat_response` -> answer in the chat (advise mode). The Studio session can **iterate** — discuss / revise / edit, review the result, repeat — bounded by `max_revisions` (R3.1 §3.2.3). Only when satisfied does the human take the Layer-3 terminal decision (§5.4). Each assist round is attributed via the `LifecycleActorEnvelope` (§9.1) and, when it mutates the artifact, emits a `human_authored_version_created` receipt that triggers revalidation (§8.2). --- ## 7. Output and routing ### 7.1 The routing decision After review (and any in-place revision), the human routes the (possibly revised) version: ```ts type ReviewRoutingDecision = // the terminal decision (one of three; see §5.4) | { kind: "approve" } // proceed with the current/revised version -> approved_out -> next step | { kind: "send_for_revision"; target_ref: string; via: RoutingVia } // route artifact + dispositions/directives to be addressed | { kind: "reject" } // honors on_reject_action (pause|redirect|abort) // NOTE: "advise" is NOT a terminal routing -- it is a session mode (interaction_mode, §3.2); // an advise-only session still terminates with approve / send_for_revision / reject. type RoutingVia = | "wired_target" | "to_revisor" | "to_producing_module" | "next_step" | "task_agent" | "forum" ``` ### 7.2 Decomposition into the existing Feedback Interpreter pipeline This is the **Tier-1 Human-Review -> Revisor path** (§11.1): in scope and buildable now (mostly wiring), and it already reaches multiple modules via the Revisor's `RepairTarget` routing and Task Agent escalation. `revision_out` carries the whole `HumanReviewResult`, but routing **decomposes** it into the existing V3.3.1 §14 pipeline rather than inventing new routing: - Each `FindingDisposition` and `GeneralDirective` → a `HumanOutcomeFeedbackEvent` (§14.2; targets optional, so un-pinned is supported) with the appropriate `authority_class` (§14.6: `current_run_instruction` = controlling vs `current_run_preference` = advisory). - The Feedback Interpreter (§14.3) parses these into a `proposed_revision_request` → Revisor (current run) and/or the materialized `proposed_findings` / `proposed_run_criteria` (§3.5). Routing of the request to the Revisor — including the no-current-plan and completed-plan cases — is the existing §14.4 rule. - **Teaching** feedback (improve the module, not this revision) → `feedback_out` only, as a `HumanOutcomeFeedbackEvent` with a durable authority class → `DirectInstructionCandidate` (§14.7). Kept separate from the revision path. - A human-edited or co-authored **version** is referenced forward (not re-sent); CIL/DOC15 auto-frames provenance to the next module ("continuation of task X, human-reviewed at a gate; here is the version + directives; revise"). Directives self-describe via their anchors. ### 7.3 Port behavior recap `approved_out` (proceed, with the revised version) · `rejected_out` (reason + payload, honoring `on_reject_action`) · `revision_out` (full `HumanReviewResult`, decomposed per §7.2) · `feedback_out` (teaching only) · `signal_out` · `error_out`. The intrinsic gate (§4.2) uses the same outputs internally without external wiring. --- ## 8. Versioning, provenance, and the revalidation trigger ### 8.1 Editing is version-creating and method-agnostic Any human edit (in-app tiptap/Convert-to-Note, DOC20 §6.16.9; or external native app) and any agent-assisted in-place edit (§6.3) produces a **new artifact version** with human / co-authored provenance; the prior version is preserved (DOC20 versions artifacts: `v{N}`, `artifacts_current.json` + events). The reference is sent forward. External-app editing builds on DOC20's "Open External" action: on external save, ingest as a new version. The editing **contract** is method-agnostic — however edited, the result is a new version referenced forward. ### 8.2 GAP/fix — a human (or co-authored) edit must trigger the revalidation cascade The revalidation cascade (V3.3.1 §11.21) and the dirty-flip (§10.5) are triggered by **revision-step** mutations only: `RevisionOperationReceipt` with `operation_kind in { candidate_version_accepted, direct_fix_applied, rollback_apply }` (`RevisionOperationKind`, §0.4.7). A human-authored version is **not** a revision step and emits none of these — so as specced, a human edit would not refresh findings, and the Revisor could plan against a stale version. **Fix (preferred — honest provenance):** add a `RevisionOperationKind` value `human_authored_version_created` and include it in the §11.21 trigger set. The review-gate edit path emits a `RevisionOperationReceipt` of that kind. The cascade then fires identically: dependent outcomes (declared via `OutcomeDependencySpec.declared_dependencies`, §11.21.1) → `dirty` → Evaluator re-runs against the human's version → findings whose target section no longer exists → `superseded_by_revision` (§5.7.1) → Revisor plans against the current version. **Zero-schema alternative (noted, not preferred):** model the human edit as a `CandidateArtifactVersion` that is immediately accepted, reusing `candidate_version_accepted`. It fires the cascade with no enum change but mislabels provenance ("candidate" = produced by revision, §0.4.5); rejected because this unit values truthful history. ### 8.3 `human_resolved` provenance (adopted) A finding a human resolves by editing (not deleting) does not acquire the `resolved` state — §5.7.2 reserves `resolved` for findings carried in a Revisor `RevisionExecutionReceipt.addressed_findings`, which a human edit does not produce. **Decision: adopt a distinct `human_resolved` provenance** so a human-fixed finding is attributed truthfully rather than silently superseded: - Add `human_resolved` to `FindingState` (or as a resolution-provenance facet on the resolved transition), set when re-evaluation against a human/co-authored version finds the targeted defect gone and a `human_authored_version_created` receipt (§8.2) is the cause. - Distinct from `superseded_by_revision` (the section changed/disappeared) and from Revisor-`resolved` (a `RevisionExecutionReceipt` addressed it). Carries the `LifecycleActorEnvelope` (§9.1) so authorship is explicit. --- ## 9. Exposure — multi-actor envelope, read contract, gated write ### 9.1 `LifecycleActorEnvelope` (the multi-actor primitive) Generalizes the existing per-object authorship (`comment.author`, `attachment.created_by`, tracked-change attribution) so a finding/comment/criterion/transition created by a human, an evaluator, the Revisor, a module, or the Task Agent is structurally identical, differing only in actor + authority. It is an extension of the converged `GovernanceEnvelope` Layer-1 mixin (card Layer 1). ```ts interface LifecycleActorEnvelope { author_kind: "human" | "evaluator" | "revisor" | "module" | "task_agent" author_ref: string // UserRef | ModuleRef | AgentRef on_behalf_of_ref: string | null // co-authored: directing human for author_kind="module" authority_class: HumanFeedbackAuthorityClass | ModuleAuthorityClass // V3.3.1 §14.6, extended basis: AssuranceBasis // human_label | model: | evaluator | ... taint_class: TaintClass // rides the object; consumers treat content as data policy_decision_ref: string // every WRITE is an EC PolicyDecision, not the actor's call schema_version: 1 } ``` ### 9.2 Per-owner READ contract (build now; first consumer is Review Studio itself) Expose the lifecycle as a **derived projection published by each owning subsystem** — DOC23 publishes finding/outcome/revision reads; DOC20 publishes comment/anchor reads — via the patterns already in use (cross-module query API, V3.3.1 §4.9.2; signal pub/sub, §14.8.4; derived read-models "derived, not invented," §11.1.1). ```ts interface LifecycleReadQuery { // pull; modeled on V3.3.1 §4.9.2 (read-only, no cross-mutation) by: "artifact" | "outcome" | "task" | "run" ref: string include: ("findings" | "comments" | "revisions" | "history")[] schema_version: 1 } // returns the existing view types (FeedbackFindingView, DOC20 comment views, // RevisionExecutionRecord/Summary), privilege/AccessTier-filtered (§16.6) under default-deny (§16.5). interface LifecycleEventSubscription { // push; over §14.8 signals + finding-state transitions events: ("finding_created" | "finding_resolved" | "finding_superseded" | "revision_applied" | "directive_raised" | "directive_satisfied")[] scope_ref: string schema_version: 1 } ``` Read guardrails: projection only, never an authoritative store (§11.1.1); privilege/AccessTier filtering (§16.6); `taint_class` rides the view; reads never mutate the owner. ### 9.3 Gated WRITE capability (declared; behaviors reserved) A typed capability so future modules can interact in the same manner, gated behind `LifecycleActorEnvelope` + an EC `PolicyDecision`. "Can module M create/resolve finding F?" is a policy decision, not M's call (preserves one-compiled-evaluator). Per-module write **behaviors are reserved** (§11) — only the contract + authority gate land now. ```ts interface LifecycleWriteCapability { op: "create_finding" | "transition_finding" | "add_comment" | "add_run_criterion" actor: LifecycleActorEnvelope // author_kind != "human" requires capability declaration target_ref: string payload_ref: string requires_policy_decision: true schema_version: 1 } ``` --- ## 10. Lints and fixtures ### 10.1 New lints ``` review_studio.finding_disposition_without_anchor_or_id review_studio.general_directive_not_materialized_to_finding_or_criterion review_studio.run_criterion_scope_wider_than_run review_studio.human_edit_without_revalidation_trigger // §8.2 review_studio.advise_mode_mutated_artifact // interaction_mode=advise must not change the doc review_studio.result_format_unhonored_by_assist_output review_studio.intrinsic_gate_used_loop_controller // intrinsic gate must not require one (§4.2) review_studio.advise_treated_as_terminal_routing // advise is a session mode, not a terminal (§5.4) review_studio.terminal_decision_not_approve_send_or_reject // Layer-3 must be one of three (§5.4) lifecycle.read_projection_treated_as_truth_store // §9.2 lifecycle.read_without_privilege_filter // §16.6 lifecycle.write_without_policy_decision // §9.3 lifecycle.actor_envelope_missing review_result.duplicates_document_review_request_schema // must extend, not fork (§3.2) ``` ### 10.2 Golden fixtures (executable assertions; gate level in brackets) ``` GS-RS-01 per-finding disposition -> human-authored finding -> Revisor routes to module [slice] GS-RS-02 general directive -> run-scoped criterion -> persists across re-eval until satisfied [cross_slice] GS-RS-03 human deletes section with a finding -> human_authored_version_created -> cascade -> finding superseded_by_revision -> Revisor plans against current version [cross_slice] GS-RS-04 advise mode: agent answers in comments/chat, artifact unchanged [slice] GS-RS-05 agent-assisted in-place edit -> new co-authored version -> route "proceed" [cross_slice] GS-RS-06 default assist target resolves to producing agent's session; override via agent_id [slice] GS-RS-07 intrinsic post_evaluation gate raised with no module wiring and no Loop Controller [slice] GS-RS-08 teaching feedback -> feedback_out -> DirectInstructionCandidate (not the revision path) [slice] GS-RS-09 read query returns privilege-filtered views; cross-matter read denied by default [final_switchover] GS-RS-10 assist result returns to surface; session iterates within max_revisions before terminal decision [cross_slice] ``` --- ## 11. Reserved sections (contract reserved, behaviors deferred) ### 11.1 Revision pathways: in scope, the evaluator-bridge, and the reserved orchestrator Three tiers, deliberately separated so we do not build a second orchestrator (§1.2): - **Tier 1 — Human-Review -> Revisor (IN SCOPE, buildable now).** A review's dispositions/directives drive the Revisor to revise the artifact / repair via the existing loop. Already contracted (HumanOutcomeFeedbackEvent -> Feedback Interpreter -> RevisionRequest -> Revisor, V3.3.1 §14); Review Studio wires into it (§7.2). **Not reserved** — mostly wiring. The Revisor already reaches **multiple modules** on its own via `RepairTarget` routing (§6.4) and Task Agent escalation (§6.9), so Tier 1 already covers much of the multi-module need. - **Tier 2 — The evaluator-bridge (recommended multi-module path; a pattern, not new machinery).** Route the human's intent **through an Evaluator**: the comments/directives become an Evaluator's findings/criteria (the materialization in §3.5 is exactly this), and the existing Revisor consumes them and does its normal multi-module job, escalating to the Task Agent where needed. Yields human-driven multi-module revision by reusing Evaluator -> Revisor -> Task-Agent, with **no new orchestrator**. It also "forces clearer goals," since intent must be expressed as checkable findings/criteria. - **Tier 3 — Human-Review -> Orchestrator engine (RESERVED).** A dedicated engine where human review directly drives runtime multi-module orchestration, bypassing the Evaluator/Revisor. **Reserved**, because it would be a second orchestrator overlapping the Revisor's (the §1.2 boundary). Architect's framing: this is essentially the existing "ask ELNOR for a task -> Task Agent designs it -> it is revised" flow, surfaced with a different level of explanation and made re-runnable mid-task. Its building blocks already exist — `TaskRunFork` (Core R0.7.1 §8622), `graph_patch_proposal` (the Revisor->Task Agent escalation output, V3.3.1 §6.9), and the Task Agent's graph-design/revision role — so assembling it later is expected to be cheap, which is why it is deferred rather than built now. Build Tier 1 + use the Tier 2 bridge in the interim; `requested_followup: FollowupIntent[]` (§3.2) captures multi-step intent as data meanwhile. ### 11.2 Self-learning from review gates The reasoning side (learning standing preferences/quality models from review-gate activity) is **reserved**, gated on DOC8/the memory flatten. The **signal layer is already wired**: V3.3.1 §14.8 emits `finding_marked_wrong`, `revision_instruction_useful`, `evaluator_plan_user_edited`, etc., to DOC72/BDSM consumers (§14.8.4). This unit emits those signals from Review Studio actions (including per-tracked-change rejections, §3.2) but does not build the learning reasoner. --- ## 12. OP-A obligations (interim pre-flatten tracker rows) Recorded in the interim cross-doc tracker (not canonical OP-A, reconciled at flatten completion). None of these are flatten-blocking. ``` OBL-RS-01 §G UI rows -> DOC20 migration OBL-RS-02 Review Studio review-surface UI (Appendix A) -> DOC20 OBL-RS-03 Reconcile HumanReviewResult ⊇ DocumentReviewRequest (request shape is DOC20-owned, §3.2) OBL-RS-04 AttachmentSchema.parent_type extension: add comment / finding / review_result (DOC20 §7.18) OBL-RS-05 plan_review room kind dependency -> DOC12 (B-15; OBL-DOC12-FORUM-01) OBL-RS-06 NoVerdictReason full consolidation -> when next in Addenda A OBL-RS-07 Unified cross-module lifecycle substrate ownership (DOC23<->DOC20) — ordinary owner-boundary decision + OP-A row; NOT a flatten/DOC80 gate, NOT a blocker OBL-RS-08 Fold the ADOPTED ModuleActivationChat surface (reprompt/chat/continuation addendum) into DOC20/DOC23 -> the §6.4/§6.5 checkpoint chat UI OBL-RS-09 RevisionOperationKind += human_authored_version_created; add to §11.21 trigger set (V3.3.1 owner) OBL-RS-10 ui_source += review_studio_card / document_viewer / email_reply (DOC20 + V3.3.1 §14.2) ``` --- ## Appendix A — DOC20 additions / obligations (liftable, mockup-ready) Clearly-labeled DOC20-owned work, liftable to DOC20 when next revised. Specified to mockup-ready depth. - **Review mode for the Document Viewer** (§6.16): a `doc` tab opened by the gate, with findings loaded into the Comments panel as a **`finding` comment kind** (extends `NoteCommentStatus`/comment-kind set). Click-finding->highlight reuses §6.6.7. - **Per-finding actions** in the Comments panel: Accept / Reject / Reject-with-modification + comment (Word-comment ergonomics). - **Interaction-mode toggle** (revise | advise) on the review surface; advise hides mutation actions. - **Result-format selector** — already present (§6.16.8 `result_format`); surface it in review mode and bind to the assist output contract. - **Context-scope control** — already present (§6.16.8 `context_scope`). - **Assist-target picker** — producing-agent default; candidate list = "agents involved in this task" (from the run graph) + Task Agent + forum; maps `agent_id`/`chat_id` (§6.2). Chat surface = ModuleActivationChat (proposal, OBL-RS-08). - **Attachment `parent_type` extension** to cover `comment` / `finding` / `review_result` (§7.18; OBL-RS-04). - **Comment-status <-> finding-state reconciliation**: `orphaned` <-> `superseded_by_revision`; carry `thread_root_id` on dispositions so threads link, not duplicate (§3.6). - **`ui_source` values** for review surfaces (OBL-RS-10). - **Plan-review layout**: Revisor plan steps as side-panel items with approve / drop / modify (consumes `plan_in`). --- ## Appendix B — Verification log (operative vs net-new) **Operative (reused, cited):** - `step.user_review_gate` spine, Review Card, email-reply actions, ports, `on_reject_action`, `max_revisions`, `revision_delivery`, Loop Controller Pattern B — DOC23 R3.1 §3.2.3 / §6.5.4 / §3.3.4 / §6.2 / §13.9. - Document Viewer, anchored comments + threading, tracked changes, Convert-to-Note, Send-to-Agent + `DocumentReviewRequest`/`DocumentReviewResultEvent`, comment event-store, attachments — DOC20 R4.3 §6.6.2 / §6.6.3 / §6.10 / §6.16.6 / §6.16.8 / §6.16.9 / §6.16.11 / §7.16–§7.18. - Finding lifecycle + `superseded_by_revision`, revalidation cascade + declared-dependency closure, `RevisionOperationKind`, `HumanOutcomeFeedbackEvent` (un-pinned supported), Feedback Interpreter + routing, authority classes, `DirectInstructionCandidate`, signals + consumers, Plan Review Forum, `RevisionRequest`, `TypedRevisionInstruction`, repair strategy/target taxonomies, Task Agent escalation, Outcome Compiler/Criterion, export/governance + default-deny + matter governance, derived-read-model "derived, not invented" — V3.3.1 §5.7 / §11.21 / §3.1.7 / §0.4.7 / §14.2 / §14.3 / §14.4 / §14.6 / §14.7 / §14.8 / §14.9 / §7.1 / §7.6 / §6.3 / §6.4 / §6.9 / §5.1.1 / §16.3 / §16.5 / §16.6 / §11.1 / §4.9.2. - Module session continuation, module follow-up, Task Agent side-panel chat, `TaskRunFork`, `TaskModuleSessionRef` — Addenda B Core R0.7.1 §3170 / §3449 / §261 / §9397 / §10363 / §8622; Reprompt §7.1 -> Addenda A §A9. **Net-new this unit (and its trace):** - `interaction_mode` revise|advise — closes a gap vs DOC20 `output_mode` respond_in_chat / `result_format` respond_in_comments (§3.1/§3.3). - `HumanReviewResult` as a superset of `DocumentReviewRequest` (§3.2) — reconciliation OBL-RS-03. - Materialization of comments -> human-authored findings / run-scoped criteria; `InterpretedOutcomeFeedback` output extension (§3.5) — built on §5.1.1 + §5.7 + §14.3. - Hybrid placeable + intrinsic gate (§4) — extends §3.2.3; intrinsic timing after Evaluator/before Revisor. - `human_authored_version_created` revalidation trigger (§8.2) — OBL-RS-09. - `LifecycleActorEnvelope`, `LifecycleReadQuery`/`LifecycleEventSubscription`, gated `LifecycleWriteCapability` (§9) — extend GovernanceEnvelope + §4.9.2/§11.1/§16. **`OPEN_FOR_ARCHITECT_REVIEW`:** none outstanding. Resolved this revision: ModuleActivationChat — **adopted** (§6.4); `human_resolved` provenance — **adopted** (§8.3); Tier-1 Human-Review->Revisor — **in scope** (§7.2/§11.1). The Tier-3 orchestrator (§11.1) is **reserved by decision** (not an open question), to revisit after the other pieces land. --- ## Revision log **Rev 2 (this pass)** — folded in architect decisions + audit findings: - Adopted the ModuleActivationChat checkpoint chat UI (§6.4, OBL-RS-08). - Adopted a distinct `human_resolved` provenance (§8.3). - Confirmed Tier-1 Human-Review->Revisor as in scope; named the Tier-2 evaluator-bridge; reserved the Tier-3 orchestrator with building-block framing (§7.2, §11.1). - Added the three-layer action model and disambiguated "Revise"; refined the `decision` enum to approve/send_for_revision/reject and removed `advise_only` as a routing kind (§5.4, §7.1). - Added assist-result handling + iteration (§6.5), no-producing-agent fallback (§6.2), relationship to agent_review_gate / panel / the human_review_gate disposition (§1.3), email-channel limits (§3.4), two action-model lints, and GS-RS-10. *End of design unit. Draft pending architect review and multi-LLM red-team.* ````