Building The Longhand Archive

How a solo archival system gets built in public

View My GitHub Profile

Superseded by ADR 0004 — Two-layer lifecycle model and ADR 0005 — Evidence-based lifecycle transitions. Retained as historical record of the live pressure-testing session and the empirical findings that led to those decisions.


Lifecycle semantics pressure-test note

Last reviewed: 2026-04-20

This note captures the follow-up from live pressure-testing of full-run behavior and current archive semantics. It is a maintainer note, not a historical handoff.

Why this review happened

Three semantics issues showed up when comparing qualifying full-run manifests, current csj_jobs/ projections, and live CSJ behavior:

  1. withdrawn_confirmed records kept broad status="active", so status-only downstream logic treated them as live.
  2. Run manifests and the mutable current projection could disagree when a previously closed role reappeared in search.
  3. expired_sid_redirect was being treated as strong enough to promote a role to withdrawn_confirmed, even though live pressure-testing showed it was only medium-confidence evidence.

What was pressure-tested

1. Status vs lifecycle semantics

Observed before the fix:

The important architectural conclusion was:

2. Manifest vs projection semantics

Observed before the fix:

That means:

3. Evidence quality of expired_sid_redirect

Live pressure-testing showed:

Conclusion:

Code changes made in this follow-up

Refresh selection now prefers lifecycle state

Changed in csj/run.py:

Reappearance in search now reopens current projections, including closed ones

Changed in csj/run.py:

This keeps the mutable current projection aligned with current search presence more reliably.

Tiering now prioritizes lifecycle state over broad active status

Changed in csj/tiering.py:

This prevents withdrawn records from remaining indefinitely hot / mutable purely because of the broad status field.

expired_sid_redirect no longer promotes to withdrawn_confirmed

Changed in csj/lifecycle.py:

Tests added/updated

The following regression expectations were locked in:

Remaining caveats

These are still true after the fix:

  1. The project still uses a two-layer model:
    • status = broad state
    • lifecycle_status = specific state

    That can work, but maintainers must remember that status="active" does not necessarily mean “currently live and healthy” unless lifecycle_status is also active.

  2. Run manifests remain stronger evidence than the mutable current projection for point-in-time questions.

  3. expired_sid_redirect is still operationally useful and may justify wording like “likely disappeared” in monitoring/reporting, but it should not be treated as archival confirmation.

Practical maintainer rule

Use this interpretation order when reasoning about a role:

  1. Manifest / reconstruction for point-in-time run membership questions
  2. lifecycle_status for specific lifecycle meaning
  3. status only as a broad bucket, not a source of fine-grained truth

If those layers disagree, trust the more specific / more evidential one, not the broad convenience field.