<!-- task=m-iop-agent-cli-runtime/20+13,17_project_log_journal plan=0 tag=API -->

# Code Review Reference - API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is mandatory.**
> Fill implementation evidence and actual outputs, then stop with active files in place. Review finalization is not an implementation action.

## Overview

date=2026-07-29
task=m-iop-agent-cli-runtime/20+13,17_project_log_journal, plan=0, tag=API

## For the Review Agent

> **[REVIEW AGENT ONLY]** Implementing agents must not execute finalization.

Compare source and actual evidence. Append verdict/signals; archive `CODE_REVIEW-cloud-G08.md` → `code_review_cloud_G08_0.log` and `PLAN-local-G08.md` → `plan_local_G08_0.log`; on PASS write `complete.log` and archive the task; on WARN/FAIL materialize the next state.

## Implementation Item Completion

| Item | Status |
|------|--------|
| API-2 CAS journal/archive | [x] |

## Implementation Checklist

- [x] Implement CAS-backed append, retention, replay, terminal archive, and restart reconciliation over device-local roots.
- [x] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Review-Only Checklist

> **[REVIEW AGENT ONLY]** Implementing agents must not modify this checklist.

- [x] Append one verdict and verified routing signals.
- [x] Verify verdict, dimensions, and finding classifications.
- [x] Archive this review as `code_review_cloud_G08_0.log`.
- [x] Archive the plan as `plan_local_G08_0.log`.
- [x] Verify the Agent-Ops managed `.gitignore` block.
- [ ] If PASS, write canonical `complete.log` and leave no active Markdown files.
- [ ] If PASS, move this task directory to the dated archive and update this checklist there.
- [ ] If PASS, remove an empty split parent or prove siblings/files remain.
- [x] If WARN/FAIL, materialize the required next state without `complete.log`.

## Deviations from Plan

None. The implementation follows the plan scope exactly: CAS-backed append with bounded retry, retention only after terminal evidence, restart-safe JSONL/timeline materialization via temp-file sync/rename, archive intent/checksum persistence before cleanup, and idempotent reconciliation that fails closed on conflicting content. The S12 event-sink mapping, WORK_LOG projection, and 11-retry parallel scenario are left to the next child as specified.

## Key Design Decisions

- One namespaced CAS integration record per project (`projectlog:<projectID>:<workspaceID>`) holds the append-only journal: schema version, next monotonic sequence, last committed archive ordinal, and the un-archived record list.
- `AppendRecord` validates the record, assigns the next sequence, and CAS-appends with bounded retry (16 attempts) on `agenttask.ErrRevisionConflict`.
- `Archive` writes the archive intent first (crash-recovery anchor), then materializes redacted JSONL and timeline files via `writeTemp` + `sync` + `os.Rename` + `syncDir`, then writes the manifest to a temp file and commits via rename, then prunes the journal. Four failure-injection phases map to the plan's crash windows: `archive_before_write`, `archive_after_rename`, `archive_before_manifest`, `archive_before_cleanup`.
- `Reconcile` scans for `.intent` files. If the manifest is missing it recomputes the checksum from the JSONL and verifies against the intent; matching content converges idempotently (writes manifest, prunes journal), conflicting content fails closed with `ErrArchiveConflict`. If neither manifest nor JSONL exists it returns `ErrArchiveIncomplete`.
- `reconcilePrune` only clears the journal when the first and last sequence match the intent range, preventing accidental loss of new appends. It retries on CAS conflict.
- Archive artifacts are stored under a SHA-256-derived directory name to avoid path injection from user-supplied project/workspace IDs.
- The timeline file is a redacted projection (sequence, timestamp, event_type, state, terminal, message) excluding locators, route status, quota observations, and metadata.
- `Archive` on an empty journal is a no-op, providing exactly-once archive semantics across restarts.

## Reviewer Checkpoints

- Accepted append, archive intent, artifact materialization, manifest commit, and cleanup are CAS/restart safe.
- Retention never removes required terminal evidence early.
- Matching restart artifacts converge idempotently; conflicting content fails closed.

## Verification Results

### Formatting

```bash
gofmt -w apps/agent/internal/projectlog/store.go apps/agent/internal/projectlog/store_test.go
```

```
(no output — all files already formatted)
```

### Focused and race tests

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

```
ok  iop/apps/agent/internal/projectlog  0.310s
ok  iop/apps/agent/internal/projectlog  1.374s
ok  iop/packages/go/agentstate  1.080s
```

### Static checks

```bash
go vet ./apps/agent/internal/projectlog
git diff --check
```

```
(no output — vet clean, no diff issues)
```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING]** Fill every implementation-owned section and leave review-only content unchanged.

## Section Ownership

| Section | Owner | Note |
|---------|-------|------|
| Header, Overview, Review Instructions | Fixed | Implementer must not modify |
| Implementation Item Completion, Implementation Checklist | Implementing agent | Check status only |
| Review-Only Checklist | Review agent | Implementer must not modify |
| Deviations, Decisions, Verification Results | Implementing agent | Record actual evidence |
| Reviewer Checkpoints | Fixed | Reviewer verifies them |
| Code Review Result and finalization | Review agent | Append/execute only after review |

## Code Review Result

- Overall Verdict: FAIL
- Dimension Assessment:
  - Correctness: Fail
  - Completeness: Fail
  - Test Coverage: Fail
  - API Contract: Fail
  - Code Quality: Pass
  - Implementation Deviation: Fail
  - Verification Trust: Pass
  - Spec Conformance: Fail
- Findings:
  - Required — `apps/agent/internal/projectlog/store.go:141`: `AppendRecord` validates `Sequence` before assigning the journal-owned sequence at line 164, so an otherwise valid record with the natural unassigned value `Sequence == 0` is rejected with `ErrInvalidIdentity`. The focused reviewer reproducer failed before any CAS write. Split caller validation from persisted-record validation or assign the candidate sequence before final validation, and add a regression proving callers do not have to guess a sequence that the store overwrites.
  - Required — `apps/agent/internal/projectlog/store.go:378`: when a manifest exists, reconciliation compares only `m.Checksum` to the intent and never requires or hashes the JSONL; it also accepts a missing timeline at lines 417-420. Focused reviewer variants deleting or tampering with committed JSONL both returned `nil` and pruned the only retained journal evidence. Validate the intent schema/identity/ordinal/range, call `ArchiveManifest.Validate`, compare all intent/manifest identity fields, require and decode/hash the JSONL, and reconstruct or verify the timeline before cleanup. Add missing/tampered JSONL, manifest-field drift, and missing/tampered timeline regressions.
  - Required — `apps/agent/internal/projectlog/store.go:425`: `reconcilePrune` removes records only when the entire current journal exactly matches the archived range. A CAS append between manifest commit and cleanup leaves the archived prefix plus the new record in the journal; reconciliation returns success without advancing the ordinal or pruning the verified prefix, and the retained early terminal record prevents a later archive. After verifying the archive content, CAS-remove the exact matching prefix while preserving concurrent suffix records and advance the archive ordinal; add a deterministic append-at-`archive_before_cleanup` regression.
  - Required — `apps/agent/internal/projectlog/store.go:490`: the integration-record key concatenates two unrestricted identities with `:`, so tuples such as `("a:b", "c")` and `("a", "b:c")` alias the same CAS journal. Loaded journals and appended records are not checked against the `Store` identity, and the focused reviewer reproducer accepted the second tuple into the first tuple's journal. Use collision-safe tuple framing or hashing and validate the journal and appended record identities against the store on every load/write path; add tuple-collision and mismatched-record regressions.
- Routing Signals:
  - review_rework_count=1
  - evidence_integrity_failure=false
- Next Step: Prepare and implement a focused follow-up plan for the four Required findings, then rerun the archive/reconciliation matrix under race.
