codex-harness is a Codex-first programming harness. Phase 23 adds a local Memory/Evidence Core with an append-only JSONL ledger, rebuildable SQLite projection, content-addressed artifacts, and exact input-set local verification reuse on top of the Phase 22.5 runtime model, Phase 22 release hardening, Phase 21 cross-platform command-runner hardening, the Phase 20 security/eval/context hardening, the Phase 19 artifact schemas and migrations, and earlier harness flow.
The harness product repository currently self-hosts through the runtime/operator surface:
TASK.md
-> node bin/ch run start --task TASK.md
-> node bin/ch run status --operator
-> manual procedure execution
This is distinct from the installed target workflow commands such as
init / worktree / prompt / context inspect / review / check / report, which
remain the target-project harness workflow and not the current product
self-hosting authority.
Run the local CLI through node bin/ch:
node bin/ch --help
node bin/ch agent record --role scout-tests --output sample.md
node bin/ch agent list
node bin/ch agent --help
node bin/ch agent prompt codex --role tests
node bin/ch agent run codex --role tests
node bin/ch capture
node bin/ch check
node bin/ch review
node bin/ch review --exec
node bin/ch report
node bin/ch hooks --help
node bin/ch hooks install
node bin/ch memory --help
node bin/ch memory init --dry-run
node bin/ch memory status
node bin/ch memory rebuild --dry-run
node bin/ch memory runs --last 5
node bin/ch memory show run-0001
node bin/ch memory export --dry-run
node bin/ch debt add --title "test debt" --type technical --severity low --reason "test"
node bin/ch debt list
node bin/ch debt resolve --id DEBT-0001
node bin/ch decisions add --title "test decision" --reason "test"
node bin/ch decisions list
node bin/ch doctor
node bin/ch doctor --help
node bin/ch doctor --all
node bin/ch doctor platform
node bin/ch doctor commands
node bin/ch security --help
node bin/ch security doctor
node bin/ch context --help
node bin/ch context inspect plan
node bin/ch context inspect work
node bin/ch context inspect review
node bin/ch context inspect scout --role tests
node bin/ch eval
node bin/ch eval playground init
node bin/ch eval playground smoke
node bin/ch eval playground clean
node bin/ch governance --help
node bin/ch governance review
node bin/ch governance proposal --title "tighten review gate"
node bin/ch governance metrics
node bin/ch governance status
node bin/ch parallel --help
node bin/ch parallel plan --worker alpha --worker beta --claim alpha:README.md --claim beta:src
node bin/ch parallel status
node bin/ch parallel close
node bin/ch install
node bin/ch install --dry-run
node bin/ch upgrade --help
node bin/ch upgrade --dry-run
node bin/ch upgrade
node bin/ch schema --help
node bin/ch schema validate
node bin/ch schema migrate --dry-run
node bin/ch schema migrate
node bin/ch status
node bin/ch init "test task"
node bin/ch init "test task" --dry-run
node bin/ch worktree
node bin/ch prompt plan
node bin/ch prompt work
node bin/ch prompt review
node bin/ch prompt scout --role tests- Generated evidence state is local/private and must stay under
.harness/**:.harness/evidence/events.jsonl,.harness/evidence/projection.sqlite,.harness/artifacts/sha256/<prefix>/<hash>, and.harness/runs/**. - The JSONL ledger is the append-only source-of-trace. The SQLite database is a rebuildable projection used through typed code, not a public raw-SQL API.
- Large command output, diffs, logs, and long reports belong in the ArtifactStore and are referenced by hash/id instead of embedded in evidence events.
- Evidence is scoped by target project id, target root, namespace, run id, and task/phase where available, so harness self-hosting evidence and ordinary project evidence do not mix by default.
- Local verification reuse is exact input-set reuse only. Changed tracked files, changed or removed untracked files, changed command sets, different roots, different base commits, failed prior verification, unsupported schemas, and missing/corrupt artifacts invalidate reuse.
- Docs/task-only changes can be classified distinctly, but reuse is still conservative: source/schema/test/package/CI input sets must not be treated as verified when they changed.
- Local evidence reuse never satisfies remote CI. Remote gate evidence remains separate and linked to pushed commit/provider-neutral status where available.
ch run closeout --dry-runis a smoke check during implementation. Do not run non-dry-runch run closeoutuntil review, final verification, commit/push/PR, and remote CI validation are complete.
npm install
npm run build
npm test
npm run release:dry-runnpm test is the canonical full-pack proof command for the current harness
workflow. npm run test:acceptance remains only as a compatibility alias to
the same acceptance runner and is not separate proof.
npm run release:dry-runis the local release gate. It builds the project, inspectsnpm pack --dry-run --json, verifies the package allowlist, and runs a packed-install smoke test without publishing anything.- The npm package contents are controlled through
package.jsonfilesand currently allow onlybin/,dist/,schemas/, andREADME.md. - The packed tarball must include
bin/ch,dist/cli/index.js, the built runtime files underdist/**, and the product schemas required by install and upgrade behavior. - The packed tarball must exclude development, task, docs, scripts, runtime-local, and secret-like files such as
src/**,tests/**,TASK.md,.harness/**,.codex/**,.agents/**, and generated tarballs. - The packed-install smoke gate installs the generated tarball into a temporary project and runs
ch --help,ch doctor platform, andch doctor commandsthrough the packagedbin/chpath. .github/workflows/ci.ymlis a verify-only workflow forpull_requestandpushtomain. It usespermissions: contents: read, runsnpm ci,npm run build,npm test,npm run test:acceptance, andnpm run release:dry-run, and does not publish or use npm tokens. In that workflow,npm testis the canonical full-pack proof command;npm run test:acceptanceis a compatibility invocation of the same runner rather than separate proof.- Future trusted publishing and provenance remain documented only. Phase 22 does not activate public npm publishing.
security doctoris inspect/report only. It audits the current product-repo or installed-target posture and does not change permission state.security doctorsucceeds in the product repo and reports installed-layer audit as unavailable there.security doctorsucceeds in installed target repos when the installed layer and config are readable, and it reports the current protected-path posture plus discovered adapter profiles.security doctorfails closed on malformed adapter config or unclear permission state.doctor platformreports runtime/platform facts without mutating repository state.doctor commandsreports the command-execution policy, acceptance-runner path, and installed-repo check-config status when available.- bare
evalruns deterministic local regression checks from the product repository root only, does not require internet, API access, or external agents, and delegates acceptance execution toscripts/run-acceptance.mjs. npm testandnpm run test:acceptanceboth delegate to the same Node-basedscripts/run-acceptance.mjsrunner.eval playground init,eval playground smoke, andeval playground cleanremain the Phase 15 disposable playground surface.context inspectis read-only only. It reports the current prompt-context inputs forplan,work,review, orscout --role <role>using the same task/worktree preconditions as prompt generation.context inspectreferences artifacts by path and preserves the rule that raw logs are not prompt context by default.
installcreates the installed harness layer, writes.harness/install.json, seeds managed baselines under.harness/templates/managed/, seeds installed schema snapshots under.harness/schemas/, and may update the optional~/.codex-harness/registry.json.upgrade --dry-runpreviews install-owned changes without writing files.upgradeupdates only install-owned static content, refreshes.harness/schemas/, creates backups before rewriting managed files, refreshes install metadata, and fails closed when managed files contain local modifications.doctor --allreads the optional project registry and reports the status of registered repositories without turning the registry into the source of truth.schema validatechecks the current installed target repository for malformed governed artifacts, missing schema snapshots, malformed[agents.*]adapter profiles, and unknown explicit schema versions.schema migrate --dry-runpreviews legacy unversioned artifact rewrites without changing the repository.schema migrateperforms explicit governed-artifact rewrites only, creates.codex-harness.bak*backups before updates, and leaves absent optional runtime artifacts absent.- Runtime/generated project state under
.harness/tasks/,.harness/memory/,.harness/governance/, and.codex/is never overwritten duringupgrade; governed runtime JSON files are touched only by explicitschema migrate. - Product-source
schemas/andmigrations/live in the realcodex-harnessrepository, while installed target repositories receive only.harness/schemas/. - Rollback is file-based: inspect the reported
.codex-harness.bak*backups before restoring any managed file manually.
governance review,governance proposal,governance metrics, andgovernance statusoperate only in installed target repositories, not in the realcodex-harnessproduct repository.- Governance artifacts live under
.harness/governance/with subdirectories forreviews/,proposals/, andmetrics/, pluschangelog.md. governance reviewwrites a dated review artifact fordaily,weekly, orreleasemode and records evidence without changing product code.governance proposal --title ...writes a human-readable Harness Enhancement Proposal with required evidence, expected benefit, risk, rollback, acceptance criteria, and evaluation-plan sections.governance proposal --research <path>records validated local research-summary file references only. It does not fetch the network.governance metricswrites deterministic local summary data to.harness/governance/metrics/harness-metrics.json.governance statusis read-only and summarizes governance, memory, debt, decisions, and agent-output counts.- Phase 17 itself did not add automatic self-modification, auto-merge, silent prompt changes, permission changes, dashboard behavior, or schema/migration infrastructure.
parallel planis an opt-in manual scaffold for splitting work across isolated worker worktrees.- Phase 16 does not execute write-capable worker agents automatically and does not extend
agent runbeyond Phase 10 read-only behavior. - The current single active task remains the explicit integrator task.
parallel planrequires:- exactly one active task
- an existing integrator worktree
- a clean source checkout
- a clean integrator worktree
- at least 2 workers
- explicit non-overlapping worker claims
- Worker claims are literal repo-relative file or directory prefixes only. They must stay inside the repo and must not target harness-managed paths.
parallel planwrites:.harness/tasks/<task-id>/parallel/plan.json.harness/tasks/<task-id>/parallel/integrator-prompt.md- one worker prompt per worker under the same
parallel/directory
- Each worker gets one isolated git worktree on a task-scoped parallel branch and dedicated external worktree path.
parallel statusreports the current scaffold state and fails when recorded worker integrity is broken.parallel closeis the final gate. It requires:- all worker worktrees still exist and are clean
- final
diff.patch,verifier.json,review.json, andresult.md - verifier result
pass - review result
PASS result.mdcontainingREADY FOR HUMAN REVIEW- final tracked integrator changes staying inside the declared claim union
parallel closerecords closure only. It does not merge branches, delete worktrees, or run external write agents.
eval playground initcreates or refreshes a managed disposable playground root.- The default playground root is the literal sibling
../codex-harness-playground. eval playground init --root <path>is allowed for local testing, but the command refuses the product repo, paths inside the product repo, the product-repo parent, and other unsafe targets.- The managed playground writes:
.codex-harness-playground.jsoneval-corpus.jsonpython-app/ts-app/
eval-corpus.jsonmaterializes the 20-task Phase 15 corpus and marks exactly 4 local deterministic smoke scenarios.eval playground smokeruns the 4 deterministic local E2E scenarios without live LLM/API calls and writessmoke-results.json.smoke-results.jsonrecords deterministic metrics for each executed scenario, including pass/fail, timing, failed checks, unsafe command blocks, and null manual-only metrics.- The docs scenario uses a separate managed target under the playground root so earlier smoke artifacts remain available until asserted.
- The safety/lifecycle scenario proves:
- non-empty unmanaged init refusal
- hook-based unsafe-command blocking
- managed clean on a separate managed target
- unmanaged clean refusal on a separate unmanaged target
eval playground cleanremoves only a managed playground root and refuses unmanaged, product-repo, parent, and filesystem-root targets.
-
reviewvalidates an existing.harness/tasks/<task-id>/review.jsonand fails closed on invalid JSON or invalid review shape. -
review --execbuilds a task-aware review prompt, runscodex exec, validates the JSON result, and writesreview.json. -
review.jsonrecordsPASSorFIX_REQUIREDplus explicit blockers, summary, mode, and timestamp. -
Local deterministic acceptance does not require a live Codex installation;
--execis optional and may be smoke-tested manually or through a stubbed executable in acceptance tests. -
reportnow referencesreview.jsonwhen present and changes the merge recommendation toDO NOT MERGEwhen review blockers exist. -
hooks installwrites minimal Codex sidecar hook files under.codex/. -
Installed hook files are:
.codex/hooks.json.codex/hooks/user-prompt-submit.cjs.codex/hooks/pre-tool-use.cjs.codex/hooks/stop.cjs
-
hooks installalso writes canonical hook templates under.harness/templates/hooks/. -
UserPromptSubmitdocuments and enforces missing task-context behavior by requiring exactly one task with a recorded worktree before coding work. -
PreToolUsedocuments and enforces a narrow dangerous-command guard for destructive shell/git patterns. -
PreToolUseblocks edit/write paths outside the current task worktree only where the hook payload exposes a path that can be checked. -
Stopprints a short reminder to runnode bin/ch checkandnode bin/ch report. -
The hook layer is intentionally best-effort. It is a small sidecar guardrail, not a full policy engine or execution boundary.
-
agent record --role <role> --output <path>creates an agent run directory under.harness/tasks/<task-id>/agents/<run-id>/. -
The ledger writes
status.jsonwith task id, run id, role, status, timestamps, prompt path, output path, and optional notes/profile metadata. -
Recording metadata does not execute any agent and does not create the output file itself.
-
Recorded outputs remain raw and untrusted until reviewed.
-
Agent output status parsing supports
raw,accepted,stale, andrejected, while Phase 9 still records new runs asrawonly. -
agent prompt <agent> --role <role>requires an adapter profile in.harness/config.toml, creates a run-localprompt.mdandcommand.json, and prints the bounded command preview without executing the external agent. -
agent run <agent> --role <role>executes only configuredcliadapters withpermission_mode = "read_only", captures stdout tooutput.md, captures stderr plus run summary tolog.txt, records command metadata instatus.json, and uses the same shared structured execution path withshell = false. -
parallel plan,parallel status, andparallel closeadd a manual Phase 16 scaffold for isolated worker worktrees plus an integrator close gate. -
Phase 16 does not add automatic write-capable worker execution.
-
governance review,governance proposal,governance metrics, andgovernance statusadd a deterministic Phase 17 maintainer-governance loop for installed harness layers only. -
Phase 17 governance produces review/proposal/metrics artifacts only. It does not edit the product repository or silently apply harness changes.
-
capturereads the active task worktree, capturesgit status --porcelain --untracked-files=all, writesdiff.patch, and seeds.harness/tasks/<task-id>/verifier.jsonwith durable capture state. -
checkrefreshes capture artifacts, reads both legacy[checks].commandsstring arrays and preferred structured[[checks.commands]]entries from.harness/config.toml, runs them from the recorded task worktree through the shared command runner, writes.harness/tasks/<task-id>/logs/check.log, and records deterministic pass/fail results inverifier.json. -
checktreats protected-path changes as failure. If[checks].protected_pathsis unset, the defaults areAGENTS.mdand.harness/config.toml. -
Legacy
[checks].commandsstring-array entries remain readable, are tokenized intocommand + args, run withshell = false, and fail closed on shell-only syntax. -
Structured
[[checks.commands]]is the preferred format for fresh config, docs, and tests.shell = falseis the default, andshell = trueis explicit opt-in only. -
diff.patchcontains tracked-file git diff output only. Untracked files are represented inverifier.json.git_status_lines. -
reviewreads or writes.harness/tasks/<task-id>/review.jsonas the Phase 14 review artifact. -
reviewvalidates review JSON locally without calling Codex. -
review --execrequiresspec.md,acceptance.md,diff.patch, andverifier.json, and includes scout/agent outputs if present. -
reportwrites.harness/tasks/<task-id>/result.mdas a deterministic, artifact-based handoff report. -
reportsummarizes task metadata, changed files, checks, risks, follow-ups, debt created/resolved, next human action, and merge recommendation. -
reportreferencesdiff.patch,verifier.json,review.json, andlogs/check.logwhen present. -
reportmay summarize agent runs and related decisions/debt for the current task, but does not treat raw agent output as accepted truth. -
reportdoes not claim PASS unlessverifier.json.resultis exactlypass. -
reportdoes not recommendREADY FOR HUMAN REVIEWwhen a valid review artifact contains blockers. -
Phase 10 adapter roles are the read-only scout roles only:
repo-map,tests,docs,security, andarchitecture. -
Adapter profiles live under
[agents.<agent_id>]in.harness/config.toml. -
Supported Phase 10 adapter fields are
transport,command,args,working_directory_policy, optionalexplicit_path,permission_mode,allowed_roles,output_contract,timeout_seconds, andrequires_human_confirmation. -
Supported argument placeholders in
argsare{prompt_path},{output_path},{log_path}, and{cwd}only. -
No adapter is enabled by default; the harness fails closed when the named profile is missing or malformed.
-
Legacy
[checks].commandsstring arrays remain readable for compatibility. -
Preferred structured check format uses
[[checks.commands]]entries withcommand,args,timeout_seconds, and optional explicitshell = true. -
[checks].protected_pathsis an optional string-array override for protected-path detection duringcheck. -
installcreates.harness/config.toml,.harness/tasks/,.harness/templates/,.harness/memory/, and.harness/install.json. -
install --dry-runpreviews the same actions without writing files. -
installalso seeds.harness/templates/managed/agents-block.mdand.harness/templates/managed/config.tomlfor future upgrade drift detection. -
installalso seeds.harness/schemas/with the product schema snapshot used by the installed layer. -
installcreates or updates a managed block inAGENTS.mdand backs up the file before patching existing content. -
Re-running
installis idempotent when the managed files already match the Phase 2 content. -
upgrade --dry-runpreviews install-owned changes without writing files. -
upgradeupdates install-owned static files only, refreshes.harness/schemas/, records additivelast_upgrademetadata in.harness/install.json, and creates.codex-harness.bak*backups before rewriting managed files. -
doctor --allsummarizes the optional~/.codex-harness/registry.jsonwithout replacing repo-local.harness/state. -
schema validatescans only existing governed artifacts plus configured[agents.*]adapter profiles and fails closed on malformed or unknown explicit schema versions. -
schema migrate --dry-runpreviews legacy unversioned artifact rewrites and planned backups without mutating the repo. -
schema migrateis the only command that rewrites governed runtime artifacts; it does not silently run duringupgrade. -
initcreates.harness/tasks/<task-id>/spec.md,acceptance.md, andstate.json. -
init --dry-runpreviews the task id and planned file paths without writing files. -
statuslists the tasks recorded under.harness/tasks/. -
worktreecreates one branch and one git worktree for the current task. -
worktreewrites.harness/tasks/<task-id>/branch.txtandworktree.txt, then updatesstate.json. -
Worktree root is configured in
.harness/config.tomlunder[worktree]. -
prompt plan,prompt work, andprompt reviewgenerate prompt files under.harness/tasks/<task-id>/. -
Generated prompt files are
prompt-plan.md,prompt-work.md, andprompt-review.md. -
Prompts reference
spec.md,acceptance.md,state.json,branch.txt,worktree.txt, andAGENTS.mdby path instead of dumping large context. -
Prompt generation includes the concise implementation-discipline block.
-
If the target repo
AGENTS.mdis missing the short implementation-discipline section, prompt generation appends it and creates a backup before patching an existing file. -
prompt scout --role <role>generates read-only scout prompts under.harness/tasks/<task-id>/prompts/. -
Supported scout roles are
repo-map,tests,docs,security, andarchitecture. -
Scout findings must be written manually to
.harness/tasks/<task-id>/scouts/<role>.md. -
Scout prompts are manual and read-only only; the harness does not execute external agents.
-
Scout prompts include output path instructions and explicit no-edit/no-write rules.
-
agent listreads the current task ledger entries and prints readable run summaries without requiring chat history. -
memory statusreports current memory paths plus debt, decision, and agent-output counts. -
debt addappends a debt item to.harness/memory/debt/debt.jsonl, refreshes.harness/memory/debt/debt.md, and updates.harness/memory/project-index.md. -
debt listshows project debt across the installed target repo with unresolved items first. -
debt resolve --id <DEBT-...>marks an existing debt item asresolvedand refreshes derived memory files. -
decisions addwrites one JSON decision record under.harness/memory/decisions/and refreshes.harness/memory/project-index.md. -
decisions listshows the recorded decision log across the installed target repo.
[agents.codex]
transport = "manual_prompt"
command = "codex"
args = ["exec", "{prompt_path}"]
working_directory_policy = "repo_root"
permission_mode = "read_only"
allowed_roles = ["tests"]
output_contract = "markdown"
timeout_seconds = 600
requires_human_confirmation = true
[checks]
protected_paths = ["AGENTS.md", ".harness/config.toml"]
[[checks.commands]]
command = "git"
args = ["status", "--short"]
timeout_seconds = 120
shell = false.codex/hook files are created only in installed target repositories, not in the product repo.- No
.agents/files are created in this phase. - No write-capable external agent mode is implemented in this phase.
- No automatic coding loop, write-capable external agent mode, secrets injection, or uncontrolled runtime state in the product repo are implemented in this phase.