Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ jobs:
raise SystemExit(f"invalid Draft 2020-12 schema in {path}: {exc.message}") from exc
schemas[path] = value

# Prove the validator is checking schema semantics rather than JSON syntax alone.
try:
Draft202012Validator.check_schema({"$schema": "https://json-schema.org/draft/2020-12/schema", "type": 7})
except SchemaError:
Expand All @@ -88,9 +87,6 @@ jobs:
f"schema major version {version_match.group(1)} must match path segment {path_major!r}"
)

# `$id` is a canonical logical identifier, not a mutable branch URL or a
# claim that an unreleased schema has already been published. Its semantic
# version therefore determines an immutable identity before the first release.
expected_id = (
"urn:contextualwisdomlab:learning-interoperability-contracts:"
f"learning-event:{version}"
Expand Down Expand Up @@ -139,12 +135,7 @@ jobs:
field = schema["properties"][field_name]
if field.get("format") != "date-time" or not field.get("pattern"):
raise SystemExit(f"{field_name} must require date-time format and a syntax pattern")

# Draft 2020-12's default metaschema treats format as annotation. The
# contract gate therefore opts into executable format checking and
# combines it with the committed lexical pattern.
field_validator = Draft202012Validator(field, format_checker=format_checker)

for candidate in valid_timestamps:
errors = list(field_validator.iter_errors(candidate))
if errors:
Expand All @@ -156,12 +147,9 @@ jobs:
parse_contract_timestamp(candidate)
except ValueError as exc:
raise SystemExit(f"{field_name} parser rejects valid timestamp: {candidate}") from exc

for candidate in invalid_timestamps:
errors = list(field_validator.iter_errors(candidate))
if not errors:
if not list(field_validator.iter_errors(candidate)):
raise SystemExit(f"{field_name} schema accepts invalid timestamp: {candidate}")

for candidate in invalid_calendar_timestamps:
try:
parse_contract_timestamp(candidate)
Expand All @@ -178,3 +166,5 @@ jobs:
raise SystemExit(f"unresolved bootstrap marker {marker!r} in {path}")

print("learning interoperability bootstrap contract validation passed")
- name: Validate xAPI protocol binding fixtures
run: python3 tests/test_xapi_protocol_binding.py
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
- Repository agent development rules.
- Product requirements defining customer/integrator jobs, contract support gates, non-goals and release outcomes.
- Technical requirements defining the artifact-only bounded context, invariants, validation, release, security and consumer ACL requirements.
- Test-first `cwl_xapi_protocol_binding/v1` contract that keeps canonical xAPI 2.0 and cmi5 Quartz/xAPI 1.0.3 compatibility mutually exclusive without carrying statement payloads or rewriting historical records.
- Positive and deliberately invalid protocol-binding fixtures covering valid xAPI 2.0, valid cmi5 Quartz, cross-version claims, unknown surfaces, and statement-payload leakage.
- ADR 0002 documenting the protocol-binding anti-corruption boundary and current standards evidence.

### Changed

- Pinned the adopted cmi5 Quartz normative source to the official immutable Quartz release commit instead of the mutable development branch.
- Reconciled the commercialization baseline so the immutable schema identity is distinguished from the still-missing protected release artifact, and portable timestamp conformance remains explicitly blocked until consumer format-assertion fixtures are executable across supported runtimes.
- Pinned the repository quality job to `ubuntu-24.04` after the live exact-head `ubuntu-latest` job remained unassigned with no executed steps; no validation, security, review, or release gate was weakened.
- Broadened repository Quality from only `develop`/`main` pull-request bases to every pull request so stacked feature PRs receive the same repository-local exact-head validation rather than silently skipping it.
- Repository Quality now requires PRD and TRD presence so foundational product/technical contracts cannot regress silently.
- Repository Quality runs on stacked pull requests, requires PRD/TRD, and executes the xAPI protocol-binding regression suite so feature-branch bases cannot silently skip repository-local validation.
48 changes: 44 additions & 4 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,50 @@ This repository owns versioned learning interoperability contracts and no applic

Primary families: xAPI 2.0, cmi5 Quartz compatibility, LTI 1.3, QTI 3, CASE 1.1, Open Badges 3.0, and CLR 2.0.

Authority boundaries:
## Domain-driven design

**Subdomain:** generic interoperability.
**Bounded context:** Learning Contract Authority.

The bounded context owns provider-neutral contract identities, versioned schemas/profiles/mappings, conformance fixtures, and reproducible generated-client contracts. It does not own learner state, content state, xAPI statement truth, psychometric computation, or product databases.

Ubiquitous language includes:

- `contract_version`: immutable semantic version of a released contract surface;
- `protocol_binding`: an immutable value object selecting one explicitly versioned protocol/profile family without translating a record;
- `compatibility_surface`: an explicitly bounded compatibility path such as cmi5 Quartz/xAPI 1.0.3;
- `normative_authority`: the pinned external specification authority used to define a contract choice;
- `conformance_fixture`: executable positive or negative evidence for one contract invariant.

Current value objects:

- `learning-event` envelope schema — provider-neutral event transport envelope candidate;
- `cwl_xapi_protocol_binding/v1` — mutually exclusive protocol-selection value object for canonical xAPI 2.0 versus cmi5 Quartz/xAPI 1.0.3 compatibility.

The protocol-binding value object is intentionally not an aggregate or transaction boundary: it carries no xAPI statement, launch session, learner, registration, content, score, or runtime state. A consumer uses it as an anti-corruption boundary before invoking its own version-specific adapter. Historical records are never silently rewritten between xAPI versions.

## Authority boundaries

- Learning Management Platform: offerings, enrollment, progression, completion policy.
- Learning Content Studio: authoring state and immutable releases.
- Learning Record Store: xAPI statements and document resources.
- Learning Content Studio: authoring state, immutable content releases, and target publication.
- Learning Record Store: authoritative xAPI statements and document resources.
- Psychometrics Commons: assessment sessions, responses, and score snapshots.
- `learning-interoperability-contracts`: reusable versioned contract authority only.

## Context map

```text
Learning Contract Authority
|
+--> released xAPI 2.0 protocol/profile contract --> consumer xAPI 2.0 adapter
|
+--> released cmi5 Quartz compatibility contract --> consumer cmi5/xAPI 1.0.3 adapter

Consumer adapters --> owning runtime aggregate / persistence
```

Consumers integrate through versioned released contracts. They do not copy contract logic into a shared database, cross-read another product database, or treat this repository as runtime truth. Compatibility adapters remain in their owning runtime unless the reusable mapping itself is the versioned interoperability product.

## Persistence and transaction boundaries

Consumers integrate through versioned contracts; cross-repository database access is not part of the architecture.
This repository owns no relational persistence, database schema, or runtime transaction. Released contract bundles are immutable release aggregates at the artifact/repository boundary. If generated SDK artifacts are introduced, reproducibility and provenance belong to the release pipeline rather than a product database.
55 changes: 55 additions & 0 deletions docs/adr/0002-xapi-protocol-binding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# ADR 0002: Explicit xAPI protocol binding without historical translation

- Status: Candidate
- Date: 2026-09-02
- Decision owner: Learning Contract Authority
- Tracks: issue #3

## Context

ContextualWisdomLab consumers need one reusable way to distinguish the canonical xAPI 2.0 contract from the existing cmi5 Quartz compatibility path. Treating the two as interchangeable would allow a consumer to infer that a cmi5/xAPI 1.0.3 record is an xAPI 2.0 record, or to silently rewrite historical evidence while crossing product boundaries.

The current authoritative standards evidence also differs by surface. ISO/IEC/IEEE 39274-1-1:2025 is the published international xAPI standard. cmi5 Quartz remains the AICC Quartz 1st Edition compatibility specification based on xAPI 1.0.3, while IEEE P9274.3.1 is still an active project authorization rather than an approved cmi5 standard. Adoption therefore must not be represented as equivalent implementation or certification evidence.

## Decision

Define `cwl_xapi_protocol_binding/v1` as a provider-neutral immutable value object in the Learning Contract Authority bounded context.

The contract has exactly two compatibility surfaces:

1. `xapi_2_0` — requires `xapi_version = 2.0.0`, `xapi_profile_format_version = 1.0.0`, and the pinned authority `ISO/IEC/IEEE 39274-1-1:2025`.
2. `cmi5_quartz` — requires `xapi_version = 1.0.3`, `xapi_profile_format_version = 1.0.0`, `cmi5_release = quartz-1st-edition`, and pinned cmi5 revision `984a9b8`.

The schema is closed (`additionalProperties: false`). xAPI 2.0 bindings reject cmi5-only fields, cmi5 bindings reject xAPI 2.0 version claims, unknown compatibility surfaces fail closed, and statement payloads are outside this value object.

No consumer may treat this protocol-selection contract as xAPI statement conformance, cmi5 launch/package conformance, third-party certification, or proof that a historical record can be translated between versions. Statement truth remains with the Learning Record Store or another owning runtime.

## DDD and integration consequences

`ProtocolBinding` is a value object, not a runtime aggregate. It has no database, repository, transaction, domain event, or mutable identity. The consumer-facing anti-corruption layer selects a version-specific adapter based on a released binding and then validates the actual protocol payload under the appropriate owning contract.

This keeps the shared kernel minimal: consumers share an immutable versioned contract artifact, not runtime code or persistence. A future full xAPI 2.0 profile/conformance slice may add statement/profile schemas and fixtures here only when they are reusable provider-neutral contracts.

## Test-first evidence

- `05bbb0936c4ecfb87b7400d73545722ca1137ec7` introduced the failing/executable regression specification before the schema and fixtures existed.
- `2bbb549f5dda58794af4979f9f15ae3f514e4249` added the closed Draft 2020-12 protocol-binding schema and positive/negative fixtures.
- `6334e925050c562e27cee0857fb37c85ee36bea0` wired the regression suite into repository Quality.
- `b90103ecdc0f6e31edbb957d18b308d1f521d267` broadened repository Quality to stacked pull requests so this child slice cannot evade exact-head validation merely because its base is another feature branch.

Exact-head GitHub checks and independent review remain required. These commits are implementation history, not a conformance or release claim.

## Rejected alternatives

- **One permissive `xapi` surface:** rejected because it erases the protocol/profile revision boundary.
- **Automatic 1.0.3-to-2.0 rewriting:** rejected because historical evidence would acquire semantics it did not originally assert.
- **Copy protocol selection into each consumer:** rejected because divergent version rules would recreate the interoperability gap this repository exists to own.
- **Put statements into the binding object:** rejected because statement truth belongs to runtime/LRS boundaries and would turn a reusable value object into an application-state contract.

## References

AICC. (n.d.). *cmi5 specification—Quartz, 1st Edition* (revision 984a9b8). GitHub. https://github.com/AICC/CMI-5_Spec_Current/blob/984a9b8/cmi5_spec.md

IEEE Standards Association. (2025). *ISO/IEC/IEEE 39274-1-1-2025: Information technology—Learning, education and training—Experience API—Part 1-1: Data and data model*. https://standards.ieee.org/ieee/39274-1-1/12268/

IEEE Standards Association. (n.d.). *P9274.3.1: Standard for learning technology—JavaScript Object Notation (JSON) data model format and Representational State Transfer (RESTful) web service for learner experience data—Part 3-1: cmi5*. https://standards.ieee.org/ieee/9274.3.1/11183/
16 changes: 12 additions & 4 deletions docs/doctoring/STANDARD_TRACEABILITY.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Standards traceability

Adoption status and implementation/conformance evidence are intentionally separate. `Adopt` records a product decision pinned to an identified specification revision; it does not imply implementation conformance or third-party certification. `Not evidenced (adoption only)` is therefore the expected bootstrap state until a consumer-facing contract surface has requirement-level executable evidence on an exact head.
Adoption status and implementation/conformance evidence are intentionally separate. `Adopt` records a product decision pinned to an identified specification revision; it does not imply implementation conformance or third-party certification. The issue #3 protocol-binding slice is therefore recorded only as an internal ContextualWisdomLab contract candidate until a precise normative requirement, implementation surface, executable fixture and terminal-success exact-head CI receipt can be bound together.

| Standard | Revision | Normative source | Scope | Adoption status | Evidence status |
|---|---|---|---|---|---|
| xAPI / ISO/IEC/IEEE 39274-1-1 | xAPI 2.0; ISO/IEC/IEEE 39274-1-1:2025 | https://www.iso.org/standard/91131.html | Canonical learning-experience record contract | Adopt | Not evidenced (adoption only) |
| cmi5 Quartz | Quartz, 1st Edition (2016), xAPI 1.0.3 compatibility | https://github.com/AICC/CMI-5_Spec_Current/blob/984a9b8/cmi5_spec.md | Version-pinned LMS launch and package compatibility | Adopt as compatibility profile | Not evidenced (adoption only) |
| xAPI / ISO/IEC/IEEE 39274-1-1 | xAPI 2.0; ISO/IEC/IEEE 39274-1-1:2025 | https://standards.ieee.org/ieee/39274-1-1/12268/ | Canonical learning-experience record contract | Adopt | **No xAPI implementation/conformance claim.** Issue #3 PR #7 adds only the internal `cwl_xapi_protocol_binding/v1` candidate that selects the xAPI `2.0.0` surface and keeps it distinct from cmi5. Candidate location: `profiles/cwl_xapi_protocol_binding/v1/protocol-binding.schema.json`; executable internal invariant fixture: `tests/test_xapi_protocol_binding.py`. Terminal-success exact-head CI and requirement-level xAPI statement/profile evidence are still absent. |
| cmi5 Quartz | Quartz, 1st Edition (2016), xAPI 1.0.3 compatibility | https://github.com/AICC/CMI-5_Spec_Current/blob/984a9b8/cmi5_spec.md | Version-pinned LMS launch and package compatibility | Adopt as compatibility profile | **No cmi5 implementation/conformance claim.** Issue #3 PR #7 adds only the internal compatibility-selection candidate pinned to Quartz revision `984a9b8` and xAPI `1.0.3`; its negative fixtures reject xAPI 2.0 crossover. Terminal-success exact-head CI plus requirement-level launch/package evidence are still absent. IEEE P9274.3.1 remains an active PAR and is not represented as an approved standard. |
| LTI Core | 1.3.0 Final | https://standards.1edtech.org/lti/specifications/core/lti-spec1p3p1 | External learning-tool launch and security contract | Adopt | Not evidenced (adoption only) |
| LTI Assignment and Grade Services | 2.0 Final | https://standards.1edtech.org/lti/specifications/services/assignments_grades/assignment-grade-services-spec | Gradebook/result service interoperability | Adopt | Not evidenced (adoption only) |
| LTI Names and Role Provisioning Services | 2.0 Final | https://standards.1edtech.org/lti/specifications/services/names_roles/names-role-provisioning-spec | Context-scoped membership and role provisioning | Adopt | Not evidenced (adoption only) |
Expand All @@ -18,4 +18,12 @@ Adoption status and implementation/conformance evidence are intentionally separa
| WCAG | 2.2, W3C Recommendation 2024-12-12 | https://www.w3.org/TR/WCAG22/ | Accessible learning and contract-facing web content | Adopt | Not evidenced (adoption only) |
| ATAG | 2.0, W3C Recommendation 2015-09-24 | https://www.w3.org/TR/ATAG20/ | Accessible authoring-tool contract | Adopt | Not evidenced (adoption only) |

An adoption row may remain `Not evidenced (adoption only)` indefinitely if no implementation surface is introduced. Before an implementation PR can claim `Implemented`, `Conformant`, or equivalent language, it must pin the precise normative requirement, implementation location, executable fixture/test path, and exact-head CI receipt. A moving overview page is insufficient evidence for a requirement-level implementation claim and must be replaced by the applicable versioned specification section when that surface is implemented. Certification claims additionally require the applicable external certification process and may not be inferred from adoption, implementation, passing local tests, or documentation alone.
An adoption row may remain `Not evidenced (adoption only)` indefinitely if no implementation surface is introduced. Before an implementation PR can claim `Implemented`, `Conformant`, or equivalent language, it must pin the precise normative requirement, implementation location, executable fixture/test path, and terminal-success exact-head CI receipt. A moving overview page is insufficient evidence for a requirement-level implementation claim and must be replaced by the applicable versioned specification section when that surface is implemented. Certification claims additionally require the applicable external certification process and may not be inferred from adoption, implementation, passing local tests, or documentation alone.

## Research references (APA 7th)

AICC. (n.d.). *cmi5 specification—Quartz, 1st Edition* (revision 984a9b8). GitHub. https://github.com/AICC/CMI-5_Spec_Current/blob/984a9b8/cmi5_spec.md

IEEE Standards Association. (2025). *ISO/IEC/IEEE 39274-1-1-2025: Information technology—Learning, education and training—Experience API—Part 1-1: Data and data model*. https://standards.ieee.org/ieee/39274-1-1/12268/

IEEE Standards Association. (n.d.). *P9274.3.1: Standard for learning technology—JavaScript Object Notation (JSON) data model format and Representational State Transfer (RESTful) web service for learner experience data—Part 3-1: cmi5*. https://standards.ieee.org/ieee/9274.3.1/11183/
Loading