<!-- task=m-iop-owned-single-request-agent-execution/07+04_workspace_catalog plan=1 tag=REVIEW_API milestone-task=workspace-binding -->

# Code Review Reference - REVIEW_API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `Implementation Checklist`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> Execute the plan's selected root cause, scope, files, and dependency decisions as written. Do not choose another owner, narrow/expand the write boundary, or replace a fix with another verification attempt.
> If implementation is blocked, record the exact blocker, attempted commands/output, and resume condition only in implementation-owned evidence fields.
> Do not ask the user directly, present choices, call user-input tools, create control-plane stop files, or classify the next state.
> Finalization (`Code Review Result`, log rename, `complete.log`, archive moves, `Review-Only Checklist`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## Overview

date=2026-08-06
task=m-iop-owned-single-request-agent-execution/07+04_workspace_catalog, plan=1, tag=REVIEW_API

## Archive Evidence Snapshot

- Prior plan: `agent-task/m-iop-owned-single-request-agent-execution/07+04_workspace_catalog/plan_local_G06_0.log`
- Prior review: `agent-task/m-iop-owned-single-request-agent-execution/07+04_workspace_catalog/code_review_cloud_G07_0.log`
- Verdict: FAIL with Required R1-R4, no Suggested or Nit findings.
- R1: direct `LoadFromConfig` accepts duplicate workspace refs and lacks the planned NodeStore regression tests.
- R2: `ResolveWorkspace` returns the store-owned `*NodeRecord`, allowing mutation of `Workspaces` after the lock is released.
- R3: zero limits admit enabled operations without effective byte or timeout bounds, contrary to the bounded-capability plan and SDD D06.
- R4: contract/spec/example wording incorrectly forbids the future dedicated Node-private capability payload required by SDD D03/D08.
- Reviewer verification: focused config, focused race, package, vet, and whitespace commands exited 0, but the NodeStore focused pattern reported `[no tests to run]`; `review_rework_count=1`, `evidence_integrity_failure=true`.
- Roadmap carryover: keep `milestone-task=workspace-binding`; this packet contributes the catalog foundation for S04 and does not assert the full Milestone Task complete.

## For the Review Agent

> **[REVIEW AGENT ONLY]** The finalization steps below are review-agent only. Implementing agents must not execute this section.

Compare implementation of each item against source files and verify that output in `Verification Results` matches code.
Review completion means the following steps are finished:

1. Append verdict and `review_rework_count` / `evidence_integrity_failure` routing signals.
2. Archive `CODE_REVIEW-cloud-G07.md` → `code_review_cloud_G07_1.log` and `PLAN-cloud-G07.md` → `plan_cloud_G07_1.log`.
3. If PASS, write `complete.log` and move active task directory to `agent-task/archive/YYYY/MM/m-iop-owned-single-request-agent-execution/07+04_workspace_catalog/`. If WARN/FAIL, fully write the next filesystem state required by the code-review skill.
4. If PASS and task group is `m-<milestone-slug>`, preserve the first-line `milestone-task` metadata in `complete.log` and report it for the runtime aggregation event. Roadmap state evaluation belongs to `sync-milestone-workstate`.
5. Check applicable `Review-Only Checklist` items at the final `.log` location before reporting.

---

## Implementation Item Completion

| Item | Status |
|------|---------|
| REVIEW_API-1 Close direct-load and lookup ownership gaps | [x] |
| REVIEW_API-2 Restore effective bounds and the private payload contract | [x] |

## Implementation Checklist

- [x] Enforce canonical unique workspace refs in direct `LoadFromConfig` and ensure `ResolveWorkspace` returns no mutable workspace-catalog aliases.
- [x] Require positive effective bounds for every enabled workspace operation while preserving existing absolute maxima and empty-catalog compatibility.
- [x] Align the config example, inner contract, and living spec with effective bounds and the deferred private Node payload boundary without claiming wire or executor implementation.
- [x] Add targeted NodeStore/config regressions and run focused race, package, vet, documentation, formatting, and whitespace verification.
- [x] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

## Review-Only Checklist

> **[REVIEW AGENT ONLY]** This checklist is used only by the review agent.
> Implementing agents must not modify or check this section.

- [x] Append one verdict of `PASS`, `WARN`, or `FAIL` and verified `review_rework_count`, `evidence_integrity_failure` to `Code Review Result`.
- [x] Verify that verdict, `Dimension Assessment`, and Required/Suggested/Nit classifications match.
- [x] Archive active `CODE_REVIEW-*-G??.md` to `code_review_cloud_G07_1.log`.
- [x] Archive active `PLAN-*-G??.md` to `plan_cloud_G07_1.log`.
- [x] Verify that the Agent-Ops managed block in `.gitignore` unignores `agent-task/**/*.md` and `agent-task/**/*.log` and ignores `agent-roadmap/current.md`.
- [x] If PASS, write `complete.log` based on `agent-ops/skills/common/code-review/templates/complete-log-template.md` and leave no active `.md` files.
- [x] If PASS, move active task directory `agent-task/m-iop-owned-single-request-agent-execution/07+04_workspace_catalog/` to `agent-task/archive/YYYY/MM/m-iop-owned-single-request-agent-execution/07+04_workspace_catalog/` and update this checklist at the final archive path.
- [x] If PASS and task group is `m-<milestone-slug>`, preserve and report `milestone-task` metadata for runtime aggregation, without modifying roadmap or directly calling `update-roadmap`.
- [x] If PASS for split work, remove empty active parent `agent-task/m-iop-owned-single-request-agent-execution/` or verify it was kept due to remaining siblings/files.
- [ ] If WARN/FAIL, write the next filesystem state matching code-review verdict and do not write `complete.log`.

## Deviations from Plan

None.

## Key Design Decisions

- `LoadFromConfig` trims copied workspace refs and owns a global canonical-ref set so direct callers cannot bypass catalog uniqueness.
- `ResolveWorkspace` returns a shallow record copy with a deep-copied workspace catalog and an independently deep-copied matching workspace; existing `FindByID`, `FindByToken`, provider, adapter, and runtime ownership semantics remain unchanged.
- Effective bounds are required only for enabled `read`, `write`, `list`, and `command` operations; `delete` has no separate numeric limit in the approved schema. Existing 1 GiB and one-hour maxima remain unchanged.
- Raw roots and command templates remain excluded from public/preset/provider surfaces. The later Node-private typed config/admission transport is expressly deferred; no wire or executor was added.

## Reviewer Checkpoints

- Confirm direct `LoadFromConfig` rejects empty and canonical duplicate workspace refs within and across nodes.
- Confirm source config, returned workspace, and returned owner catalog mutations cannot affect later resolution.
- Confirm every enabled read/list/write/command capability has its required positive effective bounds and current absolute maxima.
- Confirm docs prohibit public/preset/provider exposure while leaving the later dedicated Node-private typed boundary explicitly deferred.
- Confirm no protobuf, filesystem, command execution, admission generation, or coordinator behavior was added.

## Verification Results

Paste actual stdout/stderr for every command. If a command changes, record the replacement and reason under `Deviations from Plan`.

### 1. Dependency

`test -f agent-task/m-iop-owned-single-request-agent-execution/04+02_preset_refresh/complete.log || test "$(compgen -G 'agent-task/archive/*/*/m-iop-owned-single-request-agent-execution/04+02_preset_refresh/complete.log' | wc -l)" -eq 1`

```text

```

### 2. Formatting

`test -z "$(gofmt -l packages/go/config/load.go packages/go/config/workspace_config_test.go apps/edge/internal/node/store.go apps/edge/internal/node/store_test.go)"`

```text

```

### 3. Config catalog race tests

`go test -race ./packages/go/config -run '^TestLoadEdgeWorkspaceCatalog' -count=1`

```text
ok  	iop/packages/go/config	1.102s
```

### 4. NodeStore race tests

`go test -race ./apps/edge/internal/node -run 'Test(LoadFromConfig.*Workspace|NodeStore.*Workspace)' -count=1`

```text
ok  	iop/apps/edge/internal/node	1.029s
```

### 5. Refresh race tests

`go test -race ./apps/edge/internal/configrefresh -run '^TestClassifyWorkspace' -count=1`

```text
ok  	iop/apps/edge/internal/configrefresh	1.028s
```

### 6. Focused package regression

`go test ./packages/go/config ./apps/edge/internal/node ./apps/edge/internal/configrefresh -count=1`

```text
ok  	iop/packages/go/config	0.127s
ok  	iop/apps/edge/internal/node	0.022s
ok  	iop/apps/edge/internal/configrefresh	0.040s
```

### 7. Shared/Edge regression

`go test ./packages/go/... ./apps/edge/... -count=1`

```text
ok  	iop/packages/go/audit	0.020s
ok  	iop/packages/go/auth	10.048s
ok  	iop/packages/go/config	0.188s
ok  	iop/packages/go/credentiallease	0.090s
?   	iop/packages/go/events	[no test files]
ok  	iop/packages/go/execution	0.034s
ok  	iop/packages/go/hostsetup	0.030s
?   	iop/packages/go/jobs	[no test files]
?   	iop/packages/go/metadata	[no test files]
ok  	iop/packages/go/observability	0.051s
?   	iop/packages/go/policy	[no test files]
ok  	iop/packages/go/streamgate	0.942s
?   	iop/packages/go/version	[no test files]
ok  	iop/apps/edge/cmd/edge	0.130s
ok  	iop/apps/edge/internal/authprojection	0.033s
ok  	iop/apps/edge/internal/bootstrap	0.477s
ok  	iop/apps/edge/internal/configrefresh	0.089s
ok  	iop/apps/edge/internal/controlplane	6.600s
ok  	iop/apps/edge/internal/edgecmd	0.146s
ok  	iop/apps/edge/internal/edgevalidate	0.046s
ok  	iop/apps/edge/internal/events	0.028s
ok  	iop/apps/edge/internal/input	0.074s
ok  	iop/apps/edge/internal/input/a2a	0.054s
ok  	iop/apps/edge/internal/node	0.052s
ok  	iop/apps/edge/internal/openai	7.962s
ok  	iop/apps/edge/internal/opsconsole	0.044s
ok  	iop/apps/edge/internal/service	5.961s
ok  	iop/apps/edge/internal/transport	4.775s
```

### 8. Vet

`go vet ./packages/go/... ./apps/edge/...`

```text

```

### 9. Documentation search

`rg --sort path -n 'workspaces|workspace_ref|effective|Node-private|restart_required' configs/edge.yaml agent-contract/inner/edge-config-runtime-refresh.md agent-spec/runtime/provider-pool-config-refresh.md`

```text
configs/edge.yaml:86:# are ignored by effective policy resolution.
configs/edge.yaml:494:# workspaces[] is the operator-owned bounded capability catalog for this
configs/edge.yaml:498:# write, list, and command operation requires its effective positive bound:
configs/edge.yaml:502:# Refs must be globally unique across all nodes. An empty workspaces slice
configs/edge.yaml:505:# workspace_ref in execution_presets[].single_request references one of
configs/edge.yaml:508:# The dedicated Node-private config/admission transport is deferred; this
configs/edge.yaml:511:#   workspaces:
configs/edge.yaml:564:#       workspace_ref: "<opaque-workspace-ref>"  # never a raw path or credential
agent-contract/inner/edge-config-runtime-refresh.md:39:- Managed provider credentials are selected only through an authenticated projected route. The effective route binds one principal, slot, profile, upstream model, resource selector, credential revision, route revision, and projection generation; caller metadata and legacy provider-auth headers cannot replace any binding field.
agent-contract/inner/edge-config-runtime-refresh.md:48:- `openai.stream_evidence_gate`는 request-local Recovery Coordinator 기본값·절대 상한·ingress snapshot 제한 설정이다. `enabled`는 지원되는 Chat Completions, normalized Responses, provider tunnel passthrough, provider-pool dispatch, tool-validation recovery를 `packages/go/streamgate` request runtime이 소유하도록 라우팅할지 여부이며 omitted 기본값 false(legacy eager-write path와 legacy tool-validation retry loop를 그대로 유지)이다. `max_request_fault_recovery`는 요청당 전체 fault recovery 상한(`0..3`, omitted 기본값 3, explicit 0은 모든 fault recovery 비활성화)이다. `max_strategy_fault_recovery`는 fault strategy(exact_replay/continuation_repair/schema_repair)별 상한(`0..max_request_fault_recovery`, omitted 기본값은 effective request total 상속, explicit 0은 해당 strategy 비활성화)이며 request-start 시점에 immutable runtime option snapshot으로 각 fault strategy에 동일하게 적용된다. `max_ingress_snapshot_bytes`는 ingress snapshot 바이트 상한(`1..16777216` [16 MiB], omitted/0 기본값 16 MiB)이다. `environment`는 request-start selector snapshot이며 `dev|dev-corp`만 허용하고 omitted 기본값은 `dev`다. `filters[]`는 unique `filter` (`repeat_guard|schema_gate|provider_error`) policy이다. `enabled` omitted=true, `enforcement` omitted=`blocking`, `capability` omitted=`output.<filter>`, `hold_evidence_runes` omitted=500, `timeout_ms` omitted=5000으로 정규화하며 selector는 `environment|model_group|model|provider`로만 filter enablement/enforcement를 보정한다. base-disabled filter도 registry snapshot에 남아 더 구체적인 selector가 활성화할 수 있고, 실제 target에서 활성화된 `blocking` filter만 provider capability admission에 참여한다. `observe_only`는 evidence를 만들지만 admission을 막지 않는다. `repeat_guard` uses the configured rune bound for active request-local history/current-stream inspection and stores only bounded fingerprints, counts, and offsets in its semantic snapshot and observations. `schema_gate` and `provider_error` remain lifecycle foundations until their matcher Tasks; an unmatched provider error never creates exact replay. Config accepts no caller/agent selector.
agent-contract/inner/edge-config-runtime-refresh.md:57:- canonical `provider_pool` key가 없을 때만 legacy `nodes[].providers[].max_queue`/`queue_timeout_ms`를 compatibility 입력으로 읽는다. 참여 provider의 유효 pair가 모두 같으면 root policy로 승격하고, 하나라도 다르면 first-candidate 값을 택하지 않고 load를 거부한다. canonical root key가 있으면 legacy provider queue 값은 effective policy와 refresh diff에 영향을 주지 않는다.
agent-contract/inner/edge-config-runtime-refresh.md:63:- `execution_presets[].single_request`는 operator-owned fixed single-request policy다. 설정 시 preset은 `allowed_modes=["light"]`, `stages=[plan, work, review]`의 승인된 plan→work→review 경로를 고수한다. 절대 상한은 `wall_clock_ms ≤ 1800000`, `timeout_ms ≤ 600000`, `max_tool_iterations ≤ 64`, `max_output_bytes ≤ 16777216`이며 `timeout_ms`는 `wall_clock_ms`를 초과할 수 없다. selector와 plan/review stage는 `reasoning_effort=high`를 강제하고 work stage는 `reasoning_effort`를 선언할 수 없다. `workspace_ref`는 비어있을 수 없으며 raw path, credential, Node id, endpoint를 포함하지 않는다. single_request preset은 `workspace_tools`를 선언할 수 없다. catalog 변경과 mapping 변경은 live-apply로 분류되며 refresh 이후 새로 시작되는 logical request에만 적용된다. admitted single-request binding은 refresh 이후에도 frozen public model, stage binding, workspace reference, limits를 유지한다.
agent-contract/inner/edge-config-runtime-refresh.md:71:- `nodes[].workspaces[]` is the operator-owned bounded capability catalog for each node. Each entry is keyed by a globally unique, trimmed `ref` and declares `platform` (fixed to `darwin`), `root` (absolute clean path other than `/`), closed-set `operations` (`read`, `list`, `write`, `delete`, `command`), approved `commands` (id + fixed executable + fixed args, present iff `command` is in operations), `environment_allowlist` (unique portable env var names), and bounded `max_read_bytes`, `max_write_bytes`, `max_output_bytes`, `max_command_timeout_ms` (each enabled `read`, `write`, `list`, or `command` operation requires its effective positive bound; absolute maxima are 1 GiB / 1 hour). Refs are globally unique across all nodes. An empty workspaces slice is backward-compatible. The catalog is compiled into `NodeRecord.Workspaces` at load time and carried immutably through the store; runtime mutation is restart-required. Raw root paths and command details never enter execution presets, caller-visible responses, provider requests, or public metadata. The dedicated Node-private typed config/admission transport required for later workspace execution is deferred and not implemented by this contract. `workspace_ref` in `execution_presets[].single_request` references one entry by ref.
agent-contract/inner/edge-config-runtime-refresh.md:72:- Config refresh classifies any `nodes[].workspaces` change (root, capability, command template, environment allowlist, or limits) as `restart_required`. Active requests must never observe a root/capability mutation.
agent-contract/inner/edge-config-runtime-refresh.md:75:- `provider_id`와 effective `usage_attribution`은 OpenAI route에서 Edge service dispatch result까지 보존되는 Edge-local attribution binding이다. 기존 `RunRequest`/`ProviderTunnelRequest` protobuf payload에는 새 필드를 추가하지 않으며 Edge-Node wire schema를 바꾸지 않는다.
agent-contract/inner/edge-config-runtime-refresh.md:76:- refresh 결과는 `applied`, `restart_required`, `rejected`를 구분하고, changed node/provider/model/report slice는 안정적으로 non-nil이어야 한다.
agent-contract/inner/edge-config-runtime-refresh.md:81:- restart required: credential-plane/TLS/key references, Edge identity/listen/bootstrap/logging/metrics/console/control-plane/openai/a2a listener config, node 추가/삭제, node token/alias/agent kind, adapter 설정, provider type/category/adapter/models/health/lifecycle capability, provider-first execution fields(`provider`, `endpoint`, `base_url`, `headers`, `command`, `args`, `env`, `mode`, `resume_args`, `output_format`, `context_size`, `request_timeout_ms`) 변경, `nodes[].workspaces` 변경 (root, capability, command template, environment allowlist, limits).
agent-spec/runtime/provider-pool-config-refresh.md:102:| provider snapshot | 일반·long in-flight는 provider lease state, queued 값은 Edge queue에서 해당 provider를 후보로 포함하는 고유 pending request pressure에서 계산한다. offline provider는 catalog identity를 유지하고 effective 수치를 0으로 보고한다. |
agent-spec/runtime/provider-pool-config-refresh.md:110:| fixed single-request policy | `execution_presets[].single_request` declares an operator-owned immutable plan→work→review light path with absolute wall-clock (`≤1800000ms`), stage-timeout (`≤600000ms`), tool-iteration (`≤64`), and output-byte (`≤16MiB`) caps. Selector and plan/review stages require `reasoning_effort=high`; work stage forbids it. `workspace_ref` is opaque (never raw path/credential/Node/endpoint). single_request preset rejects `workspace_tools`. Catalog and mapping changes are live-apply and affect only new request snapshots; admitted bindings retain their frozen values across refresh. |
agent-spec/runtime/provider-pool-config-refresh.md:111:| operator-owned workspace catalog | `nodes[].workspaces[]` is the operator-owned bounded capability catalog for each node. Each entry is keyed by a globally unique, trimmed `ref` and declares `platform` (fixed to `darwin`), `root` (absolute clean path other than `/`), closed-set `operations` (`read`, `list`, `write`, `delete`, `command`), approved `commands` (id + fixed executable + fixed args, present iff `command` is in operations), `environment_allowlist` (unique portable env var names), and bounded `max_read_bytes`, `max_write_bytes`, `max_output_bytes`, `max_command_timeout_ms` (each enabled `read`, `write`, `list`, or `command` operation requires its effective positive bound; absolute maxima are 1 GiB / 1 hour). Refs are globally unique across all nodes. An empty workspaces slice is backward-compatible. The catalog is compiled into `NodeRecord.Workspaces` at load time and carried immutably through `NodeStore.ResolveWorkspace`; runtime mutation is restart-required. Raw root paths and command details never enter execution presets, caller-visible responses, provider requests, or public metadata. The dedicated Node-private typed config/admission transport is deferred and not implemented here. Config refresh classifies any `nodes[].workspaces` change as `restart_required`. Active requests must never observe a root/capability mutation. Filesystem access, admission generation fencing, process execution, and coordinator integration are explicitly deferred to later packets. |
agent-spec/runtime/provider-pool-config-refresh.md:156:- `execution_presets[].single_request` is the operator-owned fixed single-request policy. Absolute caps: `wall_clock_ms ∈ [1, 1800000]`, `timeout_ms ∈ [1, 600000]`, `timeout_ms ≤ wall_clock_ms`, `max_tool_iterations ∈ [1, 64]`, `max_output_bytes ∈ [1, 16777216]`. Stages enforce exactly plan→work→review with `reasoning_effort=high` on selector and plan/review, forbidden on work. `workspace_ref` is opaque (never raw path/credential/Node/endpoint). single_request preset rejects `workspace_tools`. Catalog/mapping changes are live-apply; admitted bindings are snapshot-isolated across refresh.
agent-spec/runtime/provider-pool-config-refresh.md:227:- 2026-08-06: Synchronized the fixed single-request policy (`execution_presets[].single_request`) absolute caps, plan→work→review stage shape, opaque `workspace_ref`, live-apply classification, and snapshot-isolation semantics with current code, contract, and classifier implementation.
agent-spec/runtime/provider-pool-config-refresh.md:228:- 2026-08-06: Required effective positive workspace-operation bounds and clarified that the later Node-private typed config/admission transport is deferred; public/preset/provider surfaces retain no raw workspace roots or command templates.
```

### 10. Whitespace

`git diff --check`

```text

```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

## Section Ownership

| Section | Owner | Note |
|---------|-------|------|
| Header comment, Overview, Review Agent Instructions | Fixed at stub creation | Implementing agent must not modify or execute these (archive, complete.log, and task-directory archive move are review-agent only) |
| Archive Evidence Snapshot | Fixed at stub creation from plan when present | Implementing agent uses it as default prior-loop context; read only the specific archive files cited there when more detail is required |
| Implementation Item Completion (item names) | Fixed at stub creation | Implementing agent checks `[ ]` → `[x]` only |
| Implementation Checklist (item text/order) | Fixed at stub creation from plan | Implementing agent checks `[ ]` → `[x]` only |
| Review-Only Checklist | Review agent only | Implementing agent must not modify or check this section |
| Deviations from Plan, Key Design Decisions | Implementing agent | Replace placeholder text with actual content |
| Reviewer Checkpoints | Fixed at stub creation | Pre-filled from plan |
| Verification Results (section headings + commands) | Fixed at stub creation | Implementing agent fills in command output only; command changes require a `Deviations from Plan` entry |
| Code Review Result | Review agent appends | Not included in stub |

## Code Review Result

- Overall Verdict: PASS
- Dimension Assessment:
  - Correctness: Pass
  - Completeness: Pass
  - Test Coverage: Pass
  - API Contract: Pass
  - Code Quality: Pass
  - Implementation Deviation: Pass
  - Verification Trust: Pass
  - Spec Conformance: Pass
- Findings: None
- Routing Signals:
  - review_rework_count=1
  - evidence_integrity_failure=false
- Next Step: Archive the active pair, write `complete.log`, move this split task to the monthly archive, and report the Milestone completion event metadata for runtime aggregation.
