<!-- task=m-iop-owned-single-request-agent-execution/19+18_work_stage plan=0 tag=API milestone-task=work-stage -->

# Work stage tool continuation

## For the Implementing Agent

Filling the implementation-owned sections of `CODE_REVIEW-cloud-G08.md` is the mandatory last implementation step. Run every verification command, paste actual output, keep both active files in place, and report ready for review; only the official code-review skill may append a verdict, archive files, write `complete.log`, or classify the next state. If blocked, record the exact blocker, attempted commands/output, and resume condition only in the review evidence fields; do not ask the user, call a user-input tool, create a control-plane stop file, or change the owner or scope.

## Background

The preceding Plan packet yields a private `plan.md` and a managed provider-stage codec, but the fixed Work stage still has no implementation. The coordinator already owns one closed internal workspace call/result continuation at a time; the missing layer is a concurrent request-safe ornith-fast runner that reads the plan, translates only server-approved workspace tools, resumes the provider with the correlated result, and produces bounded completion/verification evidence without inheriting high reasoning.

## Analysis

### Files Read

- `AGENTS.md`
- `agent-roadmap/phase/knowledge-tool-optimization-extension/PHASE.md`
- `agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/iop-owned-single-request-agent-execution.md`
- `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-owned-single-request-agent-execution/SDD.md`
- `agent-spec/runtime/edge-node-execution.md`
- `agent-contract/outer/anthropic-compatible-api.md`
- `agent-contract/inner/execution-runtime.md`
- `apps/edge/internal/service/single_request.go`
- `apps/edge/internal/service/single_request_types.go`
- `apps/edge/internal/service/single_request_tool_types.go`
- `apps/edge/internal/service/single_request_tool_loop.go`
- `apps/edge/internal/service/single_request_test.go`
- `apps/edge/internal/service/single_request_tool_types_test.go`
- `apps/edge/internal/service/single_request_tool_loop_test.go`
- `apps/edge/internal/service/single_request_cleanup_test.go`
- `apps/edge/internal/openai/chat_types.go`
- `apps/edge/internal/openai/single_request_preset_binding.go`
- `apps/edge/internal/openai/anthropic_handler.go`
- `apps/edge/internal/openai/server.go`

### SDD Criteria

- SDD: `agent-roadmap/sdd/knowledge-tool-optimization-extension/iop-owned-single-request-agent-execution/SDD.md`, `[승인됨]`, `SDD 잠금: 해제`.
- First-line contribution id: `work-stage`.
- Targeted scenario: S09 — with a plan and writable workspace, canonical `ornith-fast` reads the plan, receives no `reasoning_effort=high`, performs actual changes and verification through IOP-owned tools, and produces a completion candidate.
- Evidence Map driver: “ornith-fast tool work fixture and high-option absence test.” The checklist requires an ordered write/command/result fixture, plan artifact read, exact identity correlation, completion candidate, verification evidence, and negative high-option assertions on every Work provider request.

### Verification Context

- No verification handoff was supplied. Repository-native sources were `agent-test/local/rules.md`, `edge-smoke.md`, and the service/OpenAI tool-loop tests.
- Checkout preflight remains branch `feature/iop-owned-single-request-agent-execution`, starting HEAD `3bb4a24ad750a9ce5b7754a70db24545554ba238`; Go `1.26.2 linux/arm64` is available.
- Baseline relevant packages passed with fresh tests. The Work fixture uses deterministic provider frames and the existing typed Node-wire test doubles; it needs no endpoint, provider credential, or external runner.
- Constraint: package tests prove S09 stage behavior but are not actual Claude/Mac full-cycle evidence. That evidence belongs to S12 `claude-smoke` after Review activation.
- Confidence: high after predecessor completion. The service coordinator already enforces identity, single pending call, max iterations/output, stage deadline, capability allowlists, cancel propagation, and cleanup.

### Test Coverage Gaps

- Existing service tests prove generic internal calls and continuation, but not provider Chat tool-call decoding or multi-turn Work messages.
- Existing preset tests prove Work options omit high, but not the effective provider body on initial and resumed attempts.
- There is no cross-request pending-result correlation test for a production executor bridge and no S09 write+verify completion fixture. This packet adds both, including `-race` execution.

### Symbol References

No symbol is renamed or removed. `SingleRequestToolContinuation` at `apps/edge/internal/service/single_request_tool_types.go:88` is currently implemented only by test executors; the new request-safe bridge becomes the first production-capable implementation but is not installed until the successor packet.

### Split Judgment

- Predecessor 18 contract: authorized provider-stage codec and Plan artifact writer; PASS evidence is `agent-task/m-iop-owned-single-request-agent-execution/18+17_plan_stage/complete.log`.
- At plan creation that `complete.log` is missing, so implementation must wait. The directory name `19+18_work_stage` declares the only new sibling dependency.
- This packet's stable contract is a directly testable Work runner plus concurrent continuation bridge; it does not activate an incomplete public execution path.
- Review/repair remains separate because its pass/defect branch and `reviewing -> repairing -> finalizing` invariant require independent evidence.

### Scope Rationale

This packet excludes Review verdicts/repairs, final user response, production executor installation, public error mapping, generic no-progress/error-cancel policy, config changes, and external provider smoke. It does not forward caller tools, arbitrary environment, provider credentials, private paths, or Plan/Review reasoning options to Work.

### Final Routing

- `evaluation_mode=first-pass`; `finalizer=finalize-task-policy.sh`; `finalizer_mode=pair`.
- Build closures: scope/context/verification/evidence/ownership/decision all true. Scores `2/2/1/1/2` => G08, base `local-fit`, route `risk-boundary`, `worker/cloud/G08`, `PLAN-cloud-G08.md`.
- Review closures: all true. Scores `2/2/1/1/2` => G08, `official-review`, `review/cloud/G08`, `CODE_REVIEW-cloud-G08.md`.
- `large_indivisible_context=false`; positive loop risks: `temporal_state`, `concurrent_consistency`, `boundary_contract`, `structured_interpretation` (4), so risk boundary matched; `review_rework_count=0`; `evidence_integrity_failure=false`; no capability gap.

## Dependencies and Execution Order

1. Do not implement until `agent-task/m-iop-owned-single-request-agent-execution/18+17_plan_stage/complete.log` exists. No archive candidate exists yet at plan creation.
2. Implement the Work stage using the predecessor's exact provider-stage and artifact contracts; do not re-open or replace those boundaries.
3. Do not install the runner through `SetSingleRequestExecutor`; `20+19_review_stage` owns final composition and activation.

## Implementation Checklist

- [ ] Add a concurrent request-safe internal tool continuation bridge that correlates one provider call to one coordinator result and unregisters on every success, failure, timeout, and cancel path.
- [ ] Implement the ornith-fast Work runner to read PLAN, expose only admitted IOP workspace tools, drive ordered provider/tool continuations, and return bounded completion and verification evidence.
- [ ] Add S09 fixtures for write+verify completion, every Work request's high-option absence, identity/correlation isolation, malformed/multiple tool calls, limits, cancellation, and provider/tool failures under `-race`.
- [ ] Update the current implementation spec and run dependency, focused race, service compatibility, broader Edge, vet, deterministic option search, and diff checks without production activation.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [API-1] Correlate provider tool continuations per request

**Problem**

`SingleRequestToolContinuation` at `apps/edge/internal/service/single_request_tool_types.go:88` delivers results to an executor-level method, while `single_request_tool_loop.go:224` calls it asynchronously after the Node response. A production executor shared by concurrent requests needs exact request/stage/tool correlation without a global channel, lock-held blocking, duplicate delivery, or retained waiter after cancellation.

**Solution**

Create a private bridge in `single_request_work_stage.go` keyed by immutable `(request_id, stage_id, tool_call_id)`. Register before submitting the internal-tool envelope, reject duplicates, wait with the stage/request context, consume exactly one cloned result, and unregister in `defer` on every path. `ContinueInternalTool` validates all identities, performs one non-blocking/bounded delivery outside the map lock, and rejects missing or duplicate waiters generically.

Before (`apps/edge/internal/service/single_request_tool_types.go:88`):

```go
type SingleRequestToolContinuation interface {
    ContinueInternalTool(context.Context, InternalWorkspaceToolResult) error
}
```

After (new implementation shape):

```go
type singleRequestToolBridge struct {
    mu sync.Mutex
    pending map[singleRequestToolKey]chan edgeservice.InternalWorkspaceToolResult
}
```

**Modified Files and Checklist**

- [ ] Add bridge/key/waiter lifecycle and `ContinueInternalTool` implementation in `apps/edge/internal/openai/single_request_work_stage.go`.
- [ ] Ensure stored values contain no prompt, tool arguments, workspace paths, credentials, or provider payloads.
- [ ] Add concurrent correlation, duplicate, stale, cancellation, and waiter cleanup tests in `apps/edge/internal/openai/single_request_work_stage_test.go`.

**Test Strategy**

Write `TestSingleRequestWorkToolBridgeConcurrentCorrelation` with multiple request identities and deliberately reordered results. Add duplicate/stale/cancel table cases and assert the pending map returns to zero; run under `go test -race`.

**Verification**

Run `go test -race ./apps/edge/internal/openai -run 'TestSingleRequestWorkToolBridge' -count=1`; every correlation case passes without race reports.

### [API-2] Drive the S09 Work provider/tool loop

**Problem**

The coordinator understands internal envelopes, but no runner reads PLAN, projects the admitted workspace capability into provider tool schemas, or resumes ornith-fast after `ContinueInternalTool`. A generic caller-facing Chat tool path would incorrectly forward caller tools and could terminate the outer Anthropic request.

**Solution**

Implement `singleRequestWorkStage.Run`. Read `SingleRequestArtifactPlan`, submit `working`, build fixed Work messages with the immutable task and plan, and derive tool definitions only from the admitted operation/command/environment names. On exactly one provider tool call, decode it into `InternalWorkspaceToolCall`, register the bridge, submit `internal_tool` with saved `working`, wait for the result, submit the saved-stage return envelope, append a bounded sanitized assistant/tool exchange, and redispatch. On content, require a strict completion schema containing non-empty completion candidate and verification evidence. Reject zero/multiple mixed tool calls, unknown names, malformed arguments, identity mismatch, missing evidence, or any effective `reasoning_effort` field.

Before (`apps/edge/internal/service/single_request.go:824`):

```go
case SingleRequestStateWorking:
    return to == SingleRequestStateInternalTool || to == SingleRequestStateReviewing || ...
```

After (new runner behavior):

```go
plan := ctrl.ReadInternalArtifact(ctx, edgeservice.SingleRequestArtifactPlan)
// working -> internal_tool -> working repeats until a bounded completion candidate
```

**Modified Files and Checklist**

- [ ] Add Work prompt, tool-schema projection, multi-turn message assembly, strict completion decode, and result DTO in `apps/edge/internal/openai/single_request_work_stage.go`.
- [ ] Reuse the predecessor's provider codec and controller artifact API; do not bypass coordinator budgets or send workspace wire directly.
- [ ] Add deterministic initial/tool-result/resumed body assertions and completion parsing in `apps/edge/internal/openai/single_request_work_stage_test.go`.

**Test Strategy**

Write `TestSingleRequestWorkStageWritesAndVerifies`: fake ornith-fast first requests `workspace_write`, then an approved verification command, then returns completion/verification JSON. Assert PLAN bytes are included, each provider request targets the frozen Work route, no request contains `reasoning_effort`, tool results retain exact identities, and the completion DTO is bounded. Add table-driven malformed/multiple/unknown/tool-failure/provider-error/cancel cases.

**Verification**

Run `go test -race ./apps/edge/internal/openai -run 'TestSingleRequestWork(Stage|ToolBridge)' -count=1`; S09 and all failure/correlation fixtures pass.

### [API-3] Keep the service coordinator contract intact

**Problem**

The new runner depends on the service-owned tool state machine and cleanup gates. A locally passing fake-controller loop could still violate saved-stage transitions, max-iteration/output enforcement, cancel propagation, or cleanup ordering when used with the real coordinator.

**Solution**

Add an interoperability fixture that drives the Work runner through the existing controller contract and typed continuation surface. It must observe `working -> internal_tool -> working`, exact call/result identity, existing budget failures, caller cancellation, and no terminal cleanup regression. Do not modify service state transitions unless a compile mismatch proves a narrowly required adapter change; any such change is outside this plan and must be recorded as a deviation/blocker rather than silently expanded.

**Modified Files and Checklist**

- [ ] Add coordinator-compatible fake controller/envelope assertions to `apps/edge/internal/openai/single_request_work_stage_test.go`.
- [ ] Re-run existing `apps/edge/internal/service` tool-loop and cleanup packages unchanged as the service compatibility oracle.

**Test Strategy**

No new service test file is planned because the state-machine behavior is already covered exhaustively. The new OpenAI fixture proves the runner speaks that interface, and existing service tests are required final verification.

**Verification**

Run `go test ./apps/edge/internal/service -run 'TestSingleRequest(InternalToolLoop|Cleanup)' -count=1`; existing coordinator invariants remain green.

### [API-4] Record Work as implemented but inactive

**Problem**

After this packet the implementation spec must no longer say all provider stage drivers are absent, but Review/repair and production activation are still missing.

**Solution**

Update the spec with the implemented PLAN-read, ornith-fast option isolation, private tool continuation, completion/verification schema, and deterministic S09 fixture. Preserve the explicit deferral for Review/repair, composite installation, and S12 external evidence.

**Modified Files and Checklist**

- [ ] Update `agent-spec/runtime/edge-node-execution.md` implementation, verification, limitation, and history text.

**Test Strategy**

No document-only test; behavior is backed by API-1 through API-3.

**Verification**

Run `rg --sort path -n 'ornith-fast|Work stage|reasoning_effort|Review|not installed|deferred' agent-spec/runtime/edge-node-execution.md`; statements must match the partial implementation state.

## Modified Files Summary

| File | Items |
|------|-------|
| `apps/edge/internal/openai/single_request_work_stage.go` | API-1, API-2 |
| `apps/edge/internal/openai/single_request_work_stage_test.go` | API-1, API-2, API-3 |
| `agent-spec/runtime/edge-node-execution.md` | API-4 |
| `agent-task/m-iop-owned-single-request-agent-execution/19+18_work_stage/CODE_REVIEW-cloud-G08.md` | API-1, API-2, API-3, API-4 |

## Final Verification

Fresh output is required; Go tests use `-count=1` and cached output is not acceptable.

1. `test -f agent-task/m-iop-owned-single-request-agent-execution/18+17_plan_stage/complete.log` — predecessor completion evidence exists before implementation or review.
2. `go test -race ./apps/edge/internal/openai -run 'TestSingleRequestWork(Stage|ToolBridge)' -count=1` — S09, continuation correlation, cancellation, and failure fixtures pass without races.
3. `go test ./apps/edge/internal/service -run 'TestSingleRequest(InternalToolLoop|Cleanup)' -count=1` — existing coordinator/tool/cleanup invariants pass freshly.
4. `go vet ./apps/edge/internal/openai && go test ./apps/edge/... -count=1` — OpenAI vets cleanly and broader Edge regression passes.
5. `rg --sort path -n 'reasoning_effort' apps/edge/internal/openai/single_request_work_stage.go apps/edge/internal/openai/single_request_work_stage_test.go` — production code contains only explicit rejection/omission logic and tests prove no effective Work request field.
6. `rg --sort path -n 'SetSingleRequestExecutor|NewSingleRequestExecutor' apps/edge --glob '*.go'` — no production composite installation exists yet.
7. `rg --sort path -n 'ornith-fast|Work stage|Review|not installed|deferred' agent-spec/runtime/edge-node-execution.md` — spec records Work as implemented and later activation/review/external evidence as deferred.
8. `git diff --check` — no whitespace errors.

Actual provider/Claude full-cycle evidence remains intentionally outside this packet and belongs to SDD S12 `claude-smoke`.

After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
