Skip to content

fix(spec): resolve normative contradictions before the v0.1.0 tag - #44

Merged
maehr merged 2 commits into
textrefs:stagingfrom
maehr:fix/release-consistency
Jul 26, 2026
Merged

fix(spec): resolve normative contradictions before the v0.1.0 tag#44
maehr merged 2 commits into
textrefs:stagingfrom
maehr:fix/release-consistency

Conversation

@maehr

@maehr maehr commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review findings from #4, fixed before the release is tagged. Everything here is a place where the standard contradicts itself, contradicts the compiler, or documents something that does not exist — cheap now, expensive once v0.1.0 is a citable baseline.

Normative contradictions

  • Succession had two mechanisms. specification.md §11 said the prior reference SHOULD be linked to its replacement through an exactMatch MappingAssertion; versioning.md said MappingAssertions MUST NOT be used for succession links. §11 was the stale side — it now points at superseded_by.
  • Work.exactMatch / closeMatch vs §6. The compiler emits derived SKOS arrays on Work, but §6 still closed with "External identifiers … are not fields on the Work itself" and omitted both fields from its list. §6 now separates the authoring surface (MappingAssertion, authoritative, carries status and provenance) from the compiler's read-only projection.
  • superseded_by was unreachable for deprecated. §11 allowed a deprecated tombstone, §12 attached the successor field only to withdrawn, and the compiler rejected anything but withdrawn/blocked. The guard widens to deprecated/withdrawn/blocked, and §12 now defines the field once, in full.
  • A documented compiler invariant did not exist. versioning.md § Compiler invariants claimed a promoted record MUST NOT reference a draft Work/CitationSystem; scripts/compile.ts had no draft check at all (ADR-0003 listed it as an open follow-up). Now implemented for both references and mapping subjects. Moot while all data is draft — live at the first promotion, which is exactly when nothing would have caught it.

enforceTombstoneInvariants is renamed enforceRegistryInvariants since it no longer only handles tombstones, and blocked joins TOMBSTONE_STATUSES so the two guards agree on what a tombstone is.

Published artifacts

api/openapi.yaml never received ADR-0001/0003: it still declared target_kind (the last occurrence in the tree outside CHANGELOG.md and decisions/) and lacked conforms_to, superseded_by, and the Work SKOS arrays. This document is published at /api/.

Housekeeping

  • CONTRIBUTING.md claimed vYYYY.MM.N tags are cut from this repo's main, contradicting its own release checklist. This is the unresolved review thread blocking Release v0.1.0: ADR-0001/0002/0003, all data draft, spec fixes #6–#15, Astro 7 (#20) #4 from merging.
  • All three ADRs move from Proposed to Accepted — the implementation is merging, so the decision is made. ADR-0002 and ADR-0003 follow-up checklists are reconciled against what actually shipped; sitemap exclusion for drafts is called out as still open rather than checked off, because @astrojs/sitemap is unfiltered and drafts are in sitemap-0.xml.

Verification

npm run format:check, npm run check (0 errors), npm run build (78,940 pages, all internal links valid), npm run compile:data + npm run validate:data (39,250/39,250 records valid).

The new invariant was proved to fire, not just to pass: promoting one work to candidate against the still-draft bekker system produced 5,220 violations and failed the build with promoted reference (candidate) points at draft system https://textrefs.org/id/system/bekker. Reverted afterwards; the data/ pointer is unchanged at c0a3275.

Changelog regenerated with git-cliff --tag v0.1.0 — plain npm run changelog retitles the section [Unreleased], since the release checklist regenerates before the tag exists.

🤖 Generated with Claude Code

maehr and others added 2 commits July 26, 2026 20:30
Review of the release PR (textrefs#4) turned up four places where the shipped
standard contradicts itself or the compiler, plus a published OpenAPI
document that ADR-0001 never reached.

- specification.md §11 still routed succession through an `exactMatch`
  MappingAssertion while versioning.md says MappingAssertions MUST NOT
  carry succession links. §11 now points at `superseded_by`.
- §6 declared external identifiers "not fields on the Work itself" while
  the compiler emits derived `exactMatch`/`closeMatch` arrays. §6 now
  separates the authoring surface (MappingAssertion) from the read-only
  projection, and lists both fields.
- §11 allowed `deprecated` tombstones but only `withdrawn` could carry a
  successor. The compiler guard widens to deprecated/withdrawn/blocked
  and §12 defines `superseded_by` once, in full.
- versioning.md documented a compiler invariant that did not exist:
  promoted records must not depend on draft ones. Implemented in
  `enforceRegistryInvariants` (renamed from enforceTombstoneInvariants,
  which no longer describes its scope) for both references and mapping
  subjects; `blocked` joins TOMBSTONE_STATUSES so the two guards agree.
- api/openapi.yaml drops `target_kind`, gains `conforms_to`,
  `superseded_by`, and the Work SKOS arrays.

Also: CONTRIBUTING scoped the `vYYYY.MM.N` tag scheme to the registry
repo (unresolved review thread on textrefs#4), all three ADRs move to Accepted
with their follow-up checklists reconciled against what actually shipped
— sitemap exclusion for drafts is called out as still open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant