Skip to content

feat: Add versioned, cross-language Selene API models - #212

Open
trvto wants to merge 43 commits into
0.3-seriesfrom
travis/versioned-trace-schema
Open

trvto wants to merge 43 commits into
0.3-seriesfrom
travis/versioned-trace-schema

Conversation

@trvto

@trvto trvto commented Sep 1, 2026 •

Copy link
Copy Markdown
Collaborator

Introduces the selene-trace workspace for versioned, serializable Selene API models.

  • Add versionless "legacy" trace schema for old schema currently in use.
  • Adds trace schema v0.1.0 plus Python, Rust, and TypeScript packages.
    • v0.1.0 introduces two top level objects: Trace and Traces, which both carry a required schema version.
    • OpaquePayload.tag is encoded as canonical hexadecimal strings in JSON for cross-language precision safety.
    • Other integer values are restricted to values js can handle automatically
    • The api packages can read in legacy data and convert to the v0.1.0 schema
  • Adds validation, examples, compatibility documentation, CI, Just recipes, and pre-commit coverage.
  • Coordinates package releases under a shared selene-api-models-v tag.
  • Immutably publishes schemas to GitHub pages

Before the first release, configure:

  • A PyPI trusted publisher for selene-api-models, tied to this repository’s api_models.yml workflow. -> Done
  • Repository secret CARGO_REGISTRY_TOKEN, authorized to publish selene-api-models on crates.io. -> Done
  • Setup trusted publishing for "@quantinuum/selene-api-models"

@trvto
trvto force-pushed the travis/versioned-trace-schema branch from 9490178 to 706351e Compare September 23, 2026 16:10
@trvto
trvto force-pushed the travis/versioned-trace-schema branch from f069a8a to 8bc6ae0 Compare September 23, 2026 18:30

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Critical cross-language compatibility and precision issues, plus unresolved release workflow and dependency problems, block approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 5 High severity · 3 Medium severity · 1 Low severity

Open (9)
What changed in this PR

Adds versioned Selene trace schemas with synchronized Python, Rust, and TypeScript models, legacy conversion, documentation, examples, and release automation.

Changes:

  • Adds legacy and v0.1.0 trace schemas with validation and compatibility adapters.
  • Adds cross-language packages, tests, and examples.
  • Updates producers, snapshots, packaging, CI, and publishing workflows.

Review identified unresolved cross-language encoding, precision, compatibility, schema-validation, and workflow/dependency issues.

File Reviewed change
uv.lock Adds workspace dependencies.
selene-sim/​python/​tests/​snapshots/​test_unparsed/​test_ghz_trace_unparsed/​legacy/​trace.json Updates legacy trace snapshot.
selene-sim/​python/​tests/​snapshots/​test_unparsed/​test_ghz_trace_unparsed/​default/​trace.json Updates trace snapshot.
selene-sim/​python/​tests/​snapshots/​test_trace/​test_ghz_trace/​legacy/​trace.json Updates legacy trace snapshot.
selene-sim/​python/​tests/​snapshots/​test_trace/​test_ghz_trace/​default/​trace.json Updates trace snapshot.
selene-sim/​python/​selene_sim/​event_hooks/​instruction_log.py Emits versioned traces.
selene-protocol/​typescript/​tsconfig.json Configures TypeScript compilation.
selene-protocol/​typescript/​test/​protocol.test.mjs Tests TypeScript models and compatibility.
selene-protocol/​typescript/​src/​trace.ts Implements TypeScript models and adapters.
selene-protocol/​typescript/​src/​index.ts Exports the TypeScript API.
selene-protocol/​typescript/​README.md Documents TypeScript usage.
selene-protocol/​typescript/​package.json Defines the npm package.
selene-protocol/​scripts/​check_schema_immutability.py Checks schema immutability.
selene-protocol/​schemas/​trace/​legacy.schema.json Defines the legacy schema.
selene-protocol/​schemas/​trace/​0.1.0.schema.json Defines schema v0.1.0.
selene-protocol/​rust/​src/​trace.rs Implements Rust models and adapters.
selene-protocol/​rust/​src/​lib.rs Exports the Rust module.
selene-protocol/​rust/​README.md Documents Rust usage.
selene-protocol/​rust/​Cargo.toml Defines the Rust crate.
selene-protocol/​README.md Documents protocol structure.
selene-protocol/​python/​tests/​test_trace.py Tests Python trace models.
selene-protocol/​python/​tests/​test_schema.py Tests schema consistency.
selene-protocol/​python/​selene_api_models/​trace.py Implements Python models and adapters.
selene-protocol/​python/​selene_api_models/​schema.py Provides packaged schemas.
selene-protocol/​python/​selene_api_models/​__init__.py Exports Python APIs.
selene-protocol/​python/​README.md Documents Python usage.
selene-protocol/​pyproject.toml Defines the Python package.
selene-protocol/​examples/​trace/​traces.json Adds a collection example.
selene-protocol/​examples/​trace/​minimal.json Adds a minimal example.
selene-protocol/​examples/​trace/​legacy.json Adds a legacy example.
selene-protocol/​examples/​trace/​all-event-types.json Adds event coverage examples.
selene-protocol/​docs/​versioning.md Documents versioning.
selene-protocol/​docs/​trace/​legacy.md Documents legacy traces.
selene-protocol/​docs/​trace/​0.1.0.md Documents version 0.1.0.
selene-protocol/​docs/​publishing.md Documents coordinated publishing.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_zero_length_arrays/​interface1/​trace.json Updates argreader trace snapshot.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_zero_length_arrays/​interface1/​pass.json Updates argreader pass snapshot.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_zero_length_arrays/​interface0/​trace.json Updates argreader trace snapshot.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_zero_length_arrays/​interface0/​pass.json Updates argreader pass snapshot.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_trace/​interface1/​trace.json Updates argreader trace snapshot.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_trace/​interface1/​pass.json Updates argreader pass snapshot.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_trace/​interface0/​trace.json Updates argreader trace snapshot.
selene-ext/​utilities/​argreader/​python/​tests/​snapshots/​test_argreader/​test_arg_reader_trace/​interface0/​pass.json Updates argreader pass snapshot.
selene-ext/​utilities/​argreader/​python/​selene_argreader_plugin/​trace_pass.py Preserves trace version during filtering.
selene-ext/​runtimes/​soft_rz/​python/​tests/​snapshots/​test_batching/​test_batching_behaviour/​trace_batching_8.json Updates batching snapshot.
selene-ext/​runtimes/​soft_rz/​python/​tests/​snapshots/​test_batching/​test_batching_behaviour/​trace_batching_2.json Updates batching snapshot.
selene-ext/​runtimes/​soft_rz/​python/​tests/​snapshots/​test_batching/​test_batching_behaviour/​trace_batching_1.json Updates batching snapshot.
selene-core/​python/​selene_core/​trace.py Re-exports the public trace models.
selene-core/​pyproject.toml Adds the API-model dependency and schema packaging.
selene-core/​hatch_build.py Packages the canonical schema.
release-please-config.json Coordinates releases.
pyproject.toml Adds workspace and test configuration.
pnpm-workspace.yaml Defines the TypeScript workspace.
pnpm-lock.yaml Locks TypeScript dependencies.
justfile Adds API-model recipes.
devenv.nix Adds tooling and checks.
Cargo.toml Adds the Rust workspace member.
Cargo.lock Locks Rust dependencies.
.release-please-manifest.json Tracks the API-model version.
.gitignore Ignores generated artifacts.
.github/​workflows/​publish_schemas.yml Publishes schemas.
.github/​workflows/​build_wheels.yml Updates wheel-build triggers.
.github/​workflows/​api_models.yml Tests and publishes API packages.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread selene-trace/python/selene_api_models/trace.py
Comment thread selene-trace/rust/src/trace.rs Outdated
Comment thread selene-trace/schemas/trace/0.1.0.schema.json
Comment thread selene-trace/schemas/trace/0.1.0.schema.json
Comment thread selene-trace/typescript/src/trace.ts Outdated
Comment thread .github/workflows/api_models.yml Outdated
Comment thread selene-protocol/schemas/trace/0.1.0.schema.json Outdated
Comment thread selene-protocol/schemas/trace/legacy.schema.json Outdated
Comment thread selene-core/python/selene_core/trace.py Outdated

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Unresolved cross-language validation inconsistencies and CI/cache gaps can produce incompatible or stale artifacts.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (7)
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread selene-trace/rust/src/trace.rs Outdated

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Python currently coerces non-boolean predicate results that the schema and other bindings reject.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Previously missed (1)

In code that hasn't changed since last review

Medium severity Use strict boolean validation for parse_trace result

selene-trace/​python/​selene_api_models/​trace.py:149

result uses Pydantic's coercing boolean type, so parse_trace accepts schema-invalid JSON such as "result": 1 or "result": "false" and normalizes it, while the JSON Schema and Rust/TypeScript bindings require an actual boolean. Use the existing strict boolean alias here so all bindings validate the same wire values.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

TypeScript parsing and constructor composition can fail unexpectedly, while Rust rejects Base64 accepted by the canonical schemas.

Review effort: Balanced
Findings: None

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Previously missed (3)

In code that hasn't changed since last review

Medium severity Align Base64 pad-bit validation across implementations

selene-trace/​rust/​src/​trace.rs:234

The checked-in Base64 patterns and the TypeScript/Python bindings accept encodings with non-zero unused pad bits (for example, "Zh==" decodes to b"f"), but base64's default URL_SAFE engines reject them. Consequently, a document valid under either published schema can fail only in Rust. Either configure this decoder to match the accepted grammar or enforce canonical pad bits consistently in both schemas and the other bindings.

Medium severity Guard BigInt conversion after regex validation fails

selene-trace/​typescript/​src/​trace.ts:28

Zod continues into this refinement after a preceding regex check has marked the parse invalid, so inputs such as "abc" call BigInt("abc") and throw SyntaxError. As a result, UInt64DecimalStringSchema.safeParse and safeParseTrace can throw instead of returning a failed parse. Guard the conversion so every invalid string remains a Zod validation failure.

Medium severity Allow constructors to accept normalized trace outputs

selene-trace/​typescript/​src/​trace.ts:260

These constructors are not composable with their own normalized outputs. createTraceData converts an opaque tag from a decimal string to bigint, but createTraces reparses it through an input schema that accepts only strings, so createTraces([createTraceData(opaqueEvents)]) throws; similarly, the README's createTraceData(document.events) does not type-check when document is parsed. The constructor layer should accept normalized EventRecord/TraceData values as well as wire inputs without weakening the wire parsers.

@trvto trvto changed the title Add versioned, cross-language Selene API models feat: Add versioned, cross-language Selene API models Oct 7, 2026
@trvto
trvto requested a balanced review from Copilot October 7, 2026 13:54

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The declared decimal tag encoding conflicts with the hexadecimal contract implemented by the schema, bindings, examples, and documentation.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

"OpaquePayload": {
"properties": {
"kind": { "const": "OpaquePayload", "default": "OpaquePayload", "title": "Kind", "type": "string" },
"tag": { "format": "uint64-hex", "pattern": "^0x(0|[1-9A-F][0-9A-F]{0,15})(?![\\s\\S])", "title": "Tag", "type": "string" },

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Updated pr description

steps:
- uses: actions/checkout@v6
- name: Check package versions match the tag
run: |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

IIRC you can have a step invoke python directly by using shell: python, then make the run contents just the python script. Might be cleaner than bash/heredoc.

OTOH there may be a good case for turning this into a file and having it invokable locally as part of a git check.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I now check that the package versions match using a separate script on every commit. The script prints the shared version on success and I use it here in a normal shell to compare to the release version.

Comment thread .github/workflows/publish_schemas.yml Outdated
--base "$BASE_SHA"
--head "$HEAD_SHA"
- name: Validate and stage schemas
run: |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same here - could make it a direct python script, could make it a locally invokable file.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(ultimately, I'm not a fan of detailed steps that can't be trivially debugged locally - they always go wrong just when you need to hurry a release!)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Similar setup here now

"networkx>=2.6,<4",
"pydantic~=2.12",
"pydot>=4.0.0",
"selene-api-models~=0.1.0",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I would prefer selene_trace as the package name.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

If you think this will only ever include trace stuff happy to go with that. If we add something later that isn't a trace it would be a bit awkward.

Comment thread devenv.nix Outdated
@jake-arkinstall
jake-arkinstall added this pull request to stack #236 October 8, 2026 15:11
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.

3 participants