---
phase: 07-integration-and-end-to-end-validation
plan: 02
type: execute
wave: 2
depends_on:
  - "07-01"
files_modified:
  - examples/62_task_workflow_lifecycle.rs
autonomous: true
requirements:
  - INTG-03

must_haves:
  truths:
    - "cargo run --example 62_task_workflow_lifecycle compiles and runs successfully"
    - "Example output shows the full lifecycle: workflow invocation, handoff with completed/remaining steps, client continuation via _task_id, and final task completion"
    - "Example prints the full message list from the handoff so the reader sees user intent, assistant plan, tool call/result pairs, and the handoff narrative"
    - "Each lifecycle stage is clearly commented with Stage N labels"
  artifacts:
    - path: "examples/62_task_workflow_lifecycle.rs"
      provides: "Complete task-prompt bridge lifecycle example"
      min_lines: 150
      contains: "fn main()"
  key_links:
    - from: "examples/62_task_workflow_lifecycle.rs"
      to: "src/server/workflow/task_prompt_handler.rs"
      via: "ServerCore::handle_request dispatching GetPrompt through TaskWorkflowPromptHandler"
      pattern: "handle_request"
    - from: "examples/62_task_workflow_lifecycle.rs"
      to: "src/server/core.rs"
      via: "Fire-and-forget continuation intercept on CallTool with _task_id"
      pattern: "_task_id"
---

<objective>
Create the complete lifecycle example that replaces 62_task_workflow_opt_in.rs, demonstrating the full task-prompt bridge from workflow invocation through structured handoff to client continuation and task completion.

Purpose: This example serves as the primary teaching document for the task-prompt bridge feature (INTG-03). It shows exactly what an LLM client receives and how it should respond, making the abstract concepts from Phases 4-6 concrete and observable.

Output: `examples/62_task_workflow_lifecycle.rs` replacing the existing opt-in example, with heavy inline comments and full message list printing.
</objective>

<execution_context>
@./.claude/get-shit-done/workflows/execute-plan.md
@./.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/07-integration-and-end-to-end-validation/07-CONTEXT.md
@.planning/phases/07-integration-and-end-to-end-validation/07-RESEARCH.md
@.planning/phases/07-integration-and-end-to-end-validation/07-01-SUMMARY.md
@examples/62_task_workflow_opt_in.rs
@examples/60_tasks_basic.rs
@src/server/workflow/task_prompt_handler.rs
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create lifecycle example replacing opt-in example</name>
  <files>examples/62_task_workflow_lifecycle.rs</files>
  <action>
Delete `examples/62_task_workflow_opt_in.rs` and create `examples/62_task_workflow_lifecycle.rs`.

**Module doc (`//!`):**
Explain the full task-prompt bridge lifecycle: a workflow prompt creates a task, the server executes resolvable steps, returns a structured handoff with completed and remaining steps, the client calls remaining tools with `_task_id` to continue, and the task completes. State this replaces the former opt-in example.

**Scenario (per CONTEXT.md locked decision):**
Multi-step data processing: fetch_data -> transform_data -> store_data. NOT the deploy pipeline from the old example.

- Step 1 "fetch": tool "fetch_data", arg "source" from prompt argument, bind output as "raw_data"
- Step 2 "transform": tool "transform_data", arg "input" from step output "raw_data" (data dependency), bind output as "transformed"
- Step 3 "store": tool "store_data", arg "data" from step output "transformed"

**Pause trigger (per CONTEXT.md locked decision):**
Design `FetchDataTool` to return an error on server-side execution (return `Err(...)`). This triggers `PauseReason::ToolError` for the fetch step, then `PauseReason::UnresolvedDependency` for the transform step (which depends on fetch's output via the "raw_data" binding). This shows the data-dependency handoff.

**Tool handlers:**
- `FetchDataTool` -- returns `Err(pmcp::Error::internal("External API unavailable - client must provide data"))` to trigger pause. The client will call this tool separately with `_task_id`.
- `TransformDataTool` -- returns `Ok(json!({"transformed": true, "result": args["input"]}))`
- `StoreDataTool` -- returns `Ok(json!({"stored": true, "location": "db://processed"}))`

**fn main() structure (per CONTEXT.md: synchronous, use block_on):**

```rust
fn main() {
    let rt = tokio::runtime::Runtime::new().unwrap();
    rt.block_on(async {
        // All async operations
    });
}
```

**Lifecycle stages (per CONTEXT.md: heavy inline comments with Stage N labels):**

```
// Stage 1: Build the server
// - Create task store + router
// - Define 3-step data pipeline workflow with task support
// - Register tools and workflow on ServerCoreBuilder
// - Use stateless_mode(true) for direct handle_request calls

// Stage 2: Invoke the workflow prompt
// - Construct GetPrompt request for "data_pipeline" with arguments
// - Call server.handle_request()
// - The server creates a task, attempts to execute steps server-side
// - fetch_data fails -> pause at step 1 with ToolError
// - transform_data unresolvable -> UnresolvedDependency (depends on raw_data)

// Stage 3: Inspect the handoff
// - Extract _meta from GetPromptResult
// - Print task_id, task status, step progress, pause_reason
// - Print the full message list (per CONTEXT.md: user intent, assistant plan, tool/result pairs, handoff narrative)
// - The reader sees exactly what an LLM client receives

// Stage 4: Client continuation
// - Construct CallTool request for "fetch_data" with _task_id in _meta
// - Call server.handle_request() -- tool succeeds this time
// - The server records the continuation (fire-and-forget)
// - Print the tool result

// Stage 5: Complete the workflow
// - Send tasks/cancel with result to mark the task as completed
// - This uses cancel-with-result (result field transitions to Completed, not Cancelled)
// - Poll tasks/result to verify final state
// - Print the completed task with all accumulated variables
```

**Per CONTEXT.md locked decisions:**
- Print the FULL message list from the handoff response. Iterate over all messages in the GetPromptResult and print role + content for each.
- Use `Request::Client(Box::new(ClientRequest::GetPrompt(...)))` for prompt requests
- Use `Request::Client(Box::new(ClientRequest::CallTool(...)))` with `_meta: Some(RequestMeta { _task_id: Some(task_id), ... })` for continuation
- Use `Request::Client(Box::new(ClientRequest::TasksCancel(...)))` for cancel-with-result
- Use `Request::Client(Box::new(ClientRequest::TasksResult(...)))` for polling

**Print format:** Use `println!` with clear section headers and indentation. Print JSON values with `serde_json::to_string_pretty` where helpful. The example is a teaching document -- clarity over brevity.

**Important implementation notes:**
- The example depends on the bug fix from Plan 01 (task_id extraction). Without it, _meta will be None.
- `stateless_mode(true)` is required to skip the initialization handshake.
- Owner resolves to "local" automatically when `allow_anonymous: true` and auth_context is None.
- Pattern-match on `ResponsePayload::Result(v)` / `ResponsePayload::Error(e)` for response extraction.
  </action>
  <verify>
Run `cargo run --example 62_task_workflow_lifecycle` -- must compile and run to completion without panics. Verify the output shows all 5 lifecycle stages with meaningful data (task_id, step progress, handoff messages, continuation result, final completed state). Run `cargo clippy --example 62_task_workflow_lifecycle -- -D warnings` for zero warnings. Verify the old `62_task_workflow_opt_in.rs` file no longer exists.
  </verify>
  <done>
The lifecycle example demonstrates the complete task-prompt bridge: workflow invocation creates a task, server executes steps until it hits a failure and data dependency, returns a structured handoff with _meta and narrative, client continues via _task_id, and the task completes. The full message list is printed so readers see exactly what an LLM client receives. The old opt-in example is replaced.
  </done>
</task>

</tasks>

<verification>
1. `cargo run --example 62_task_workflow_lifecycle` completes successfully with visible lifecycle output
2. `cargo clippy --example 62_task_workflow_lifecycle -- -D warnings` passes (zero warnings)
3. `ls examples/62_task_workflow_opt_in.rs` returns "no such file" (old file removed)
4. Output includes: task_id, step statuses, handoff message list, continuation result, completed task state
5. `cargo test --package pmcp-tasks -- --test-threads=1` still passes (example change doesn't break tests)
</verification>

<success_criteria>
- Example compiles and runs with `cargo run --example 62_task_workflow_lifecycle`
- All 5 lifecycle stages visible in output with clear stage labels
- Full message list printed from handoff (user intent, assistant plan, handoff narrative)
- Data-dependency pause trigger demonstrated (fetch fails, transform has unresolved dependency)
- Client continuation with _task_id shown
- Cancel-with-result completion demonstrated
- Old 62_task_workflow_opt_in.rs removed
</success_criteria>

<output>
After completion, create `.planning/phases/07-integration-and-end-to-end-validation/07-02-SUMMARY.md`
</output>
