Skip to content

[PR-13/#29] Merge approval and documentReview into one approval type #445

@DKuleshov

Description

@DKuleshov

[PR-13/#29] Merge approval and documentReview into one approval type

Parent

#29

Problem

We have two question types that are both approval flows:

Type Attachments Decisions
approval not rendered approved / rejected / abstained
documentReview rendered with review checkboxes approved / changes_requested / comment_only

Both ask a human to make an approval decision. The only real difference is whether the reviewer needs to look at an attached document. That is not a reason to have two types — it is a reason to make attachments optional on one type.

Having two types forces the outpost to know upfront whether a document will be attached. It also confuses outpost authors: "which one do I use?"

Decision set analysis

Before proposing the merge, it is worth clarifying what each decision value means for the agent:

Decision Agent behavior Status
approved proceed keep
rejected stop, fix keep
changes_requested stop, fix same as rejected — merge into rejected
comment_only proceed (same as approved + comment) no separate behavior — drop
abstained undefined — agent stuck no defined outcome — drop

Simplified: two outcomes, two buttons.

Decision Agent behavior Comment
approved proceed optional
rejected stop + fix required

Proposal

Single approval type. Attachments optional. Two decisions: approved / rejected.

Type shape

Field Rule
type "approval"
attachmentList optional. If present — UI renders attachment list with "I reviewed this" checkboxes before decision buttons. If absent — decision buttons only.
deliverableSummary optional. Describes document content when attachments present.
reviewLinks optional on both cases.

Answer shape

"answer": {
  "approvalDecision": "approved | rejected",
  "comment": "optional on approved; required on rejected",
  "reviewedAttachmentIds": ["..."]  // present when attachmentList non-empty; reviewer must confirm at least one
}

Examples

Approval without document:

{
  "type": "approval",
  "title": "Approve architecture v2 - monolith split",
  "description": "Move auth, billing, notifications into services.",
  "options": []
}

Answer: approved or rejected + comment.

Approval with document:

{
  "type": "approval",
  "title": "Review PRD draft - billing service",
  "deliverableSummary": "Billing service - invoice API, async events, Postgres datastore.",
  "options": [],
  "attachmentList": [
    { "id": "...", "name": "prd-billing-service.pdf", "contentType": "application/pdf", "sizeBytes": 184500 }
  ]
}

Answer: approved or rejected + comment, plus reviewedAttachmentIds.

What changes

Validator (QuestionTemplateValidator.cs)

  • Drop documentReview from QuestionTypes.AllowedTypes
  • Allow attachmentList on approval
  • Update ApprovalDecisions.ApprovalAllowed to [ "approved", "rejected" ]
  • Drop DocumentReviewAllowed
  • comment required when approvalDecision = "rejected"

Web form (Respond.cshtml)

  • Merge case QuestionTypes.DocumentReview into case QuestionTypes.Approval
  • Within approval case: branch on Model.Template.Attachments is { Count: > 0 } to render attachment list + review checkboxes
  • Decision buttons: Approve + Reject only (drop Abstain, changes_requested, comment_only)

Outpost UI (actions.js) + dual-surface push-back

PR #417 implements dual-surface push-back for approval type: reviewer clicks Approve / Reject / Abstain in the Outpost Decisions tab, outpost POSTs back to mothership /api/responses with answeredVia: "outpost".

This merge is compatible with PR #417:

  • Type name approval stays — no rename needed
  • PR [PR-11/#29] Dual-surface approval (P2) #417 must drop the Abstain button (decision set is now approved / rejected only)
  • PR [PR-11/#29] Dual-surface approval (P2) #417 must render the attachment list + review checkboxes when question.attachmentList is non-empty (currently only the mothership web form does this)
  • Send-LocalApprovalResponse payload shape stays the same — just fewer valid approvalDecision values

Dual-surface push-back stays scoped to approval per issue #29. The merged type covers both doc and no-doc cases within that scope.

Out of scope

  • Role-based routing (Project team and roles (v4 phase 14) #98)
  • Batch questions
  • Other types: singleChoice, freeText, priorityRanking
  • Escalation decisions — future versions may add decision values that trigger escalation (e.g. escalated, needs_more_info) to signal the agent to ask a different person or wait. Not in scope now (YAGNI — no escalation mechanism exists yet). Add when role routing (Project team and roles (v4 phase 14) #98) lands.

Metadata

Metadata

Assignees

Labels

readyTriaged and ready for a contributor to pick upserverMothership/notification servertype:featureNew feature or enhancement

Projects

Status

In Review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions