Skip to content

feat(crosscheck): GLM-5.2 Foundry reviewer lane, retire the interim claude lane (R6) - #264

Merged
ruby-dlee merged 8 commits into
mainfrom
fm/crosscheck-glm-reviewer
Aug 20, 2026
Merged

feat(crosscheck): GLM-5.2 Foundry reviewer lane, retire the interim claude lane (R6)#264
ruby-dlee merged 8 commits into
mainfrom
fm/crosscheck-glm-reviewer

Conversation

@ruby-dlee

@ruby-dlee ruby-dlee commented Aug 20, 2026

Copy link
Copy Markdown
Owner

What

Implements R6 (decision record: docs/azure-requirements.md, R6 final: GLM-5.2 via the Fireworks partner lane on our own Azure AI Foundry resource; interim claude reviewer context from PR #259): the Crosscheck second reviewer's sole primary family becomes GLM-5.2 (FW-GLM-5.2 on resource aif-fm7c799d-eus01), driven by pi through the azure-glm custom provider, and the interim claude reviewer lane is retired end to end.

  • bin/fm-crosscheck.py

    • allowed_profiles: ("pi", "FW-GLM-5.2", "xhigh") is the primary profile; ("pi", "gpt-5.6-sol", "xhigh") and ("codex", "gpt-5.6-sol", "xhigh") remain the dormant fallback family; ("claude", "claude-opus-5", "xhigh") is removed (retired artifact 1 of 3).
    • Provider derivation is an explicit model-to-provider mapping (PI_MODEL_PROVIDERS): FW-GLM-5.2 -> --provider azure-glm, gpt-* -> --provider openai-codex, and any unmapped model refuses by name instead of guessing.
    • GLM credential shape: a GLM reviewer's account_home is a dedicated pi agent dir whose credential is models.json (new inspect_pi_glm_credential). It must parse and contain exactly the azure-glm provider with baseUrl equal to the pinned endpoint, api openai-completions (chat completions only; a Responses-API-shaped configuration is refused), usable apiKey material, and the FW-GLM-5.2 deployment id. The endpoint is an allowlist of exactly https://aif-fm7c799d-eus01.cognitiveservices.azure.com/openai/v1, pinned as module constants with the R6 comment; any other baseUrl refuses with an exact string.
    • credential_identifier is a NON-SECRET binding: glm-foundry-binding:sha256("aif-fm7c799d-eus01/FW-GLM-5.2\n" + pinned baseUrl). The api key and any digest of it never enter identity, ledger, or output; the ledger reviewer identity is azure-glm:aif-fm7c799d-eus01/FW-GLM-5.2.
    • Loud fallback: every validated roster entry records durable review_family_mode (glm-primary for GLM, codex-fallback for the gpt family) in the ledger reviewer record the run already writes; a fallback run prints the exact warning line CROSSCHECK DEGRADED: codex-family fallback reviewer <harness> <model> is standing in for the GLM-5.2 primary lane; crosscheck-same-model relaxation was required|was not required, and the readable report renders Review family: **CODEX FALLBACK**. Ledger validation admits only the two family values.
  • bin/fm-crosscheck-azure.py

    • "claude": api.anthropic.com leaves HARNESS_PROVIDER_HOSTS (retired artifact 2).
    • effective_provider_host is model-aware: a pi FW-GLM-5.2 review derives aif-fm7c799d-eus01.cognitiveservices.azure.com and refuses a conflicting configured provider_host; the codex-family fallback keeps its existing derivation.
    • The claude credential packaging/boot-copy lane is removed (retired artifact 3): no .credentials.json inspection, archive name, CLAUDE_CONFIG_DIR selector, or claude launch branch remains; an unknown harness refuses by name. The packaged compartment credential for the GLM profile is the api-key models.json under the same endpoint allowlist pin, and validate_azure_reviewer_record additionally requires a GLM record's provider_host to equal the pinned Foundry host.
    • The GLM preflight treats the api-key credential as non-expiring and uses the shape/allowlist inspection itself as the spend gate.
  • bin/fm-crosscheck-azure-model-guest.sh: claude branch deleted; the pi branch maps the model to its provider (FW-GLM-5.2 -> azure-glm, gpt-5.6-sol -> openai-codex, otherwise refuse); the credential unpack expects models.json for the GLM profile, verifies the pinned baseUrl, and digests the non-secret Foundry binding as the executing account.

  • Docs: docs/crosscheck.md, docs/azure-crosscheck.md, and docs/configuration.md now name GLM-5.2 as the sole primary review family, the pi-codex fallback as loud/degraded, the claude lane as retired, and the exact endpoint binding.

Why

R6 requires the merge-gate reviewer to sit outside the author's model family. Firstmate authors run on codex-family and claude models; GLM-5.2 on our own Foundry deployment reviews all authors cross-family, with reviewer identity bound to the Foundry resource + deployment (an api key names no upstream account). The claude lane existed only as the interim cross-provider stopgap and is retired per the decision record.

Test evidence

  • tests/fm-crosscheck.test.sh: full suite green, 80/80 ok, rc=0 (post-change run).
    • New/updated cases: test_reviewer_policy_profiles_and_independence (GLM accepted as primary; claude refused with the exact profile message must be codex gpt-5.6-sol xhigh or pi FW-GLM-5.2 xhigh or pi gpt-5.6-sol xhigh), test_claude_reviewer_profile_is_retired, test_glm_reviewer_executes_bound_policy_profile (asserts the constructed pi argv --mode json --provider azure-glm --model FW-GLM-5.2 --thinking xhigh ... via the argv-dumping pi fixture, plus ledger glm-primary and the non-secret binding), test_glm_credential_binding_is_key_independent (two configs differing only in apiKey yield byte-identical identifiers; neither key nor its sha256 appears; wrong baseUrl/missing file/Responses api/multi-provider/wrong deployment each refuse with their exact strings; provider mapping refuses unmapped models), test_codex_fallback_family_is_loud_and_recorded (exact degraded warning line with and without the same-model relaxation, durable ledger marker, report marker).
  • tests/fm-crosscheck-azure.test.sh: 15/15 ok, rc=0.
    • New units: glm_provider_host_unit (model-aware host derivation, foreign-host refusal, claude host retired from the table and refused, adapter/core constant equality, ledger-record pinned-host enforcement), glm_credential_lane_unit (inspect_reviewer_credential GLM shape, create_credential_archive packages models.json with the allowlist pin and refuses a foreign endpoint, the claude credential lane refuses by name, GLM preflight usable/missing behavior). static_contract now asserts the guest carries the azure-glm mapping and zero claude references.
  • bash -n on the model guest; python3 -m py_compile on both python entrypoints; bin/fm-lint.sh (pinned ShellCheck 0.11.0) green on the three changed shell files.

Mutation proofs (applied, proven red, reverted; outputs recorded)

  1. Widened the endpoint allowlist (if False and base_url != GLM_ALLOWED_BASE_URL): test_glm_credential_binding_is_key_independent went red - AssertionError: unusable GLM credential was accepted: GLM reviewer endpoint allowlist refused baseUrl 'https://aif-other.cognitiveservices.azure.com/openai/v1'; ... (rc=1). Reverted; rc=0.
  2. Dropped the degraded marker (roster always records glm-primary): test_codex_fallback_family_is_loud_and_recorded went red - not ok - the codex-family fallback did not announce itself with the exact degraded warning (rc=1). Reverted; rc=0.
  3. Readmitted ("claude", "claude-opus-5", "xhigh") into allowed_profiles: test_claude_reviewer_profile_is_retired went red (not ok - the retired claude profile was not refused at reviewer preflight) and test_reviewer_policy_profiles_and_independence went red (AssertionError: reviewer configuration.reviewers[0] must be claude claude-opus-5 xhigh or codex ...), both rc=1. Reverted; rc=0.

Review absorption (adversarial review round 1)

BLOCKER (fixed in fix(crosscheck): refuse model-level baseUrl/api overrides that outrank the pinned GLM endpoint): pi's provider composer gives MODEL-level fields precedence over the provider level (dist/core/provider-composer.js: api = definition.api ?? providerConfig.api, baseUrl = definition.baseUrl ?? providerConfig.baseUrl, verified against the installed pi 0.84.2), so a models.json keeping the pinned endpoint at provider level while smuggling "baseUrl"/"api" inside the FW-GLM-5.2 model entry escaped the allowlist. All three gates now refuse any model entry carrying either field, even one repeating the pinned values: inspect_pi_glm_credential (core), the create_credential_archive GLM branch (azure adapter), and the model guest's credential unpack. Covered by the exact exploit shape in test_glm_credential_binding_is_key_independent (foreign override AND pinned-value repeat both refuse) and glm_credential_lane_unit (inspection + archive gate), plus a guest static marker; mutation proof 4 below.

NOTE 1 (fixed in fix(crosscheck): remove the retired claude identity reader and bind the family marker to the model): the now-unreachable claude branch in account_identity (the last .credentials.json reference in the crosscheck tree) is deleted; an unknown harness refuses by name.

NOTE 2 (same commit): validate_ledger now binds review_family_mode to the reviewer model in both directions - glm-primary requires the GLM model (provider-slot prefixes stripped via model_identity), codex-fallback requires a non-GLM one - so a forged record cannot claim the wrong family. Unit added in test_codex_fallback_family_is_loud_and_recorded covering honest pairings (including the absent-field older-ledger shape) and both forged directions; mutation proof 5 below.

Mutation proofs (round 2)

  1. Disabled the model-level override guard (if False and (...)): test_glm_credential_binding_is_key_independent went red - AssertionError: unusable GLM credential was accepted: model-level baseUrl/api override (rc=1). Reverted; rc=0.
  2. Disabled the family-model pairing (True or (...) in the validate_ledger require): test_codex_fallback_family_is_loud_and_recorded went red - AssertionError: forged family glm-primary for gpt-5.6-sol validated (rc=1). Reverted; rc=0.

Honest limits

  • The currently built fm-ccm model image has NO pi binary baked (verified 2026-08-16, ledger M29), so the Azure-compartment GLM lane in this PR is code-complete but not executable until an image rebake and gallery promotion repoint model_image_id. No rebake is attempted here. The executable GLM lane tonight is the LOCAL pi reviewer.
  • The Foundry deployment currently carries a 25K TPM quota cap (DataZoneStandard, capacity 25), which bounds review throughput until quota is raised.
  • All suite coverage here is hermetic (fixture pi/codex/gh doubles); live end-to-end GLM review runs happen after merge, when the roster config points at the real GLM agent dir.
  • The tracked model-image declaration (docs/azure-crosscheck/model-image.json) still pins the claude CLI closure; it is a build-input declaration, the pinned image is unchanged by this PR, and dropping the claude CLI from the bake belongs to the future rebake.

@ruby-dlee
ruby-dlee merged commit f86d07c into main Aug 20, 2026
13 checks passed
ruby-dlee added a commit that referenced this pull request Aug 20, 2026
… owed

R6 still read NOT DONE with a work list describing work that merged in #264
and is now serving. Records what landed, what is genuinely still owed (the
live end-to-end GLM review, blocked on a 25K token-per-minute Fireworks
quota that is an owner portal action; the startup-credit decrement check;
the compartment lane's image rebake), and leaves the acceptance sentence
unmet because it is.
ruby-dlee added a commit that referenced this pull request Aug 20, 2026
… owed (#275)

* docs(azure): make the R6 status true to what landed and what is still owed

R6 still read NOT DONE with a work list describing work that merged in #264
and is now serving. Records what landed, what is genuinely still owed (the
live end-to-end GLM review, blocked on a 25K token-per-minute Fireworks
quota that is an owner portal action; the startup-credit decrement check;
the compartment lane's image rebake), and leaves the acceptance sentence
unmet because it is.

* docs(azure): correct the R6 status to what the artifacts actually show

A verification pass found ten findings against this section, three of them
merge-blocking. All ten are addressed here, docs only, one file.

The image claim is refuted rather than softened. The current fm-ccm image
does carry pi. Config model_image_id names gallery version 1.0.1787092687,
whose source managed image img-fm7c799d-ccm-1.0.1787091895 carries the
pi-tarball-sha256 and node-tarball-sha256 tags that only a build from the
Pi-carrying declaration (#246) can write, its Image Builder run succeeded on
2026-08-18 between 22:26:20Z and 22:36:46Z, after #246 landed on main at
20:51:35Z, and that declaration asserts pi --version against a tracked
version twice, before and after the credential purge. The digests match
docs/azure-crosscheck/model-image-closure.json for pi-coding-agent 0.84.1
and Node v22.23.2. The old finding was correct about 1.0.1786915905, which
the config stopped naming on 2026-08-18, and it was already stale when it
was written into docs/azure-crosscheck.md on 2026-08-20. The dangling
"ledger M29" provenance is dropped. The operative fact the section omitted
is now stated: the lane is off because crosscheck-azure.json has
enabled:false.

The status line no longer overclaims. BUILT AND SERVING becomes BUILT
2026-08-20 with the fact that matters first: zero GLM reviews have ever
completed, six attempts on 2026-08-20 all recorded tool-failure, and the
lane's only verdict came from the pi-codex fallback. The current roster
state is reflected, including the restored fallback entries with
crosscheck-same-model on.

Other corrections: 510K tokens was one hour reported as a day, and the
measured total is 727,136; the reasoning_effort probe is restated as an
unretained observation; the five-tool-turns figure is removed because no
run record carries a turn count; both per-minute limits are stated and the
token attribution is labelled inference; the account of what killed each
attempt is replaced with what the ledger records; the C1 forward reference
is dropped; the zeroed GLM cost table is recorded as a spend-visibility
gap; the Cost Management implication is dropped while keeping the fact;
and three Work items that appeared in neither list are now covered.

R9 is left alone: it already says a pi review on the current image is
unproven, which stays true and is consistent with the corrected text.

* docs(azure): keep the quota wording consistent with the inference caveat

* docs(azure): retire the fm-ccm no-pi claim at its source and in C1

Scope expansion approved by the coordinator: the requirement doc corrected
this claim while the component doc it originated in still asserted it, and
C1 (merged in #274 while this branch was open) had since built five further
claims on top of it.

docs/azure-crosscheck.md, where the sentence originated, now records the
corrected limit with the evidence chain: the current fm-ccm image carries
pi, and the lane is off because crosscheck-azure.json has enabled:false.
The 2026-08-16 measurement is kept and attributed, since M29 is not a
dangling reference, only one that lives in the owner's mutation ledger
outside this repository, which is now said explicitly. Two neighbouring
sentences depended on the false one: the instrumentation follow-up
described as bound to an image rebake, and the phases paragraph attributing
the lane's silence to a missing image capability. Both now name the flag.

C1 depended on it five times and one of those dependencies was independently
wrong: it stated the operator home has no config/crosscheck-azure.json. The
file exists, carries enabled:false, and names a current model_image_id. Also
corrected: the status line and order-of-work entry no longer say the phases
wait on a rebake; the argument that the 75 minutes cannot have come from a
compartment run after 2026-08-16 is withdrawn rather than restated, since
its premise was the false claim; and unmeasurable becomes unmeasured, which
is a reversible condition.

C1's "known contradiction" paragraph is resolved rather than left stale:
R6's status line no longer reads NOT DONE. It now carries the correction
that matters to C1, which is that GLM has never completed a review, so the
pi-codex fallback is what served the one measured run.
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