Skip to content
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ here.

### Added

- Name the next Core release `0.3.0`, define conformance maturity independently, and require `v0.3.0-rc.1` before release (#231).

- Policy companion decision (#211): keep RFC 0023 Accepted at draft maturity and Policy 1.0.0 pinned, record its duplicate-identity and no-list-priority rules, and leave disagreement refusal and the second independently authored reader open.
- RFC 0022 aligns reusable-subgraph bounds, routed handoff provenance, dialect-owned remapping and
cross-installation packaging with the decisions on #129, #219, #232 and #170 (#233).
Expand Down
38 changes: 32 additions & 6 deletions VERSIONING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ Git tags. Specification `0.2.0-draft` is identified by the exact tag `v0.2.0-dra
by `v0.1.0-draft`. Only a tag and GitHub release published by the maintainers establish an immutable
release; similarly named files on the mutable `main` branch do not.

The next release is `0.3.0`, identified by `v0.3.0`. It is the first Core `specVersion` without the
retired `-draft` suffix; the identifiers and tags of `0.1.0-draft` and `0.2.0-draft` do not change.

## Specification versions

`specVersion` identifies the specification release a Judgment Pack targets. Readers MUST compare
the complete value; they must not infer compatibility from a shared major or minor number during
the `0.x` research period.
the complete value; they must not infer compatibility from a shared major or minor number before
`1.0.0`.

A conformance claim is made against one exact `specVersion`. That applies to every class, and it
binds hardest on evaluator conformance (Core §3.4): such a claim names the exact version and the
Expand All @@ -25,8 +28,31 @@ claim. A preserved schema is served at the `$id` it was published under, and whe
re-pointed to this project's own domain it differs from the tagged artifact in that one member and nothing
else — the release notes of the version that preserved it publish the digest of both forms.

Any `0.x` release may change reader, writer, or semantic behavior incompatibly. Release notes must
identify those effects and include migration guidance when an earlier pack can be transformed.
Before `1.0.0`, a release may change reader, writer, or semantic behavior incompatibly. Its release
notes must record the change and include a `specVersion` migration note, including when no automatic
migration is available.

## Maturity levels

The `status` in each Core conformance manifest is a maturity level, not a version. Its closed ladder
is:

- `draft`: the document is still being exercised and the acceptance evidence is not yet complete;
- `candidate`: independent conforming implementations, production adopters, and sustained outside
contribution are in and recorded for the document; and
- `release`: the evidence has been accepted and recorded for the `1.0.0` standards claim.

Movement is one step at a time. The recorded evidence above moves a document from `draft` to
`candidate`; the maintainer's recorded `1.0.0` acceptance of that evidence moves it from `candidate`
to `release`. Production use alone does not move a document or establish a standard.

## Core pre-releases

A Core release candidate uses the SemVer `-rc.N` form. The `0.3.0` release is preceded by exactly
one candidate, tag `v0.3.0-rc.1`, published as a GitHub pre-release for about one week so adopters'
tooling can read the renamed manifest status. The unsuffixed `v0.3.0` tag is the release. The Policy
companion's `policy-v<releaseVersion>-draft.N` route remains independent and is not replaced by this
Core convention.

The `main` branch describes work in progress. It is not an immutable specification release and
must not be used as a reproducibility anchor.
Expand All @@ -52,7 +78,7 @@ No compatibility dimension is implied merely because two releases share a versio

## Release artifacts

An immutable Core preview release contains, at minimum:
An immutable Core release contains, at minimum:

- the tagged Core prose specification;
- the tagged JSON Schema with a versioned `$id`, plus any superseded schema still published;
Expand All @@ -67,7 +93,7 @@ each artifact is permitted to make.

## Deprecation and support

`0.x` draft releases have no compatibility or security service-level guarantee. Maintainers
Pre-`1.0.0` releases have no compatibility or security service-level guarantee. Maintainers
may deprecate or remove behavior in a later `0.x` release, but must record the change in release
notes. A stable release will require a separate support and deprecation policy before publication.

Expand Down
2 changes: 1 addition & 1 deletion conformance/evaluation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ including the two invariants JSON Schema cannot express — and stop there.
| -------------- | ---------------------------------------------------------------------------------------------- |
| `suiteVersion` | The corpus version an evaluator-conformance claim must name (Core §3.4.1). |
| `specVersion` | The exact Core version these expectations are computed under. |
| `status` | `research-preview`, matching the maturity of the specification itself. |
| `status` | `draft`, the corpus maturity level; `candidate` and `release` are later ladder steps. |
| `label` | `seed` — this corpus is not exhaustive and does not aim to be. |

`suiteVersion` equals the `specVersion` the corpus was published for, and the corpus is frozen when
Expand Down
2 changes: 1 addition & 1 deletion conformance/evaluation/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "./manifest.schema.json",
"suiteVersion": "0.2.0-draft",
"specVersion": "0.2.0-draft",
"status": "research-preview",
"status": "draft",
"label": "seed",
"cases": [
{
Expand Down
2 changes: 1 addition & 1 deletion conformance/evaluation/manifest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"const": "0.2.0-draft"
},
"status": {
"const": "research-preview"
"enum": ["draft", "candidate", "release"]
},
"label": {
"const": "seed"
Expand Down
2 changes: 1 addition & 1 deletion conformance/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "./manifest.schema.json",
"suiteVersion": "0.2.0-draft",
"specVersion": "0.2.0-draft",
"status": "research-preview",
"status": "draft",
"validationProfile": {
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"formatAssertionRequired": true,
Expand Down
2 changes: 1 addition & 1 deletion conformance/manifest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"const": "0.2.0-draft"
},
"status": {
"const": "research-preview"
"enum": ["draft", "candidate", "release"]
},
"validationProfile": {
"type": "object",
Expand Down
43 changes: 43 additions & 0 deletions docs/releases/v0.3.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# v0.3.0

`0.3.0`, tagged `v0.3.0`, is the first Core release whose `specVersion` has no `-draft` suffix.
The released `0.2.0-draft` identifier and its tag keep their names. Before the release, one
`v0.3.0-rc.1` GitHub pre-release gives adopters about a week to verify that their tooling reads the
manifest maturity `status` as `draft` rather than the retired `research-preview` value.

## Included work

- Core escalation routes from RFC 0025: an exclusive single target or bounded conditional routes,
with routed handoff provenance and complete retained reasons.
- The `base` and `extended` document ceiling profiles from RFC 0026, including reader negotiation
and explicit refusal of an unsupported profile.
- The non-normative rule-overlap check and its closed `JPS-RULES-OVERLAP` diagnostic.
- RFC 0020's bulk amendment: contributing-rule output records, disposition summaries, reproducible
seeded samples, drift comparison, and the closed workflow schema and hand-written fixture that
verify those records.
- RFC 0020's later-sibling rule, limited to instances admitted for acquisition so an admission
failure retains its own finding.
- Dialect data-quality conversions, reconciliation, typed research-result states, lineage,
versioned source profiles, resolved settings, and byte-retaining replay contracts.
- RFC 0022's alignment with the landed composition decisions for subgraph bounds, routed handoff
provenance, dialect-owned remapping, and cross-installation packaging.

## Versioning and maturity

Pre-`1.0.0` Core releases may be incompatible when their notes record the change and give a
`specVersion` migration note. Conformance manifest `status` is now the independent maturity ladder
`draft`, `candidate`, and `release`; `0.3.0` remains `draft`. The `release` maturity is reserved for
the `1.0.0` standards claim after the governance acceptance evidence is met and recorded. Production
use does not by itself establish that claim.

The Policy companion remains on its independent `policy-v1.0.0-draft.N` route until that format's
first release and is not renamed by the Core scheme change.

RFC 0024 and the Policy companion's record land in the release if merged before the tag.

## Migration note

The exact Core identifier accepted by packs and readers is not changed by this preparation. Before
the tag, the maintainer must decide which documents, schemas, vectors, and readers gain `0.3.0`
beside `0.2.0-draft`; the release cannot be cut until those exact-version surfaces and the Runtime's
vendored copy are updated together.
2 changes: 1 addition & 1 deletion rfcs/0000-rfc-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ the question was raised by that record and ruled on at its acceptance.

## Review

Research-preview RFCs remain open for public comment for a reasonable period based on complexity.
Draft RFCs remain open for public comment for a reasonable period based on complexity.
Maintainers may request prototypes or conformance cases before disposition. A stable normative
feature should not be accepted without evidence from two independent implementations.

Expand Down
2 changes: 1 addition & 1 deletion schema/conformance-manifest-0.1.0-draft.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"const": "0.1.0-draft"
},
"status": {
"const": "research-preview"
"enum": ["draft", "candidate", "release"]
},
"validationProfile": {
"type": "object",
Expand Down
2 changes: 1 addition & 1 deletion schema/judgment-pack-core-0.1.0-draft.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://judgmentpack.org/schema/0.1.0-draft/judgment-pack-core.schema.json",
"title": "Judgment Pack Core",
"description": "Research-preview structural schema. Conformance does not establish truth, authority, safety, or operational fitness.",
"description": "Structural schema for 0.1.0-draft. Conformance does not establish truth, authority, safety, or operational fitness.",
"$comment": "JPS structural conformance requires uri, date, and date-time format assertions even when a general-purpose validator treats format as annotation-only.",
"type": "object",
"additionalProperties": false,
Expand Down
2 changes: 1 addition & 1 deletion schema/judgment-pack-core.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://judgmentpack.org/schema/0.2.0-draft/judgment-pack-core.schema.json",
"title": "Judgment Pack Core",
"description": "Research-preview structural schema. Conformance does not establish truth, authority, safety, or operational fitness.",
"description": "Structural schema for 0.2.0-draft. Conformance does not establish truth, authority, safety, or operational fitness.",
"$comment": "JPS structural conformance requires uri, date, and date-time format assertions even when a general-purpose validator treats format as annotation-only.",
"type": "object",
"additionalProperties": false,
Expand Down
22 changes: 22 additions & 0 deletions tests/conformance-status-vectors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"status": "draft",
"valid": true
},
{
"status": "candidate",
"valid": true
},
{
"status": "release",
"valid": true
},
{
"status": "research-preview",
"valid": false
},
{
"status": "",
"valid": false
}
]
17 changes: 13 additions & 4 deletions tests/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,17 @@


class ReleaseBuilderTests(unittest.TestCase):
def test_0_3_0_release_naming_is_recorded(self) -> None:
versioning = (ROOT / "VERSIONING.md").read_text(encoding="utf-8")
notes = ROOT / "docs" / "releases" / "v0.3.0.md"
self.assertIn("`v0.3.0-rc.1`", versioning)
self.assertIn("`v0.3.0`", versioning)
self.assertTrue(notes.is_file())
self.assertEqual("# v0.3.0", notes.read_text(encoding="utf-8").splitlines()[0])

def test_release_version_accepts_exact_semver_tags(self) -> None:
self.assertEqual(BUILD_RELEASE.release_version("v0.1.0-draft"), "0.1.0-draft")
self.assertEqual(BUILD_RELEASE.release_version("v0.3.0-rc.1"), "0.3.0-rc.1")
self.assertEqual(BUILD_RELEASE.release_version("v1.2.3-rc.1"), "1.2.3-rc.1")
self.assertEqual(BUILD_RELEASE.release_version("v1.2.3-0"), "1.2.3-0")
self.assertEqual(BUILD_RELEASE.release_version("v1.2.3-alpha.1"), "1.2.3-alpha.1")
Expand Down Expand Up @@ -55,20 +64,20 @@ def test_artifact_validation_pins_the_evaluation_corpus(self) -> None:
# must not build even when every document artifact is correctly re-pinned.
for stale in ("specVersion", "suiteVersion"):
with self.subTest(member=stale), tempfile.TemporaryDirectory() as directory:
root = self._release_tree(Path(directory), "0.3.0-draft")
root = self._release_tree(Path(directory), "0.3.0")
evaluation_path = root / "conformance" / "evaluation" / "manifest.json"
evaluation = json.loads(evaluation_path.read_text(encoding="utf-8"))
evaluation[stale] = "0.2.0-draft"
evaluation_path.write_text(json.dumps(evaluation), encoding="utf-8")
with self.assertRaises(ValueError) as raised:
BUILD_RELEASE.validate_artifacts(
"0.3.0-draft", "v0.3.0-draft", root=root
"0.3.0", "v0.3.0", root=root
)
self.assertIn("evaluation corpus", str(raised.exception))
# The same tree validates once the corpus is re-pinned.
evaluation[stale] = "0.3.0-draft"
evaluation[stale] = "0.3.0"
evaluation_path.write_text(json.dumps(evaluation), encoding="utf-8")
BUILD_RELEASE.validate_artifacts("0.3.0-draft", "v0.3.0-draft", root=root)
BUILD_RELEASE.validate_artifacts("0.3.0", "v0.3.0", root=root)

def test_validate_requires_head_to_be_the_release_commit(self) -> None:
# Artifacts are validated from the worktree and archived from the commit, so a release built
Expand Down
30 changes: 30 additions & 0 deletions tests/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
f"https://judgmentpack.org/schema/{PREVIOUS_SPEC_VERSION}"
"/conformance/manifest.schema.json"
)
STATUS_VECTORS_PATH = ROOT / "tests" / "conformance-status-vectors.json"
# §8.3: the reason vocabulary a disposition may carry.
REASONS = {
"not-applicable",
Expand Down Expand Up @@ -919,6 +920,7 @@ def test_manifest_matches_its_schema(self) -> None:
self.assertEqual([], [error.message for error in errors])
self.assertEqual(self.manifest["suiteVersion"], SPEC_VERSION)
self.assertEqual(self.manifest["specVersion"], SPEC_VERSION)
self.assertEqual("draft", self.manifest["status"])
self.assertTrue(self.manifest["validationProfile"]["formatAssertionRequired"])
self.assertTrue(self.manifest["validationProfile"]["rejectDuplicateObjectMembers"])
diagnostic_validator = validator.evolve(
Expand All @@ -930,6 +932,33 @@ def test_manifest_matches_its_schema(self) -> None:
set(), rule_overlap_diagnostic_keywords(diagnostic_validator, diagnostic)
)

def test_conformance_manifest_status_ladder_vectors(self) -> None:
vectors = strict_json_loads(STATUS_VECTORS_PATH.read_text(encoding="utf-8"))
schemas = (
self.manifest_schema,
strict_json_loads(
EVALUATION_MANIFEST_SCHEMA_PATH.read_text(encoding="utf-8")
),
strict_json_loads(PREVIOUS_MANIFEST_SCHEMA_PATH.read_text(encoding="utf-8")),
)
for schema in schemas:
status_validator = Draft202012Validator(schema["properties"]["status"])
for vector in vectors:
with self.subTest(schema=schema["$id"], status=vector["status"]):
self.assertEqual(
vector["valid"], status_validator.is_valid(vector["status"])
)

def test_core_schema_descriptions_name_their_spec_versions(self) -> None:
for path in (SCHEMA_PATH, PREVIOUS_SCHEMA_PATH):
schema = strict_json_loads(path.read_text(encoding="utf-8"))
version = schema["properties"]["specVersion"]["const"]
self.assertEqual(
f"Structural schema for {version}. Conformance does not establish truth, "
"authority, safety, or operational fitness.",
schema["description"],
)

def test_rule_overlap_advisory_vectors_cover_the_recommendation(self) -> None:
self.assertEqual(["JPS-RULES-OVERLAP"], self.manifest["diagnosticVocabulary"]["advisory"])

Expand Down Expand Up @@ -1346,6 +1375,7 @@ def test_evaluation_manifest_matches_its_schema(self) -> None:
self.assertEqual([], [error.message for error in errors])
self.assertEqual(manifest["suiteVersion"], SPEC_VERSION)
self.assertEqual(manifest["specVersion"], SPEC_VERSION)
self.assertEqual("draft", manifest["status"])
self.assertEqual(manifest["label"], "seed")
ids = collections.Counter(case["id"] for case in manifest["cases"])
for case_id, count in sorted(ids.items()):
Expand Down
Loading