Skip to content

A versioning policy, and CI that runs the published SDKs against every build (API-09, #1750) - #1929

Merged
Kalyanpulikanti-01 merged 6 commits into
samyama-ai:devfrom
Raghuvarma905:api-09/1750-versioning-policy
Oct 22, 2026
Merged

Kalyanpulikanti-01 merged 6 commits into
samyama-ai:devfrom
Raghuvarma905:api-09/1750-versioning-policy

Conversation

@Raghuvarma905

@Raghuvarma905 Raghuvarma905 commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

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-benchmarks reads 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

Versioning policy: semver for the wire protocol and SDKs, an N-1 compatibility guarantee, deprecation with a two-minor-release notice. Policy published + enforced in CI.

Before this PR:

  • No policy. The only mention of semver in the tree was in CONTRIBUTING, about which git tags trigger the release workflow.
  • No compatibility check against released SDKs. Nothing ran a previously released SDK against a new server.
  • One deprecation with no end date. The bundled visualizer has been deprecated since 1.7.0 (Deprecate bundled web visualizer; point to graph.samyama.cloud #259). The page it serves says it "will be removed in an upcoming release" but never names one, and the 1.7.0 release notes don't mention the deprecation at all.

The policy: docs/VERSIONING.md

  • One version of record covers the HTTP API, RESP and the Python/TypeScript SDKs. That's already enforced by version_consistency (API-10).
  • What each kind of release may contain.
    • Patch: fixes only.
    • Minor: additions, fixes and new deprecations; no breaking changes.
    • Major: breaking changes, including removing deprecated things.
  • What counts as breaking, spelled out for each surface.
  • A fix is not a break. If the engine was giving a wrong answer and now gives the right answer, or an error, that's a fix. It ships in a patch or minor release, with a "Read this before upgrading" note. This is where 1.12.0 already drew the line in practice: a vector search against a missing index went from an empty result to an error (NDS-01: index contract holds 10 of 16 clauses; 0 of 3 structures survive restart (H1: documented, 2 ported) #1660). Without this rule, the policy would be contradicted by the release that shipped yesterday.
  • N-1 guarantee: the previous minor's SDKs work against the current server.
  • Deprecation in four steps: mark it, announce it in the release notes, keep it working for two more minors, and remove it only in a major release. That keeps "two minors of notice" consistent with semver.
  • A "Not checked yet" section at the end, so readers don't assume the checks cover more than they do.

It applies to releases from 1.13.0, since 1.12.0 shipped yesterday.

Enforcement

1. The sdk-compat CI job (sdk/compat/run.py)

  • It installs the SDKs as published: samyama from PyPI and samyama-sdk from npm, not the copies in this tree.
  • It picks the latest patch of each of the two most recent minors at or below Cargo.toml's version. Today that's 1.12.0 and 1.11.0 of each.
  • It runs a suite through each one against the release binary that the test job built. The suite checks:
    • connecting and status
    • reads and writes, including typed values and Unicode
    • nodes and edges in results
    • streaming
    • a read-only call refusing a write
    • a refused statement raising an error
    • EXPLAIN (TypeScript only)
  • Why two minors: Cargo.toml doesn't say what the next release will be. Just after 1.12.0 ships, dev still 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.
  • Nothing names a version. Versions come from the manifest and the package indexes on every run, and a version that can't be found fails the job instead of skipping it.
  • The suites call only what the 1.11 SDKs actually shipped. I checked that against the 1.11.0 .pyi stubs and client.ts.
  • The job is in 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 to UNGATED in tests/ci_gate_enumeration.rs.

2. tests/deprecations_follow_the_policy.rs (5 tests), which checks docs/deprecations.json:

  • every entry is well-formed, and none is dated after the version of record;
  • a removal happens only in a later major, with at least two minor releases of notice in between (read from docs/release-notes/);
  • every deprecated HTTP operation that hasn't been removed is still in openapi.yaml and marked deprecated: true, and every operation marked deprecated: true has an entry;
  • release notes mention each deprecation their release made, from 1.13.0 on. Older entries must carry a note saying how they were announced.

Also in this PR:

  • openapi.yaml marks getIndex (GET /) as deprecated: true.
  • The registry records the visualizer's real history, including that the 1.7.0 release notes never announced it.
  • CONTRIBUTING's release section points to the policy.
  • docs/README.md and sdk/README.md index the new files.

Verified (macOS, against a release build of this branch)

Check Result
sdk/compat/run.py: Python 1.12.0 and 1.11.0 from PyPI, TypeScript 1.12.0 and 1.11.0 from npm 4 of 4 passed; 8 tests each, none skipped
Can the compat suite fail? A proxy renaming records → rows in front of a real server, with the published 1.11.0 Python SDK 8 of 8 failed. The same SDK connected directly passed 8 of 8.
deprecations_follow_the_policy 5 passed
Can the deprecation test fail? Five deliberate breaks: removal in a minor (1.9.0), deprecated: true removed from openapi.yaml, an unlisted operation marked deprecated, deprecated_in set in the future, a post-policy entry the release notes don't mention Each one failed in the intended test with a readable message, e.g. bundled-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) 17 passed
CH-API (api_contract) after the OpenAPI change the document and server agree on 29 operations
CH-API-STABILITY (api_stability.py --check) 256 interactions replayed, 0 changed
CH-DOC-EXEC (doc_check) 0 failures
check_lint_ratchet.sh 796 Locally (clippy 1.97): 784, with 0 warnings in the new test file. CI's first run failed at 797: CI uses clippy 1.99.1, whose type_complexity lint 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).
ruff on sdk/compat/ clean

Not verified / not in this PR

…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.
@Kalyanpulikanti-01

Copy link
Copy Markdown
Contributor

Updated this PR from dev after #1931 merged, preserving the author history. New head: 9b2b7e84fd8f2d61d3e3779b998ad3d50d109093; included dev merge: d82bebcca2ef7ce7d7ebeefc11694fedd32e4afe.

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.

@Kalyanpulikanti-01

Copy link
Copy Markdown
Contributor

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 92af950113f984b75bbd0b1b74ffc84f5ab9135a: discard any cached executable before downloading; use it only after a successful download; remove partial output and rebuild with --locked otherwise. The fallback now fails if its build fails.

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 Kalyanpulikanti-01 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Kalyanpulikanti-01 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@Kalyanpulikanti-01
Kalyanpulikanti-01 merged commit d61af99 into samyama-ai:dev Oct 22, 2026
13 checks passed
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.

2 participants