# Factory GPT Engine Integration — request

audience: AI coding agents first.

**Goal:** Make existing Factory Pi engine carry Sol session identity, preserve typed provider failures/retry semantics, expose honest usage/trace, and ship four GPT presets without weakening self-write protection.

**Context:** Master contract: `docs/plans/2026-08-11-factory-gpt-model.md`. Provider contract: `docs/plans/2026-08-11-factory-gpt-provider-runtime.md`. This lane MUST be implemented by authorized non-Factory worker because it modifies `modules/harness/factory/**`.

## Files

- Modify `modules/harness/factory/adw_modules/agent_pi.py` — derived session child env, typed provider failure extraction, estimated usage/context handling.
- Modify `modules/harness/factory/adw_modules/agents.py` — retry classification and exact terminal receipt while preserving Pi lifecycle/Report/gates.
- Modify `modules/harness/factory/adw_modules/data_types.py` only for pinned `ProviderFailure`/result fields; preserve `AgentConfig.coding_agent: Literal["pi", "claude_code"]`.
- Modify `modules/harness/factory/adw_modules/tracer.py` — payload-first provider/session/context/billing fields; use `MIGRATIONS` only if queryable columns are proven necessary.
- Modify `modules/harness/factory/adw_modules/watch.py` — render typed terminal failure/context estimate in terminal watcher.
- Create `modules/harness/factory/presets/gpt-sol-medium.yaml`.
- Create `modules/harness/factory/presets/gpt-sol-high.yaml`.
- Create `modules/harness/factory/presets/gpt-sol-xhigh.yaml`.
- Create `modules/harness/factory/presets/gpt-sol-pro.yaml`.
- Modify `modules/harness/factory/tests/test_agent_pi.py` — child env, typed errors, estimated usage, cancellation.
- Modify `modules/harness/factory/tests/test_agent_attempts.py` — exact retry suppression, usage classification, and terminal receipts.
- Modify `modules/harness/factory/tests/test_presets.py` — four preset overlays and account-materialized provider discovery.
- Create `modules/harness/factory/tests/test_gpt_provider.py` — deterministic fake-provider full loop, error/retry/context/cancellation integration.
- Modify `apps/web/src/lib/factory-types.ts` — typed provider/session/context fields.
- Modify `apps/web/src/components/factory/FactoryRunMetadata.tsx` — provider/model/effort/host/account/session/readiness metadata.
- Modify `apps/web/src/components/factory/FactoryTraceTables.tsx` and `FactoryEventTable.tsx` — queue/tool/repair/failure/context/billing display using existing components.
- Modify `apps/web/src/components/factory/FactoryTraceTables.test.tsx`, `FactoryContent.test.tsx`, and `factory-helpers.test.ts` — required fields, typed failures, and honest unavailable states.

Before UI edits, read `.claude/skills/od-ui-dev/SKILL.md`. Reuse existing `@overdeck/deck-ui`/primitives and tokens; NEVER add primitive.

## Contract

Child session metadata:

```text
source: PiRequest.session_id
env: OVERDECK_PI_CLIENT_SESSION
value: v1.<base64url-no-padding(SHA-256(UTF-8 session_id))>
validation: ^v1\.[A-Za-z0-9_-]{43}$
```

Compute before spawn; add only to Pi child environment built by `operator_env`; invalid/empty source fails before process. Derived value is non-secret and inherited by Pi tool children. Preserve retries/session ID.

Provider failure:

```text
ProviderFailure = {
  kind: capped | unavailable | protocol | context_overflow | timeout | cancelled,
  detail: string,
  retry_after_seconds?: int,
  resume_at?: string
}
```

Preserve this shape in `agent_attempt_end` and terminal event payload. Never classify `capped|unavailable|protocol` as context overflow. Never immediately retry `capped|unavailable|protocol`; cap terminates visibly with `resume_at`. Timeout/cancellation retain existing process-group terminal-once invariants. No fallback or effort downgrade.

Usage:

```text
context_window=120000
max_tokens=16000
usage_estimated=true
billing_status="unavailable"
cost=null
```

Do not add estimated usage to monetary totals as measured cost. Existing non-GPT providers retain current usage/cost semantics.

Each preset overlays exactly `planner|builder|scout|reviewer|documenter` without truncating roster or changing accounts:

```yaml
seats:
  planner: {model: gpt/sol-web-<effort>, thinking: off}
  builder: {model: gpt/sol-web-<effort>, thinking: off}
  scout: {model: gpt/sol-web-<effort>, thinking: off}
  reviewer: {model: gpt/sol-web-<effort>, thinking: off}
  documenter: {model: gpt/sol-web-<effort>, thinking: off}
```

Keep `coding_agent: pi`; preserve seat accounts. Unsupported/missing model fails config validation/resolution.

UI must visibly distinguish:

- declared coding agent/provider/model/effort;
- Pi session and derived Sol client session;
- host/account/provider health, seats/active/queue/cap resume;
- tool/protocol repair/Report correction/gate events;
- typed failure and timeout/cancellation;
- context occupancy labeled estimate;
- billing/cost labeled unavailable.

No fabricated values. Missing legacy fields render honest unknown/unavailable, not zero.

## Behavior

- Preserve `agent_pi.run` state machine: starting, streaming, terminating, terminal; one terminal receipt.
- Preserve standard Pi tool schemas, process group, raw output, same-session Report correction, write enforcement, gates.
- Preserve `claude_code` schema compatibility.
- Factory agents remain unable to write `modules/harness/factory/**`; tests assert protection unchanged.
- Provider/runtime readiness remains wrapper responsibility; direct `factory --preset` failure still produces exact typed provider receipt.
- Carry new observability in existing trace event payload/`usage_json`; do not add trace DB columns or edit shipped table definitions.

## Out of scope

- New `coding_agent` backend, `agent_gpt.py`, generic backend abstraction.
- gptbridge browser/service implementation.
- `ask-gpt --factory`, attachments, action JSON, automatic cap scheduler.
- New UI primitive, unrelated Factory refactor, permission weakening.

## Acceptance

Run clean:

```text
python3 -m pytest modules/harness/factory/tests/ -q
pnpm --filter web test
pnpm --filter web typecheck
pnpm --filter web build
```

Deterministic fake-provider integration proves:

- exact derived session header source survives retry and differs across identical concurrent sessions;
- tool call/result/final Report path mutates isolated fixture and gates pass;
- capped/unavailable/protocol failures make zero forbidden retries and preserve metadata;
- context overflow causes installed Pi compaction/replay or fails exact kill-gate contract;
- cancellation sends process-group termination once and records terminal event once;
- GPT estimated usage never increments measured cost;
- all four presets resolve provider models in default and account-composed Pi directories;
- `/factory` component tests show all required fields and honest unavailable states.

No live Sol model call. Integrated installed proof occurs only after provider-runtime lane passes.
