<!-- task=m-iop-agent-cli-runtime/15+13_project_logs plan=0 tag=API -->

# Durable Project Logs and WORK_LOG Timeline

## For the Implementing Agent

Fill every implementation-owned section in `CODE_REVIEW-cloud-G08.md`, including actual command output. Keep active files in place and report ready for review; only the review agent finalizes. Record blockers and resume conditions in evidence fields without asking the user or creating control-plane artifacts.

## Background

The shared manager emits normalized events and durable locators, but the standalone host has no project-local presentation/recovery log. S12 requires stable loop, attempt, locator, and completion archive evidence even through retries, parallel work, and restart.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md`
- Milestone link: [Milestone 문서](agent-roadmap/phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md)
- Task ids:
  - `project-logs`: project-local event/log plus WORK_LOG loop/attempt/locator and exactly-once archive lifecycle
- Completion mode: check-on-pass

## Analysis

### Files Read

- `agent-roadmap/phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md`
- `agent-roadmap/sdd/automation-runtime-bridge/iop-agent-cli-runtime/SDD.md`
- `agent-contract/inner/agent-runtime.md`
- `agent-contract/inner/iop-agent-cli-runtime.md`
- `packages/go/agenttask/ports.go`
- `packages/go/agenttask/types.go`
- `packages/go/agentstate/store.go`
- `packages/go/agentconfig/runtime_config.go`
- `agent-ops/skills/project/orchestrate-agent-task-loop/SKILL.md`

### SDD Criteria

The approved SDD scenario S12 maps to `project-logs`. Its Evidence Map requires a WORK_LOG loop/attempt/locator fixture, dynamic frontier behavior, and archive reconciliation. PASS evidence must show 11 retries/follow-ups for one task, an independent parallel task, separate archive ordinal, stable identities, and terminal-only exactly-once archive/cleanup.

### Verification Context

No handoff was supplied. Local rules are `agent-test/local/rules.md` plus the platform-common and testing smoke profiles. Use fresh focused tests, an agentstate/projectlog race run, filesystem restart fixtures, `go vet`, and `git diff --check`; cached output is not acceptable. No external service or secret is required.

### Test Coverage Gaps

- `agentstate.Store` has checksum/CAS tests but no typed project-log journal.
- `agenttask.EventSink` defaults to a no-op and has no durable standalone adapter.
- Dispatcher WORK_LOG tests are Python-specific and do not prove Go host restart/archive behavior.

### Symbol References

None. The new adapter implements the existing `agenttask.EventSink` without changing that interface.

### Split Judgment

The packet has one invariant: an accepted append and terminal archive must share one CAS-governed project journal so restart cannot duplicate or lose logical records. It depends only on index 13; `13_standalone_host_foundation` has no active or archived `complete.log` yet. CLI and local control are not dependencies because the sink exposes a stable adapter contract.

### Scope Rationale

Do not parse provider raw output, duplicate task-manager transitions, mutate `agent-task/**`, or store credentials/raw unbounded streams. Do not change the Python dispatcher; it is only behavioral reference. Do not add UI rendering.

### Final Routing

- evaluation_mode: `first-pass`
- finalizer: `finalize-task-policy.sh pair`
- build: `local-G08`, basis `local-fit`, filename `PLAN-local-G08.md`
- review: `cloud-G08`, basis `official-review`, filename `CODE_REVIEW-cloud-G08.md`
- large_indivisible_context: `false`
- positive loop risks: `CAS/archive crash windows`, `retry/parallel identity matrix` (count `2`)
- recovery signals: rework `0`, evidence-integrity failure `false`
- capability-gap evidence: none

## Implementation Checklist

- [ ] Define a versioned, bounded ProjectLogRecord and stable project/work/attempt/locator identity schema.
- [ ] Implement CAS-backed append, retention, replay, terminal archive, and restart reconciliation over device-local roots.
- [ ] Implement the agenttask EventSink adapter and deterministic WORK_LOG projection without raw provider output.
- [ ] Prove the S12 11-retry, parallel-task, ordinal, crash-window, and exactly-once archive matrix under the race detector.
- [ ] Update the standalone contract with actual S12 source/test paths and verification evidence.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [API-1] Define Stable Project Log Records

#### Problem

`agent-contract/inner/iop-agent-cli-runtime.md:50-61` describes `ProjectLogRecord`, while `packages/go/agenttask/types.go:266-403` contains the normalized identities/events, but no concrete bounded record exists.

#### Solution

Add a versioned record with project/work/attempt identity, loop and dispatch ordinals, event type, safe route/quota status, typed locator references, state revision, timestamp, and terminal marker. Validate IDs and cap message/metadata sizes. Never persist credentials, raw environment, or raw provider output.

#### Modified Files and Checklist

- [ ] `apps/agent/internal/projectlog/record.go` — define/validate immutable records and archive manifests.
- [ ] `apps/agent/internal/projectlog/record_test.go` — cover valid, malformed, oversized, and secret-bearing inputs.

#### Test Strategy

Write `TestRecordValidationMatrix` and `TestRecordRejectsSensitiveOrUnboundedFields`.

#### Verification

```bash
go test -count=1 ./apps/agent/internal/projectlog -run 'TestRecord'
```

Expected: normal and boundary matrices pass.

### [API-2] Implement CAS Journal and Archive Reconciliation

#### Problem

`packages/go/agentstate/store.go:50-136` supports opaque CAS integration records, but no project-log adapter uses it to coordinate append, retention, or archive state.

#### Solution

Use one namespaced integration record per project as the logical journal. Append by CAS with bounded retry, assign monotonic sequence and independent archive ordinal, prune only per configured retention after terminal evidence, and materialize redacted JSONL/timeline files using temp-file sync/rename. Persist archive intent/checksum before cleanup; on restart, reconcile a matching artifact idempotently and fail closed on conflicting content.

#### Modified Files and Checklist

- [ ] `apps/agent/internal/projectlog/store.go` — implement append/replay/archive/reconcile.
- [ ] `apps/agent/internal/projectlog/store_test.go` — cover CAS conflict, retention, crash phases, restart, and exactly-once output.

#### Test Strategy

Use temp roots and real `agentstate.Store`. Inject failures before write, after artifact rename, before manifest commit, and before cleanup. Assert one logical archive and unchanged evidence on replay.

#### Verification

```bash
go test -count=1 ./apps/agent/internal/projectlog -run 'TestStore|TestArchive|TestReconcile'
```

Expected: all crash/restart cases converge or fail closed without duplicates.

### [API-3] Add Event Sink and WORK_LOG Projection

#### Problem

`packages/go/agenttask/ports.go:345-350` permits an `EventSink`, but the standalone host has no durable implementation or human-readable timeline.

#### Solution

Implement `agenttask.EventSink` by normalizing manager events into journal records. Project a stable chronological WORK_LOG view with loop, attempt, role/stage, result, and locators while keeping raw streams external. Make projection a pure function of the durable journal so restart output is reproducible.

#### Modified Files and Checklist

- [ ] `apps/agent/internal/projectlog/sink.go` — implement the event adapter and projection.
- [ ] `apps/agent/internal/projectlog/sink_test.go` — cover mapping and deterministic output.

#### Test Strategy

Write `TestSinkMapsEveryEventType` and `TestTimelineProjectionIsStableAndRedacted`.

#### Verification

```bash
go test -count=1 ./apps/agent/internal/projectlog -run 'TestSink|TestTimeline'
```

Expected: all normalized event types are handled with stable ordering.

### [API-4] Prove the S12 Matrix

#### Problem

`agent-roadmap/sdd/automation-runtime-bridge/iop-agent-cli-runtime/SDD.md:154,179` requires the 11-attempt loop, independent parallel loop, archive ordinal separation, and terminal closure, but no Go test reproduces that matrix.

#### Solution

Add a single integration fixture that appends 11 failed/retry/follow-up attempts for task A while task B advances independently, restarts stores between selected phases, closes both tasks in different orders, and asserts distinct exactly-once archives plus retained locator identity.

#### Modified Files and Checklist

- [ ] `apps/agent/internal/projectlog/store_test.go` — add `TestS12LoopParallelArchiveMatrix`.
- [ ] `agent-contract/inner/iop-agent-cli-runtime.md` — add S12 actual source/test entries.

#### Test Strategy

The named fixture is mandatory and must use real files plus concurrent goroutines. Run it with `-race`.

#### Verification

```bash
go test -count=1 -race ./apps/agent/internal/projectlog -run TestS12LoopParallelArchiveMatrix
```

Expected: one archive per terminal task, independent ordinals, 11 preserved attempts, no duplicate records.

## Dependencies and Execution Order

Predecessor index 13 must complete at `agent-task/m-iop-agent-cli-runtime/13_standalone_host_foundation/complete.log` or its exact same-group archive path before work begins. Complete API-1 before API-2/API-3; API-4 follows both.

## Modified Files Summary

| File | Item |
|------|------|
| `apps/agent/internal/projectlog/record.go` | API-1 |
| `apps/agent/internal/projectlog/record_test.go` | API-1 |
| `apps/agent/internal/projectlog/store.go` | API-2 |
| `apps/agent/internal/projectlog/store_test.go` | API-2, API-4 |
| `apps/agent/internal/projectlog/sink.go` | API-3 |
| `apps/agent/internal/projectlog/sink_test.go` | API-3 |
| `agent-contract/inner/iop-agent-cli-runtime.md` | API-4 |

## Final Verification

```bash
gofmt -w apps/agent/internal/projectlog/*.go
go test -count=1 ./apps/agent/internal/projectlog
go test -count=1 -race ./apps/agent/internal/projectlog ./packages/go/agentstate
go vet ./apps/agent/internal/projectlog
git diff --check
```

Expected: fresh and race suites pass, archives are exactly once, and no secret/raw-output field is persisted. After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
