Skip to content

issue_102: Separate artifact validity from review - #103

Merged
dieterbaier merged 3 commits into
mainfrom
issue_102
Sep 21, 2026
Merged

dieterbaier merged 3 commits into
mainfrom
issue_102

Conversation

@dieterbaier

@dieterbaier dieterbaier commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Closes #102.

Documentation only. #101 implements the axis and stays open.

An accepted mitigates relation must not become rejected when its target risk
stops existing. rejected is defined as a verdict about the claim — "considered
and 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 status enum had the same gap from the other side. It offered
deprecated without ever defining it, mixed review maturity with temporal
validity, and for Risk artifacts collided with risk-management vocabulary,
where an accepted risk is one the team deliberately carries.

issue_102: Separate artifact validity from review

ADR-009 keeps relationship status a review state and moves "does this still
hold" onto a separate validity axis: validity (active | retired) with
retired_on, retired_reason and retired_note. A retired risk keeps
status: accepted, because both statements are true at once — the description
is accepted knowledge, and the risk is gone.

Three options were weighed with a Pugh matrix: a closed value in the shared
status enum (-1), the separate axis (4), and a prose-only closure note
(0). The cheap option loses because a closed artifact has no review state
left, 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 in
force, discouraged for new work" — a component being phased out, not an artifact
whose subject is gone.

issue_102: Close the gaps the convergence check found

From 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 documents or
supersedes; 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-residual is
not a retirement reason.

Reason and explanation stop competing. retired_reason is machine-readable
for filtering, retired_note is for human readers. The vocabulary is
no-longer-applicable and removed for every type, plus mitigated and
materialized for Risk.

The metamodel also states the invariants the axis needs, including that an
absent validity is read as active by validator and generator — a JSON Schema
default annotates without materializing anything.

issue_102: Name the two values the split left behind

From the review. The section claimed two independent axes while superseded and
deprecated stayed on status carrying temporal meaning — a clean separation
that ADR-009 deliberately has not completed, because that migration overlaps
with deriving superseded_by from an outgoing supersedes relation (#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 13510ca

Run immediately before integration, against the commit being integrated. It
replaces the provisional results; the one recorded against 9fe97ca was void.
No commit landed after 13510ca, local and remote heads are identical, and CI
validate is green.

Integration hazard, handled. #105 is stacked on this branch, and this
repository deletes head branches on merge. Deleting issue_102 would close #105
irrecoverably (#73), so #105 was retargeted to main before this merge.

Result: Converged.

# Question Answer
1 Intent and scope Passed (assisted). All four acceptance criteria of #102 are met. The check found one scope change recorded only in the diff — the four semantics closed by the second commit — and it is now recorded in #102 as well. Disposition: fixed.
2 Behaviour Not applicable (deterministic). No observable behaviour changes: the diff is two .adoc files under src/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.
3 Architecture impact Passed (assisted). Two artifacts changed, both genuinely affected: the new ADR and the metamodel document it refines. No collateral edits to other chapters.
4 Decisions Passed (human tier, applied). The decision is the ADR. Proportionality was checked against the four criteria in #102 before drafting. Three questions are explicitly left open rather than answered by accident, and the overlap with #67 on superseded/deprecated is recorded as coordination, not resolved silently.
5 Traceability Passed (deterministic for the relation path). #102 → ADR-009 → refines DOC-04001-metamodel, addresses QS-004, introduces_risk R-004 → regenerated impact and traceability fragments. Validation reports no dangling targets.
6 Implementation and verification Passed (deterministic). See below.
7 Documentation and delivery state Passed (assisted). One review finding, fixed in 13510ca: the section described the axis separation as complete while two temporal values stayed on status. Stale references are gone — no accepted-as-residual remains 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 the superseded_by overlap.

Verification

Run Result
./build.sh all on 13510ca Ruby 29 runs, 144 assertions, 0 failures; CLI 4 runs, 13 assertions, 0 failures; JS 41 pass, 0 fail; adapters current
./build.sh build Errors: 0. Renders build/architecture/index.html, no Asciidoctor warnings, both new xrefs resolve.
./build.sh validate 38 warnings, all pre-existing bidirectional-relation false positives tracked as #93. None names an artifact from this change.
node --test, all JS suites 41 pass, 0 fail
ruby -Itest test/validate_metamodel_test.rb 29 runs, 144 assertions, 0 failures
ruby -Itest test/validate_metamodel_cli_test.rb 4 runs, 13 assertions, 0 failures

Residual risk. The validity axis is documented before it is implementable.
Until #101 lands, metamodel/artifact.schema.yaml rejects the fields the
metamodel 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.

Dieter Baier added 2 commits September 21, 2026 16:41
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 dieterbaier left a comment

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.

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.

Comment thread src/docs/arc42/04-solution-strategy/doc-04001-metamodel.adoc Outdated
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 dieterbaier left a comment

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.

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.

@dieterbaier
dieterbaier merged commit ecf8729 into main Sep 21, 2026
1 check passed
@dieterbaier
dieterbaier deleted the issue_102 branch September 21, 2026 17:15
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.

Record an ADR: relation status is a review verdict, not a validity period

1 participant