diff --git a/CHANGELOG.md b/CHANGELOG.md
index 875ad77..0d3d829 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [0.1.8] - 2026-07-21
+
+### Fixed
+
+- Bounded the evidenced-partner deny guidance: include the recorded partners, or stop and review the exception with a human; no approval bypass is implied.
+- Distinguished the local two-partner fixture walkthrough from Billfold's separate one-partner provider-demo proof path.
+- Corrected public wording for the hero, generator producer, network boundary, path coverage limits, and Billfold reproduction links.
+
## [0.1.5] - 2026-07-17
### Fixed
diff --git a/README.md b/README.md
index dc724dd..482a0ff 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
-
Portable repository history that changes Codex's plan before an evidenced risky edit lands.
+Repository evidence that helps Codex plan around recorded risky changes.
@workspacejson/codex-mcp
@@ -25,9 +25,8 @@
| | |
| --- | --- |
| Task | Update the checkout route |
-| Without `workspace.json` | Codex proposes one file |
-| With `workspace.json` | The hook identifies two evidenced partners |
-| Enforcement | The incomplete patch is denied |
+| Recorded evidence | The route and its webhook partner share a co-change history — an incident and a revert, not an import |
+| An incomplete patch | The hook denies it, citing the specific evidence and the omitted partner |
| Outcome | Codex revises the changeset before the edit lands |
## Installation
@@ -115,7 +114,7 @@ npx agents-audit@0.4.3 generate .
This writes `.agents/workspace.json` with repository topology and hygiene. Today, `generated.fileIndex` is empty and `manual` fragility/co-change evidence is not auto-generated — those remain human-authored (ASSERTED tier at minimum, OBSERVED when backed by evidence records). The generator does not guess risk signals; guessed churn has no evidence records, remains ASSERTED, and cannot block. See [`fixture/`](fixture/) for a worked example with manual evidence.
-### Verify in two minutes
+### Local proof path — two recorded partners
`generate` (above) writes repository topology only — no fragility or co-change evidence, so a freshly generated `workspace.json` has nothing to deny yet. To see the deny path itself, use this repo's `fixture/`, whose `manual` evidence is hand-authored for exactly this demo:
@@ -125,12 +124,36 @@ This writes `.agents/workspace.json` with repository topology and hygiene. Today
No configuration beyond step 1 above. On your own repo, the same deny path activates once you've authored `manual.fragileFiles` / `manual.coChangePatterns` yourself — see [`docs/workspace-contract.md`](docs/workspace-contract.md).
+### Provider-demo proof path — Billfold's one recorded partner
+
+The judge-facing demo runs against [`workspace-json/billfold`](https://github.com/workspace-json/billfold), a small public payments service. This is a separate proof path from this repository's local `fixture/`: Billfold uses the single recorded pairing shown on camera, `src/routes/checkout.ts` and `src/webhooks/stripe.ts`; the local walkthrough above uses `src/auth/session.ts` and `src/lib/format.ts`.
+
+```bash
+git clone https://github.com/workspace-json/billfold.git
+cd billfold
+git checkout 5e97f1dc9e6a41eb80d2d6eb80d5ef703cbe1cde # main as of 2026-07-20; no tag covers this pairing yet
+npm install
+npx @workspacejson/codex-mcp install --with-hook
+```
+
+1. Open `billfold` in Codex. Ask it to change the idempotency-key format in `src/routes/checkout.ts`.
+2. The hook denies the patch, citing the recorded revert/incident and the omitted partner, `src/webhooks/stripe.ts`.
+3. Ask Codex to include `src/webhooks/stripe.ts` and retry — the patch proceeds. That clears the recorded-partner check; it is not a correctness verdict on the change (see [Current limitations](#current-limitations)).
+
+This pins to the commit above because `billfold`'s `main` is mutable and the two existing tags (`fixture-v1`, `fixture-v2`) predate this pairing — clone and stay on `main` instead if you want the current state.
+
## How it works
MCP supplies context. A deterministic hook enforces evidenced omissions. An optional, direct read-only GPT-5.6 API review challenges a supplied completed diff and preserves its request/response receipt locally. The reviewer never controls the hook, and a `PASS` verdict is not a safety certification.
+```bash
+git diff | npx @workspacejson/codex-mcp review --diff-stdin
+```
+
+Requires `OPENAI_API_KEY` (or `OPENROUTER_API_KEY`) in the environment. Without one, it reports `UNAVAILABLE` and deterministic enforcement is unaffected.
+
Full derivation rules for evidence tiers (`ASSERTED`/`OBSERVED`/`VERIFIED`), the hook's fail-open behavior, and the GPT-5.6 reviewer's scope live in [`docs/how-it-works.md`](docs/how-it-works.md).
## Operational guarantees
@@ -147,7 +170,9 @@ Each is checkable, not asserted: run `npm run verify` from a clean clone to repr
## Trust boundary
-The MCP and deterministic hook run locally over stdio and do not upload repository contents. Initial package installation may contact npm. The optional `review` command sends only the diff you explicitly supply to a configured API provider: OpenAI (`OPENAI_API_KEY`) or OpenRouter (`OPENROUTER_API_KEY`). When both keys exist, set `WORKSPACEJSON_REVIEWER_PROVIDER` to `openai` or `openrouter`; an explicit `WORKSPACEJSON_REVIEWER_BASE_URL` also selects OpenRouter. It uses `store: false` with OpenAI and preserves a local request/response receipt that identifies the provider and model. Do not supply diffs containing secrets.
+**Local, no network:** the MCP server, the deterministic hook, and the VS Code extension run over stdio and the local filesystem only. None of them upload repository contents or make network calls.
+
+**Network, by explicit action only:** `npx` package installation contacts npm. The optional `review` command sends only the diff you explicitly supply to a configured API provider: OpenAI (`OPENAI_API_KEY`) or OpenRouter (`OPENROUTER_API_KEY`). When both keys exist, set `WORKSPACEJSON_REVIEWER_PROVIDER` to `openai` or `openrouter`; an explicit `WORKSPACEJSON_REVIEWER_BASE_URL` also selects OpenRouter. It uses `store: false` with OpenAI and preserves a local request/response receipt that identifies the provider and model. Do not supply diffs containing secrets.
## Current limitations
@@ -156,6 +181,7 @@ The MCP and deterministic hook run locally over stdio and do not upload reposito
- Missing or malformed `workspace.json` fails open with an explicit unavailable warning.
- Stale evidence is not treated as proof of current risk.
- `fragile:false` means the file has no recorded fragility, not that it is verified safe.
+- Including a recorded partner's path clears the omission check; it confirms path coverage, not that the partner's content is correct or sufficient.
- This does not replace tests, review, or repository instructions.
## Learn more
@@ -168,7 +194,7 @@ The MCP and deterministic hook run locally over stdio and do not upload reposito
- [Verification](docs/verification.md) — what's been verified and how
- [Build Week disclosure](docs/submission/build-week.md) — what was authored in-window
- [Development](docs/development.md) — build, test, and smoke-suite commands
-- [Clean-install audit](docs/clean-install-audit.md) · [Fixture verification](docs/fixture-verification.md)
+- [Clean-install audit](docs/clean-install-audit.md) · [Fixture verification](docs/fixture-verification.md) · [`billfold`](https://github.com/workspace-json/billfold) — the public repo behind the demo video
## License
diff --git a/docs/fixture-verification.md b/docs/fixture-verification.md
index d82d474..2e41484 100644
--- a/docs/fixture-verification.md
+++ b/docs/fixture-verification.md
@@ -1,42 +1,68 @@
-# Checkout fixture verification
+# Billfold fixture verification
-This public fixture is a small, controlled checkout scenario for reproducing
-the documented co-change behavior. It is not a production incident record.
+Billfold is the public fixture for the `workspace.json` / Codex demonstration. It is a
+small, controlled checkout scenario for reproducing the documented co-change behavior —
+not a production incident record.
-## Frozen fixture
+## Repository
-- Repository: `workspace-json/codex-demo-fixture`.
-- Annotated tag and commit: [`fixture-v2`](https://github.com/workspace-json/codex-demo-fixture/tree/dc6f4d721affac96d517ca96cad8ccf8d9c15e3c)
- → `dc6f4d721affac96d517ca96cad8ccf8d9c15e3c`.
-- Artifact: [`.agents/workspace.json`](https://github.com/workspace-json/codex-demo-fixture/blob/dc6f4d721affac96d517ca96cad8ccf8d9c15e3c/.agents/workspace.json).
-- Artifact Git blob: `a6807d3ad39aa3f3a1f3471c2ae1d4288f879149`.
+- Repository: [`workspace-json/billfold`](https://github.com/workspace-json/billfold).
+- Reference commit: [`5e97f1d`](https://github.com/workspace-json/billfold/tree/5e97f1dc9e6a41eb80d2d6eb80d5ef703cbe1cde)
+ → `5e97f1dc9e6a41eb80d2d6eb80d5ef703cbe1cde` (2026-07-20).
+- No annotated tag currently covers this pairing. The two existing tags,
+ `fixture-v1` and `fixture-v2`, predate it and point to a different recorded
+ pairing (`checkout.ts` co-changing with `src/auth/session.ts` and
+ `src/lib/format.ts` — the same pairing this repo's own `fixture/` directory
+ reproduces locally). Do not cite `fixture-v1`/`fixture-v2` for the pairing
+ described below.
+- Artifact: [`.agents/workspace.json`](https://github.com/workspace-json/billfold/blob/5e97f1dc9e6a41eb80d2d6eb80d5ef703cbe1cde/.agents/workspace.json).
+- Artifact Git blob: `b86f453b716e1f03dc2cb93734e48ba20fdd9f55`.
- Artifact SHA-256:
- `5c97c81c8d6457e795c174d740026862512925cbf2efa9c66c1a18712285593d`.
+ `be4072f3e1937f970fab290ec96ba9eabe34827623a84176be816d13e64b0484`.
-The primary edit path is `src/routes/checkout.ts`; its recorded co-change
-partners are `src/auth/session.ts` and `src/lib/format.ts`.
+This is the provider-demo proof path. It is separate from this repository's local
+`fixture/` walkthrough, which records two checkout partners (`src/auth/session.ts` and
+`src/lib/format.ts`); Billfold records the one checkout/Stripe partner below.
+
+The primary edit path is `src/routes/checkout.ts`; its recorded co-change partner is
+`src/webhooks/stripe.ts`. The relationship is not visible through a direct import or
+shared symbol — checkout builds a retry key that the webhook parses independently.
+It is recorded as a co-change pattern plus a fragility reason citing a 2026-02-28
+rounding change to `checkout.ts` that was reverted two days later
+(`985b0d4`, `05989dc`), both reproducible with the `git log`/`git show` commands
+embedded in the artifact's own evidence entries.
## Reproduce
```sh
-git clone https://github.com/workspace-json/codex-demo-fixture.git
-cd codex-demo-fixture
-git switch --detach fixture-v2
-npm test
+git clone https://github.com/workspace-json/billfold.git
+cd billfold
+git checkout 5e97f1dc9e6a41eb80d2d6eb80d5ef703cbe1cde
+npm install
+npx @workspacejson/codex-mcp install --with-hook
```
-The route-only regression commit
-`ca1f7ec8e124b4050deb5cd6d704bea0fe1dcee7` fails `npm test`. The corrective
-co-change commit `a9729be1486dc199adc1f42371847217cba9d883` and `fixture-v2`
-pass it.
+Ask Codex to change the idempotency-key format in `src/routes/checkout.ts` alone. The
+hook denies the patch (exit code 2), citing the recorded evidence and the omitted
+partner, `src/webhooks/stripe.ts`. Including that partner in the same patch clears the
+deny; this confirms the recorded path is present, not that the included change is
+correct — see the README's [Current limitations](../README.md#current-limitations).
+
+`billfold`'s own `scripts/capture-red-evidence.mjs` still hardcodes a regression commit
+(`ca1f7ec8e124b4050deb5cd6d704bea0fe1dcee7`) from the prior `session.ts`/`format.ts`
+pairing, predating the `stripe.ts` evidence above. It has not been updated for this
+pairing and should not be used to reproduce a red/green `npm test` pair for the
+checkout/webhook relationship described here.
## Spec compatibility
The plugin reads only `manual.fragileFiles`, `manual.coChangePatterns`,
`generated.fileIndex`, and `generated.frameworkManifest` when present.
-The frozen artifact is a documented validate-and-warn case: with
-`@workspacejson/spec` v0.4.1, both `validate()` and `validateV4()` return
-`false`. The consumer still normalizes the locked paths, returning the checkout
-fragility record, both recorded partners, and an indexed primary path. This
-does not turn the validation discrepancy into an approval or safety claim.
+Checked against the currently published `@workspacejson/spec@0.4.3`: `validate()`
+returns `true` for the reference artifact above; `validateV4()` and `validateLegacy()`
+both return `false`. The consumer still normalizes the locked paths, returning the
+checkout fragility record, the recorded partner, and an indexed primary path. This
+does not turn the `validateV4()`/`validateLegacy()` result into an approval or safety
+claim, and `validate() === true` is not a correctness claim about the recorded
+evidence either — only that the document's shape matches the general schema.
diff --git a/docs/submission/build-week.md b/docs/submission/build-week.md
index fef662e..562c388 100644
--- a/docs/submission/build-week.md
+++ b/docs/submission/build-week.md
@@ -1,5 +1,5 @@
# For the OpenAI Build Week submission
-> This project was built during OpenAI Build Week as a new Codex integration for the open `workspace.json` standard. The `workspace.json` standard and its generator (`@workspacejson/cli`) are pre-existing open-source work, used here as a dependency the same way any participant could depend on it. The Build Week contribution is `@workspacejson/codex-mcp`: the MCP server, its tool surface, deterministic hook, packaging, and optional direct GPT-5.6 read-only API reviewer, all authored or integrated in-window and contained in this repository.
+> This project was built during OpenAI Build Week as a new Codex integration for the open `workspace.json` standard. The `workspace.json` standard and its generator (`agents-audit`) are pre-existing open-source work, used here as a dependency the same way any participant could depend on it. The Build Week contribution is `@workspacejson/codex-mcp`: the MCP server, its tool surface, deterministic hook, packaging, and optional direct GPT-5.6 read-only API reviewer, all authored or integrated in-window and contained in this repository.
Codex accelerated implementation, regression-test generation, packaging validation, and adversarial review. Human decisions control the product boundary: deterministic evidence remains the enforcement plane; GPT-5.6 performs visible semantic risk review without write or enforcement authority; Q approves the fixture, claims, evidence tiers, design, narration, and submission.
diff --git a/package-lock.json b/package-lock.json
index 32a53b9..6167355 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@workspacejson/codex-mcp",
- "version": "0.1.7",
+ "version": "0.1.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@workspacejson/codex-mcp",
- "version": "0.1.7",
+ "version": "0.1.8",
"license": "Apache-2.0",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.20.0",
diff --git a/package.json b/package.json
index 356d37b..3fcdeaa 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@workspacejson/codex-mcp",
- "version": "0.1.7",
+ "version": "0.1.8",
"description": "MCP server that surfaces workspace.json fragility and co-change intelligence to OpenAI Codex before it edits code.",
"license": "Apache-2.0",
"type": "module",
diff --git a/scripts/smoke.mjs b/scripts/smoke.mjs
index 87f6bb0..696d1c5 100644
--- a/scripts/smoke.mjs
+++ b/scripts/smoke.mjs
@@ -41,6 +41,14 @@ check(
]),
names.join(","),
);
+const assessTool = tools.find((tool) => tool.name === "workspace_assess_change");
+check(
+ "assessment tool describes the bounded human-review path",
+ assessTool?.description?.includes(
+ "Include the recorded co-change partners, or stop and review the exception with a human.",
+ ),
+ assessTool?.description,
+);
// ── Tier derivation through file context ──
const r1 = await client.callTool({ name: "workspace_get_file_context", arguments: { path: "src/routes/checkout.ts" } });
@@ -102,6 +110,13 @@ check(
"deny message names missing partners",
/src\/auth\/session\.ts/.test(d1.structuredContent?.assessments?.[0]?.message ?? ""),
);
+check(
+ "deny message uses bounded human-review wording, not an approval bypass",
+ /Include the recorded co-change partners, or stop and review the exception with a human\./.test(
+ d1.structuredContent?.assessments?.[0]?.message ?? "",
+ ) && !/get explicit human approval/i.test(d1.structuredContent?.assessments?.[0]?.message ?? ""),
+ d1.structuredContent?.assessments?.[0]?.message,
+);
const d2 = await client.callTool({
name: "workspace_assess_change",
diff --git a/src/evidence.ts b/src/evidence.ts
index ac88d23..347e847 100644
--- a/src/evidence.ts
+++ b/src/evidence.ts
@@ -163,7 +163,7 @@ export function decideEnforcement(input: {
if (evidencedFragile && missingPartners.length > 0) {
action = "deny";
- message = `BLOCK [tier ${input.tier}]: ${input.path} is fragile${input.reason ? ` (${input.reason})` : ""} and historically co-changes with ${missingPartners.join(", ")}, which this change omits.${cite} Include the co-change partners or get explicit human approval to proceed without them.`;
+ message = `BLOCK [tier ${input.tier}]: ${input.path} is fragile${input.reason ? ` (${input.reason})` : ""} and historically co-changes with ${missingPartners.join(", ")}, which this change omits.${cite} Include the recorded co-change partners, or stop and review the exception with a human.`;
} else if (evidencedFragile) {
action = "warn";
message = `CAUTION [tier ${input.tier}]: ${input.path} is fragile${input.reason ? ` (${input.reason})` : ""}.${cite} Prefer minimal, well-tested changes.${
diff --git a/src/index.ts b/src/index.ts
index 861f16d..5ead151 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -5,7 +5,7 @@ import { isVerifyEnabled } from "./config.js";
import { SERVER_INSTRUCTIONS } from "./constants.js";
import { registerWorkspaceTools } from "./tools/workspace.js";
-const VERSION = "0.1.7";
+const VERSION = "0.1.8";
function buildServer(): McpServer {
const server = new McpServer(
diff --git a/src/tools/workspace.ts b/src/tools/workspace.ts
index 3339ced..01e28cc 100644
--- a/src/tools/workspace.ts
+++ b/src/tools/workspace.ts
@@ -409,7 +409,7 @@ Returns JSON:
description: `Evaluate a SET of file paths (a proposed change) against workspace.json fragility and co-change history, and return a mechanical enforcement decision.
Decision semantics (derived, never model-emitted):
- - "deny": an evidenced-fragile file is touched while its recorded co-change partners are absent from the changeset. Include the partners or get explicit human approval.
+ - "deny": an evidenced-fragile file is touched while its recorded co-change partners are absent from the changeset. Include the recorded co-change partners, or stop and review the exception with a human.
- "warn": evidenced-fragile file touched (partners covered), or co-change partners missing on a non-evidenced file.
- "annotate": fragility asserted without evidence. Context only.
- "none": no recorded history. This is NOT a safety approval; this tool never certifies a change as safe.
diff --git a/tests/unit/evidence.test.ts b/tests/unit/evidence.test.ts
index 3b0e11c..4e6731a 100644
--- a/tests/unit/evidence.test.ts
+++ b/tests/unit/evidence.test.ts
@@ -125,9 +125,30 @@ describe("decideEnforcement", () => {
expect(result.message).toContain("BLOCK");
expect(result.message).toContain("src/auth/session.ts");
expect(result.message).toContain("revert d4e5f6");
+ expect(result.message).toContain(
+ "Include the recorded co-change partners, or stop and review the exception with a human.",
+ );
+ expect(result.message).not.toContain("get explicit human approval");
expect(result.message).not.toContain("safe");
});
+ it("uses path membership and has no override for an evidenced missing partner", () => {
+ const input = {
+ path: "src/routes/checkout.ts",
+ fragile: true,
+ tier: "OBSERVED" as const,
+ evidence: [{ claim: "revert d4e5f6" }],
+ coChangePartners: ["src/auth/session.ts"],
+ changesetPaths: ["src/routes/checkout.ts", "src/auth/session-helper.ts"],
+ override: true,
+ };
+
+ const result = decideEnforcement(input);
+
+ expect(result.action).toBe("deny");
+ expect(result.missingPartners).toEqual(["src/auth/session.ts"]);
+ });
+
it("warns when evidenced fragility is touched but partners are covered", () => {
const result = decideEnforcement({
path: "src/routes/checkout.ts",