[#3254] pin-advance batch: masfeat/OJK additive extension - #224
Merged
Conversation
…iction deprecations, dataclass gate binding (#3262) Per the operator ruling on getaxonflow/axonflow-enterprise#3254 (pin-advance batch), verified per model against server source at tag v9.13.0 (platform/orchestrator/masfeat/types.go) rather than inheriting the Go train's verdicts - the Python parsers already read the real wire names as fallbacks, so the zero-out class does not apply here: - RegistrySummary: ADD real fields org_id/assessments_due/ kill_switches_triggered (parser reads them); DEPRECATE by_use_case/ by_status (never served on 9.x, no wire equivalent). The *_count fields are correct-by-fallback (wire high/medium/low_materiality). - KillSwitch: no fiction (triggered_reason is populated from the real trigger_reason); trigger_conditions/restore_reason stated as informational gaps, not added. - AISystemRegistry: DEPRECATE technical_owner (never served; the wire carries owner_email/owner_team); business_owner/customer_impact/ model_complexity/human_reliance are correct-by-fallback. - OJKAuditExportResponse: not modeled in this SDK; nothing to do. #3262: the masfeat dataclasses are now BOUND into the wire-shape gate by driving the real *_from_dict parsers with a key-recording payload (source-derived seeds carrying only real wire names so every legacy fallback read is attempted and recorded). Chosen over a pydantic migration (public-type change, next-major work) and over a declared mapping table (would test the declaration, not the path). The rename- escape guard, staleness report and the baseline regenerator all learn the dataclass bindings. Red-first proven at the current pin; curated baseline entries name #3254 and the PR #214 pin advance. Self-tests: decoy fiction read caught, negative control, presence-probe exclusion, seed hygiene. Live leg: masfeat routes are enterprise-gated on the community stack (404 observed via the SDK's own masfeat_get_registry_summary) - evidence rests on server-source citations and source-derived fixtures, declared as such. falsey_clobber baseline: line-number refresh only (docstring insertions in masfeat.py shifted 11 entries; finding set unchanged at 51). Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
… (#3254) Drives the real SDK's masfeat_get_registry_summary() against a real agent. On Enterprise it asserts the typed parse of the #3254 additions and that the deprecated fiction fields stay empty; on Community the masfeat surface is Enterprise-gated - the 404 is DIAGNOSED (the stack must still prove reachable via /health through the same client) and reported as GATED, not skipped and not counted as covering the Enterprise assertions. Observed on the live community v9.13.0 stack: GATED with /health healthy. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
python scripts/refresh_wire_shape_baseline.py puts scripts/ (not the repo root) at sys.path[0], so 'import axonflow' inside the loaded test helpers resolved through the venv's editable install - which can point at a DIFFERENT checkout. Observed during the #3254 batch-2 regen: a sibling checkout's pre-fix masfeat parser produced a wrong-but-plausible RegistrySummary drift entry (org_id/assessments_due/ kill_switches_triggered recorded spec_only) with no error. The script now inserts its own repo root at sys.path[0] before importing. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
saurabhjain1592
added a commit
that referenced
this pull request
Aug 4, 2026
Refreshes tests/fixtures/wire_shape_baseline.json via scripts/refresh_wire_shape_baseline.py against a checkout of getaxonflow/axonflow tag v9.13.0 (df027c788) docs/api. Stacked on the #3254 pin-advance batch (PR #224): the audit fiction fields, request_type, and now the masfeat legacy spellings + fiction fields (by_use_case/by_status/technical_owner/triggered_reason/*_count) stay as consciously noted deprecated-pending-removal drift entries naming #3254 and the coordinated next-major burn-down. The masfeat dataclass entries are computed by the #3262-extended regenerator from the real parsers' consumed wire keys. Regen result: 15 per-model drift entries (12 from the July recipe + 3 masfeat dataclass bindings), MCPCheckInputRequest out (spec declares content_type + tool), 93 registered models (90 pydantic-era + 3 dataclass), spec-bug-pending count 0. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
…line allowances now hard-fail Batch R3 on #224, two latent findings fixed rather than filed: 1. The ghost-read evasion was concretely exploitable: a parser doing 'data[k] if k in data else None' on a key absent from the seed left no consumed trace, and the gate stayed green at both pins. _WireKeyRecorder now records __contains__ into a separate probed set, and the extractor FAILS on probed-but-never-read keys unless declared in _ENVELOPE_DISPATCH_KEYS (response-shape unwrapping, the kill_switch_from_dict envelope - the only entry, parser named). Proven by mutation: the ghost read injected into the real registry_summary_from_dict goes red at BOTH pins with the key named; the envelope dispatch stays green; the decoy/negative controls still pass; a probe followed by a read is clean. 2. test_baseline_has_not_grown_stale was print-only, so a phantom sdk_only allowance passed silently - a hole the width of a future regression, and a cross-SDK asymmetry (Go's equivalent hard-fails). It now fails listing the dead allowances. Proven by mutation: a phantom entry appended to KillSwitch.sdk_only goes red naming it; the committed baselines are regen-exact so both pins stay green honestly. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
saurabhjain1592
added a commit
that referenced
this pull request
Aug 4, 2026
Refreshes tests/fixtures/wire_shape_baseline.json via scripts/refresh_wire_shape_baseline.py against a checkout of getaxonflow/axonflow tag v9.13.0 (df027c788) docs/api. Stacked on the #3254 pin-advance batch (PR #224): the audit fiction fields, request_type, and now the masfeat legacy spellings + fiction fields (by_use_case/by_status/technical_owner/triggered_reason/*_count) stay as consciously noted deprecated-pending-removal drift entries naming #3254 and the coordinated next-major burn-down. The masfeat dataclass entries are computed by the #3262-extended regenerator from the real parsers' consumed wire keys. Regen result: 15 per-model drift entries (12 from the July recipe + 3 masfeat dataclass bindings), MCPCheckInputRequest out (spec declares content_type + tool), 93 registered models (90 pydantic-era + 3 dataclass), spec-bug-pending count 0. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
saurabhjain1592
added a commit
that referenced
this pull request
Aug 4, 2026
Refreshes tests/fixtures/wire_shape_baseline.json via scripts/refresh_wire_shape_baseline.py against a checkout of getaxonflow/axonflow tag v9.13.0 (df027c788) docs/api. Stacked on the #3254 pin-advance batch (PR #224): the audit fiction fields, request_type, and now the masfeat legacy spellings + fiction fields (by_use_case/by_status/technical_owner/triggered_reason/*_count) stay as consciously noted deprecated-pending-removal drift entries naming #3254 and the coordinated next-major burn-down. The masfeat dataclass entries are computed by the #3262-extended regenerator from the real parsers' consumed wire keys. Regen result: 15 per-model drift entries (12 from the July recipe + 3 masfeat dataclass bindings), MCPCheckInputRequest out (spec declares content_type + tool), 93 registered models (90 pydantic-era + 3 dataclass), spec-bug-pending count 0. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
saurabhjain1592
added a commit
that referenced
this pull request
Aug 4, 2026
Refreshes tests/fixtures/wire_shape_baseline.json via scripts/refresh_wire_shape_baseline.py against a checkout of getaxonflow/axonflow tag v9.13.0 (df027c788) docs/api. Stacked on the #3254 pin-advance batch (PR #224): the audit fiction fields, request_type, and now the masfeat legacy spellings + fiction fields (by_use_case/by_status/technical_owner/triggered_reason/*_count) stay as consciously noted deprecated-pending-removal drift entries naming #3254 and the coordinated next-major burn-down. The masfeat dataclass entries are computed by the #3262-extended regenerator from the real parsers' consumed wire keys. Regen result: 15 per-model drift entries (12 from the July recipe + 3 masfeat dataclass bindings), MCPCheckInputRequest out (spec declares content_type + tool), 93 registered models (90 pydantic-era + 3 dataclass), spec-bug-pending count 0. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
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.
Summary
Python leg of the #3254 pin-advance batch (operator ruling, comment 5175919799 on getaxonflow/axonflow-enterprise#3254): extends the additive interim to the masfeat/OJK read models, and folds in getaxonflow/axonflow-enterprise#3262 by binding the masfeat dataclasses into the wire-shape contract gate. Additive only - nothing removed, renamed or retyped.
Per-model verdicts (verified against SERVER SOURCE at tag v9.13.0,
platform/orchestrator/masfeat/types.goin getaxonflow/axonflow @df027c788- NOT inherited from the Go train)The Python parsers already read the real wire names as fallback spellings (pinned by
tests/test_masfeat.py), so the Go train's zero-out verdicts do NOT transfer:RegistrySummaryby_use_case/by_status; missing real fieldshigh/medium/low_materiality_countare correct-by-fallback (parser reads wirehigh_materialityetc., types.go:431-440).by_use_case/by_statushave NO wire equivalent (flat counts only) - deprecated with canonical wording. Real fields the SDK lacked -org_id,assessments_due,kill_switches_triggered- added (defaulted, parser reads them).KillSwitchtriggered_reasonis correct-by-fallback (wiretrigger_reason, types.go:288). Informational gaps NOT added (not fiction-class):trigger_conditions,restore_reason.AISystemRegistrytechnical_ownerplatform/orchestrator/masfeat/ormasfeat-api.yamlat the tag - alwaysNoneon read; the register/update write paths send it, unread server-side (kept sending, additive-only). Deprecated with canonical wording pointing at the realowner_email(read intobusiness_owner) +owner_team.business_owner/customer_impact/model_complexity/human_relianceare correct-by-fallback (wireowner_email/risk_rating_impact/risk_rating_complexity/risk_rating_reliance).OJKAuditExportResponseaxonflow/; no OJK client surface in this SDK. Nothing to do.Deprecation idiom: dataclass docstring "Deprecated:" attribute notes with the canonical wording (dataclasses have no Field descriptions); same choice as the merged audit interim (#223), no runtime warnings.
#3262: masfeat dataclasses bound into the wire-shape gate
Choice (stated per the issue): extract wire names by DRIVING THE REAL PARSERS (
*_from_dict) with a key-recording payload - not a pydantic migration (changes the public types: constructor semantics,dataclasses.asdictconsumers, isinstance checks - next-major work), and not a hand-declared field-to-wire table (would test the declaration, not the path).Mechanics:
_WireKeyRecorderrecords every key a parser attempts viaget/[](deliberately NOTin- thekill_switchenvelope probe is response-shape dispatch, not a field read; pinned by its own test). Seeds are SOURCE-DERIVED from the v9.13.0 server structs (declared as such, not captures) and carry ONLY real wire names, so every legacy-name read - which always sits first in anx or ychain - is attempted and recorded; a seed containing a legacy name would satisfy the chain early and hide the real-name read (pinned by a seed-hygiene test). The gate diffs consumed keys vs themasfeat-api.yamlschema and holds the result to the same baseline discipline as the pydantic gate. The rename-escape guard, the staleness report andscripts/refresh_wire_shape_baseline.pyall learn the dataclass bindings, so the #214 pin-bump regen recomputes this drift instead of silently dropping it.Red-first evidence (extended gate, PRE-FIX models, current pin
0bd92562)Note what this shows: the current pin is the FICTION-ERA spec (it declares
by_use_case/technical_owner/triggered_reason), so at this pin the gate flags the parsers' REAL-name fallback reads - proof the binding sees the actual wire reads, not the dataclass field names. Post-fix (with the three addedRegistrySummaryfields) the uncovered set grows byorg_id/assessments_due/kill_switches_triggered, as expected. Green after curated baseline entries naming #3254/#3262 and the #214 pin advance: 20/20 at the current pin (post-R3 count). At the v9.13.0 pin these entries flip to the legacy spellings (stated in each note); the #214 regen recomputes them via the extended script.Batch R3 fixes (commit
946e929)data[k] if k in data else Noneon an absent key left no consumed trace and the gate stayed green at both pins._WireKeyRecordernow recordsinprobes into a separateprobedset and the extractor FAILS on probed-but-never-read keys unless declared in_ENVELOPE_DISPATCH_KEYS(single entry: thekill_switch_from_dictenvelope, parser named). Mutation-proven: the ghost read injected into the realregistry_summary_from_dictgoes red at BOTH pins naming the key (ghost-evasion-red.txt); envelope dispatch stays green; probe-followed-by-read is clean; decoy/negative controls unchanged. Honest residual: reads via iteration/copy (for k in data,dict(data)) are still unrecorded shapes - no bound parser uses them.test_baseline_has_not_grown_stale), matching the Go SDK's equivalent: a phantom sdk_only allowance is a hole the width of a future regression. Mutation-proven red on an injectedphantom_dead_allowance(stale-allowance-red.txt); the committed baselines are regen-exact, so both pins stay green honestly.Self-tests (machinery, run in the regular suite)
decoy_fiction_field(absent key,getreturns None - the exact fiction-read shape) MUST surface as sdk-only drift - caught.Additive-only public API proof
dataclasses.fieldsdiff, main vs branch, for the three touched models - additions only, all defaulted:Live leg (honest report)
masfeat_get_registry_summary()via the SDK against the session-3254 community v9.13.0 stack (127.0.0.1:38080): HTTP 404 - the masfeat routes are enterprise-gated on a community deployment, as the batch spec anticipated. No capture fabricated; evidence rests on (a) the server-source citations above at tagdf027c788and (b) source-derived fixture tests (declared as source-derived in every test/seed comment).Test evidence
tests/test_masfeat.py: new-field population from a source-derived real-shape payload, old-server defaults, deprecated fields stay empty against real-shaped payloads.Items not modified in this PR (with justification)
KillSwitch.trigger_conditions/restore_reasonandAISystemRegistry.data_sources/model_type/version/deployment_date/last_assessment_date/next_assessment_due/updated_by: real wire fields the SDK does not model - informational coverage gaps, not fiction-class wrongness; per the batch canonical this is not a full-coverage exercise. They appear as spec_only drift at the v9.13.0 pin with notes.KillSwitchEventvs the server'sKillSwitchHistory: different schema names, so no name-match binding exists; its parser already dual-readsevent_type/action,created_at/performed_at,created_by/performed_by. Out of the four-model batch scope.high_materiality_count,triggered_reasonreads, etc.) kept - additive-only interim; renames ride the next major.Merge order: this PR first, then #214 (the v9.13.0 spec pin re-land, stacked on this branch).
Refs getaxonflow/axonflow-enterprise#3254, getaxonflow/axonflow-enterprise#3262.