Repository navigation
Conversation
…ma 8 The collector should check calibration_diagnostics.json at intake without importing Microcosm's pydantic models. The existing calibration_diagnostics_json_schema() returns the parse adapter's union with the legacy schema-6/7 envelope. It declares no dialect and doesn't say which model rules it leaves out. calibration_diagnostics_v8_json_schema() generates the schema from CalibrationDiagnosticsV8 in validation mode and adds the Draft 2020-12 dialect, an $id, a title and a description. The description lists every rule the models enforce that a generated schema cannot express, from the JsonSchemaGap register: cross-field reconciliations, finite numbers, non-blank text, strict integers and digest anchoring under Python's re. It also notes the one place the schema is stricter, literal values, which the models compare with Python equality. The tests pin four things: - every validator function in the schema-8 model tree is listed; - each listed rule has a document the schema accepts and the models refuse; - valid documents are accepted by both; - representative invalid documents are refused by both. The two schema-8 document builders move from test_schema.py to test_support, so both test modules share them. jsonschema, already locked through microcosm-build, joins the microcosm-diagnostics dev group. The primary-QRF worker identity's approved uv.lock digest moves with the lock, as it does for every lock change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ainst it Consumers need the schema as a file at a stable path, and the file must not drift from the models. It is committed at packages/microcosm-diagnostics/src/microcosm/diagnostics/schemas/calibration_diagnostics.v8.schema.json, where it ships in the wheel. tools/generate_calibration_diagnostics_json_schema.py regenerates it, or checks it with --check. A byte-exact drift test fails while the file differs from freshly generated output. The engine-free test builders that already write real schema-8 diagnostics now also validate them against the committed file, after strict JSON parsing: - the US national release writer; - the ACS local-area calibrate stage; - the UK writer, with and without skipped targets and consumption drift; - the UK graph terminal gate kernel, with a measured rotated holdout; - the transport toy country's terminal kernel. The UK kernel test and the US NaN-loss test move their setup into helpers so the new tests share it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
calibration-diagnostics-json-schema
branch
from
October 19, 2026 20:36
8ad3184 to
7ede7dd
Compare
…figures microcosm#1301 changed UKAreaFit on main: released diagnostics withhold an area's support figures (nonzero_households, nonzero_source_households, effective_sample_size) and carry support_below_floor instead. The figure fields became optional so earlier documents still parse. The committed schema was generated before that change. It still required the three figures and did not declare the flag, so it refused the diagnostics that UKFullGateKernel now writes. That kernel runs the UK build's full set of validation checks on the final calibrated weights and writes its calibration diagnostics. Regenerated with tools/generate_calibration_diagnostics_json_schema.py. Only the UKAreaFit definition changes: support_below_floor is an optional boolean or null, and each figure is optional, null or at least 0, as before. New tests check the published file the way consumers read it. It must accept a UK area fit with the floor flag only, with neither flag nor figures, with legacy figures, or with explicit nulls, and the models must accept each. It must also refuse a negative legacy figure, as the models do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
calibration-diagnostics-json-schema
branch
from
October 19, 2026 20:36
7ede7dd to
c0549d2
Compare
This was referenced Oct 19, 2026
…-schema Stack this branch on us-calibration-epoch-thinning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added this pull request to stack #1323
October 19, 2026 21:09
…-schema Carry us-calibration-epoch-thinning up the stack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-schema Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-schema Brings in main (#1289, #1305) through the base branch. GitHub builds each stacked pull request's test merge on top of main. test_uk_graph_terminal.py conflicted: this branch and #1305 each pulled the terminal gate kernel run out of a test into a helper. #1305's helper, _run_final_gate_kernel, also takes brma_row and solved, so it is kept, with this branch's docstring sentence on the forbidden diagnostics rebuild. The schema test this branch added calls it, and #1305's two withheld-row tests follow it. main's #1305 also changed microcosm.diagnostics.schema, so the committed JSON Schema is stale after this merge; the next commit regenerates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main's #1305 changed microcosm.diagnostics.schema: UK geography pass rates gain the brma level, and uk_diagnostics gains model_figures_withheld (UKWithheldModelFigures) for rows whose model figures a UK build withholds. The committed schema is regenerated with tools/generate_calibration_diagnostics_json_schema.py. Only three definitions change: UKWithheldModelFigures is new, UKDiagnosticsV1 gains model_figures_withheld, and UKGeographyPassRate accepts brma. The terminal kernel's schema test now also runs #1305's fixture with a withheld BRMA row, so a real producer covers both new parts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
removed this pull request from stack #1323
October 20, 2026 18:01
…-schema Carries the restored main-only Tests workflow trigger (#1322 is not wanted) up the stack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Fixes #1293
Stack
main← #1295 ← #1297 ← #1296 ← #1298 (GitHub stack #1328, linked on 2026-10-20 withgh stack link).#1322 taken out of the stack (2026-10-20): CI runs only for pull requests into
mainon purpose, to limit the number of simultaneous runs on the organization's shared runners. #1322, which removed that filter, is closed, and the old stack #1323 was removed.4ced66de0on #1295 restores the four files #1322 changed to their versions onmain, and each branch above merges the one below it: #129794a5bff93, #1296b0406fd76, #12987cb857716. None of those merges had conflicts, andtest_ci_integration_job.pypasses on every branch (9 passed). No commit was rewritten. From now on only the bottom pull request, which targetsmain, gets CI; each one above gets CI once it becomes the bottom.us-calibration-epoch-thinning(Thin US calibration epoch telemetry to the UK's rule #1296). It is at the top because it changesuv.lockand its pinned digest; none of the four pull requests below it changes the lock.eb13b6e4amerges Thin US calibration epoch telemetry to the UK's rule #1296's branch,79c6b9ba4and15923a198merge it again after review fixes below, and531591bbbmerges it aftermain(a90eec3cb) came up the stack. The first three had no conflicts;531591bbb's is described under commit 4 below. Commit 5 regenerates the schema formain's model change.6df396734.APPROVED_UV_LOCK_SHA256still equals the SHA-256 ofuv.lock(751721b2…), checked at15923a198and6df396734.mainhas not changeduv.locksince 41209b3, anduv lock --checkpasses.Why
mainwas merged in (2026-10-20): GitHub builds each stacked pull request's test merge on top of the test merge of the pull request below it, starting frommain:refs/pull/1322/mergehasmainas its first parent, and each later one has the previous one's. Oncemaingained #1305, #1296's change torowwise_staging.pyconflicted with it, so GitHub could not build #1296's test merge. It reported #1296 as conflicting although its branch contained its base, and started no CI for #1296 or #1298.main(a90eec3cb) was merged into #1322's branch, and each branch into the one above, with merge commits; #1296 is now mergeable.Merge order: #1295, #1297, #1296, #1298, each after the one below it, with merge commits (or
gh stack merge). Every branch above #1295 has its parent merged in rather than rebased, so no commit was rewritten. Squash-merging a lower pull request would leave its original commits in the branches above, which would then need rebasing.Summary
This PR publishes a Draft 2020-12 JSON Schema for
calibration_diagnostics.jsonschema 8. It is generated from the pydantic models inmicrocosm-diagnostics, so the collector can check submitted diagnostics at intake without importing Microcosm. The diagnostics format doesn't change, and nothing is published outside the repository.microcosm.diagnostics.calibration_diagnostics_v8_json_schema()generates the schema fromCalibrationDiagnosticsV8in validation mode and adds$schema,$id,$comment,titleand adescription.tools/generate_calibration_diagnostics_json_schema.pywrites the committed file, or checks it with--check.packages/microcosm-diagnostics/src/microcosm/diagnostics/schemas/calibration_diagnostics.v8.schema.jsonand ships in themicrocosm-diagnosticswheel.load_calibration_diagnostics_v8_json_schema()reads it. The package README, the root README and the agent guide document the path and the regeneration command.jsonschemawas already locked as amicrocosm-buildruntime dependency. It joins themicrocosm-diagnosticsdev group, so no new package enters the lock.Commits
Local checks were limited to the test files this branch adds or modifies, at the user's request. The full suite, including the complete engine-free category and the country jobs, runs in CI on this PR.
On 2026-10-20 the branch was rebased onto
mainat 41209b3, after microcosm#1308 merged and made it conflict. Commits 1 and 2 are the original two, replayed; commit 3 is new. "Rebase ontomain" below lists how each conflict was resolved.509e4da6eGenerate a Draft 2020-12 JSON Schema for calibration diagnostics schema 8 (wasbcf6d3dc9)AttributeError: module 'microcosm.diagnostics' has no attribute ..., naming the generator, gap register or renderer that didn't exist yet.test_json_schema.py,test_schema.py) gave 116 passed.main'stest_uk_area_fit_still_parses_legacy_support_figures.ruff check .clean;ruff format --checkclean on the changed files;tools/ci_test_plan.py verifyok;uv lock --checkok.test_spawned_workers_score_identically_to_sequential_cli, where the tool's own version check refuses the local Python 3.14.6. That failure is environment-only.b7cf8a256Commit the schema-8 JSON Schema and validate US and UK diagnostics against it (was8ad318481)AttributeErrorforload_calibration_diagnostics_v8_json_schema.AttributeErrorforcommitted_calibration_diagnostics_v8_json_schema_path.FileNotFoundErrorfor the tool that didn't exist yet.main'sUKAreaFitchange, which commit 3 fixes: the byte-exact drift test, the generator tool's test, andtest_final_gate_kernel_diagnostics_match_the_published_json_schema. The last of these validates the diagnostics written byUKFullGateKernel, which runs the UK build's full set of validation checks on the final weights.ruff check .clean;ruff format --checkclean on the changed files;tools/ci_test_plan.py verifyok;microcosm-diagnosticswheel builds and passescheck-wheel-contents==0.6.3, with the schema file inside.c0549d21bRegenerate the schema-8 JSON Schema for UKAreaFit's withheld support figures (new)UKAreaFitonmain. Released diagnostics withhold an area's support figures (nonzero_households,nonzero_source_households,effective_sample_size) and carrysupport_below_floorinstead. The figure fields became optional, so earlier documents still parse. The committed schema still required the three figures and didn't declare the flag.tools/generate_calibration_diagnostics_json_schema.py. Only theUKAreaFitdefinition changes:support_below_flooris an optional boolean or null, and each figure is optional, null, or at least 0 as before.test_json_schema.pycheck the published file the way consumers read it:test_published_schema_accepts_uk_area_fits_with_the_floor_flag_or_legacy_support_figures, with four cases: the floor flag only, neither the flag nor the figures, legacy figures, and explicit nulls. The models must accept each one too.test_published_schema_and_models_refuse_a_negative_legacy_support_figure.support_below_floor. The 2 guards passed: legacy figures were accepted, and a negative figure was refused.ruff check .clean;ruff format --checkclean on the 14 changed Python files;tools/ci_test_plan.py verifyok;uv lock --checkok;generate_calibration_diagnostics_json_schema.py --checkreports the file current;microcosm/diagnostics/schemas/calibration_diagnostics.v8.schema.json, and passescheck-wheel-contents==0.6.3.Rebase onto
mainThese are mechanical conflict resolutions, so they have no red step; the tests above were re-run after each one.
uv.lock: git merged it without conflict. Its only difference frommain's lock is this PR'sjsonschemaentry in themicrocosm-diagnosticsdev group, anduv lock --checkpasses, souv lockwould write the same file.APPROVED_UV_LOCK_SHA256inpackages/microcosm-build/src/microcosm/build/us_runtime/worker_identity.py: re-pinned to751721b231ab8cc6b3d10164f61ca429f5171661951494503fb0873e3f67b117, the SHA-256 of the new lock.mainhade5d5818b…, and the original commit had561e9ab1….worker_identity._approved_uv_lock_sha256()accepts the new lock.packages/microcosm-diagnostics/tests/engine_free/shared/test_schema.py: commit 1 moves the schema-8 document builders totest_support/microcosm_diagnostics/payloads.py.mainchanged one of them:_uk_payload()'s weakest area now carries"support_below_floor": Truein place of the three figures. That change is now inuk_schema_8_payload().main's newtest_uk_area_fit_still_parses_legacy_support_figuresstays intest_schema.pyand callsuk_schema_8_payload(). Apart from that change and this PR's docstrings, the moved builders equalmain's.packages/microcosm-build/tests/engine_free/uk/test_uk_graph_terminal.py: commit 2 moves the body oftest_final_gate_kernel_owns_complete_diagnostics_and_reuses_decoded_resultinto the helper_run_uk_full_gate_kernel(replaced by Place UK private rent and BRMA at the assigned area; bind Scotland's rents at BRMA grain (#1262, #1090) #1305's_run_final_gate_kernelin commit 4).mainadded seven tests and a helper just before it, and they are kept.mainalso gave that body an import ofuk_terminal_only_code_hashand a"terminal_code"context entry; both are now in the helper.README.md,docs/agent-guide.mdandtest_uk_diagnostics.py: git merged them without conflict.Merging
mainup the stack (2026-10-20)15923a198merged #1296 with #1322's and #1297's latest review fixes, without conflicts (no red step; the seven changed test files gave 547 passed and 8 skipped). Then:531591bbbMerge us-calibration-epoch-thinning, bringing inmainata90eec3cbtest_uk_graph_terminal.py. This PR and Place UK private rent and BRMA at the assigned area; bind Scotland's rents at BRMA grain (#1262, #1090) #1305 each moved the body oftest_final_gate_kernel_owns_complete_diagnostics_and_reuses_decoded_resultinto a helper. Place UK private rent and BRMA at the assigned area; bind Scotland's rents at BRMA grain (#1262, #1090) #1305's_run_final_gate_kernelalso takesbrma_rowandsolved, so it is kept, with this PR's docstring sentence on the forbidden diagnostics rebuild._run_uk_full_gate_kernelis gone; this PR's schema test calls_run_final_gate_kernel, and Place UK private rent and BRMA at the assigned area; bind Scotland's rents at BRMA grain (#1262, #1090) #1305's two withheld-row tests follow it.microcosm.diagnostics.schema, so the committed JSON Schema is stale. The failures are the byte-exact drift test and the generator tool's test, which found the file differs from the generated schema, and the two UK writer cases and theUKFullGateKernelcase, which the stale schema refused because it does not acceptbrmaas a geography level.6df396734Regenerate the schema-8 JSON Schema for withheld model figures and BRMAbrmalevel to UK geography pass rates anduk_diagnostics.model_figures_withheld(UKWithheldModelFigures) for rows whose model figures a UK build withholds.tools/generate_calibration_diagnostics_json_schema.py. Three definitions change:UKWithheldModelFiguresis new,UKDiagnosticsV1gainsmodel_figures_withheld, andUKGeographyPassRateacceptsbrma.test_final_gate_kernel_diagnostics_match_the_published_json_schemais parametrized to also run Place UK private rent and BRMA at the assigned area; bind Scotland's rents at BRMA grain (#1262, #1090) #1305's fixture with a withheld BRMA row, so a real producer covers both new parts.ruff checkandruff format --checkclean on the changed test file;generate_calibration_diagnostics_json_schema.py --checkreports the file current;uv lock --checkok.Producers now validated against the committed file, after strict JSON parsing:
_write_release_calibration_diagnostics);UKFullGateKernel, which runs the UK build's full set of validation checks on the final weights, with local fit and a measured rotated holdout, and with a withheld BRMA row;test_transport_terminal_kernels.py).Schema path
packages/microcosm-diagnostics/src/microcosm/diagnostics/schemas/calibration_diagnostics.v8.schema.json. Its$idiscalibration_diagnostics.v8.schema.json, relative, followingspec_engine/schema/*.schema.json.Expressiveness gaps
The schema's
descriptionlists each of these, fromCALIBRATION_DIAGNOSTICS_V8_JSON_SCHEMA_GAPS. A test fails if a validator function appears in the schema-8 model tree without an entry. Another test fails if an entry has no document that the schema accepts and the models refuse.options,metadataandbuildDiagnosticsModel.reject_non_finite_numbers,CalibrationDiagnosticsV8.finite_optional_scalarjsonaccepts those tokens, and a JSON Schemanumbercan't exclude what they decode to. Intake must parse strictly.strict=True2.0and1e3as integers. The strict models refuse them because Python decodes them as floats._require_non_blankpatternPropertiesfor the dict-key uses, which would leave values under non-matching keys unconstrained, so it stays a documented gap.Field(pattern=...)$matches only at the end. Python'srealso lets$match before a final newline, so Python validators accept a digest followed by\n.category.provider_id == provider.id, unique dimension idsCalibrationHierarchy.category_matches_providerhierarchy.target.id == target_nameTargetDiagnosticV8.hierarchy_target_matches_rowTargetSurface.reconcile_matrix_shapetargets,n_records,n_specsCalibrationDiagnosticsV8.reconcile_countsCalibrationDiagnosticsV8.reconcile_countsif/then, but pydantic doesn't generate it. The value reconciliation and the sums can't be expressed.UK*model validators andUKDiagnosticsV1.reconcile_uk_diagnosticsThe schema is also stricter than the models' parser in one place. The models compare
Literalvalues with Python equality, so their parser also accepts1fortrueandtruefor1, for example inrotated_holdout.skipped. The schema requires the declared JSON value, which is what the canonical writer always emits. The description says so.Risks
uv.lockis pinned by digest inmicrocosm.build.us_runtime.worker_identity.APPROVED_UV_LOCK_SHA256, so this PR re-pins it, following 3623ca5 (UK: track the defects uk-data is fixing that microcosm still has #1095). The pin is now the digest ofmain's lock at 41209b3 plus this PR'sjsonschemadev entry. Any other PR that changes the lock conflicts on both lines, and whichever merges second re-pins.$id. I didn't invent a public URL; publication is out of scope. A consumer that registers the schema by$idgets the relative id.Unverified
c0549d21b.title,description,$commentanddefault.$id, orif/thenrules for the UK block's presence, is left to K4.🤖 Generated with Claude Code