workbench(vault): give the evidence rail an honest vault-entry progression (#764)

Stop the rail reading as a wall of 'not applicable to vault entries':

- each dim stage now carries a specific honest reason (intent: a stored
  field has no originating user intent; authority: vault recall is
  read-only; action: no emission)
- replay lights on the recorded versor_digest exactly as a turn lights
  on its trace_hash — a content-addressable fingerprint, NOT a verified
  replay claim (honesty contract sanctioned)
- provenance/admissibility derivations enriched (versor_digest + metadata;
  epistemic_state / epistemic_status)

Fixed 7-stage spine and honesty contract preserved; labels unchanged.
Strengthened the meaningfully-fail test to cover replay + dim stages.
This commit is contained in:
Shay 2026-06-15 01:49:54 -07:00 committed by GitHub
parent 3e8f40b685
commit b1708a76d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 7 deletions

View file

@ -161,7 +161,7 @@ describe("EvidenceChainRail honesty contract", () => {
expect(statusOf(missingDeterminism, "provenance")).toBe("lit");
});
it("MEANINGFULLY FAILS vault_entry: removing versor_digest hollows exactly provenance", () => {
it("MEANINGFULLY FAILS vault_entry: versor_digest drives provenance+replay, epistemic_state drives admissibility", () => {
const full: EvidenceSubject = {
kind: "vault_entry",
entryIndex: 3,
@ -172,13 +172,19 @@ describe("EvidenceChainRail honesty contract", () => {
},
};
expect(statusOf(full, "provenance")).toBe("lit");
expect(statusOf(full, "replay")).toBe("lit");
expect(statusOf(full, "admissibility")).toBe("lit");
// A stored, read-only entry has no mutation authority and emits no action.
expect(statusOf(full, "authority")).toBe("dim");
expect(statusOf(full, "action")).toBe("dim");
const missingVersor: EvidenceSubject = {
...full,
data: { ...full.data, versor_digest: null },
};
// versor_digest drives BOTH provenance and replay; epistemic_state is independent.
expect(statusOf(missingVersor, "provenance")).toBe("hollow");
expect(statusOf(missingVersor, "replay")).toBe("hollow");
expect(statusOf(missingVersor, "admissibility")).toBe("lit");
});

View file

@ -272,15 +272,32 @@ export function deriveStages(subject: EvidenceSubject): RailStage[] | null {
];
}
case "vault_entry": {
// A persisted snapshot entry: subject -> provenance/metadata -> epistemic
// standing -> digest evidence. The dim stages each carry a specific,
// honest reason rather than a repeated "not applicable". replay lights on
// the recorded versor_digest exactly as a turn lights on its trace_hash —
// a recorded content fingerprint, NOT a verified-replay claim.
const d = subject.data;
return [
stage("intent", "dim", "not applicable to vault entries"),
stage("intent", "dim", "a stored field carries no originating user intent"),
stage("subject", "lit", "selected vault entry"),
stage("provenance", d ? evidenceOf(d.versor_digest) : "hollow", "versor_digest"),
stage("admissibility", d ? evidenceOf(d.epistemic_state) : "hollow", "epistemic_state"),
stage("replay", "dim", "not applicable to vault entries"),
stage("authority", "dim", "not applicable to vault entries"),
stage("action", "dim", "not applicable to vault entries"),
stage(
"provenance",
d ? evidenceOf(d.versor_digest) : "hollow",
"versor_digest (content fingerprint) + stored metadata",
),
stage(
"admissibility",
d ? evidenceOf(d.epistemic_state) : "hollow",
"epistemic_state / epistemic_status",
),
stage(
"replay",
d ? evidenceOf(d.versor_digest) : "hollow",
"versor digest recorded — content-addressable, not a verified replay",
),
stage("authority", "dim", "vault recall is read-only — no mutation authority"),
stage("action", "dim", "no action emitted by a stored entry"),
];
}
case "audit_event": {