# openspec/changes/wf-escalation-to-recovery/proposal.md

## Why

Support sees the complaint, engineering sees the error and sales sees the deal. Nobody sees all three, so the fix ships and the customer hears about it last. A customer judges you on how fast you recover and whether you told them. This makes both visible, with proof the account team can show.

## What Changes

- Add the `escalation-to-recovery` workflow to the PromptReports workflow library, run by the workflow runner as an agent acting for a person.
- CommitOps: Open a case from the customer message and match it to a promise (today: Planned).
- RepoOps: Trace the error to its likely change and agent session (today: Built).
- RepoOps: Propose the fix (today: Built).
- PromptCompute: One approval for the fix and the customer notice together (today: Planned).
- RepoOps: Measure recovery after the fix deploys (today: Built).
- CommitOps: Mark the promise kept or broken (today: Switching on).
- Sales as Code: Show the kept promise on the deal (today: Switching on).
- Gate `repoops.build_fix`, `commitops.customer.notify`, `crm.deal.update` through PromptCompute approvals; each gated step runs only after `verifyResume` passes, with `final_args`.
- Write a signed record at the end of each run and count one workflow request.

## Impact

- Products: CommitOps, RepoOps, PromptCompute, Sales as Code.
- Outside the family: Slack or your support inbox, GitHub, HubSpot, Salesforce or Attio.
- State: Partly built. Sales as Code shows a kept promise on the deal, switching on with the customer join. Three parts to go.
- Plan row: LDG-2270.

# openspec/changes/wf-escalation-to-recovery/tasks.md

## 1. Connect and authorize

- [ ] 1.1 Confirm the org has a connection for each of: CommitOps, RepoOps, PromptCompute, Sales as Code. Stop and tell the user which is missing.
- [ ] 1.2 Get a PromptReports ID agent token for each product the run calls (RFC 8693 exchange). Where a product does not accept ID tokens yet, use its connect key.
- [ ] 1.3 Register policy for `repoops.build_fix`, `commitops.customer.notify`, `crm.deal.update` with `require_approval` as the default.

## 2. Build the steps

- [ ] 2.1 CommitOps: Open a case from the customer message and match it to a promise. Blocked: this part is Planned; until it ships, record the step's evidence as `missing` and continue.
- [ ] 2.2 RepoOps: Trace the error to its likely change and agent session.
- [ ] 2.3 RepoOps: Propose the fix.
- [ ] 2.4 PromptCompute: One approval for the fix and the customer notice together. Blocked: this part is Planned; until it ships, record the step's evidence as `missing` and continue.
- [ ] 2.5 RepoOps: Measure recovery after the fix deploys.
- [ ] 2.6 CommitOps: Mark the promise kept or broken.
- [ ] 2.7 Sales as Code: Show the kept promise on the deal.

## 3. Verify and record

- [ ] 3.1 Run a dry run with the user's inputs: Customer = Acme Freight; Report source = Slack #acme-support; Promise = C-1182 (optional, found if blank).
- [ ] 3.2 Run it once for real; approve each gate as the user.
- [ ] 3.3 Measure the outcomes: Hours from customer report to verified recovery; Promises at risk that end kept; Customer notices sent before the fix was verified: target 0.
- [ ] 3.4 Confirm the run left a signed record with a task id and one workflow request counted.

# openspec/changes/wf-escalation-to-recovery/specs/workflow-escalation-to-recovery/spec.md

## ADDED Requirements

### Requirement: The notice waits for the fix

The workflow SHALL send the customer notice only after RepoOps marks the recovery verified.

#### Scenario: The notice waits for the fix (1)

- **WHEN** the fix is approved and deployed but recovery is not yet verified
- **THEN** the notice step waits and the run shows the recovery check as missing

#### Scenario: The notice waits for the fix (2)

- **WHEN** recovery is verified
- **THEN** the notice step sends final_args through commitops.customer.notify

### Requirement: One decision covers both actions

The approval step SHALL present the fix and the notice on one card, and SHALL record one decision for both.

#### Scenario: One decision covers both actions

- **WHEN** the approver rejects the notice text
- **THEN** neither action runs and the run returns to the draft step

### Requirement: Evidence stays honest

Each step SHALL report what it saw as measured, inferred or missing, and SHALL never report missing as measured.

#### Scenario: A product part is not built

- **WHEN** a step depends on a part that is Planned or Proposed
- **THEN** the step records `missing`, names the part, and the approval card shows the gap

### Requirement: One run is one workflow request

The runner SHALL count one workflow request when the first step starts, and SHALL NOT count retries, resumes or dry runs.

#### Scenario: A gated step resumes after two days

- **WHEN** a person approves a step and the run resumes
- **THEN** the org's usage does not change
