Repository navigation
Capability gate: promptfoo codex-sdk harness for the Codex jcodemunch, ai-memory and M13 gates, reconciled with native OTel - #433
Merged
seathatflowsinourveins merged 5 commits intoSep 27, 2026
Conversation
…, ai-memory and M13 gates tools/capability-gate runs the #381 Codex capability gates on promptfoo 0.123.1's openai:codex-sdk provider (`codex exec --profile stack-worker` through a one-line profile launcher) and scores them with promptfoo's trajectory:tool-used plus tool-result assertions over the provider's raw items. Invoke counts are reconciled per row with Codex's native OTel codex.tool_result records in Loki (service codex_sdk_ts, keyed by thread id). M13 runs two worktrees x 20 repetitions with a beforeEach hook that writes each row's fresh token, plus a disabled and a wrong-root control. Decision record: docs/decisions/2026-09-27-capability-gate-harness.md. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…ibed-call M13 scoring, safe Loki paging Repair round for the GPT-6 cross-family review of #433 (six P2 findings): - run_gate.py: every arm must produce exactly its expected rows, each row needs a distinct conversation id, and every control row must fail with its predicted outcome while untouched tools keep working (refused for approval per codex-rs/core/src/mcp_tool_call.rs#L1612 at rust-v0.157.1; no call when disabled; M13 wrong-root classes return the other tree's token, an error or nothing). - assertions.js: a class is own only from a completed, error-free call made as the brief prescribes (relative path, no cwd, no directory change, no token in the arguments; ctx_search only after a ctx_index of the fixture); a foreign token in any call of the class, completed or failed, is wrong_root_or_stale. - Loki: the query filters event_name="codex.tool_result" (label filter on structured metadata, Loki v3.7.8), pages resume at their last timestamp inclusive with deduplication, and a full page within one timestamp fails closed. - promptfoo: inherited PROMPTFOO_* settings are dropped and PROMPTFOO_LOG_DIR is pinned inside the private directory (src/logger.ts#L227 at 0.123.1). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…servation Under the wrong-root control ctx_index reports indexing the fixture and ctx_search under the same source returns no results (6 of 6 rows in both 2026-09-27 M13 smokes); the control shows the own token is not returned, not which tree was indexed. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Hot-file protocol: main's manifests/evidence.json, the branch's files re-registered, component matrix and new-host grand list rewritten, validate.py passed. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Collaborator
Author
Repair round for the GPT-6 cross-family review (one round, per the bounded review loop)The read-only GPT-6 review (codex exec,
Tests: 22 synthetic tests, up from 14, with cases for each finding.
Live re-run at
Merged main ( Residuals: none open from this review. |
… to the run that showed it Only the 20:47Z M13 smoke's raw items were inspected; the 20:16Z smoke recorded a tally only. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
seathatflowsinourveins
deleted the
claude/capability-gate-harness-20260927
branch
September 27, 2026 21:34
seathatflowsinourveins
pushed a commit
that referenced
this pull request
Sep 27, 2026
… gate rows The decision addendum and the evidence README said #433 was open. Its merged body records the first smoke's route miss (6 of 6), the repaired-scoring rows (order search_symbols 6 of 6, each returning the signature) and the pre-repair smokes as superseded; the two passages now say so. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This was referenced Sep 27, 2026
Closed
seathatflowsinourveins
pushed a commit
that referenced
this pull request
Sep 29, 2026
…echeck stamps, stack revision (#437 review H5a-d) (a) Summaries run to 606 characters, not 600: summarize() cuts at 600 and appends the 6-character " [...]" marker; 138 of 206 are cut and 60 exceed 600. The subset's own method field keeps the generator's wording and stays as generated. (b) The 38 exit-null records are 12 MCP requests (seven Claude Code tool calls: six socraticode, one qmd; five mcporter requests to repomix) and 26 shell plumbing, upstream CLI runs, a capture harness and local checks, not "mostly MCP calls". (c) The socraticode, qmd and ai-memory release rechecks are stamped 2026-09-27T01:11:26Z-01:24:04Z (2026-09-26 local). (d) condense.py stops at the first card whose pin differs from manifests/stack.json; the cards assume the stack manifest at 34c5634 (#372), which the rtk and toon cards cite, and 55fc8d1 (#433) has the same pins. The Reproduce section runs condense.py in a temporary root with that manifest; the documented block exited 0 with identical bytes at 2026-09-29T03:28Z (also with 55fc8d1). It also restores the pin sentence the previous commit split. Tests derive each statement from the bundle's data and fail on the previous README. Co-Authored-By: Claude Opus 5.5 <[email protected]>
seathatflowsinourveins
added a commit
that referenced
this pull request
Sep 29, 2026
… drift notes and a weekly native E2E (#437) * Token topic: 2026-09-27 per-tool card edition, stack-pinned join and drift note docs/token-efficiency-stack.json gains a dated edition. 17 rows carry a card condensed from the sanitized token-stack cards: upstream, native adaptation, E2E returned results, adapted performance per payload and lane, invoke rates and GPT-6 review, each labelled with its evidence class. The other 7 rows carry an explicit "no card in this edition" marker. gpt-tokenizer has a card but no stack.json component, so it is listed under edition.cards_without_row. scripts/build_ecosystem.py joins each row to manifests/stack.json for the version and repository and rejects row-level pins. When a card's recorded pin differs from the stack pin, the row shows a drift note instead of editing the card. The build validates every card block's evidence class, each comparison's counts and the card's source bytes and sha256. The edition and its artifacts link at the publication ref. evidence/artifacts/token-stack-cards-20260927 holds the sanitized cards, the invoke snapshot, the 206 cited returned-result records (command, exit, summary and the sha256 of each omitted body), the GPT-6 review index, a README with evidence classes and dates, and the generators. native-token-e2e.yml adds a weekly Monday 07:11 UTC schedule. AGENTS.md and docs/token-session-handbook.md each gain one pointer to the rows. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Token topic page: render the per-tool cards (template outside the brief's path list — coordinator to accept or reassign) The page's only inline script lives in docs/ecosystem/template.html, so the edition header, the stack-pinned drift note, the no-card marker and the six card blocks (upstream, native adaptation, E2E returned results, performance per payload and lane, invoke rates, GPT-6 review) render there. Each block states its evidence class; figures keep their lane, payload and unit and are never added across them. Only existing helpers (make/add/link with safeHref, textContent) are used; the build recomputes the CSP script hash. tests/test_ecosystem_manifest.py runs the real template through the Node page harness and asserts the rendered card text, the drift note and the no-card marker. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Hot files: evidence registration and generated reports Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * Token topic cards: card link fields pass the build's public_url gate (#437 review H2) docs/ecosystem/template.html topicCard renders upstream.recommended_install.url, recommended_wiring[].url, new_since_pin[].url and limitations[].url as links, but token_topic_card returned the card unchanged, so these reached safeHref, which accepts any http/https URL. Each now passes public_url, the gate card.source and the build's other external source links use; a rejected URL fails --check with the card's source path and the field. Tests plant http://, 127.0.0.1 and javascript: URLs in each field (12 cases, all passed the unchanged build) and accept a clean HTTPS set unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Token stack cards: bundle.py keys the returned results by the supplied basename (#437 review H5e) source() records each input under clean_text(path.name), but main() read inputs["returned-results.json"], so renaming the --returned-results file raised KeyError at line 190. The subset's source block now uses the supplied basename for both the lookup and its name; with the canonical name the output is unchanged. tests/test_token_stack_cards.py runs bundle.main on a synthetic input set under both names (the renamed case raised KeyError before the fix). Co-Authored-By: Claude Opus 5.5 <[email protected]> * Token stack cards: retained ledger readings behind the native_snapshot figures (#437 review H1) The five native_snapshot figures (rtk 42,367,855 and 26,531,271, headroom 579,411, context-mode 3,244,032 and 6,311,424) cited private assembly inputs only. tools/counter_readings.py opens the private token-report ledger read-only (sqlite3 URI mode=ro), matches each entry to its one snapshots row on tool, $HOME-relative scope, observed_at to the second and saved figure, requires the kind and session estimate the entry's basis quotes to equal the row's, and writes counter-readings.json: ledger ids 67, 68, 69, 71 and 72 with tool, scope, observed_at, success, saved, kind and, for context-mode, the session estimate (27,109,948 and 157,255). The evidence column and metrics.raw are never copied; the output passes a private-content scan before it is written. The copy re-measures nothing. The README's new section tabulates the backed figures and names the two rtk shortfall figures the card cites without a reading (39.2% over the host's lifetime, 16,493 rtk discover skips): they rest only on the private rtk.json input (sha256 in the Reproduce table) and this artifact does not verify them. The jcodemunch-mcp card has no native_snapshot entry. Tests require an identical reading for every entry, fail when one reading's saved figure, scope or time changes, allow only the sanitized fields and check the README section. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Token stack cards README: measured summary bound, exit-null counts, recheck stamps, stack revision (#437 review H5a-d) (a) Summaries run to 606 characters, not 600: summarize() cuts at 600 and appends the 6-character " [...]" marker; 138 of 206 are cut and 60 exceed 600. The subset's own method field keeps the generator's wording and stays as generated. (b) The 38 exit-null records are 12 MCP requests (seven Claude Code tool calls: six socraticode, one qmd; five mcporter requests to repomix) and 26 shell plumbing, upstream CLI runs, a capture harness and local checks, not "mostly MCP calls". (c) The socraticode, qmd and ai-memory release rechecks are stamped 2026-09-27T01:11:26Z-01:24:04Z (2026-09-26 local). (d) condense.py stops at the first card whose pin differs from manifests/stack.json; the cards assume the stack manifest at 34c5634 (#372), which the rtk and toon cards cite, and 55fc8d1 (#433) has the same pins. The Reproduce section runs condense.py in a temporary root with that manifest; the documented block exited 0 with identical bytes at 2026-09-29T03:28Z (also with 55fc8d1). It also restores the pin sentence the previous commit split. Tests derive each statement from the bundle's data and fail on the previous README. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Token session handbook: token topic rows are the adoption reference, cards are dated snapshots (#437 review H4) The line this PR added made each tool's topic row "its lane and adoption reference", but the cards are dated 2026-09-26/27 snapshots and the qmd card's lane_rule is already superseded by the SubagentStart carrier (adoption/hooks/claude/token-lanes-block.md L9 also names foundation-docs and foundation-adoption). The row is now the adoption reference, the current lane list is the carrier block, and each card block is called a dated snapshot. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Hot files: AGENTS.md token-topic pointer and evidence registration (#437 review H4) AGENTS.md: the pointer this PR added now makes a tool's topic row its adoption reference, calls its card a dated snapshot, and names the SubagentStart carrier block (adoption/hooks/claude/token-lanes-block.md) as the current lane list; one line, no other line touched. manifests/evidence.json registers the changed listed files (AGENTS.md, docs/token-session-handbook.md, scripts/build_ecosystem.py, tests/test_ecosystem_manifest.py, the card bundle README and tools/bundle.py) and the new evidence files counter-readings.json and tools/counter_readings.py. component_matrix.py --write and new_host_grand_list.py --write left their four reports unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Token stack cards: reproduction block status, truncation condition, list guard, test comment (#437 verifier findings) The round-one verifier found the README's reproduction block reported cmp's status, so it passed even when condense.py stopped: the block now runs under set -e and the README states the measured exit statuses of the block as written and with the current stack manifest. The truncation sentence names its condition (cut at the last space only when it is past character 300). token_topic_card's list guard now rejects any non-list, including a falsy one: a test covers {}, "" and null and fails against the previous guard. A test comment states where card.source.url comes from. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> * AgentsView re-pin registry: count the per-tool card lines that name the pinned version #437 adds per-tool card blocks to docs/token-efficiency-stack.json. The agentsview card names 0.43.0 on 12 lines as dated card facts (the pin the card recorded), so main's RepinLocationRegistryTests, which pairs every matching line of a re-pin file with a recorded location, failed with 14 matching lines against 2 recorded locations (CI run 36526587362). The registry entry now records dated_record_lines (count 12, with its basis) and location_mismatches counts them exactly; a wrong count fails a new test. A re-pin still changes only the two install lines. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> * Hot files: re-register the AgentsView registry files in the evidence manifest (manifests/evidence.json only; last commit per docs/lanes.md) Co-Authored-By: Claude Sonnet 5.5 <[email protected]> --------- Co-authored-by: Scout <scout@local> Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
7 of 8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
tools/capability-gate/runs the PR-H: E2E preregistration for the token-save-practice stack (frozen tasks, metrics, gate, procedure) #381 Codex capability gates on promptfoo 0.123.1'sopenai:codex-sdkprovider, and reconciles every row with Codex's native OTel records in Loki. The gates are jcodemunch, ai-memory (decision F7) and M13 worktree binding. The self-written transcript scorers are no longer used.0f76651d, merged with main ate82e6be7under the hot-file protocol.lane:foundationtools/capability-gate/;tests/test_capability_gate.py;docs/decisions/2026-09-27-capability-gate-harness.md;manifests/evidence.json(registration only).Why. The user asked that E2E and A/B checks use SOTA upstream harnesses rather than self-written tests. token-efficiency-evidence-cards owns
matrix_scan.pyand recommended upstream scoring for these receipts. promptfoo's evaluator and assertions, plus the native OTel counts, replace the earlier drivers:matrix_scan.pyscoring and the coordinator's scratchm13_probe.py.What runs
run_gate.py {jcodemunch,ai-memory,m13}runspromptfoo evalon the gate's config.PROMPTFOO_*settings are dropped, andPROMPTFOO_LOG_DIRis pinned inside that directory.codex.tool_resultcount in Loki.codex-profile-exec: inserts--profile "$CODEX_PROFILE"afterexec. The provider has no profile key, and codex-cli 0.157.1 rejects-c profile=....assertions.js: reads only tool results from the provider's raw items.trace-error-spansis not used, because of a promptfoo 0.123.1 bug:codex-sdk.ts:1508-1512treats Codex's"error": nullas a failure.ctx_searchcounts only after a completedctx_indexof the fixture.wrong_root_or_stale.m13_tests.jsinterleaves the rows a, b, and atmaxConcurrency: 2the two worktrees' sessions overlap;m13_hooks.js(beforeEach) writes each row's fresh token into.cg/<rep>/of that row's worktree;order search_symbolsexplicitly. In the first smoke,routewith areposent the whole task sentence as the query (counter.py:616-630, 1.108.319) and missed both symbols in 6 of 6 runs. The gate correctly failed that. token-efficiency-evidence-cards is changing the lane guidance.SOTA sources
34f74d34), https://github.com/promptfoo/promptfoo/tree/0.123.1:site/docs/providers/openai-codex-sdk.md: the provider;src/providers/openai/codex-sdk.ts#L1508-L1512: the null-error check;#L2430: raw items;site/docs/configuration/expected-outputs/deterministic.md#trajectorytool-used;site/docs/configuration/reference.md"Extension Hooks";site/docs/configuration/test-cases.md: test-levelprovidersand dynamic tests;src/evaluator.ts#L3587:beforeEachper step;#L4102: ordered steps with at mostmaxConcurrencyin flight;src/logger.ts#L227:PROMPTFOO_LOG_DIR.dist/index.jspassesworking_diras--cdand setsCODEX_INTERNAL_ORIGINATOR_OVERRIDE=codex_sdk_ts.rust-v0.157.1(tag commitac0e23e5):codex-rs/config/src/mcp_types.rs#L379:enabledper MCP server;#L262-L272:default_tools_approval_modeandenabled_tools, per decision F7;codex-rs/core/src/mcp_tool_call.rs#L1612: the refusal error that thepromptcontrols must show.09e6ce2f):docs/sources/reference/loki-http-api.md#L474-L475:startis inclusive andendexclusive, which the pager relies on;docs/sources/get-started/labels/structured-metadata.md#L74: label filters on structured metadata;counter.py#L584(_QUERY_ARG) and#L616-L630(shape_execute_args).Evidence-class table
memory_query. ctrl-prompt fails 2/2 as predicted (every call refused with the approval-policy error). ctrl-disabled fails 2/2 as predicted (0 calls). 10 rows as expected in 10 distinct sessions. Loki 10/10 rows (8 MCP tool results).python3 tools/capability-gate/run_gate.py ai-memoryat4079e0dd, run 2026-09-27T20:47:31Zorder search_symbolsthat returned the signature. ctrl-prompt fails 2/2 as predicted. ctrl-disabled fails 2/2 as predicted. 10 rows as expected in 10 distinct sessions. Loki 10/10 rows.run_gate.py jcodemunchat4079e0dd, run 2026-09-27T20:52:51Zownin 40/40 through prescribed calls, with 0 foreign tokens. ctrl-disabled fails 6/6 as predicted: the context-mode classes areno_call6/6, and shell and serena areown6/6. ctrl-wrongroot fails 6/6 as predicted: ctx_execute and ctx_execute_file arewrong_root_or_stale6/6, ctx_index_search ismiss6/6, and shell and serena areown6/6. 52 rows as expected in 52 distinct sessions. Loki 52/52 rows (236 MCP tool results).run_gate.py m13at4079e0dd, run 2026-09-27T20:47:31Z, about 15 min{service_name="codex_sdk_ts"} | event_name="codex.tool_result"returns the same 604 tool results over 82 conversations as client-side filtering of the 2,721 service records, per (conversation, namespace), over 20:00–20:45Z.routemissed the symbol 6/6.run_gate.pyat7f2fcf7cpython3 -m unittest tests.test_capability_gate(22 tests)Review. A GPT-6 cross-family read-only review (codex exec at max) of
7f2fcf7cfound six P2 issues and no P0 or P1. All six are fixed in4079e0dd; the PR comment maps each finding to its fix and test. This was one review plus one repair round, and no residuals are open.Receipts follow in a separate PR. They are recorded with
scripts/host_receipts.py recordfrom a detached worktree at the published main commit that contains this harness.Local commands run
Decision record
docs/decisions/2026-09-27-capability-gate-harness.mdcovers:matrix_scan.py, the scratchm13_probe.py, Inspect Scout 0.5.3 and Harbor v0.23.0;Host evidence
Not applicable. This PR adds no receipt.
🤖 Generated with Claude Code