Skip to content

fix(compile): stop projecting retired mapping assertions onto Work (#45) - #86

Merged
maehr merged 1 commit into
textrefs:stagingfrom
maehr:fix/45-retired-mapping-projection
Aug 24, 2026
Merged

fix(compile): stop projecting retired mapping assertions onto Work (#45)#86
maehr merged 1 commit into
textrefs:stagingfrom
maehr:fix/45-retired-mapping-projection

Conversation

@maehr

@maehr maehr commented Aug 24, 2026

Copy link
Copy Markdown
Member

Closes #45.

What

The direct alternateOf / isReferencedBy edges on Work (scripts/compile.ts:491) excluded only withdrawn and blocked assertions. deprecated still projected, so a mapping the registry had taken out of use kept emitting a live, unqualified edge.

That contradicts the standard's own definitions:

  • standard/schema/common.ts:5 — "The remaining three are tombstone states for records that have left active use" (deprecated, withdrawn, blocked).
  • specification.md:301 — "deprecated — retained but no longer recommended."
  • specification.md:305 — an incorrect active record "MUST instead be moved to deprecated, withdrawn, or blocked".

The edge carries no status, so it cannot say the mapping is retired. Now it simply is not published.

How

The set that means "left active use" already existed. Gate the projection on it, and rename it from SUPERSEDABLE_STATUSES to RETIRED_STATUSES so it reads correctly at both call sites.

TOMBSTONE_STATUSES stays. Its two remaining uses (:651, :671) are about broken resolution, and a deprecated work still resolves — the two rules are genuinely different.

The allowlist half of #45 is declined

#45 also proposed switching to an allowlist so draft assertions stop projecting, on the grounds that a consumer cannot tell a reviewed equivalence from an unreviewed one.

TextRefs' guarantees attach to CanonicalReference — identity, persistence, resolution. The Work projection is enrichment and never claimed review, so gating it on promotion would buy a guarantee the standard does not make.

It would also cost real capability. Every one of the 24 seed mappings is draft, and the compiled Work has no back-link to its assertions (src/pages/id/work/[key].json.ts:15 publishes the record verbatim, and there is no /reg/mapping/ index). Under an allowlist, v0.1.0 works would lose their only machine-readable path to Wikidata.

So the docs now state what the arrays are for, instead of implying a promise the standard does not make. specification.md §6 and json-ld.md gain: the arrays enrich the work, they make no claim about review, and a consumer that needs the status of a mapping reads the MappingAssertion.

No published output changes

Every record in data/ is draft, so no assertion is deprecated today. dist/dump/works.jsonl is byte-identical before and after:

b35b36e2d79a0e89f81934ca5b0865ca4fcb6e82d5f344b340151e470d57c76b  works.jsonl   (before)
b35b36e2d79a0e89f81934ca5b0865ca4fcb6e82d5f344b340151e470d57c76b  works.jsonl   (after)

This closes the hole before a demotion ever happens. It is not a release-scope change: #68 §4 triages #45 as "fine to ship without", and that stays true. No submodule bump.

Verification

npm run verify and npm run validate:data, both clean:

  • format:check clean, astro check 0 errors, 31/31 tests, 204,350 pages built, all internal links valid.
  • validate:data — 68005/68005 records valid (works=12, systems=10, refs=67959, mappings=24).

The gate was also proved to fire, by temporarily demoting one mapping in data/works/aristotle.nicomachean-ethics.yaml to deprecated and recompiling:

works carrying alternateOf:  12 -> 11
mapping records:             24 -> 24   (unchanged)

The demoted assertion survives in full at https://textrefs.org/id/mapping/d5d6ca80-c7e7-5919-8f95-6d96cf4f90b2, still pointing at https://www.wikidata.org/entity/Q474537 and still carrying "status": "deprecated". Only the unqualified edge is gone. The data/ edit was reverted; the submodule pointer is untouched.

Not in this PR

  • No ADR — decisions/README.md reserves those for choices that cross PR boundaries, and this changes no published byte.
  • No spec version bump and no !. Behaviour against current data is unchanged.

🤖 Generated with Claude Code

https://claude.ai/code/session_017PUm3GZBhwznL6uZEpDMKg

…extrefs#45)

The direct `alternateOf` / `isReferencedBy` edges on `Work` excluded only
`withdrawn` and `blocked` assertions. `deprecated` still projected, so a
mapping the registry had taken out of use kept emitting a live edge.

That contradicts the standard's own definitions. `deprecated`, `withdrawn`
and `blocked` are the three states for records that have left active use
(ADR-0004, `standard/schema/common.ts`), and specification §12 defines
`deprecated` as "retained but no longer recommended". The edge carries no
status, so it cannot say the mapping is retired.

Gate the projection on the set that already means "left active use", and
rename it from SUPERSEDABLE_STATUSES to RETIRED_STATUSES so it reads
correctly at both call sites. TOMBSTONE_STATUSES stays: the two remaining
uses are about broken resolution, and a deprecated record still resolves.

The published output does not change. Every record in `data/` is `draft`,
so no assertion is deprecated today and `dist/dump/works.jsonl` is
byte-identical. This closes the hole before a demotion ever happens.

Issue textrefs#45 also proposed an allowlist, so that `draft` assertions stop
projecting too. Declined: TextRefs' guarantees attach to
`CanonicalReference`, and the Work projection is enrichment that never
claimed review. The docs now say so, rather than implying a promise the
standard does not make.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PUm3GZBhwznL6uZEpDMKg
Copilot AI lite review requested due to automatic review settings August 24, 2026 15:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the compiler and documentation so Work.alternateOf / Work.isReferencedBy projections no longer publish unqualified edges for mapping assertions that have left active use (deprecated, withdrawn, blocked). This aligns the emitted Work enrichment with the lifecycle semantics in the standard, while keeping the reified MappingAssertion records authoritative for status/provenance.

Changes:

  • Update scripts/compile.ts to exclude deprecated mapping assertions from Work mapping-edge projections (and rename the status set to RETIRED_STATUSES).
  • Update standard docs and OpenAPI descriptions to clarify projection semantics (enrichment-only; no review claim; read MappingAssertion for status).
  • Add a unit test covering exclusion of deprecated mapping assertions from Work projections.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
standard/schema/work.ts Clarifies Work schema comments for mapping projection semantics and excluded statuses.
src/content/docs/standard/specification.md Updates §6 text to exclude deprecated and clarify “no review claim; read MappingAssertion”.
src/content/docs/standard/json-ld.md Updates JSON-LD documentation to match the new projection gating and semantics.
scripts/compile.ts Implements projection gating using RETIRED_STATUSES and updates invariant check naming.
scripts/compile.test.ts Adds regression test ensuring deprecated mappings do not project onto Work edges.
api/openapi.yaml Updates API schema descriptions for alternateOf/isReferencedBy projections and their meaning.

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

- `isReferencedBy` → `dcterms:isReferencedBy`, when the target is a document or page about the work (e.g. a Wikipedia article).

Published `Work` records additionally carry direct `alternateOf` / `isReferencedBy` arrays derived from mapping assertions that are not `withdrawn` or `blocked`, published as `prov:alternateOf` / `dcterms:isReferencedBy` edges from the work IRI to the mapped identifiers without dereferencing the reified `MappingAssertion` records. The arrays are a read-only projection; the assertion stays authoritative ([Specification §6](/standard/specification/#6-work)).
Published `Work` records additionally carry direct `alternateOf` / `isReferencedBy` arrays derived from mapping assertions that are not `deprecated`, `withdrawn` or `blocked`, published as `prov:alternateOf` / `dcterms:isReferencedBy` edges from the work IRI to the mapped identifiers without dereferencing the reified `MappingAssertion` records. The arrays are a read-only projection; the assertion stays authoritative ([Specification §6](/standard/specification/#6-work)). The arrays enrich the work. They make no claim about review: a consumer that needs the status of a mapping must read the `MappingAssertion`.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Declining this one — the lowercase is deliberate.

json-ld.md carries no RFC 2119 keywords at all. Counting uppercase keywords across the standard:

file MUST SHOULD MAY
specification.md 70 12 10
versioning.md 18 3 3
identifier-syntax.md 16 0 1
system-profiles.md 12 1 1
json-ld.md 0 0 0

The comparison is across files rather than within one. json-ld.md is the descriptive companion to the context document; it explains how records map to RDF and states no requirements of its own. Introducing a single MUST here would make it the only normative sentence on an otherwise non-normative page.

The requirement itself is already stated normatively, in the place that owns it — specification.md §6, in this same PR: "a consumer that needs the status of a mapping MUST read the MappingAssertion." The json-ld.md sentence restates it descriptively and links back to §6, which is the existing relationship between the two pages.

@maehr
maehr merged commit f5a037f into textrefs:staging Aug 24, 2026
2 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