chore(contract): bump OpenAPI spec pin to community v9.13.0 - #214
Conversation
|
Backlog-clearance verification 2026-08-03: attempted refresh of this pin to community v9.13.0 (tag
Additive-only deltas (not blocking): Regenerating the baseline to v9.13.0 as-is would baseline these two breaks with no burn-down note - exactly the "regenerating to silence a failure hides the bug" case the refresh script warns about. Needs an operator decision: either fix the SDK Local run detail for whoever picks this up: rebase conflict is confined to |
|
Framing correction after checking the server source at both tags: |
f380e01 to
78e11bb
Compare
…onse_time_ms, deprecate the seven fiction fields (#3254) Additive interim per the operator decision on getaxonflow/axonflow-enterprise#3254: the orchestrator has never served query_summary/success/blocked/risk_score/latency_ms/policy_violations/ metadata on the 9.x line; the real wire carries policy_decision, policy_details and response_time_ms. AuditSearchRequest gains action (the filter the 9.x server actually reads); request_type is deprecated on the search request (silently ignored server-side). - AuditLogEntry: three new defaulted fields; docstring deprecation notes on the seven fiction fields (kept, still parse, removal rides the next major); policy_details/metadata/policy_violations are null-tolerant (the orchestrator marshals a nil Go map/slice as JSON null - observed live, caught by the runtime-e2e suite) - AuditSearchRequest.action wired into _build_audit_search_body; request_type still sent when set (harmless, ignored) - tests: real v9.13.0 capture fixture (session 3254) + old-server tolerance + both-present + null-tolerance, action filter on the wire - runtime-e2e/audit_real_wire_fields: real-stack proof (typed parse of fresh rows, action filter read server-side, request_type no-op) - wire_shape_baseline: curated sdk_only entries for the new fields against the pre-v9 spec pin, notes name #3254 and the PR #214 pin bump that clears them - falsey_clobber baseline: line-number refresh only (comment insertion in client.py shifted 15 entries; finding set unchanged at 51) Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
78e11bb to
f684202
Compare
7cb8dda to
db07367
Compare
* feat(audit): add real wire fields policy_decision/policy_details/response_time_ms, deprecate the seven fiction fields (#3254) Additive interim per the operator decision on getaxonflow/axonflow-enterprise#3254: the orchestrator has never served query_summary/success/blocked/risk_score/latency_ms/policy_violations/ metadata on the 9.x line; the real wire carries policy_decision, policy_details and response_time_ms. AuditSearchRequest gains action (the filter the 9.x server actually reads); request_type is deprecated on the search request (silently ignored server-side). - AuditLogEntry: three new defaulted fields; docstring deprecation notes on the seven fiction fields (kept, still parse, removal rides the next major); policy_details/metadata/policy_violations are null-tolerant (the orchestrator marshals a nil Go map/slice as JSON null - observed live, caught by the runtime-e2e suite) - AuditSearchRequest.action wired into _build_audit_search_body; request_type still sent when set (harmless, ignored) - tests: real v9.13.0 capture fixture (session 3254) + old-server tolerance + both-present + null-tolerance, action filter on the wire - runtime-e2e/audit_real_wire_fields: real-stack proof (typed parse of fresh rows, action filter read server-side, request_type no-op) - wire_shape_baseline: curated sdk_only entries for the new fields against the pre-v9 spec pin, notes name #3254 and the PR #214 pin bump that clears them - falsey_clobber baseline: line-number refresh only (comment insertion in client.py shifted 15 entries; finding set unchanged at 51) Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com> * fix(review): restore historic CHANGELOG entries byte-for-byte; fail loudly on a set-but-missing specs dir R3 round 1 follow-ups on #223: - CHANGELOG.md: a global editor hook had rewritten 129 em/en dashes across ~250 lines of already-published release entries (9.0.0, 8.5.1, ...) - retroactive mutation of dated release records. Restored from main byte-for-byte; the diff vs main is now exactly the 13-line Unreleased hunk (13 insertions, 0 deletions). - tests/test_wire_shape.py _specs_dir(): when AXONFLOW_OPENAPI_SPECS_DIR was SET but pointed at a missing directory, all 7 gate tests skipped silently with exit 0 - a broken CI specs checkout read as a green wire-shape gate. That case now pytest.fail()s with a clear message (7 errors, exit 1); an UNSET variable keeps the designed local-dev skip. Three guard tests pin all directions (unset skips, set+missing fails naming the variable, set+valid resolves); they run in the regular suite too. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com> * fix(review): AXONFLOW_OPENAPI_SPECS_DIR set-but-empty fails loudly; pin the set-to-a-file direction R3 round 2 on #223: an EMPTY (or whitespace-only) value read as unset and produced the same 7 silent skips + exit 0 the round-1 fix targeted - a CI consumer wiring the variable from an expression that evaluates empty would get a green gate. Choice: FAIL on set-but-empty (rather than pinning empty-as-unset), stated in the test comment; unset keeps the designed local-dev skip. Also pins the set-to-a-FILE direction (behaviorally covered by is_dir(), previously unpinned) so a refactor to exists() cannot reopen the class. Proven end-to-end: empty env = 7 errors exit 1; unset = 7 skips; valid dir = 12 passed. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com> --------- Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
fee832d to
da35af2
Compare
* feat(masfeat): #3254 pin-advance batch - additive real wire fields, fiction 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> * test(masfeat): runtime-e2e suite for RegistrySummary real wire fields (#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> * fix(scripts): bind the baseline regenerator to its own repo's package 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> * fix(review): recorder fails on probed-but-never-read keys; stale baseline 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> --------- Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
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>
da35af2 to
e0930f0
Compare
Summary
Re-lands the parked spec-pin refresh at community v9.13.0 (the original v9.6.1 target is superseded). Refreshes the wire-shape contract baseline (
tests/fixtures/wire_shape_baseline.json) via the repo's own regenerator (scripts/refresh_wire_shape_baseline.py) against a checkout of getaxonflow/axonflow tagv9.13.0docs/api.Spec pin:
0bd92562(v7.4.x era) ->df027c788b60c18d044278c45aa4bce3a1ac8717(tag v9.13.0).Merge order (this PR is STACKED, batch 2): #223 is MERGED on main (
0fb80acd8); this branch is now rebased onto main + #224 ([#3254] pin-advance batch: masfeat/OJK additive extension) and contains #224's commits. #224 merges FIRST. Without the batch, this pin would go red honestly on the audit models (the original 2026-08-03 stop) AND on the masfeat dataclass bindings #224 adds.Why the stop is resolved
The stop comments found that
AuditLogEntry/AuditSearchRequestwere built to spec fiction: the v9.6.1-era spec described fields (blocked/success/risk_score/latency_ms/query_summary/policy_violations/metadata, and therequest_typesearch filter) thatplatform/orchestrator/audit_logger.gohas never served on the 9.x line. The operator decision on getaxonflow/axonflow-enterprise#3254 sanctioned the additive interim: #223 adds the real wire fields (policy_decision/policy_details/response_time_ms, plusactionon search) with deprecation notes on the fiction fields, and this PR explicitly note-acknowledges the remaining drift instead of silently baselining it:AuditLogEntry-deprecated-pending-removalentry naming #3254: sdk_only is exactly the seven deprecated fiction fields, burning down in the coordinated four-SDK next major per the #3254 operator decision. spec_only lists the 15 real wire fields not yet modeled (query/query_hash,user_id/user_role/org_id,cost,error_message,correlation_id/session_id/plane/decision_id,redacted_fields/response_sample/compliance_flags/security_metrics) - a read-side coverage gap, not a break.AuditSearchRequest-deprecated-pending-removalentry naming #3254: sdk_onlyrequest_type(server-side silent no-op, proven by the session-3254 live capture), removed in the next major; spec_onlysession_id(filter not yet modeled).Regen result vs the parked recipe
The stop comment predicted: 12 per-model drift entries,
MCPCheckInputRequestdrops out, 14 newly registered models. Actual regen (--sha df027c788b60c18d044278c45aa4bce3a1ac8717, via the #3262-extended regenerator): 15 per-model drift entries = the 12 the recipe predicted + 3 masfeat dataclass bindings (RegistrySummary/KillSwitch/AISystemRegistry) that #224 newly binds into the gate;MCPCheckInputRequestdropped (spec now declarescontent_type+tool); 93 registered models = the recipe's 90 + the 3 bound dataclasses; spec-bug-pending count 0. At this pin the masfeat entries flip exactly as #224's notes predicted: sdk_only becomes the legacy spellings the parsers read first-for-compatibility (high/medium/low_materiality_count,triggered_reason,business_owner/customer_impact/model_complexity/human_reliance) plus the deprecated fiction fields (by_use_case/by_status,technical_owner), each noted deprecated-pending-removal naming #3254/#3262 and the next-major burn-down; spec_only lists the informational coverage gaps stated in #224 (trigger_conditions/restore_reason;data_sources/model_type/version/deployment_date/last_assessment_date/next_assessment_due/updated_by).RegistrySummaryspec_only is EMPTY - the #224 parser readsorg_id/assessments_due/kill_switches_triggered, verified by the regen itself.Differences from the recipe's raw run, all explained by stacking on #223:
AuditLogEntry's sdk_only no longer containspolicy_decision/policy_details/response_time_ms(now modeled AND spec-declared, so they match) and no longer containsdata_residency/transfer_basis(the v9.13.0 spec declares them - the #1745 portion of that entry resolved);AuditSearchRequest's sdk_only shrinks torequest_typeonly (actionnow modeled and declared;decision_id/offset/override_id/policy_nameare spec-declared since v9.6.1).Baseline entry changes (9 at v9.6.1 plan -> 12 at v9.13.0)
Resolved by the v9.13.0 spec (former notes dropped):
MCPCheckInputRequest(content_type+tooldeclared),MCPCheckOutputResponse.redaction_evaluated(declared, as its v9.6.1 note predicted for the next pin bump),DecisionExplanation.context/context_truncated(declared),AuditLogEntry.data_residency/transfer_basis(declared).Kept (notes carried/updated):
DecideResponse.error(unchanged),DynamicPolicyMatch/ExfiltrationCheckInfo/PolicyOverride/PolicyVersion(deprecated-pending-removal 'Removed in v7' entries;PolicyOverridegains spec_onlyorganization_id/policy_type/tenant_id/updated_at/updated_by- spec superset, no break),MCPCheckOutputResponse(re-noted: sdk_only nowpolicy_matches/redacted_message, the Plugin Batch 1 v7.1.0-cycle fields the spec has not declared).New spec-superset entries (each noted, additive server-side, no consumer break):
DecisionTarget.server(#2904 two-field identity),HITLApprovalRequest(4 fields),UnifiedStepStatus(4 fields), plus the audit entries above.No true consumer break beyond the audit class surfaced - every non-audit delta is either an SDK superset the platform accepts or a spec superset the SDK ignores on parse.
Cross-train verification: the Go train's second stop (four non-audit read models)
The Go re-land (sdk-go#185) stopped a second time after its v9.13.0 regen surfaced the zero-out fiction class on four read models beyond the audit class:
RegistrySummary(high_materiality_count/by_statusvs the server'shigh_materiality, masfeat/types.go:431),KillSwitch.triggered_reasonvs the server'strigger_reason(masfeat/types.go:288),OJKAuditExportResponse.record_count, andAISystemRegistry.technical_owner. Checked the Python SDK against SERVER SOURCE at tag v9.13.0 (platform/orchestrator/masfeat/types.goin a checkout of getaxonflow/axonflow @df027c788), not the spec alone:axonflow/masfeat.pyparses each with an explicit real-wire fallback, pinned bytests/test_masfeat.py:high_materiality_count = data.get("high_materiality_count") or data.get("high_materiality", 0)(same for medium/low),triggered_reason = data.get("triggered_reason") or data.get("trigger_reason"), andAISystemRegistrymapscustomer_impact/model_complexity/human_reliancefrom the server'srisk_rating_impact/risk_rating_complexity/risk_rating_relianceandbusiness_ownerfromowner_email. Real server payloads populate these correctly today.OJKAuditExportResponseis not modeled in Python at all (zero OJK references underaxonflow/).AISystemRegistry.technical_owner(no such field anywhere inplatform/orchestrator/masfeat/ormasfeat-api.yamlat the tag; the SDK also SENDS it on register/update where the server does not read it) andRegistrySummary.by_use_case/by_status(no server equivalent; always{}). These are candidates for the #3254 next-major burn-down alongside the audit fiction fields.masfeat-api.yamlschemas - they appear in neitherregistered_modelsnorper_model_drift. This regen therefore neither hides nor acknowledges anything about them; the dual-name parsing above is enforced bytests/test_masfeat.py, not by the contract gate. Worth folding into the #3254 next-major plan as a gate coverage gap.Conflict resolution (per the parked recipe)
Rebase conflict was confined to
tests/fixtures/wire_shape_baseline.json; resolved by merging the note sets (main's #216/#218-eraAuditToolCallRequest,MCPCheckOutputRequest, extendedMCPCheckInputRequestnotes taken as the base; this branch's v9.6.1-refresh note updates forDecideResponse/DecisionExplanationmerged in) and then regenerating - the regenerator carries notes forward verbatim by model name.Validation
pytest tests/test_wire_shape.py -m wire_shapewithAXONFLOW_OPENAPI_SPECS_DIRpointing at a detached checkout of getaxonflow/axonflow @df027c788(tag v9.13.0): 7/7 passed (cross-spec divergence gate and rename-escape guard included).pytest tests/test_refresh_wire_shape_baseline.py: 4/4 passed (note-preservation and no-unannotated-drift gates).tests/fixtures/wire_shape_baseline.json).The
spec-pin-bumplabel stays applied to authorize theopenapi_specs_shachange per the wire-shape-contract CI guard.Refs getaxonflow/axonflow-enterprise#3254, getaxonflow/axonflow-enterprise#2861.
Regen integrity note (batch 2)
The first batch-2 regen attempt recorded a wrong-but-plausible
RegistrySummaryentry (the three #224 additions as spec_only):python scripts/refresh_wire_shape_baseline.pyhadscripts/atsys.path[0], soimport axonflowresolved through the venv's editable install - which pointed at a sibling checkout with the pre-fix parser. Caught by inspecting the regen output against the #224 parser, fixed in #224 (09cd65f): the script now pins its own repo root atsys.path[0]. The committed baseline here was regenerated AFTER that fix;RegistrySummary.spec_only == []is the observable proof the right parser was measured.