공식 리뷰가 지적한 두 가지 승인 경계 결함을 고친다. `plan_file`/`review_file`은
edge.yaml 디렉터리 기준 상대 경로만 허용하고 절대/빈 경로는 파일 접근 전에 거부한다.
필수 heading과 Review `PASS`는 부분 문자열이 아니라 정확한 단독 줄로 검증하며,
문서화된 placeholder를 제거한 뒤 남는 `{{`/`}}`를 거부해 문법을 닫는다.
리뷰가 존재한다고 기술했지만 실제로는 없던 회귀 근거를 추가한다. admission 시
고정된 effective 템플릿 쌍이 clone과 workspace 재검증을 통과하는지, refresh가
이미 승인된 요청이 아니라 새 요청에만 적용되는지, custom Review 템플릿이 내부
artifact만 바꾸고 caller 최종 출력은 그대로인지를 각각 확정 검증한다.
현재 문서도 실제 동작에 맞춘다. Edge 실행 spec의 낡은 Plan JSON Schema 서술을
direct PlanMD 검증으로 고치고, outer Anthropic 계약과 input spec에 템플릿이
Edge 내부 stage 입력일 뿐 caller 요청/응답 계약을 바꾸지 않음을 명시한다.
Refs: agent-task/single_request_plan_review_templates/PLAN-cloud-G08.md
19 KiB
Single-request Template Contract Repair - REVIEW_API
For Implementing Agent: Implement only the checked-in scope below. Do not archive task files, create
complete.log, or start/monitor orchestration. Record actual implementation and verification evidence in the paired code-review file.
Background
The preceding implementation introduced configurable single-request Plan and Review templates, but official review found two admission-boundary defects, material gaps in the prescribed regression suite, and stale public/current documentation. The follow-up keeps the accepted execution architecture intact and repairs only those repository-owned review findings. Caller-visible response schemas, provider selection, and workspace authority remain unchanged.
Archive Evidence Snapshot
- Prior task:
single_request_plan_review_templates, plan0, tagAPI(active origin). - Archived plan:
agent-task/single_request_plan_review_templates/plan_local_G07_0.log. - Archived review:
agent-task/single_request_plan_review_templates/code_review_cloud_G07_0.log. - Prior verdict:
FAIL; Required R1-R4 cover relative-only template file loading, exact static template grammar, missing boundary/snapshot tests, and incomplete contract/spec synchronization. - Verification: the reviewer reran the focused packages, race suite, full Edge/Go suite, and smoke self-test successfully; the failure is based on untested/incorrect boundaries and stale documentation, not a failing existing command.
- Roadmap carryover: none; this is a non-milestone task.
Finding Resolution Map
| Finding | Closure | Direct-fix target | Changed precondition / invariant |
|---|---|---|---|
| R1 | direct-fix | packages/go/config/load.go, config tests |
plan_file and review_file must be non-empty paths relative to the directory containing edge.yaml; absolute paths are rejected before filesystem access. |
| R2 | direct-fix | packages/go/singlerequesttemplate/template.go, template tests |
Required headings and Review PASS are exact standalone lines, and only the documented placeholder inventory may remain in admitted templates. |
| R3 | direct-fix | config, binding, preset-refresh, and Review-stage tests | Every prescribed admission, freeze/clone/revalidation, refresh-isolation, and rendered-artifact boundary has deterministic regression evidence. |
| R4 | direct-fix | outer contract and three current specs | Documentation consistently describes direct PlanMD, frozen effective templates, templated internal Review input, and unchanged caller final-output semantics. |
Analysis
Files Read
agent-ops/rules/project/rules.mdagent-ops/rules/common/rules-roadmap.mdagent-roadmap/current.mdagent-ops/skills/common/router.mdagent-ops/skills/common/code-review/SKILL.mdagent-ops/skills/common/plan/SKILL.mdagent-ops/skills/common/finalize-task-routing/SKILL.mdagent-ops/rules/common/rules-agent-spec.mdagent-ops/rules/project/domain-edge.mdagent-ops/rules/project/domain-platform-common.mdagent-ops/rules/project/domain-testing.mdagent-test/local/rules.mdagent-test/local/smoke/edge.mdagent-test/local/smoke/platform-common.mdagent-test/local/smoke/testing.mdagent-contract/index.mdagent-contract/inner/edge-config.mdagent-contract/outer/anthropic-compatible-api.mdagent-spec/index.mdagent-spec/runtime/provider-pool-config-refresh.mdagent-spec/runtime/edge-node-execution.mdagent-spec/input/openai-compatible-surface.mdpackages/go/singlerequesttemplate/template.gopackages/go/singlerequesttemplate/template_test.gopackages/go/config/load.gopackages/go/config/model_execution_preset_config_test.goapps/edge/internal/service/single_request_types.goapps/edge/internal/service/single_request_types_test.goapps/edge/internal/openai/single_request_preset_binding.goapps/edge/internal/openai/single_request_preset_binding_test.goapps/edge/internal/openai/single_request_plan_stage.goapps/edge/internal/openai/single_request_plan_stage_test.goapps/edge/internal/openai/single_request_review_stage.goapps/edge/internal/openai/single_request_review_stage_test.goagent-task/single_request_plan_review_templates/plan_local_G07_0.logagent-task/single_request_plan_review_templates/code_review_cloud_G07_0.log
SDD / Contract Context
- SDD is not applicable: the accepted architecture is unchanged and this plan repairs review findings within existing contracts.
agent-contract/inner/edge-config.mdalready establishesedge.yaml-relative template files; implementation must converge to that contract rather than broaden it.- The outer Anthropic-compatible API contract must state that template customization affects Edge-owned internal stage inputs only and never changes the caller request/response contract.
Verification Context
- There is no separate handoff. The active plan/review pair, cited archive evidence, current rules, contracts, and specs are the authoritative inputs.
- Fresh reviewer verification of the preceding implementation passed locally: focused package tests, race tests,
go test -count=1 ./apps/edge/... ./packages/go/..., andmake test-single-request-claude-smoke-self-testall exited0. - Archived remote-profile evidence identifies
toki@toki-labs.com,/Users/toki/agent-work/iop-dev, Darwin/arm64, Claude CLI2.1.177, SOPS3.13.1, and implementation commitb6e0080f. A new implementation HEAD must be pushed, synchronized, rebuilt, and rechecked before claiming remote evidence. - The approved SOPS age identity was unavailable in the prior remote environment. If it remains unavailable, record the exact raw failure and resume condition; do not substitute an unrelated provider credential or claim a live smoke pass.
Test Gaps to Close
- Config loading lacks per-file fallback, absolute-path rejection, exact 8192-byte acceptance, symlink/non-regular/unreadable rejection, and a complete invalid-grammar matrix.
- Binding admission lacks an effective-template snapshot and workspace-revalidation/clone preservation evidence.
- Preset refresh lacks proof that already-admitted work keeps frozen templates while newly admitted work receives refreshed templates.
- Review-stage coverage lacks a custom-template rendered-artifact snapshot while preserving caller-visible final output.
Symbol / Text Reference Audit
- No production symbol rename is planned.
- Remove or rewrite stale textual references to Edge-owned Plan
json_schema, strict plan/verification JSON, and stage-owned JSON Schema override protection inagent-spec/runtime/edge-node-execution.md.
Split Decision
- Use one plan. R1-R4 form one compact admission-and-documentation invariant and can be verified by the same focused/full suites. There are no cross-project dependencies or independently releasable subtasks.
Scope Exclusions
- Do not change caller request/response schemas, provider routing, workspace authorization, the Review loop decision model, protobufs, Node packages, UI surfaces, or centrally managed
agent-ops/rules/common/**andagent-ops/skills/common/**. - Do not add a new template syntax or expand the documented placeholder inventory.
- Do not manufacture remote live-smoke evidence when the approved encrypted credential cannot be decrypted.
Final Routing
- Closure booleans: all Required findings are repository-owned and
direct-fix=true; noexternal-follow-uporuser-decisionclosure is needed. - Build scoring: scope
2, state1, blast radius1, evidence2, verification2. - Review scoring: scope
2, state1, blast radius1, evidence2, verification2. - Positive loop risks:
boundary_contract,structured_interpretation,variant_product(3). large_indivisible_context=false;review_rework_count=1;evidence_integrity_failure=true.- Exact finalizer result: build basis
recovery-boundary, buildcloud/G08(PLAN-cloud-G08.md), review basisofficial-review, reviewcloud/G08(CODE_REVIEW-cloud-G08.md). No route-cap gap applies.
Implementation Checklist
- [REVIEW_API-1] Enforce relative-only template loading and exact Plan/Review grammar with boundary regressions.
- [REVIEW_API-2] Add admission, clone/workspace revalidation, preset refresh, and custom Review artifact snapshot tests.
- [REVIEW_API-3] Synchronize current contracts/specs with direct PlanMD, frozen templates, templated internal Review, and unchanged caller output.
- [REVIEW_API-4] Run fresh focused/full/local and remote-profile verification, recording the exact external blocker if the approved SOPS identity remains unavailable.
- Fill implementation-owned sections in
CODE_REVIEW-cloud-G08.mdwith actual implementation notes and verification output.
Implementation Items
REVIEW_API-1 — Close Template Admission Boundaries
Problem
loadTemplateFile accepts absolute paths even though the config contract is relative-only. Template validation uses substring checks for required headings and Review PASS, allowing malformed variants such as ### Plan, ### Review, and NOTPASS; the placeholder grammar is not demonstrably closed.
Solution
- Trim the configured path, reject empty and absolute values before opening anything, then join only the relative path to the directory containing
edge.yaml. - Retain existing regular-file, size, UTF-8, and fallback behavior, but cover both Plan and Review independently.
- Validate required headings and the Review result token as exact standalone lines.
- After accounting for every required placeholder exactly as documented, reject any remaining template delimiters or unknown placeholders.
Before:
target := strings.TrimSpace(relOrAbsPath)
if !filepath.IsAbs(target) {
target = filepath.Join(baseDir, target)
}
After:
target := strings.TrimSpace(relativePath)
if filepath.IsAbs(target) {
return "", fmt.Errorf("template path must be relative to edge.yaml")
}
target = filepath.Join(baseDir, target)
Replace substring grammar checks such as:
if strings.Index(tmpl, "# Plan") < 0 { /* ... */ }
with a line-aware exact matcher and closed-token validation shared by both variants.
Modified Files Checklist
packages/go/singlerequesttemplate/template.gopackages/go/singlerequesttemplate/template_test.gopackages/go/config/load.gopackages/go/config/model_execution_preset_config_test.go
Test Strategy
- Extend
TestValidatePlanTemplateandTestValidateReviewTemplatefor exact headings/result lines, missing/duplicate/unknown placeholders, and delimiter residue. - Extend
TestLoadEdgeSingleRequestTemplatesfor Plan/Review absolute-path rejection, relative success, per-file fallback, exact size boundary, and filesystem-kind failures.
Verification
- Run the focused template/config tests and confirm every malformed variant is rejected without exposing file content in errors.
REVIEW_API-2 — Prove Freeze, Refresh, and Render Semantics
Problem
The preceding review claimed coverage that is absent from the actual test files. The admitted effective template snapshot, clone/workspace revalidation, refresh isolation, and custom Review artifact are therefore not protected against regression.
Solution
- Add deterministic service-level assertions that admitted bindings carry the exact effective Plan/Review template pair through clone and workspace revalidation paths.
- Add preset refresh assertions that existing work retains its frozen templates and newly admitted work observes the refreshed pair.
- Add a Review-stage custom-template snapshot proving internal artifact rendering uses the frozen template while
decision.outputremains the caller-visible final response. - Do not change production behavior unless a new regression exposes a concrete defect.
Modified Files Checklist
apps/edge/internal/service/single_request_types_test.goapps/edge/internal/openai/single_request_preset_binding_test.goapps/edge/internal/openai/single_request_review_stage_test.go
Test Strategy
- Add/extend
TestSingleRequestBindingTemplateSnapshot. - Add/extend
TestSingleRequestPresetBindingTemplateRefreshIsolation. - Add/extend
TestSingleRequestReviewStageCustomTemplateSnapshot. - Assert both the internal rendered artifact and unchanged caller output; do not rely on substring-only assertions where an exact snapshot is stable.
Verification
- Run the named focused packages, then the race suite covering OpenAI stages, service admission, refresh, config, and template validation.
REVIEW_API-3 — Synchronize Current Contracts and Specs
Problem
The current runtime spec still describes a Plan JSON Schema path that the implementation removed. The outer API contract and input spec do not yet document the accepted frozen-template/direct-PlanMD/internal-Review model, leaving the current documentation contradictory.
Solution
- Update the outer Anthropic-compatible contract to describe unchanged caller I/O and Edge-owned internal template customization.
- Update the provider-pool refresh spec with admission-time effective-template freezing and refresh isolation.
- Rewrite stale Plan JSON Schema passages in the Edge execution spec to direct PlanMD validation and templated Review artifact semantics.
- Update the OpenAI-compatible input surface to distinguish internal stage templates from caller-visible input/output.
- Preserve existing terminology and add the required current-spec change records where that spec format requires them.
Modified Files Checklist
agent-contract/outer/anthropic-compatible-api.mdagent-spec/runtime/provider-pool-config-refresh.mdagent-spec/runtime/edge-node-execution.mdagent-spec/input/openai-compatible-surface.md
Test Strategy
- Search the current spec for the known stale Plan JSON Schema phrases and require no matches.
- Cross-check every new statement against the implementation and the inner Edge config contract.
Verification
- Run the documented
rgguard and manually confirm the four surfaces agree on admission, execution, refresh, and caller-output boundaries.
REVIEW_API-4 — Produce Trustworthy Verification Evidence
Problem
The earlier implementation evidence checked off work and named tests/docs that were absent. Local behavior passed, but the recorded completeness and remote live-smoke claims cannot be trusted without fresh evidence.
Solution
- Run every command in Final Verification against the completed working tree and paste actual output into the paired review file.
- Confirm the pushed commit and the remote checkout are identical before a remote rebuild or live smoke.
- If approved SOPS decryption remains unavailable, record the exact failing command, raw error, exit code, and resume condition. Treat that as an allowed external-profile blocker only; never convert it into a local pass.
Modified Files Checklist
agent-task/single_request_plan_review_templates/CODE_REVIEW-cloud-G08.md
Test Strategy
- Verify formatting, focused tests, race tests, the full Edge/Go suite, the deterministic smoke self-test, the documentation guard, and the approved remote profile.
Verification
- Evidence must identify the tested commit and clearly separate local success from any externally blocked live qualification.
Modified Files Summary
| File | Item |
|---|---|
packages/go/singlerequesttemplate/template.go |
REVIEW_API-1 |
packages/go/singlerequesttemplate/template_test.go |
REVIEW_API-1 |
packages/go/config/load.go |
REVIEW_API-1 |
packages/go/config/model_execution_preset_config_test.go |
REVIEW_API-1 |
apps/edge/internal/service/single_request_types_test.go |
REVIEW_API-2 |
apps/edge/internal/openai/single_request_preset_binding_test.go |
REVIEW_API-2 |
apps/edge/internal/openai/single_request_review_stage_test.go |
REVIEW_API-2 |
agent-contract/outer/anthropic-compatible-api.md |
REVIEW_API-3 |
agent-spec/runtime/provider-pool-config-refresh.md |
REVIEW_API-3 |
agent-spec/runtime/edge-node-execution.md |
REVIEW_API-3 |
agent-spec/input/openai-compatible-surface.md |
REVIEW_API-3 |
agent-task/single_request_plan_review_templates/CODE_REVIEW-cloud-G08.md |
REVIEW_API-4 |
Final Verification
Run locally from the repository root:
test -z "$(gofmt -l packages/go/singlerequesttemplate/template.go packages/go/singlerequesttemplate/template_test.go packages/go/config/load.go packages/go/config/model_execution_preset_config_test.go apps/edge/internal/service/single_request_types_test.go apps/edge/internal/openai/single_request_preset_binding_test.go apps/edge/internal/openai/single_request_review_stage_test.go)"
go test -count=1 ./packages/go/singlerequesttemplate ./packages/go/config
go test -count=1 ./apps/edge/internal/service -run 'TestSingleRequestBinding'
go test -count=1 ./apps/edge/internal/openai -run 'TestSingleRequest(PresetBinding|ReviewStage)'
go test -race -count=1 ./apps/edge/internal/openai ./apps/edge/internal/service ./apps/edge/internal/configrefresh ./packages/go/config ./packages/go/singlerequesttemplate
go test -count=1 ./apps/edge/... ./packages/go/...
make test-single-request-claude-smoke-self-test
if rg --sort path -n 'Edge-owned OpenAI `json_schema` response format|strict small plan/verification JSON|stage-owned JSON Schema override protection' agent-spec/runtime/edge-node-execution.md; then exit 1; fi
Then verify the approved remote profile against the exact pushed implementation commit:
test "$(git branch --show-current)" = "feature/single_request_plan_review_templates"
test -z "$(git status --short)"
git push origin feature/single_request_plan_review_templates
ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && git fetch origin feature/single_request_plan_review_templates && git switch feature/single_request_plan_review_templates && git reset --hard origin/feature/single_request_plan_review_templates && git clean -fd && test "$(git rev-parse HEAD)" = "$(git rev-parse origin/feature/single_request_plan_review_templates)" && test "$(go env GOOS)/$(go env GOARCH)" = "darwin/arm64" && claude --version && sops --version && test -f dev-openai-toki.edge.yaml && test -f dev-openai-toki.sops.yaml'
ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && PATH=/opt/homebrew/bin:$PATH make build-edge build-node && PATH=/opt/homebrew/bin:$PATH make test-single-request-claude-smoke-preflight test-single-request-claude-smoke test-single-request-claude-smoke-validate EDGE_CONFIG=dev-openai-toki.edge.yaml SOPS_CONFIG=dev-openai-toki.sops.yaml'
If the remote SOPS age identity is unavailable, paste the exact raw failure and exit code into CODE_REVIEW-cloud-G08.md, state the identity-mount/export resume condition, and leave live API qualification explicitly blocked. Do not reuse old output or substitute another credential.
Do not archive this plan, write complete.log, or move the task directory; those actions belong to the review agent after an official verdict.