Repository navigation
A versioning policy, and CI that runs the published SDKs against every build (API-09, #1750) - #1929
Conversation
…y build (API-09, samyama-ai#1750) API-09 asks for semver for the wire protocol and the SDKs, an N-1 compatibility guarantee, and deprecation with a two-minor-release notice -- published, and enforced in CI. None of it existed: the only mention of semver in the tree described which tags fire the release workflow, and the one deprecation on record (the bundled visualizer, since 1.7.0) has promised removal "in an upcoming release" for twelve releases without naming one. docs/VERSIONING.md is the policy. One version of record for the HTTP API, RESP and the Python and TypeScript SDKs (already enforced by API-10); what a patch, minor and major release may contain; what counts as breaking, per surface; and the line between a break and a fix, drawn where 1.12.0 drew it in practice -- a wrong answer turning into a right one or an error is a fix, owed a "Read this before upgrading" entry, not a major release. N-1: the previous minor's SDKs work against the current server. Deprecation: mark, announce, keep working for two minors, remove only in a major. It ends with what is not checked yet, so the enforcement table is not read as covering more than it does. Enforcement: sdk/compat/run.py and the `sdk-compat` job install the Python and TypeScript SDKs AS PUBLISHED, from PyPI and npm, for the latest patch of each of the two most recent minors at or below Cargo.toml's version, and run a suite through each against the release binary `test` built. Today that is 1.12.0 and 1.11.0 of both. Versions are read from the manifest and the indexes on every run; a version that cannot be found fails the job. It is in ci-ok's needs: a compatibility promise that does not block a merge that breaks it is not enforced. tests/deprecations_follow_the_policy.rs checks docs/deprecations.json: a removal only in a later major with two minors of notice (read from docs/release-notes/), a deprecated HTTP operation still in the OpenAPI document and marked `deprecated: true` -- both directions -- and release notes announcing what their release deprecated, from 1.13.0. openapi.yaml marks getIndex `deprecated: true`, and the registry records the visualizer's real history, including that the 1.7.0 notes never announced it.
…INT-RATCHET to 797 CI runs clippy from rustc 1.99.1, which flags the `(BTreeSet<(String, String)>, BTreeSet<(String, String)>)` that openapi_operations() returned. That one warning took the ratchet from 796 to 797 against a ceiling of 796. The local 1.97 clippy does not have the lint, which is why it passed here. A struct with named fields, and an `Operation` alias for the key. Clean under clippy 1.99.1; the five tests still pass, and a deliberately unlisted deprecated operation is still caught.
|
Updated this PR from Fresh CI: https://github.com/samyama-ai/samyama-graph/actions/runs/39455208560 Waiting for all applicable checks, including GPML and the published-SDK compatibility job, before merging this head. Later PRs will be updated only after this one merges. |
|
During merge review I reproduced a binary-freshness gap in the SDK job: with an existing executable and a failed download, the old shell branch reported that it was using the test-job binary without building current source. Fixed in Validation: Actionlint passed. The actual workflow shell block reproduced the old stale-executable behaviour, then passed five cases: successful fresh artifact, successful download with no executable, failed download with partial output, failed download with no file, and failed fallback build. This supersedes the earlier CI head. Waiting for fresh CI, GPML and published-SDK compatibility before merging into dev. |
Kalyanpulikanti-01
left a comment
There was a problem hiding this comment.
Local PR agent — AI review of exact head 92af950.
Verdict: changes_requested.
Reviewed all 11 changed files. Two enforcement gaps allow CI to pass without satisfying the published compatibility and removal policies.
-
P2 sdk/compat/run.py:102 — Selecting the newest available minors silently substitutes older releases when an expected minor is missing or filtered out. For example, with version 1.12.0, excluding deprecated npm releases for 1.11 causes 1.12 and 1.10 to pass the two-version check, leaving the promised N-1 SDK untested. npm deprecation does not prevent existing users from holding that SDK. Determine the required minor versions explicitly and fail if they cannot be tested instead of falling back to older minors.
-
P2 tests/deprecations_follow_the_policy.rs:175 — Checking only that the removal's major number exceeds the deprecation's major number also accepts removal in 2.1.0 or 2.0.1 after deprecation in 1.x, provided the notice count passes. Those are minor and patch releases, which the new policy explicitly forbids from removing contract features. Require removed_in to identify a major release (minor and patch both zero) as well as a later major number.
The queue is held here for a maintainer; no automatic code edits or merge.
This is an AI review comment, not a human approval or a CI result.
Kalyanpulikanti-01
left a comment
There was a problem hiding this comment.
Addressed both reported policy-enforcement gaps in 8a77e73.
- SDK resolution now requires the exact current and immediately preceding minor. Missing required minors fail instead of selecting older ones. Deprecated npm versions remain eligible; yanked PyPI files remain excluded. Major boundaries fail with an explicit compatibility-window diagnostic.
- Deprecation removal must be a later MAJOR.0.0, in addition to the existing two-minor notice requirement.
- Added eight offline Python regressions to the SDK CI job and a Rust regression rejecting later-major patch/minor removals.
Validation: all eight Python tests and all six Rust policy tests passed; actionlint and git diff --check passed. Live registry resolution selected Python and TypeScript 1.12.0/1.11.0. The new tests fail against the original selection/removal logic. The branch was refreshed from dev before the fixes. Full GitHub CI is being rerun on the new head.
Keeping this PR open and excluded from automatic merging, as requested.
Part of #1750 (API-09). It delivers the policy and the CI enforcement the requirement names. The scorecard row only flips once the CH-API check in
samyama-graph-competitor-benchmarksreads them, and this PR doesn't touch that repository. The issue's provenance item is covered under "Not in this PR" below.What API-09 asks for, and what was there
Before this PR:
The policy:
docs/VERSIONING.mdversion_consistency(API-10).It applies to releases from 1.13.0, since 1.12.0 shipped yesterday.
Enforcement
1. The
sdk-compatCI job (sdk/compat/run.py)samyamafrom PyPI andsamyama-sdkfrom npm, not the copies in this tree.Cargo.toml's version. Today that's 1.12.0 and 1.11.0 of each.testjob built. The suite checks:Cargo.tomldoesn't say what the next release will be. Just after 1.12.0 ships,devstill reads 1.12.0 on its way to 1.13 (whose N-1 is 1.12), while a 1.12.1 would still need to serve 1.11. Testing both covers either case..pyistubs andclient.ts.ci-ok's required checks. A compatibility promise that doesn't block the merge that breaks it isn't enforced, and "enforced in CI" is the requirement. If a maintainer would rather not block merges on PyPI/npm being reachable, it's a one-line move toUNGATEDintests/ci_gate_enumeration.rs.2.
tests/deprecations_follow_the_policy.rs(5 tests), which checksdocs/deprecations.json:docs/release-notes/);openapi.yamland markeddeprecated: true, and every operation markeddeprecated: truehas an entry;notesaying how they were announced.Also in this PR:
openapi.yamlmarksgetIndex(GET /) asdeprecated: true.docs/README.mdandsdk/README.mdindex the new files.Verified (macOS, against a release build of this branch)
sdk/compat/run.py: Python 1.12.0 and 1.11.0 from PyPI, TypeScript 1.12.0 and 1.11.0 from npmrecords→rowsin front of a real server, with the published 1.11.0 Python SDKdeprecations_follow_the_policydeprecated: trueremoved fromopenapi.yaml, an unlisted operation marked deprecated,deprecated_inset in the future, a post-policy entry the release notes don't mentionbundled-visualizer: removed in 1.9.0, deprecated in 1.7.0 -- removal is a breaking change and only a major release may contain one. Files restored afterwards.docs_index_lists_every_document,ci_gate_enumeration,version_consistency(debug)api_contract) after the OpenAPI changeapi_stability.py --check)doc_check)check_lint_ratchet.sh 796type_complexitylint flags a tuple return type in the new test. That's fixed in 214883e and is clean under clippy 1.99.1 (checked locally with that toolchain).ruffonsdk/compat/Not verified / not in this PR
sdk-compatjob hasn't run in CI yet. It waits fortest, so it was skipped when the first run failed on the lint ratchet. The run after 214883e is its first, on Linux with Node 20. Locally I used macOS and Node 24.snapshot_hash, the issue's provenance item. That's TRUST-06, tracked in TRUST-06: 2 of 3 result-provenance fields present; no plan_hash, snapshot_version is not a hash #1706. The issue also saysplan_hashis "blocked on TRUST-06: a query result cannot name the plan that produced it #1034", but TRUST-06: a query result cannot name the plan that produced it #1034 closed on 2026-09-14 and every query response already carriesplan_hash.Deprecationheader or SDK warning yet).docs/API-PARITY.mdis already out of date ondev. Regenerating it withfeature_matrixchanges the NLQ row, because RESP and the Python/TypeScript SDKs have NLQ now. That's unrelated to this change, so I left it alone.ci.ymlat the same spot, beforeci-ok. Whichever merges second will have a small conflict there.