issue_102: Separate artifact validity from review - #103
Conversation
An accepted mitigates relation must not become rejected when its target risk stops existing. Rejected is a verdict about the claim itself, so using it to express the passage of time rewrites a statement that was true when it was reviewed. ADR-009 keeps relationship status a review state and moves "does this still hold" onto a separate validity axis. The metamodel document gains the artifact status table it never had, so every status value and both axes have a defined meaning, including what deprecated does and does not mean. The schema, validator, and generator are unchanged; #101 implements the axis. The documentation says so explicitly, because artifact.schema.yaml rejects unknown metadata fields today.
The first version of ADR-009 left four semantic questions to the implementation, where they would have become accidental decisions in generator code. A relation is now inactive when either endpoint is retired, not only its target, because "active relation" has to mean the same thing from both sides. A new relation to a retired artifact is allowed and warned about: rejecting it would block legitimate historical links such as documents or supersedes, while a silent accept would hide stale references. A deliberately carried residual risk stays active. Retirement means the subject is gone, not that it is knowingly accepted, so an accepted residual risk must not vanish from the active-risk view. The machine-readable reason and its explanation are separate fields, so filtering and human explanation stop competing for one value, and the reason vocabulary is split into universal values and risk-specific ones. The metamodel also states the invariants the axis needs: retirement fields are absent while active, retired_on is on or after created, and an absent validity is read as active by validator and generator, because a schema default annotates without materializing anything.
dieterbaier
left a comment
There was a problem hiding this comment.
The central decision is sound, the four findings from the convergence check are now explicitly resolved, and the documentation-only scope is respected. CI is green, and I found no implementation changes hidden in this PR.
One finding to resolve before merge: the current wording overstates the separation that ADR-009 actually delivers. status is called a pure review axis while superseded and deprecated deliberately remain temporal states in that same enum pending a follow-up decision. The ADR itself correctly acknowledges this transitional mixture, so the metamodel should say so as well.
Non-blocking delivery note: #101 still contains the earlier reason vocabulary (including accepted-as-residual) and still asks questions now decided by ADR-009. Since #101 is the implementation follow-up, its body should be synchronized with #102/ADR-009 before implementation starts.
GitHub does not allow a formal request-changes review on one's own PR, so this is submitted as a comment review.
The section claimed two independent axes while superseded and deprecated stayed on status with temporal meaning. ADR-009 defers that migration on purpose, because it overlaps with deriving superseded_by from an outgoing supersedes relation, so the document has to say so rather than describe a separation the decision has not completed. Both values are now marked transitional where they are defined, and the lead paragraph states the exception instead of implying it away.
dieterbaier
left a comment
There was a problem hiding this comment.
Re-check against 13510ca: the finding is resolved. The metamodel now states the transitional exception explicitly, marks superseded and deprecated as temporal values still carried in status, and links the deferral to the overlap with #67. #101 has also been synchronized with ADR-009/#102, including the endpoint semantics, residual-risk treatment, reason/note split, metadata invariants, and acceptance criteria. The current Validate run is green. No further findings from this review.
Closes #102.
Documentation only. #101 implements the axis and stays open.
An accepted
mitigatesrelation must not becomerejectedwhen its target riskstops existing.
rejectedis defined as a verdict about the claim — "consideredand intentionally rejected" — so using it to express the passage of time
rewrites a statement that was true and reviewed when it was made.
The artifact
statusenum had the same gap from the other side. It offereddeprecatedwithout ever defining it, mixed review maturity with temporalvalidity, and for
Riskartifacts collided with risk-management vocabulary,where an accepted risk is one the team deliberately carries.
issue_102: Separate artifact validity from reviewADR-009 keeps relationship status a review state and moves "does this still
hold" onto a separate validity axis:
validity(active|retired) withretired_on,retired_reasonandretired_note. A retired risk keepsstatus: accepted, because both statements are true at once — the descriptionis accepted knowledge, and the risk is gone.
Three options were weighed with a Pugh matrix: a
closedvalue in the sharedstatus enum (-1), the separate axis (4), and a prose-only closure note
(0). The cheap option loses because a
closedartifact has no review stateleft, and because "closed" means nothing for an ADR or a component.
The metamodel document gains the artifact status table it never had. Every
status value now has a definition, including
deprecated, which means "still inforce, discouraged for new work" — a component being phased out, not an artifact
whose subject is gone.
issue_102: Close the gaps the convergence check foundFrom the convergence check on #101. The first version delegated four semantic
questions to the implementation, where they would have become accidental
decisions in generator code.
Either endpoint, not just the target. A relation is inactive when its source
is retired too. "Active relation" has to mean the same thing from both sides.
Allowed and warned, not rejected. Rejecting a new relation to a retired
artifact would block legitimate historical links such as
documentsorsupersedes; a silent accept would hide stale references.A residual risk stays active. Retirement means the subject is gone, not that
it is knowingly carried. Marking an accepted residual risk as retired would make
a present risk disappear from the active-risk view, so
accepted-as-residualisnot a retirement reason.
Reason and explanation stop competing.
retired_reasonis machine-readablefor filtering,
retired_noteis for human readers. The vocabulary isno-longer-applicableandremovedfor every type, plusmitigatedandmaterializedforRisk.The metamodel also states the invariants the axis needs, including that an
absent
validityis read asactiveby validator and generator — a JSON Schemadefaultannotates without materializing anything.issue_102: Name the two values the split left behindFrom the review. The section claimed two independent axes while
supersededanddeprecatedstayed onstatuscarrying temporal meaning — a clean separationthat ADR-009 deliberately has not completed, because that migration overlaps
with deriving
superseded_byfrom an outgoingsupersedesrelation (#67).The lead paragraph now states the exception instead of implying it away, and
both values are marked "Transitional, temporal" where they are defined.
Convergence Check — authoritative, against
13510caRun immediately before integration, against the commit being integrated. It
replaces the provisional results; the one recorded against
9fe97cawas void.No commit landed after
13510ca, local and remote heads are identical, and CIvalidateis green.Integration hazard, handled. #105 is stacked on this branch, and this
repository deletes head branches on merge. Deleting
issue_102would close #105irrecoverably (#73), so #105 was retargeted to
mainbefore this merge.Result: Converged.
.adocfiles undersrc/docs, and no script, schema, template or skill is touched. This question would have failed had the schema or validator moved with the documentation, which is exactly what the NOTE in the metamodel prevents.superseded/deprecatedis recorded as coordination, not resolved silently.refines DOC-04001-metamodel,addresses QS-004,introduces_risk R-004→ regenerated impact and traceability fragments. Validation reports no dangling targets.13510ca: the section described the axis separation as complete while two temporal values stayed onstatus. Stale references are gone — noaccepted-as-residualremains anywhere. The not-yet-implemented NOTE is deliberately kept and names the schema constraint that makes it necessary. Deferred work has follow-ups: #101 for the axis, #67 for thesuperseded_byoverlap.Verification
./build.sh allon13510ca./build.sh buildbuild/architecture/index.html, no Asciidoctor warnings, both new xrefs resolve../build.sh validatenode --test, all JS suitesruby -Itest test/validate_metamodel_test.rbruby -Itest test/validate_metamodel_cli_test.rbResidual risk. The validity axis is documented before it is implementable.
Until #101 lands,
metamodel/artifact.schema.yamlrejects the fields themetamodel now describes. The NOTE in the document is the mitigation, and it is
removed by #101's acceptance criteria — a review-enforced guard, not a
deterministic one, because no check can read prose intent.