Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7424598
devlog: the win32 recipe was executed, not assumed
lidge-jun Aug 22, 2026
472beb3
devlog: the attest from/to cascade, and the lessons opencodex paid for
lidge-jun Aug 25, 2026
49d90e6
fix(attest): tell agents the shape the gate actually requires
lidge-jun Aug 25, 2026
c19e578
fix(attest): close four review blockers on the shape hint and its nei…
lidge-jun Aug 25, 2026
db12971
fix(cli,docs): finish the attest-contract surfaces and pin them again…
lidge-jun Aug 25, 2026
3d5d0d3
docs(dev-devops): the freeze-gate rules opencodex paid for
lidge-jun Aug 25, 2026
6cf7b69
docs(testing): make the flaky policy elimination-first, with one owner
lidge-jun Aug 25, 2026
836954d
docs(dev-devops): correct three invented claims the audit caught
lidge-jun Aug 25, 2026
3ae3847
devlog: record what the wp2 audit disproved
lidge-jun Aug 25, 2026
6268501
docs(testing): close the severity hole the flaky-policy audit found
lidge-jun Aug 25, 2026
f0e6442
devlog: record what the wp3 audit changed
lidge-jun Aug 25, 2026
438ddd3
devlog: untrack two plan units that were never mine to commit
lidge-jun Aug 25, 2026
7f2dd5e
devlog: closeout for the attest from/to and devops-lessons unit
lidge-jun Aug 25, 2026
260e2b4
devlog: re-run the falsification checks against the final tree
lidge-jun Aug 25, 2026
7991fd7
devlog: untrack the user plan units again, and say why it recurred
lidge-jun Aug 25, 2026
c84d105
devlog: record that the scope violation recurred
lidge-jun Aug 25, 2026
964669d
fix(interview): make readiness reachable by interviewing, not by asse…
lidge-jun Aug 25, 2026
677a85f
release(0.2.13): bump every version surface for the attest, interview…
lidge-jun Aug 25, 2026
cd342bf
release(0.2.13): sync the test badge and stop the skill teaching the …
lidge-jun Aug 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,69 @@ All notable changes to codexclaw are documented here. The format follows

## [Unreleased]

## [0.2.13] — 2026-08-25

Three gates that obstructed the agents following them, and the operational
lessons from a release train that got several of these wrong first.

### Fixed

- **The attest gate rejected what its own documentation taught.** `coerceAttest`
requires `from`/`to` before any other check, and the "Required attest keys"
table in `cxc-pabcd` — the table agents copy — named neither, nor `planUnit`,
`workPhaseId`, or `testReceiptPath`. A goalplan-bound `P>A` therefore cost
three separate refusals, one turn each. `attest JSON missing valid from/to`
appears 50+ times across four repos since 2026-08-13.

The table now names every key each edge requires, with copy-paste objects. The
refusal names the real edge instead of restating the problem: `to` is the verb,
`from` is the session's phase, and only that edge's extra keys are listed. An
illegal edge gets its legal routes and no example, because every example would
be rejected.

Same family, found while inventorying: the goal-idle block emitted `evidence`
where the schema says `did` — silently, since `IDLE>P` is ungated;
`review-round`, `plan`, `metric` and `divergence` rejected `--help`; and
`cxc freeze --help` ran the freeze and wrote `freeze.json`, exiting 0.

- **Interview readiness was unreachable.** `isInterviewReady` demanded level
`max` on all four dimensions, and no shipped writer could produce it —
`deriveLevel` tops out at `high` and `--dim <d>=max` is rejected. Every
interview either dead-ended or spent an attested override, which made the
override's ledger row meaningless: it recorded "bypassed the gate" for the
thorough interview and the skipped one alike.

Simply accepting `high` would have been worse — four `--known` flags reach
all-`high` in one command. So the gate now asks the append-only Q&A ledger where
a level came from: a dimension counts when a question was asked, answered, and
attributed with `--map`. `max` still satisfies readiness as a deliberate
assertion, and the override survives as the exception it was designed to be.

Not breaking: an interview that passes today still passes. Worth knowing on
upgrade — a session already sitting at all-`high` becomes shape-ready, so
`flags.interview`, `cxc freeze`, and the human `orchestrate p` free-pass will
now treat it as ready. The agent CLI path still requires the ledger backing.
This unsticks interviews that were stranded; it does not close any that were open.

### Added

- **`DEVOPS-*` freeze-gate rules** in `cxc-dev-devops` §2.8 and its references:
pin a readiness report to the SHA its gates describe; never excuse a red gate
inside the report it failed; unresolved review threads on merged PRs block GO;
a gate with no implementing phase is a wish. Plus the evidence mechanics —
replay CI's real partition, prove "environmental" with a baseline triple, do
not change the verification instrument while certifying with it, re-read the
head before claiming exact-head evidence.

### Changed

- **The flaky-test policy is elimination-first and has one owner.**
`dev-testing` said a flake is a bug and also said "quarantine if blocking";
the router and its reference both claimed the protocol, with different
strength. `references/ci-pipeline.md` §5 is now canonical `TEST-FLAKE-*`:
re-running to green is not a fix, quarantine needs test name, owner, deadline
and suspected cause recorded together, and "environmental" needs proof.

## [0.2.12] — 2026-08-22

Three bugs filed against codexclaw, all of them cases where the tool obstructed
Expand Down
2 changes: 1 addition & 1 deletion README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<p align="center">
<a href="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml"><img src="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<img src="https://img.shields.io/badge/tests-1%2C961_passing-brightgreen" alt="1,961 tests passing">
<img src="https://img.shields.io/badge/tests-1%2C995_passing-brightgreen" alt="1,995 tests passing">
<img src="https://img.shields.io/badge/skills-28-blue" alt="28 skills">
<img src="https://img.shields.io/badge/hooks-22-blue" alt="22 hooks">
<a href="https://lidge-jun.github.io/codexclaw/"><img src="https://img.shields.io/badge/docs-codexclaw-black" alt="Documentation"></a>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<p align="center">
<a href="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml"><img src="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<img src="https://img.shields.io/badge/tests-1%2C961_passing-brightgreen" alt="1,961 tests passing">
<img src="https://img.shields.io/badge/tests-1%2C995_passing-brightgreen" alt="1,995 tests passing">
<img src="https://img.shields.io/badge/skills-28-blue" alt="28 skills">
<img src="https://img.shields.io/badge/hooks-22-blue" alt="22 hooks">
<a href="https://lidge-jun.github.io/codexclaw/"><img src="https://img.shields.io/badge/docs-codexclaw-black" alt="Documentation"></a>
Expand Down
2 changes: 1 addition & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<p align="center">
<a href="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml"><img src="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<img src="https://img.shields.io/badge/tests-1%2C961_passing-brightgreen" alt="1,961 tests passing">
<img src="https://img.shields.io/badge/tests-1%2C995_passing-brightgreen" alt="1,995 tests passing">
<img src="https://img.shields.io/badge/skills-28-blue" alt="28 skills">
<img src="https://img.shields.io/badge/hooks-22-blue" alt="22 hooks">
<a href="https://lidge-jun.github.io/codexclaw/"><img src="https://img.shields.io/badge/docs-codexclaw-black" alt="Documentation"></a>
Expand Down
5 changes: 5 additions & 0 deletions bin/codexclaw.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ const TOP_LEVEL_HELP = [
" loop init|show|validate manage the project-local goalplan substrate",
" goalplan init|show|validate deprecated alias for loop",
" plan init <slug> [--phases N] scaffold the devlog/_plan unit the P>A gate verifies",
" receipt test -- <command> produce the test receipt a bound C>D requires",
" review-round open|show|abort the opt-in A-gate plan-audit round",
" scan record|show record interview coverage and contradiction scans",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Remove the nonexistent scan show verb from help

The new top-level help advertises cxc scan show, but the repository-wide command search finds no show handler and parseScanCliArgs accepts only record plus help aliases. Users following this entry therefore receive unknown scan action 'show'; either implement the read-only verb or list only the supported record command.

Useful? React with 👍 / 👎.

" metric record/show objective metrics",
" divergence record divergence mode and candidate archive state",
"",
Expand All @@ -282,6 +285,8 @@ const TOP_LEVEL_HELP = [
"",
"Agent notes:",
" Mutating PABCD commands require the current session id: cxc orchestrate P --session <id>",
" Every --attest object names the edge it advances: {\"from\":\"<phase>\",\"to\":\"<phase>\",\"did\":\"...\"}",
" plus that edge's keys. Run cxc orchestrate --help for the per-edge examples.",
" Use --json only on subcommands that document it, such as orchestrate status --json.",
" For command-specific help, start with: cxc orchestrate --help or cxc map --help.",
].join("\n");
Expand Down
2 changes: 1 addition & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codexclaw/cli",
"version": "0.2.12",
"version": "0.2.13",
"private": true,
"type": "module",
"description": "codexclaw CLI — status, subagent config, provider toggle, GUI launcher.",
Expand Down
39 changes: 39 additions & 0 deletions devlog/_plan/260822_attest_win_parity/040_recipe_verified.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 040 - the win32 recipe, executed rather than assumed

The attest fix tells Windows users to do this:

```powershell
'<json>' | Set-Content -Encoding utf8 .codexclaw/attest.json
cxc orchestrate <phase> --session <id> --attest-file .codexclaw/attest.json
```

That recommendation was executed before it was written down, because the
archive already contains a case where the obvious encoding advice is wrong
(`fuck-powershell#7`: `Out-File -Encoding utf8` writes a BOM on 5.1, and
`utf8NoBOM` does not exist there at all).

## Measured

```
bytes=48 head=efbbbf7b2266726f bom=UTF-8 BOM
utf8 matches=1
```

So `Set-Content -Encoding utf8` does prepend a BOM here too. The recipe is still
safe, because `orchestrate-cli.test.ts` already carries an explicit case:

> `#31: --attest-file tolerates a UTF-8 BOM (PowerShell 5.1 Set-Content -Encoding utf8)`

The CLI accepted the file; the only refusal was the phase gate (`IDLE -> D`),
which is correct.

## Why this is worth a page

Two of the three recommendations in the wider archive turned out to be wrong on
this host. A workaround that has not been run on the platform it targets is a
guess, and shipping a guess inside an error message is worse than shipping no
message — the agent trusts it and loses a turn.

The recipe is now exercised continuously rather than tested once: every attest in
this loop since the fix has gone through `--attest-file`, including the ones
closing these cycles.
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# 000 — baseline and scope: the attest from/to cascade, and the lessons opencodex paid for

Two things share one unit because they share one failure shape: **a gate that
rejects work the documentation told the agent to do.**

The attest half is the shipped CLI refusing an attestation whose shape the skill
never described. The devops half is opencodex's v2.32.1 freeze train discovering,
repeatedly, that a gate nobody can satisfy honestly gets satisfied dishonestly —
a red suite argued into an exception, a flaky test re-run until green, a
readiness report describing a tree that had already moved.

The flaky-test policy sits between them. It is currently the clearest instance
in this repo of a rule that contradicts itself in the same file.

## Baseline

Repo: `/Users/jun/Developer/new/700_projects/codexclaw` at `74245989`
(`devlog: the win32 recipe was executed, not assumed`), version 0.2.12.

Pre-existing dirty state, NOT created by this unit and to be preserved:

```
M scripts/dev-symlink.sh
?? devlog/_plan/260722_260722-repo-governance-config/
?? devlog/_plan/260814_260814-fix-main-ci-windows-worktree/
?? mktemp:
```

Test baseline before any edit, full declared command:

```
npm test
-> tests 1961 pass 1961 fail 0 duration_ms 36311.187 exit 0
```

The pabcd-state slice alone, run twice by the error-hunt lane:
865 pass / 0 fail both times, exit 0, 6.24s then 9.54s. Same 865 test names.
**No flaky test was observed in this repo's own suite.** That matters for scope:
the flaky work here is policy text, not a test repair.

## The defect, stated exactly

`coerceAttest` returns null unless `from` and `to` are strings
(`components/pabcd-state/src/attest.ts:91-96`). The CLI turns that null into:

```
attest JSON missing valid from/to
```

at `orchestrate-cli.ts:227` (inline) plus `orchestrate-grammar.ts:88` for the
chat surface. The `--attest-file` path at `:257` emits a DIFFERENT string,
`attest file <path> is missing valid from/to` — same defect, separate wording,
and therefore separate test coverage (see 002 blocker 2).

The contract agents actually read — the "Required attest keys" table at
`skills/pabcd/SKILL.md:91-98` — lists `did`, `auditOutput`, `auditVerdict`,
`auditResidual`, `checkOutput`, `exitCode`. It never names `from` or `to`.
An agent that copies the table writes `{"did":"..."}` and is refused before any
other check runs.

This is not theoretical and it is not rare:

```
cxc chat search "missing valid from/to" --days 0
-> 50 hits (3/9457 files scanned)
```

across opencodex, ima2-gen, cli-jaw and codexclaw sessions, the oldest sampled
at 2026-08-13. Every one of those is a wasted turn inside somebody's loop.

### It is a cascade, not a single error

The from/to refusal is only the first gate. Fixing it alone walks the agent into
the next two, because `planUnit`, `workPhaseId` and `testReceiptPath` are ALSO
absent from every skill doc (`rg` over pabcd/loop/interview returns zero hits for
all three) while the runtime requires them:

| # | Refusal | Source |
|---|---------|--------|
| 1 | `attest JSON missing valid from/to` | `orchestrate-cli.ts:227` (parse time, before session/plan/binding) |
| 2 | `P -> A requires "planUnit"` | `plan-gate.ts:38-43` |
| 3 | `A goalplan is bound ... pass "workPhaseId"` | `attest.ts:148` |
| 4 | `C -> D on a goalplan-bound session requires "testReceiptPath"` | `check-gate.ts:37` |

A bound HOTL session on P>A therefore needs FIVE keys the skill names ONE of.
Documenting only `from`/`to` would trade one round trip for two.

### Why 260822 did not already fix this

`devlog/_plan/260822_attest_win_parity/` fixed a different failure with a
similar surface: on Windows, PowerShell mangles inline `--attest '{...}'` so the
CLI sees invalid JSON. That unit made the recipes platform-aware and pushed
`--attest-file`. It never touched the key list, because the key list was not the
bug it was chasing. The from/to omission survived that sweep intact.

## Scope

IN:

- `skills/pabcd/SKILL.md` attest table and the copy-paste examples under it
- `skills/interview/SKILL.md:64,144` (two override examples missing from/to)
- `skills/loop/SKILL.md` attest references
- `structure/20_pabcd_dispatch_doctrine.md:72` (names the keys as invalid JSON)
- `components/pabcd-state/src/orchestrate-cli.ts` + `orchestrate-grammar.ts`
null-coerce error text, and `hook.ts` injected examples
- `components/pabcd-state/test/` regression coverage
- `skills/dev-devops/SKILL.md` + `references/ci-cd-deploy.md`,
`references/sre-foundations.md` (new DEVOPS-* rules)
- `skills/dev-testing/SKILL.md` §5.4 + `references/ci-pipeline.md` §5,
`skills/dev-debugging/SKILL.md` Scenario D + anti-pattern row,
`skills/dev/references/skill-ownership.md` (missing flaky row)
- this devlog unit

OUT:

- `~/.codex/plugins/cache/codexclaw/**` — the installed payload. The repo is the
source of truth; a rebuild may be RUN, no cache file is authored.
- the opencodex repo. It is read-only evidence this cycle: no branch, no PR, no
commit there.
- `git push`, PRs, npm publish, version bumps. Local commits only (LOOP-GIT-01).
- repairing the interview-readiness dead end found by the error-hunt lane (001
§F.1). It is a design decision about what `isInterviewReady` should accept,
not a text fix, and it gets its own unit.
- the docs-site quickstart and guide attest examples. They are a live
copy-paste surface and they are incomplete, but docs-site is its own build
with its own review; recorded as a follow-up (002 nit 4).

**Amended after audit (002 blocker 3):** `cxc freeze --help` was originally
listed OUT here while 010 §7 listed it IN. It is now **IN**. It is a workspace
mutation behind a read-only-looking flag that exits 0, so nothing signals it,
and the guard belongs in the same file family wp1 already opens.

## Accept criteria

| # | Criterion | Proof |
|---|-----------|-------|
| 1 | The attest table names every key the runtime requires per edge, with a copy-paste object | diff + `rg` for `workPhaseId` in `skills/pabcd` returning hits |
| 2 | The null-coerce refusal prints a correct example for the requested edge | actual CLI output of a failing invocation |
| 3 | A regression test pins that message | test name + green run |
| 4 | dev-devops carries the freeze-train lessons as named rules with devlog citations | `rg` for the new rule ids |
| 5 | Flaky guidance is elimination-first with one canonical owner and no surviving contradiction | `rg -i -e flaky -e quarantine` across the four skills |
| 6 | `npm test` green at the final tree | `cxc receipt test` path, exit 0 |

## Terminal outcome expected

DONE. `NOOP` is unavailable: the divergence is measured above, not hypothesized.
Loading
Loading