Skip to content

feat(eval): add bounded host experiment recorder - #2

Merged
jgoneit merged 14 commits into
mainfrom
codex/eval-bounded-host-experiment
Aug 26, 2026
Merged

feat(eval): add bounded host experiment recorder#2
jgoneit merged 14 commits into
mainfrom
codex/eval-bounded-host-experiment

Conversation

@jgoneit

@jgoneit jgoneit commented Aug 26, 2026

Copy link
Copy Markdown
Owner

목적

Eval을 아직 Toolkit 제품으로 승격하지 않고, 다음 20개 eligible root Codex Task에서 기록 지속성과 실사용 부담만 확인하는 bounded Host experiment로 교체합니다. 기존 Native Agent MVP는 호환 계층, 분석 명령, Plugin 자동 선택, 모듈별 확장 계약을 한 번에 제품화해 실제 데이터가 없는 상태에서 책임 범위를 키웠습니다. 이 PR은 실험 실행에 필요한 recorder와 private-store 안전 경계만 남깁니다.

변경 내용

  • v1/v2 reader, revision chain, analyzer, public validator/summarize/compare, fixtures, report template, manifest, Plugin/Skill, Python verifier를 삭제했습니다.
  • 공개 표면을 evalctl --version과 항상 best-effort인 evalctl observe [--state-root ABS]로 제한했습니다.
  • 성공 행만 최대 20개 contiguous slot으로 기록하는 eval-experiment/v1 typed Journal을 추가했습니다.
  • strict duplicate-key/unknown-key/integer decoding과 Ward·Seal used/version/effect 관계 검증을 추가했습니다.
  • Go os.Root로 commit 경로를 고정하고 kernel lock, private ownership/mode, symlink/reparse-point, hard-link, temp sync, atomic replace, directory sync 경계를 Darwin/Linux/Windows에 구현했습니다.
  • GitHub Actions에서 format, vet, test, race, 3개 OS build/test, 삭제된 surface 재유입 검사를 수행합니다.
  • README에 20-Task 모집단, 종료 기준, 수동 privacy/product decision 경계를 정의했습니다.

설계 판단

  • 선택한 방식:
    • 호환 계층 없는 새 Journal과 observe-only CLI
    • 성공 observation만 저장하고 전체 분모와 누락은 Codex Host Task 이력에서 수동 대조
    • used:true + version:null을 허용해 usage cohort에는 포함하고 exact-version 판단 자료로는 쓰지 않음
  • 대안:
    • 기존 v1/v2 migration과 validate/summarize/compare 유지
    • Plugin/Skill implicit invocation 유지
    • task identity와 skipped row를 Journal에 추가
  • 선택 이유:
    • 20-Task 실험에서 아직 반복 필요가 확인되지 않은 제품 책임과 legacy를 제거하기 위함입니다.
    • 관측 실패가 원 Task를 실패시키거나 UX를 침범하지 않도록 하기 위함입니다.
  • 포기한 것:
    • 자동 집계, correction, exact task linkage, automatic experiment-stop 판단
    • 기존 observation/report 호환성

기존 PR #1 리뷰 대응

리뷰 처리 근거
author-specific validator path 관련 surface 삭제 Plugin/Skill 및 Python scripts/verify.sh를 제거했고 CI는 저장소 자체 Go 경계만 사용합니다.
future invalid row in as-of snapshot 관련 surface 삭제 as-of dataset, correction chain, analyzer를 제거했습니다.
post-replace failure reported as skipped 직접 수정 replace가 commit된 이후 sync 실패는 recorded + durability:"unconfirmed"로 반환합니다.
exact JSON number loss 직접 수정 typed strict decoder가 정수 token을 exact int64로 검증하며 fractional/exponent 표현을 거부합니다.
hard-linked private data 직접 수정 Darwin/Linux/Windows 모두 regular file link count가 1이 아니면 fail closed하며, Windows는 reparse/identity/DACL도 함께 검사합니다.
real observation in valid fixtures 관련 surface 삭제 fixture catalog와 synthetic fixture 관리 계약을 제거했고 clean-slate CI가 fixture 디렉터리 재유입을 거부합니다.
mixed v1/v2 report provenance 관련 surface 삭제 v1/v2 분석 및 report template과 toolkit-module.json을 제거했습니다.

검증 방법

  • 단위 테스트 실행
  • 통합 테스트 실행
  • 로컬 수동 테스트
  • 회귀 영향 확인
  • 문서 확인
  • Darwin/Linux/Windows cross-build
  • Windows runner에서 실제 Store test 실행

검증 결과

  • go test -count=1 ./... 통과
  • go test -race -count=1 ./... 통과
  • go vet ./... 통과
  • gofmtgit diff --check 통과
  • Darwin/Linux/Windows amd64 build 통과, Windows/Linux vet 및 test-binary compile 통과
  • duplicate key, fractional number, used/version/effect 관계, invalid Journal, 20-slot 상한, concurrent unique slot, permission, unsafe root, symlink, hard link, lock timeout, partial write, replace 전후 fault, durability 상태 테스트 통과
  • concurrency 회귀 테스트 25회 반복 통과
  • 삭제된 Plugin/manifest/schema/path/analyzer/validator surface scan 통과
  • final head 278d407GitHub Actions run 32979861433에서 Linux/macOS/Windows format·vet·test·build, Linux race, clean-slate surface 전부 통과
  • Plugin 없는 fresh codex exec --ephemeral --json에서 completed/failed/abandoned 각각 정확히 1행 기록 확인
  • 같은 Host E2E에서 permission denied 및 missing Core는 각각 단일 시도 후 append/retry/approval/final Eval 문구 없이 원 artifact와 completed outcome 유지 확인
  • 초기 Host E2E 2건은 Agent가 허용되지 않은 추가 필드를 생성해 skip됐고, Host 입력 지침을 exact 최소 JSON으로 고정한 뒤 terminal matrix 3/3이 통과했습니다.

영향 범위

  • Eval CLI와 private experiment Journal
  • Eval repository schema, tests, CI, documentation
  • 기존 Eval Plugin/Skill 및 v1/v2 product surface를 사용하는 개발 경로

리스크

  • Host 정책 준수는 모델 동작에 의존하며, task identity를 저장하지 않으므로 20개 모집단과 누락 대조 및 managed block 제거는 Host task history를 이용한 수동 운영이 필요합니다.
  • Windows ACL/lock/replace 동작은 final-head GitHub Windows runner에서 통과했지만, 다른 Windows filesystem과 정책 조합은 추가 검증이 필요할 수 있습니다.
  • Windows에서 replacement 후 directory durability를 확인할 수 없는 경우 성공 행을 숨기지 않고 durability:"unconfirmed"로 반환합니다.
  • 호환 계층을 의도적으로 제거했으므로 기존 v1/v2 state는 읽거나 migration하지 않습니다.

롤백 방법

  • 이 브랜치의 clean-slate 구현 커밋을 역순으로 revert하면 repository의 이전 contract scaffold로 돌아갈 수 있습니다.
  • Host experiment는 managed AGENTS block을 제거하고 experiment evalctl provisioning을 중단하면 즉시 정지합니다.
  • legacy private state는 migration하지 않았으므로 별도 보관 위치에서 원래 경로로 복구할 수 있습니다.

리뷰어가 중점적으로 봐야 할 부분

  • post-replace 오류가 skipped가 아니라 committed/unconfirmed로 분리되는지
  • os.Root 기반 rename과 lock 아래 Journal 전체 검증이 경로 교체·동시 writer를 막는지
  • Unix hard-link/permission 및 Windows owner/DACL/reparse 검사가 private-store 경계를 충분히 fail closed하는지
  • 최소 observation 계약이 20-Task 실험에 필요한 사실만 요구하는지
  • 삭제된 product/compatibility surface가 다시 우회 도입되지 않았는지

Agent Note

  • Agent 책임: terminal outcome이 고정된 eligible root Task에서 한 번만 best-effort observe를 시도합니다.
  • State 변경: 원 Task가 아닌 외부 private Journal의 다음 immutable slot만 변경합니다.
  • Tool 호출: Ward·Seal을 version/metric 확인 목적으로 실행하지 않습니다.
  • Retry / fallback: retry, repair, approval request가 없고 모든 관측 실패는 원 Task에 영향을 주지 않습니다.
  • Human-in-the-loop 필요 여부: 개별 관측에는 없으며, 20개 종료 후 privacy review와 retain/promote/remove 판단은 사람이 수행합니다.
  • 비용/지연 리스크: terminal 시점의 단일 로컬 process 호출이 추가됩니다.
  • 벤더 종속 리스크: Plugin 종속은 제거했지만 모집단 정의와 silent invocation은 Codex Host의 AGENTS 정책에 의존합니다.

Why:
- The bounded 20-task experiment does not require v1 compatibility, report scaffolding, or module-specific schemas.
- Keeping those contracts would preserve unsupported product surface and inflate the recorder implementation.

What:
- Remove the v0.1 schema, fixtures, verifier, report template, distributed protocol documents, and toolkit manifest.
- Leave only repository metadata before adding the clean-slate recorder.

Validation:
- git diff --cached --check
- No runtime tests apply to this deletion-only commit
Why:
- Eval needs a small host-owned instrument before product surfaces or analysis are justified.
- The experiment must preserve primary task outcomes when input or private storage is unavailable.

What:
- Add the observe-only evalctl contract and a twenty-slot typed journal.
- Add strict duplicate-key and integer decoding with one stored-row schema.
- Add rooted private storage, exclusive locking, atomic replacement, and commit-aware durability reporting for Darwin, Linux, and Windows.

Validation:
- go test ./...
- go test -race ./...
- go vet ./...
- GOOS=darwin/linux/windows cross-build and vet
- Manual observe smoke with contiguous slots
Why:
- The bounded experiment is useful only if malformed input and storage failures cannot corrupt or expand the journal.

What:
- Cover strict decoding, field relationships, canonical rows, and the twenty-slot limit.
- Exercise concurrent writers, invalid state, permissions, symlinks, hard links, lock timeout, and rooted path replacement.
- Inject partial writes and pre/post-replace failures to distinguish skipped writes from recorded durability uncertainty.
- Add Windows owner, protected DACL, reparse, hard-link, and LockFileEx coverage.

Validation:
- go test ./...
- go test -race ./...
- go vet ./...
- Darwin, Linux, and Windows test binaries compiled
Why:
- The experiment recorder needs remote proof on every supported operating system before the host policy is enabled.

What:
- Run formatting, vet, tests, and evalctl builds on Linux, macOS, and Windows.
- Run the race detector on Linux.
- Reject reintroduction of removed Plugin, compatibility, analyzer, validator-command, and local-path surfaces.

Validation:
- Workflow YAML parsed locally
- Surface commands passed locally
- go test, race, and vet passed locally
Why:
- The recorder needs an explicit experimental population and human decision boundary without restoring product documentation layers.

What:
- Document the observe-only contract, private journal, and failure semantics.
- Define eligible host tasks, silent terminal recording, denominator ownership, and the twentieth-task stop.
- Record promotion, privacy review, and cohort-size boundaries.

Validation:
- Markdown and links reviewed locally
- go test ./... passed
- git diff --check passed
Why:
- Windows checkout converted Go sources before the shared gofmt gate, so the Windows job failed before tests ran.
What:
- Mark Go sources as LF in repository attributes across all runners.
Validation:
- gofmt -l . produced no output
- git check-attr reports eol=lf for Unix and Windows Go files
@jgoneit jgoneit self-assigned this Aug 26, 2026
Why:
- Elevated Windows runners can use a token default owner that differs from the current-user SID.
- The DACL accessor boolean reports whether the ACL was defaulted, not whether it is present.
What:
- Set the current user explicitly as owner and sole full-control trustee on new private objects.
- Check SE_DACL_PRESENT through descriptor control bits before inspecting state-root access.
Validation:
- Windows amd64 store and CLI test binaries compiled
- Windows vet passed
- Local go test and race test passed
- GitHub Windows execution pending on the updated head
Why:
- GitHub Windows temp directories inherit broader ACLs than an accepted private state root.
- Windows may block a state-root rename while os.Root handles are open instead of allowing the Unix path-move scenario.
What:
- Run CLI tests against recorder-created private state roots.
- Keep the Unix anchored-rename test and add a Windows assertion for either a blocked move or an anchored commit.
Validation:
- Local unit and race tests passed
- Windows amd64 store and CLI test binaries compiled
- Windows vet passed
- GitHub Windows execution pending on the updated head

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6618f0391d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/store/store.go
Comment thread .gitignore
Comment thread internal/state/state.go Outdated
Why:
- An absolute-path miss during a state-root move could classify an anchored Journal as empty and risk replacing prior rows.
What:
- Treat the Journal as absent only when rooted and absolute entries are both absent.
- Reject one-sided absence and file-identity mismatch as unsafe.
Validation:
- go test -count=1 ./internal/store
- go test -count=1 ./...
- go test -race -count=1 ./...
Why:
- The rooted-read regression requires a deterministic state-root move that Unix permits while os.Root handles remain open.
What:
- Seed a Journal, move its state root, and assert the anchored read fails closed without changing prior bytes.
Validation:
- go test -count=1 ./internal/store
- go test -race -count=1 ./...
- git diff --check
Why:
- Native Windows normally provides USERPROFILE rather than HOME, so the default recorder path could be skipped as unsafe.
What:
- Resolve explicit and XDG roots before a platform-aware user-home fallback.
- Inject os.UserHomeDir through the internal CLI runtime for deterministic tests.
Validation:
- go test -count=1 ./internal/state ./internal/cli
- go vet ./...
- GOOS=windows GOARCH=amd64 go vet ./...
- Darwin, Linux, and Windows evalctl cross-builds
Why:
- Root precedence and the Windows USERPROFILE fallback need regression coverage independent of the host environment.
What:
- Cover explicit, XDG, resolver-error, and invalid-home cases with injected dependencies.
- Add a Windows integration test that records without --state-root when only USERPROFILE is set.
Validation:
- go test -count=1 ./internal/state ./internal/cli
- go test -race -count=1 ./internal/state ./internal/cli
- Windows state, CLI, and Store test binaries cross-compiled
- Windows execution pending GitHub Actions
Why:
- The default Journal documentation described only the Unix HOME fallback.
What:
- Distinguish the shared XDG path from Darwin/Linux HOME and Windows USERPROFILE fallbacks.
Validation:
- Markdown source reviewed
- git diff --check
Why:
- Upgraded checkouts may still contain previously ignored private observations that git add -A must never stage.
What:
- Keep only the two retired checkout-local private paths ignored.
- Add a CI canary that verifies they remain untracked, ignored, and absent from dry-run staging.
Validation:
- git check-ignore passed for both root-only paths
- git ls-files reported no tracked legacy private data
- workflow static check passed when actionlint was available
- git diff --check
@jgoneit
jgoneit merged commit d530249 into main Aug 26, 2026
5 checks passed
@jgoneit
jgoneit deleted the codex/eval-bounded-host-experiment branch August 26, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant