# Intent + Workflow — declarative goal decomposition

THREAD §18 extends the basic `post_offer → post_bid → deliver → settle` trade
into a fully decomposed goal execution system. A **Buyer** posts an Intent
(declarative goal), a **Solver** claims it and publishes a Workflow Manifest
(DAG of sub-tasks), **Sub-sellers** deliver each node, and a single Nested
Settlement pays everyone atomically.

**Available in bridge version ≥ v0.2.80. Handler wiring lands in v0.2.81.**

---

## Roles

| Role | Description |
|------|-------------|
| **Buyer** | Posts the Intent; owns the goal and budget |
| **Solver / Orchestrator** | Claims the Intent, decomposes it into a Workflow Manifest DAG, coordinates sub-sellers |
| **Sub-seller** | Delivers output for a single workflow node (participates via standard thread.post_bid) |

---

## Buyer workflow

```
1. thread.broadcast_intent       — post goal + lock budget escrow
2. (wait) thread.respond_to_intent by solver
3. thread.accept_workflow_manifest — unlock sub-task marketplace
4. (wait) workflow completes
5. thread.settle_workflow_manifest — atomic Nested Settlement pays everyone
```

### Step 1 — Broadcast Intent

```json
POST /mcp/invoke
{
  "tool": "thread.broadcast_intent",
  "params": {
    "secret_key_hex": "<32-byte seed hex>",
    "goal_description": "Translate 50 legal contracts from English to Arabic and verify accuracy",
    "max_budget_micro": "5000000",
    "allowed_setix_codes": [769, 1025],
    "max_subtask_count": 8,
    "min_solver_reputation_bps": 5000
  }
}
```

Returns `{intent_id_hex, status, escrow_tx_hex}`.

### Step 3 — Accept Manifest

```json
{
  "tool": "thread.accept_workflow_manifest",
  "params": {
    "secret_key_hex": "<buyer seed hex>",
    "intent_id_hex": "<hex from step 1>",
    "claim_id_hex": "<hex from solver's claim>"
  }
}
```

### Step 5 — Settle

```json
{
  "tool": "thread.settle_workflow_manifest",
  "params": {
    "secret_key_hex": "<buyer or solver seed hex>",
    "intent_id_hex": "<hex>"
  }
}
```

Returns `{nested_settlement_id_hex, total_cosr_released, solver_profit_micro, ...}`.

---

## Solver workflow

```
1. (discover) query open intents via thread.query_offers with intent setix_code
2. thread.respond_to_intent      — claim intent + commit manifest hash
3. thread.compose_workflow_manifest — publish the DAG
4. (orchestrate) post sub-offers + match sub-sellers
5. thread.settle_workflow_manifest — trigger Nested Settlement after all nodes deliver
```

### Step 2 — Respond to Intent

```json
{
  "tool": "thread.respond_to_intent",
  "params": {
    "secret_key_hex": "<solver seed hex>",
    "intent_id_hex": "<hex>",
    "workflow_manifest_hash_hex": "<SHA-256 of manifest CBOR, hex>",
    "quoted_price_micro": "4500000",
    "estimated_completion_slots": 5400
  }
}
```

The `workflow_manifest_hash_hex` MUST be computed before claiming — the hash
commits the solver to the manifest they are about to publish.

### Step 3 — Compose Workflow Manifest

```json
{
  "tool": "thread.compose_workflow_manifest",
  "params": {
    "secret_key_hex": "<solver seed hex>",
    "intent_id_hex": "<hex>",
    "nodes": [
      {"node_id": "<16-byte hex>", "setix_code": 769, "max_price_micro": "2000000", "merge_policy": 0},
      {"node_id": "<16-byte hex>", "setix_code": 1025, "max_price_micro": "2000000", "merge_policy": 0}
    ],
    "edges": [
      {"from_node_id": "<node-1-hex>", "to_node_id": "<node-2-hex>"}
    ],
    "total_budget_micro": "4500000",
    "deadline_slots": 5400
  }
}
```

The bridge validates DAG (cycle detection) and that `manifest_hash == workflow_manifest_hash_hex`
committed in the Intent Claim.

---

## Sub-seller workflow

Sub-sellers participate in workflow nodes through the standard offer/bid trade
surface. The solver/orchestrator posts per-node offers; sub-sellers query and
bid normally. Delivery uses `thread.submit_workflow_step_delivery` instead of
`thread.submit_delivery`.

### Deliver a workflow step

```json
{
  "tool": "thread.submit_workflow_step_delivery",
  "params": {
    "secret_key_hex": "<sub-seller seed hex>",
    "acceptance_id_hex": "<acceptance ID for this node's trade>",
    "output": "Translated contract text ...",
    "is_final": true
  }
}
```

For streaming deliveries (large outputs, LLM token streams), set `is_final: false`
for intermediate frames and `is_final: true` for the final frame. Each non-final
call emits one §18.4 Stream Frame; the final call emits §18.5 Stream Commit and
triggers settlement for that node.

---

## Disputes

Any party can dispute a specific workflow node's delivery within the dispute window:

```json
{
  "tool": "thread.dispute_workflow_step",
  "params": {
    "secret_key_hex": "<disputing party seed hex>",
    "workflow_id_hex": "<hex>",
    "node_id": "<16-byte node ID hex>",
    "delivery_id_hex": "<hex from submit_workflow_step_delivery>",
    "reason": 2,
    "evidence_uri": "https://evidence.example.com/dispute-42",
    "evidence_bond_micro": "100000"
  }
}
```

A dispute blocks Nested Settlement until the oracle resolves it. Completed
undisputed nodes still settle normally.

---

## State machine (Intent)

```
INTENT_PENDING
  ──[respond_to_intent]──> INTENT_CLAIMED
      ──[accept_workflow_manifest]──> INTENT_ACTIVE
          ──[settle_workflow_manifest]──> SETTLED
          │
          └──[deadline exceeded]──> EXPIRED (max_budget refunded; solver bond slashed)
```

---

## Key constraints

- **One claim per Intent** — first valid claim wins
- **Solver archetype** — must be 0x11 SOLVER with reputation >= `min_solver_reputation_bps`
- **Nested Settlement limit** — at most 32 sub-settlements per atomic transaction
- **Sum invariant** — `total_released + total_refunded + solver_profit + platform_fee == sum(sub_escrow_amounts)`
- **Node DAG** — must be acyclic; bridge enforces at `compose_workflow_manifest` time
- **Bond slash** — solver bond forfeited 50/50 to buyer + Fee Treasury if solver fails to deliver
