Merge pull request #748 from AssetOverflow/codex/lived-life-surface

feat(workbench): Lived Life surface — the always-on heartbeat made felt
This commit is contained in:
Shay 2026-06-14 16:55:54 -07:00 committed by GitHub
commit 99a52746ae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 1321 additions and 10 deletions

1
.gitignore vendored
View file

@ -59,6 +59,7 @@ teaching/math_proposals/proposals.jsonl
engine_state/manifest.json
engine_state/recognizers.jsonl
engine_state/discovery_candidates.jsonl
engine_state/lived_life.json
# Private outreach / personal packet — never tracked
01_Anthropic/

View file

@ -36,14 +36,21 @@ the idle/heartbeat half.
from __future__ import annotations
import json
import time
from dataclasses import dataclass
from typing import Callable
from pathlib import Path
from typing import Any, Callable
from algebra.versor import versor_condition
from core.engine_identity import engine_identity_for_config
from engine_state import get_git_revision
# The name of the persisted lived-life artifact (one per always-on run) in the
# engine-state dir, read-only, for the workbench Lived Life surface.
LIVED_LIFE_FILENAME = "lived_life.json"
LIVED_LIFE_SCHEMA_VERSION = "lived_life_v1"
# The non-negotiable field invariant (CLAUDE.md). The heartbeat READS this as evidence;
# it never repairs to keep it true — closure is owned by ``algebra/versor.py``.
CLOSURE_CEILING = 1e-6
@ -88,6 +95,45 @@ class AlwaysOnReport:
return len(self.records)
def serialize_report(report: AlwaysOnReport) -> dict[str, Any]:
"""Deterministic, JSON-able projection of an always-on run — the persisted lived-life
evidence the workbench reads."""
return {
"schema_version": LIVED_LIFE_SCHEMA_VERSION,
"identity": report.identity,
"heartbeats": report.heartbeats,
"closure_ceiling": CLOSURE_CEILING,
"closure_observed": report.closure_observed,
"closure_held": report.closure_held,
"final_checkpoint_ok": report.final_checkpoint_ok,
"total_facts_consolidated": report.total_facts_consolidated,
"total_proposals_created": report.total_proposals_created,
"records": [
{
"tick": r.tick,
"versor_condition": r.versor_condition,
"field_valid": r.field_valid,
"facts_consolidated": r.facts_consolidated,
"proposals_created": r.proposals_created,
"pending_proposals": r.pending_proposals,
"did_work": r.did_work,
}
for r in report.records
],
}
def write_lived_life(report: AlwaysOnReport, path: Path) -> None:
"""Persist the lived-life evidence deterministically (sorted keys) so the workbench can
read it as a read-only artifact. Overwrites the artifact is the latest always-on run
(a cumulative whole-life log is a future enhancement)."""
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
json.dumps(serialize_report(report), indent=2, sort_keys=True) + "\n",
encoding="utf-8",
)
def _live_versor_condition(runtime) -> float | None:
"""Read the closure of the runtime's live field, or None if no turn built one yet.
@ -106,6 +152,7 @@ def run_continuous(
sleep_seconds: float = 0.0,
on_heartbeat: Callable[[HeartbeatRecord], None] | None = None,
stop: Callable[[], bool] | None = None,
report_path: Path | None = None,
) -> AlwaysOnReport:
"""Run the always-on heartbeat for up to ``heartbeats`` beats.
@ -118,6 +165,13 @@ def run_continuous(
Bounded for falsifiable soaks; a daemon passes a large ``heartbeats`` + a ``stop``
predicate (and a real ``sleep_seconds`` cadence). ``stop`` is checked BEFORE each
beat so a clean shutdown still persists the final state.
When ``report_path`` is given, the run's lived-life evidence is persisted there after
the loop exits point it at ``<engine_state>/lived_life.json`` so the workbench Lived
Life surface reads the continuous life. A clean ``stop`` still writes the full report
(the report captures everything accumulated up to the stop). On a crash the engine
state is still checkpointed in ``finally`` for recovery, but the workbench report is
best-effort and simply not refreshed the surface keeps the last good run.
"""
if heartbeats < 0:
raise ValueError("heartbeats must be >= 0")
@ -161,7 +215,7 @@ def run_continuous(
final_checkpoint_ok = False
observed = [r.versor_condition for r in records if r.versor_condition is not None]
return AlwaysOnReport(
report = AlwaysOnReport(
records=tuple(records),
identity=identity,
closure_observed=bool(observed),
@ -170,3 +224,6 @@ def run_continuous(
total_facts_consolidated=sum(r.facts_consolidated for r in records),
total_proposals_created=sum(r.proposals_created for r in records),
)
if report_path is not None:
write_lived_life(report, report_path)
return report

View file

@ -59,7 +59,7 @@ successful proof.
## 4. Current Route Map
The route registry in `workbench-ui/src/app/routes.ts` is the source of truth.
Current route count: 15.
Current route count: 16.
| Section | Route | Path | Shortcut | Purpose |
|---|---|---|---|---|
@ -71,6 +71,7 @@ Current route count: 15.
| Determinism | Demos | `/demos` | Palette | Run registered determinism demos. |
| Evidence | Proposals | `/proposals` | `⌘4` | Review cognition and math proposal evidence. |
| Evidence | Runs | `/runs` | `⌘6` | Browse recorded run/session evidence. |
| Evidence | Lived Life | `/lived-life` | Palette | Watch the always-on heartbeat hold one continuous life (closure read-not-repaired over uptime + learned-while-idle). |
| Evidence | Vault | `/vault` | `⌘8` | Inspect persisted vault metadata when persistence exists. |
| Evidence | Audit | `/audit` | `⌘9` | Read deterministic audit events. |
| Discipline | Evals | `/evals` | `⌘5` | Run/read allowlisted eval lanes and wrong=0 ledgers. |
@ -93,6 +94,7 @@ the command palette.
| Demos | Registered demo scenarios pass or fail with recorded scenario evidence and proof/entailment DAGs where the demo emits them. |
| Proposals | Proposal evidence, replay facts, and ratification commands are inspectable without applying mutation. |
| Runs | Recorded run/session references, checkpoint gaps, and identity-continuity verdicts are discoverable. |
| Lived Life | A persisted always-on run shows the engine living + learning over uptime, with closure (`versor_condition < 1e-6`) read as evidence each beat (never repaired); the surface's `closure_held` is consistency-checked against the per-beat measurements, so it can never paint a breached field as valid. |
| Vault | Persisted vault metadata is inspectable when persistence is configured. |
| Audit | Audit events are readable with payload digests and mutation-boundary flags. |
| Evals | Allowlisted eval lanes and wrong/correct/refused metrics are visible. |

View file

@ -11,7 +11,9 @@ Wrong=0 / no-hot-path-repair are preserved by composition — the heartbeat only
from __future__ import annotations
from chat.always_on import CLOSURE_CEILING, run_continuous
import json
from chat.always_on import CLOSURE_CEILING, LIVED_LIFE_FILENAME, run_continuous
from chat.runtime import ChatRuntime, RuntimeConfig
from core.cognition.pipeline import CognitiveTurnPipeline
from generate.meaning_graph.reader import comprehend
@ -93,6 +95,30 @@ def test_life_survives_interruption_as_the_same_life(tmp_path) -> None:
assert "mortal" in _stored_members(resumed._context, "socrates")
def test_persisted_run_is_a_readable_lived_life_surface(tmp_path) -> None:
"""run_continuous(report_path=...) leaves the workbench a readable, validated surface —
the persist seam the Lived Life route reads (engine_state/lived_life.json)."""
from workbench.lived_life import lived_life_from_payload
state_dir = tmp_path / "engine_state"
runtime = ChatRuntime(config=_RESUME_CONFIG, engine_state_path=state_dir)
_seed_continuous_life(runtime)
report_path = state_dir / LIVED_LIFE_FILENAME
report = run_continuous(runtime, heartbeats=4, report_path=report_path)
# The artifact exists where the workbench reads it, and round-trips through the
# read-model honesty gate (closure_held / totals consistent with the per-beat bytes).
assert report_path.exists()
raw = json.loads(report_path.read_text(encoding="utf-8"))
surface = lived_life_from_payload(raw)
assert surface.status == "recorded"
assert surface.heartbeats == report.heartbeats == 4
assert surface.closure_observed and surface.closure_held
assert surface.total_facts_consolidated == report.total_facts_consolidated >= 1
assert surface.converged is True # the saturated life is at rest by the final beat
def test_heartbeat_never_repairs_closure(tmp_path) -> None:
"""The heartbeat READS versor_condition as evidence; it must never repair the field.
A no-op idle life (nothing to learn) keeps closure stable without any mutation."""

View file

@ -0,0 +1,239 @@
"""Lived Life surface — the read-only projection of a persisted always-on run.
These prove the surface is HONEST BY CONSTRUCTION: an absent artifact is honest absence,
a recorded artifact projects faithfully, and a TAMPERED artifact (a beat that lies about
its closure, an inflated aggregate, a miscounted total) makes ``validate`` raise rather
than render a false continuity claim. That fail-loud-on-tamper property is the wrong=0
analogue for the continuity surface (CLAUDE.md Schema-Defined Proof Obligations): each
mutation below would silently pass if the gate were decoration.
"""
from __future__ import annotations
import pytest
from chat.always_on import (
AlwaysOnReport,
HeartbeatRecord,
serialize_report,
write_lived_life,
)
from workbench import readers
from workbench.lived_life import (
lived_life_from_payload,
missing_lived_life,
validate,
)
from workbench.schemas import LivedLife, LivedLifeHeartbeat
def _report() -> AlwaysOnReport:
"""A representative life: closure observed + held, learns on beat 0, at rest on beat 1."""
records = (
HeartbeatRecord(
tick=0,
versor_condition=8.2e-13,
field_valid=True,
facts_consolidated=1,
proposals_created=0,
pending_proposals=0,
did_work=True,
),
HeartbeatRecord(
tick=1,
versor_condition=8.2e-13,
field_valid=True,
facts_consolidated=0,
proposals_created=0,
pending_proposals=0,
did_work=False,
),
)
return AlwaysOnReport(
records=records,
identity="sha256:lived-life-test",
closure_observed=True,
closure_held=True,
final_checkpoint_ok=True,
total_facts_consolidated=1,
total_proposals_created=0,
)
def test_missing_artifact_is_honest_absence() -> None:
surface = missing_lived_life("no always-on run has been persisted yet")
assert surface.status == "missing_evidence"
assert surface.identity is None
assert surface.heartbeats == 0
# An absent life claims nothing.
assert surface.closure_observed is False and surface.closure_held is False
assert surface.records == []
def test_recorded_artifact_projects_faithfully() -> None:
surface = lived_life_from_payload(serialize_report(_report()))
assert surface.status == "recorded"
assert surface.identity == "sha256:lived-life-test"
assert surface.heartbeats == 2
assert surface.closure_observed and surface.closure_held
assert surface.total_facts_consolidated == 1
# CONVERGED is derived from the records (final beat at rest), not trusted from bytes.
assert surface.converged is True
assert [b.tick for b in surface.records] == [0, 1]
# No current identity supplied -> the resume verdict is honestly unknown.
assert surface.resume_status == "unknown"
def test_resume_verdict_tracks_identity_vs_substrate() -> None:
payload = serialize_report(_report()) # identity == "sha256:lived-life-test"
# Matching substrate identity -> a reboot resumes THIS life.
same = lived_life_from_payload(payload, current_identity="sha256:lived-life-test")
assert same.resume_status == "would_resume"
assert "resumes this life" in same.resume_summary
# Changed substrate identity -> a reboot would refuse (IdentityContinuityError).
changed = lived_life_from_payload(payload, current_identity="sha256:other")
assert changed.resume_status == "substrate_changed"
assert "refuse" in changed.resume_summary
# No recomputable substrate identity -> honest unknown.
unknown = lived_life_from_payload(payload, current_identity=None)
assert unknown.resume_status == "unknown"
def test_reader_reads_persisted_artifact(tmp_path, monkeypatch) -> None:
state_dir = tmp_path / "engine_state"
state_dir.mkdir()
write_lived_life(_report(), state_dir / "lived_life.json")
monkeypatch.setattr(readers, "ENGINE_STATE_ROOT", state_dir)
surface = readers.lived_life()
assert surface.status == "recorded"
assert surface.closure_held and surface.converged
# The surface links to the raw artifact for provenance.
assert surface.artifact is not None
assert surface.artifact.kind == "lived_life"
def test_reader_absent_artifact(tmp_path, monkeypatch) -> None:
monkeypatch.setattr(readers, "ENGINE_STATE_ROOT", tmp_path / "engine_state")
surface = readers.lived_life()
assert surface.status == "missing_evidence"
def test_unrecognized_schema_is_absence_not_error() -> None:
payload = serialize_report(_report())
payload["schema_version"] = "lived_life_v999"
surface = lived_life_from_payload(payload)
assert surface.status == "missing_evidence"
assert "schema_version" in (surface.missing_reason or "")
# --- Non-vacuous tamper rejections: each mutation MUST make validate raise. ---
def test_tamper_field_valid_lies_about_breach_is_rejected() -> None:
payload = serialize_report(_report())
# A beat breaches the ceiling but still claims a valid field.
payload["records"][0]["versor_condition"] = 5e-3
payload["records"][0]["field_valid"] = True
with pytest.raises(ValueError, match="field_valid"):
lived_life_from_payload(payload)
def test_tamper_inflated_closure_held_is_rejected() -> None:
payload = serialize_report(_report())
# An honest beat breaches the ceiling, but the aggregate lies that closure held.
payload["records"][0]["versor_condition"] = 5e-3
payload["records"][0]["field_valid"] = False
payload["closure_held"] = True
with pytest.raises(ValueError, match="closure_held"):
lived_life_from_payload(payload)
def test_tamper_closure_observed_is_rejected() -> None:
payload = serialize_report(_report())
# No beat observed a field, but the surface claims one did.
for rec in payload["records"]:
rec["versor_condition"] = None
rec["field_valid"] = True
payload["closure_observed"] = True
payload["closure_held"] = True
with pytest.raises(ValueError, match="closure_observed"):
lived_life_from_payload(payload)
def test_tamper_miscounted_total_is_rejected() -> None:
payload = serialize_report(_report())
payload["total_facts_consolidated"] = 99 # records sum to 1
with pytest.raises(ValueError, match="total_facts_consolidated"):
lived_life_from_payload(payload)
def test_tamper_converged_mismatch_is_rejected() -> None:
# Direct construction: a recorded surface whose `converged` contradicts the final beat.
beats = [
LivedLifeHeartbeat(
tick=0,
versor_condition=8.2e-13,
field_valid=True,
facts_consolidated=0,
proposals_created=0,
pending_proposals=0,
did_work=True, # final beat still working -> NOT converged
)
]
surface = LivedLife(
schema_version="lived_life_v1",
status="recorded",
missing_reason=None,
identity="sha256:x",
heartbeats=1,
closure_observed=True,
closure_held=True,
closure_ceiling=1e-6,
final_checkpoint_ok=True,
converged=True, # lies: the final beat did work
total_facts_consolidated=0,
total_proposals_created=0,
current_identity="sha256:x",
resume_status="would_resume",
resume_summary="a reboot resumes this life — its identity matches the current substrate",
records=beats,
)
with pytest.raises(ValueError, match="converged"):
validate(surface)
def test_tamper_resume_status_mismatch_is_rejected() -> None:
# Direct construction: a surface that claims "would_resume" while the persisted identity
# differs from the current substrate identity — a reboot would actually refuse.
surface = LivedLife(
schema_version="lived_life_v1",
status="recorded",
missing_reason=None,
identity="sha256:persisted",
heartbeats=0,
closure_observed=False,
closure_held=True, # vacuously true with no observed field (passes the closure gate)
closure_ceiling=1e-6,
final_checkpoint_ok=True,
converged=False,
total_facts_consolidated=0,
total_proposals_created=0,
current_identity="sha256:current-DIFFERENT",
resume_status="would_resume", # lies: identities differ -> substrate_changed
resume_summary="a reboot resumes this life — its identity matches the current substrate",
records=[],
)
with pytest.raises(ValueError, match="resume_status"):
validate(surface)
def test_persist_is_deterministic() -> None:
report = _report()
once = serialize_report(report)
twice = serialize_report(report)
assert once == twice
# And the written bytes are stable (sorted keys), so the artifact is replay-citable.
import json
assert json.dumps(once, sort_keys=True) == json.dumps(twice, sort_keys=True)

View file

@ -237,6 +237,34 @@
"source_digest",
"calibration_evidence_ref"
],
"LivedLife": [
"schema_version",
"status",
"missing_reason",
"identity",
"heartbeats",
"closure_observed",
"closure_held",
"closure_ceiling",
"final_checkpoint_ok",
"converged",
"total_facts_consolidated",
"total_proposals_created",
"current_identity",
"resume_status",
"resume_summary",
"records",
"artifact"
],
"LivedLifeHeartbeat": [
"tick",
"versor_condition",
"field_valid",
"facts_consolidated",
"proposals_created",
"pending_proposals",
"did_work"
],
"LogosAlignmentRow": [
"edge_id",
"source_id",

View file

@ -30,6 +30,7 @@ import type {
FieldEvidence,
EvidenceBundle,
DeterminismTour,
LivedLife,
TurnJournalEntry,
TurnJournalSummary,
ContemplationRunDetail,
@ -210,6 +211,10 @@ export async function fetchTour(): Promise<DeterminismTour> {
return apiFetch<DeterminismTour>("/tour");
}
export async function fetchLivedLife(): Promise<LivedLife> {
return apiFetch<LivedLife>("/lived-life");
}
export async function fetchAuditEvents(
limit?: number,
offset?: number,

View file

@ -34,6 +34,7 @@ import {
fetchTraceField,
fetchTraceBundle,
fetchTour,
fetchLivedLife,
fetchTraceTurns,
fetchContemplationRun,
fetchContemplationRuns,
@ -71,6 +72,7 @@ import type {
FieldEvidence,
EvidenceBundle,
DeterminismTour,
LivedLife,
TurnJournalEntry,
TurnJournalSummary,
EvalLaneSummary,
@ -255,6 +257,16 @@ export function useTour() {
});
}
export function useLivedLife() {
return useQuery<LivedLife, WorkbenchApiError>({
queryKey: ["api", "lived-life"],
queryFn: fetchLivedLife,
// The life advances over uptime — keep it fresh without hammering.
refetchInterval: 30_000,
refetchOnWindowFocus: false,
});
}
export function useAuditEvents(limit?: number, offset?: number) {
return useQuery<{ items: AuditEvent[] }, WorkbenchApiError>({
queryKey: ["api", "audit", "events", limit ?? null, offset ?? null],

View file

@ -37,6 +37,11 @@ const ProposalsRoute = lazy(() =>
const RunsRoute = lazy(() =>
import("./runs/RunsRoute").then((module) => ({ default: module.RunsRoute })),
);
const LivedLifeRoute = lazy(() =>
import("./lived-life/LivedLifeRoute").then((module) => ({
default: module.LivedLifeRoute,
})),
);
const VaultRoute = lazy(() =>
import("./vault/VaultRoute").then((module) => ({ default: module.VaultRoute })),
);
@ -87,6 +92,7 @@ export const ROUTE_ELEMENTS: RouteElementMap = {
demos: lazyRoute(<DemoTheaterRoute />),
proposals: lazyRoute(<ProposalsRoute />),
runs: lazyRoute(<RunsRoute />),
"lived-life": lazyRoute(<LivedLifeRoute />),
vault: lazyRoute(<VaultRoute />),
audit: lazyRoute(<AuditRoute />),
evals: lazyRoute(<EvalsRoute />),

View file

@ -85,11 +85,11 @@ describe("Shell", () => {
expect(document.querySelector('[data-density="compact"]')).toBeInTheDocument();
});
it("LeftNav has exactly 15 items in section-grouped order", () => {
it("LeftNav has exactly 16 items in section-grouped order", () => {
renderShell();
const nav = document.querySelector('[data-region="leftnav"]')!;
const links = nav.querySelectorAll("a");
expect(links).toHaveLength(15);
expect(links).toHaveLength(16);
const labels = Array.from(links).map((l) => l.textContent);
// Grouped by section (Converse → Cognition → Determinism → Evidence →
// Discipline → Substrate → Settings), derived from the route registry.
@ -102,6 +102,7 @@ describe("Shell", () => {
"Demos",
"Proposals",
"Runs",
"Lived Life",
"Vault",
"Audit",
"Evals",

View file

@ -0,0 +1,198 @@
import { render, screen } from "@testing-library/react";
import { QueryClientProvider } from "@tanstack/react-query";
import { MemoryRouter } from "react-router-dom";
import { afterEach, describe, expect, it, vi } from "vitest";
import { createTestQueryClient } from "../../test/createTestQueryClient";
import { LivedLifeRoute, LIVED_LIFE_ABSENCE_STATEMENT } from "./LivedLifeRoute";
import type { LivedLife } from "../../types/api";
/**
* The Lived Life surface must render the continuous life HONESTLY: it shows the
* heartbeat-over-uptime facts when a life is recorded, and it can NEVER paint a
* breached field as valid. These assert the rendered content, not just that the
* route mounts (the frontend analogue of the backend's non-vacuous tamper tests).
*/
const GENERATED_AT = "2026-06-14T00:00:00Z";
function stubFetch(life: LivedLife) {
vi.stubGlobal(
"fetch",
vi.fn(() =>
Promise.resolve({
json: async () => ({ ok: true, generated_at: GENERATED_AT, data: life }),
}),
),
);
}
function renderRoute() {
return render(
<QueryClientProvider client={createTestQueryClient()}>
<MemoryRouter initialEntries={["/lived-life"]}>
<LivedLifeRoute />
</MemoryRouter>
</QueryClientProvider>,
);
}
const HEALTHY: LivedLife = {
schema_version: "lived_life_v1",
status: "recorded",
missing_reason: null,
identity: "sha256:abcdef0123456789",
heartbeats: 3,
closure_observed: true,
closure_held: true,
closure_ceiling: 1e-6,
final_checkpoint_ok: true,
converged: true,
total_facts_consolidated: 2,
total_proposals_created: 0,
current_identity: "sha256:abcdef0123456789", // matches identity -> would_resume
resume_status: "would_resume",
resume_summary:
"a reboot resumes this life — its identity matches the current substrate",
records: [
{
tick: 0,
versor_condition: 8.2e-13,
field_valid: true,
facts_consolidated: 2,
proposals_created: 0,
pending_proposals: 0,
did_work: true,
},
{
tick: 1,
versor_condition: 8.2e-13,
field_valid: true,
facts_consolidated: 0,
proposals_created: 0,
pending_proposals: 0,
did_work: false,
},
{
tick: 2,
versor_condition: 8.2e-13,
field_valid: true,
facts_consolidated: 0,
proposals_created: 0,
pending_proposals: 0,
did_work: false,
},
],
artifact: {
artifact_id: "engine_state/lived_life.json",
kind: "lived_life",
path: "engine_state/lived_life.json",
digest: "sha256:deadbeefcafe",
created_at: null,
},
};
afterEach(() => {
vi.unstubAllGlobals();
});
describe("LivedLifeRoute", () => {
it("renders the continuous life: heartbeats, closure held, learned-while-idle, beats", async () => {
stubFetch(HEALTHY);
renderRoute();
expect(await screen.findByText("One continuous life")).toBeInTheDocument();
// Learned while idle (non-zero, from the records).
expect(screen.getByText("2 learned while idle")).toBeInTheDocument();
// Closure held below the ceiling (never claimed without observation).
expect(screen.getAllByText(/closure held/i).length).toBeGreaterThan(0);
// The heartbeat over uptime: each beat is shown.
expect(screen.getByText("beat 0")).toBeInTheDocument();
expect(screen.getByText("beat 2")).toBeInTheDocument();
// A saturated life is at rest.
expect(screen.getAllByText(/at rest/i).length).toBeGreaterThan(0);
// The resume-as-same-life verdict is made felt: this life wakes up as itself.
expect(screen.getByText(/resumes as same life/i)).toBeInTheDocument();
expect(
screen.getByText(/its identity matches the current substrate/i),
).toBeInTheDocument();
// The per-reboot lineage chain is honestly cross-linked to Runs.
expect(screen.getByRole("link", { name: /Runs/ })).toBeInTheDocument();
});
it("a breached beat surfaces the closure warning, never a false 'held'", async () => {
const breached: LivedLife = {
...HEALTHY,
heartbeats: 1,
closure_held: false,
converged: true,
records: [
{
tick: 0,
versor_condition: 5e-3, // breaches the 1e-6 ceiling
field_valid: false,
facts_consolidated: 0,
proposals_created: 0,
pending_proposals: 0,
did_work: false,
},
],
};
stubFetch(breached);
renderRoute();
expect(await screen.findByText(/closure BREACHED/i)).toBeInTheDocument();
// The breached beat is marked INVALID, never painted valid.
expect(screen.getByText("INVALID")).toBeInTheDocument();
expect(screen.queryByText(/closure held/i)).not.toBeInTheDocument();
});
it("a changed substrate surfaces the would-refuse warning, never a false resume", async () => {
const changed: LivedLife = {
...HEALTHY,
current_identity: "sha256:0000different0000",
resume_status: "substrate_changed",
resume_summary:
"the substrate changed — a reboot would refuse (IdentityContinuityError)",
};
stubFetch(changed);
renderRoute();
expect(
(await screen.findAllByText(/substrate changed/i)).length,
).toBeGreaterThan(0);
expect(
screen.getByText(/a reboot would refuse/i),
).toBeInTheDocument();
expect(screen.queryByText(/resumes as same life/i)).not.toBeInTheDocument();
});
it("an absent artifact shows honest absence, never a fabricated life", async () => {
const absent: LivedLife = {
...HEALTHY,
status: "missing_evidence",
missing_reason: "no always-on run has been persisted yet",
identity: null,
heartbeats: 0,
closure_observed: false,
closure_held: false,
converged: false,
total_facts_consolidated: 0,
total_proposals_created: 0,
current_identity: null,
resume_status: "unknown",
resume_summary:
"resume verdict unavailable — the current substrate identity could not be recomputed",
records: [],
artifact: null,
};
stubFetch(absent);
renderRoute();
expect(
await screen.findByText(LIVED_LIFE_ABSENCE_STATEMENT),
).toBeInTheDocument();
// No fabricated heartbeat content.
expect(screen.queryByText("One continuous life")).not.toBeInTheDocument();
expect(screen.queryByText("beat 0")).not.toBeInTheDocument();
});
});

View file

@ -0,0 +1,365 @@
import { useState, type ReactNode } from "react";
import { Activity, HeartPulse } from "lucide-react";
import { Link } from "react-router-dom";
import { WorkbenchApiError } from "../../api/client";
import { useLivedLife } from "../../api/queries";
import { DigestBadge } from "../../design/components/DigestBadge/DigestBadge";
import { MetadataTable } from "../../design/components/MetadataTable/MetadataTable";
import { Panel } from "../../design/components/Panel/Panel";
import { StableJsonViewer } from "../../design/components/StableJsonViewer";
import { Button } from "../../design/components/primitives/Button";
import { EmptyState } from "../../design/components/states/EmptyState";
import { ErrorState } from "../../design/components/states/ErrorState";
import { LoadingState } from "../../design/components/states/LoadingState";
import type { LivedLife, LivedLifeHeartbeat } from "../../types/api";
// Conformance contract strings (ADR-0162 §6) — kept verbatim in
// routeConformance.test.tsx; the absence state IS the primary state until an
// always-on run lands an artifact (fail-closed, like Vault/Calibration).
export const LIVED_LIFE_LOADING = "Loading lived life...";
export const LIVED_LIFE_ABSENCE_STATEMENT =
"No always-on run recorded yet. The continuous-life heartbeat persists its evidence here when it runs.";
export const LIVED_LIFE_ABSENCE_ACTION =
"Run the always-on heartbeat to persist engine_state/lived_life.json";
function errorMessage(error: unknown): string {
return error instanceof WorkbenchApiError
? error.message
: "Lived-life request failed.";
}
function digestPayload(value: string | null | undefined): string | null {
if (!value) return null;
return value.replace(/^sha256:/, "");
}
function closureDisplay(versorCondition: number | null): string {
return typeof versorCondition === "number"
? versorCondition.toExponential(3)
: "no field yet";
}
/** A small status pill. `tone` maps to a state color token. */
function Pill({
tone,
children,
}: {
tone: "verified" | "warning" | "muted";
children: ReactNode;
}) {
const color =
tone === "verified"
? "var(--color-state-verified)"
: tone === "warning"
? "var(--color-state-warning-text)"
: "var(--color-text-secondary)";
return (
<span
className="inline-flex h-6 items-center gap-1 rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface-inset)] px-2 text-xs"
style={{ color }}
>
{children}
</span>
);
}
/** The headline: one continuous life, stated as falsifiable facts. */
function LifeHeadline({ life }: { life: LivedLife }) {
const closureTone = life.closure_held ? "verified" : "warning";
return (
<Panel
title="One continuous life"
toolbar={
<span className="inline-flex items-center gap-1 text-[var(--color-text-muted)]">
<HeartPulse size={14} aria-hidden />
<span className="text-xs">always-on heartbeat</span>
</span>
}
>
<div className="grid gap-3">
<p className="m-0 text-sm text-[var(--color-text-secondary)] [text-wrap:balance]">
CORE held itself alive over {life.heartbeats}{" "}
{life.heartbeats === 1 ? "heartbeat" : "heartbeats"} with no user turn,
learned while idle, and kept its field valid by construction the
heartbeat READS closure as evidence, it never repairs it.
</p>
<div className="flex flex-wrap gap-2">
<Pill tone="muted">
{life.heartbeats}{" "}
{life.heartbeats === 1 ? "heartbeat" : "heartbeats"}
</Pill>
<Pill tone={closureTone}>
{life.closure_observed
? life.closure_held
? `closure held < ${life.closure_ceiling.toExponential(0)}`
: "closure BREACHED"
: "no field observed"}
</Pill>
<Pill tone={life.total_facts_consolidated > 0 ? "verified" : "muted"}>
{life.total_facts_consolidated} learned while idle
</Pill>
{life.total_proposals_created > 0 ? (
<Pill tone="muted">
{life.total_proposals_created} proposals (reviewable)
</Pill>
) : null}
<Pill tone={life.converged ? "verified" : "muted"}>
{life.converged ? "at rest" : "still churning"}
</Pill>
<Pill tone={resumeTone(life.resume_status)}>
{life.resume_status === "would_resume"
? "resumes as same life"
: life.resume_status === "substrate_changed"
? "substrate changed"
: "resume unknown"}
</Pill>
</div>
</div>
</Panel>
);
}
function resumeTone(
status: LivedLife["resume_status"],
): "verified" | "warning" | "muted" {
if (status === "would_resume") return "verified";
if (status === "substrate_changed") return "warning";
return "muted";
}
function LifeSummary({ life }: { life: LivedLife }) {
const identity = digestPayload(life.identity);
const current = digestPayload(life.current_identity);
const artifact = digestPayload(life.artifact?.digest);
return (
<MetadataTable
rows={[
{
key: "identity",
value: identity ? (
<DigestBadge digest={identity} truncate={16} />
) : (
<span className="text-[var(--color-text-muted)]">not recorded</span>
),
},
{ key: "heartbeats", value: String(life.heartbeats), mono: true },
{
key: "closure_observed",
value: life.closure_observed ? "yes" : "no field this run",
mono: true,
},
{
key: "closure_held",
value: life.closure_held
? `held (< ${life.closure_ceiling.toExponential(0)})`
: "BREACHED",
mono: true,
},
{
key: "facts_consolidated",
value: String(life.total_facts_consolidated),
mono: true,
},
{
key: "proposals_created",
value: String(life.total_proposals_created),
mono: true,
},
{
key: "converged",
value: life.converged ? "yes (final beat at rest)" : "no (still working)",
mono: true,
},
{
key: "final_checkpoint_ok",
value: life.final_checkpoint_ok ? "yes" : "FAILED",
mono: true,
},
{
key: "current_identity",
value: current ? (
<DigestBadge digest={current} truncate={16} />
) : (
<span className="text-[var(--color-text-muted)]">not recomputed</span>
),
},
{
key: "artifact",
value: artifact ? (
<DigestBadge digest={artifact} truncate={12} />
) : (
<span className="text-[var(--color-text-muted)]">not linked</span>
),
},
]}
/>
);
}
function HeartbeatRow({ beat }: { beat: LivedLifeHeartbeat }) {
const valid = beat.field_valid;
return (
<div className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 border-b border-[var(--color-border-subtle)] px-3 py-2 last:border-b-0">
<span className="font-mono text-xs text-[var(--color-text-muted)]">
beat {beat.tick}
</span>
<span className="flex items-center gap-2 text-xs">
<span
className="font-mono"
style={{
color: valid
? "var(--color-state-verified)"
: "var(--color-state-warning-text)",
}}
title="versor_condition (field closure) — read, never repaired"
>
{closureDisplay(beat.versor_condition)}
</span>
<span className="text-[var(--color-text-muted)]">
{valid ? "valid" : "INVALID"}
</span>
</span>
<span className="justify-self-end text-xs text-[var(--color-text-secondary)]">
{beat.did_work ? (
<span className="inline-flex items-center gap-1">
<Activity size={12} aria-hidden />
{beat.facts_consolidated > 0
? `+${beat.facts_consolidated} fact${beat.facts_consolidated === 1 ? "" : "s"}`
: null}
{beat.proposals_created > 0
? ` +${beat.proposals_created} prop${beat.proposals_created === 1 ? "" : "s"}`
: null}
{beat.facts_consolidated === 0 && beat.proposals_created === 0
? "working"
: null}
</span>
) : (
<span className="text-[var(--color-text-muted)]">at rest</span>
)}
</span>
</div>
);
}
function HeartbeatTimeline({ life }: { life: LivedLife }) {
if (life.records.length === 0) {
return (
<p className="m-0 text-sm text-[var(--color-text-secondary)]">
This run recorded no heartbeats.
</p>
);
}
return (
<div className="grid gap-3">
<p className="m-0 text-xs text-[var(--color-text-muted)]">
Each beat advances continuous learning, then reads the field's closure
(<span className="font-mono">versor_condition</span>) as evidence. Closure
stays flat below the ceiling across the life the engine never patches the
field to keep it valid.
</p>
<div className="rounded-md border border-[var(--color-border-subtle)]">
{life.records.map((beat) => (
<HeartbeatRow key={beat.tick} beat={beat} />
))}
</div>
</div>
);
}
function ResumeVerdict({ life }: { life: LivedLife }) {
const tone = resumeTone(life.resume_status);
const color =
tone === "verified"
? "var(--color-state-verified)"
: tone === "warning"
? "var(--color-state-warning-text)"
: "var(--color-text-muted)";
return (
<div
className="grid gap-1 border-l-2 pl-3"
style={{ borderColor: color }}
>
<p className="m-0 text-sm" style={{ color }}>
{life.resume_summary}
</p>
<p className="m-0 text-xs text-[var(--color-text-secondary)] [text-wrap:balance]">
This is the resume guarantee made felt: a reboot recomputes the engine
identity and refuses if it differs from the persisted one, so this life
wakes up as <em>itself</em>, not a copy. The per-reboot lineage chain
lives under{" "}
<Link
to="/runs"
className="text-[var(--color-text-primary)] underline underline-offset-2"
>
Runs Identity
</Link>
.
</p>
</div>
);
}
function RawJson({ life }: { life: LivedLife }) {
const [expanded, setExpanded] = useState(false);
return expanded ? (
<StableJsonViewer source={JSON.stringify(life, null, 2)} />
) : (
<div className="grid justify-items-start gap-2">
<p className="m-0 text-sm text-[var(--color-text-secondary)]">
Raw lived-life JSON is collapsed by default.
</p>
<Button type="button" variant="quiet" onClick={() => setExpanded(true)}>
Expand raw JSON
</Button>
</div>
);
}
export function LivedLifeRoute() {
const query = useLivedLife();
if (query.isLoading) {
return <LoadingState label={LIVED_LIFE_LOADING} />;
}
if (query.isError) {
return (
<ErrorState
whatFailed={errorMessage(query.error)}
mutationStatus="No lived-life mutation occurred."
reproducer="curl /lived-life"
retrySafety="Retry: safe"
/>
);
}
const life = query.data;
if (!life || life.status !== "recorded") {
return (
<EmptyState
statement={LIVED_LIFE_ABSENCE_STATEMENT}
nextAction={LIVED_LIFE_ABSENCE_ACTION}
/>
);
}
return (
<div className="h-full min-h-0 overflow-y-auto">
<div className="mx-auto grid max-w-3xl gap-4 p-1">
<LifeHeadline life={life} />
<Panel title="Life summary">
<div className="grid gap-4">
<LifeSummary life={life} />
<ResumeVerdict life={life} />
</div>
</Panel>
<Panel title="Heartbeat timeline">
<HeartbeatTimeline life={life} />
</Panel>
<Panel title="Raw">
<RawJson life={life} />
</Panel>
</div>
</div>
);
}

View file

@ -15,6 +15,12 @@ import { EvalsRoute } from "./evals/EvalsRoute";
import { ReplayRoute } from "./replay/ReplayRoute";
import { DemoTheaterRoute } from "./demos/DemoTheaterRoute";
import { RunsRoute } from "./runs/RunsRoute";
import {
LivedLifeRoute,
LIVED_LIFE_LOADING,
LIVED_LIFE_ABSENCE_STATEMENT,
LIVED_LIFE_ABSENCE_ACTION,
} from "./lived-life/LivedLifeRoute";
import { PacksRoute } from "./packs/PacksRoute";
import { LogosRoute } from "./logos/LogosRoute";
import { VaultRoute } from "./vault/VaultRoute";
@ -168,6 +174,17 @@ const MOUNT_ROUTES: MountRouteSpec[] = [
emptyStatement: "No runs recorded yet. Use Chat to create evidence.",
emptyCommand: "core chat",
},
{
name: "Lived Life",
element: <LivedLifeRoute />,
path: "/lived-life",
initialEntry: "/lived-life",
loadingLabel: LIVED_LIFE_LOADING,
// Fail-closed: until an always-on run persists an artifact, honest absence
// is the primary state (no fabricated life).
emptyStatement: LIVED_LIFE_ABSENCE_STATEMENT,
emptyCommand: LIVED_LIFE_ABSENCE_ACTION,
},
{
name: "Replay",
element: <ReplayRoute />,

View file

@ -170,6 +170,19 @@ export const WORKBENCH_ROUTES: readonly WorkbenchRoute[] = [
keyboardDigit: "6",
routeConformanceRequired: true,
},
{
id: "lived-life",
path: "/lived-life",
routePattern: "lived-life",
label: "Lived Life",
description: "Watch the always-on heartbeat hold one continuous life.",
section: "Evidence",
leftNavVisible: true,
commandPaletteVisible: true,
landingRouteAllowed: true,
keyboardDigit: null,
routeConformanceRequired: true,
},
{
id: "vault",
path: "/vault",

View file

@ -52,11 +52,11 @@ describe("CommandPalette keyboard contract", () => {
expect(screen.getByRole("button", { name: "Open Trace" })).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Open Replay" })).toBeInTheDocument();
// One Navigate command per palette-visible route (15), derived from the
// route registry — Demos, Calibration, Contemplation, Tour, and CORE-Logos
// are included (the prior hand-maintained list of 10 dropped them).
// One Navigate command per palette-visible route (16), derived from the
// route registry — Demos, Calibration, Contemplation, Tour, CORE-Logos, and
// Lived Life are included (the prior hand-maintained list of 10 dropped them).
const items = dialog.querySelectorAll('[role="option"]');
expect(items.length).toBe(15);
expect(items.length).toBe(16);
const lastIndex = items.length - 1;
// Initially first item (index 0) is focused — check aria-selected

View file

@ -114,6 +114,53 @@ export interface FieldEvidence {
transition_inner_product: number | null;
}
/**
* One beat of the continuous life (read-only telemetry mirrored from
* `chat.always_on.HeartbeatRecord`): the closure of the live field that beat
* (`versor_condition`, READ never repaired), whether it held the `< ceiling`
* invariant, and what the life learned that beat.
*/
export interface LivedLifeHeartbeat {
tick: number;
versor_condition: number | null;
field_valid: boolean;
facts_consolidated: number;
proposals_created: number;
pending_proposals: number;
did_work: boolean;
}
/**
* L10 lived-life surface evidence that CORE is ONE continuous life. A read-only
* projection of the persisted always-on run (`engine_state/lived_life.json`): the engine
* holds itself alive over uptime with no user turn, learns while idle (Step-D
* consolidation + proposal-only proposals), and holds closure BY CONSTRUCTION
* (`versor_condition` is READ as evidence each beat, never repaired). `closure_held` is
* consistency-checked against the per-beat measurements at construction (the wrong=0
* analogue for the continuity surface); `converged` is honest telemetry (a saturated life
* stops churning the final beat did no work); `identity` is the life's content identity
* (the "same life" thread, not a continuity proof that is owned by Runs).
*/
export interface LivedLife {
schema_version: "lived_life_v1";
status: PipelineEvidenceStatus;
missing_reason: string | null;
identity: string | null;
heartbeats: number;
closure_observed: boolean;
closure_held: boolean;
closure_ceiling: number;
final_checkpoint_ok: boolean;
converged: boolean;
total_facts_consolidated: number;
total_proposals_created: number;
current_identity: string | null;
resume_status: "would_resume" | "substrate_changed" | "unknown";
resume_summary: string;
records: LivedLifeHeartbeat[];
artifact: ArtifactRef | null;
}
/**
* D3 shareable evidence bundle a turn's deterministic evidence exported as one
* content-addressed, citable artifact. `bundle_digest` content-addresses the
@ -452,6 +499,7 @@ export type ArtifactKind =
| "contemplation_report"
| "telemetry"
| "engine_state_manifest"
| "lived_life"
| "unknown";
export type ContentType = "json" | "jsonl" | "text" | "unknown";

View file

@ -149,6 +149,8 @@ class WorkbenchApi:
return ApiResponse(200, ok({"status": "ok"}))
if method == "GET" and path == "/runtime/status":
return ApiResponse(200, ok(readers.runtime_status()))
if method == "GET" and path == "/lived-life":
return ApiResponse(200, ok(readers.lived_life()))
if method == "GET" and path == "/artifacts":
limit = int(query.get("limit", ["100"])[0])
return ApiResponse(200, ok({"items": readers.list_artifacts(limit=limit)}))

199
workbench/lived_life.py Normal file
View file

@ -0,0 +1,199 @@
"""L10 lived-life surface — read-only projection of the persisted always-on run.
The always-on heartbeat (``chat.always_on``) holds CORE alive over uptime and persists
its evidence to ``engine_state/lived_life.json`` (``write_lived_life``). This module
projects that artifact into the read-only :class:`~workbench.schemas.LivedLife` model the
workbench renders, and fail-closes: a ``recorded`` surface must be CONSISTENT with the
persisted per-beat measurements it can never claim the field stayed valid while a beat
breached the ``versor_condition`` ceiling (the wrong=0 analogue for the continuity
surface).
No engine math is re-implemented here. The scalars (``versor_condition``, the closure
ceiling, the learning counts) are exactly what ``chat.always_on`` measured and persisted;
this module only re-projects and re-checks them.
"""
from __future__ import annotations
from typing import Any, Literal
from chat.always_on import CLOSURE_CEILING, LIVED_LIFE_SCHEMA_VERSION
from workbench.schemas import ArtifactRef, LivedLife, LivedLifeHeartbeat
ResumeStatus = Literal["would_resume", "substrate_changed", "unknown"]
_RESUME_SUMMARY: dict[ResumeStatus, str] = {
"would_resume": "a reboot resumes this life — its identity matches the current substrate",
"substrate_changed": "the substrate changed — a reboot would refuse (IdentityContinuityError)",
"unknown": "resume verdict unavailable — the current substrate identity could not be recomputed",
}
def _resume_status(identity: str | None, current_identity: str | None) -> ResumeStatus:
"""The L11 reboot guarantee as a self-contained verdict: a reboot recomputes the engine
identity and refuses if it differs from the persisted one, so ``would_resume`` the
persisted life's identity equals the current substrate identity."""
if not identity or not current_identity:
return "unknown"
return "would_resume" if identity == current_identity else "substrate_changed"
def missing_lived_life(reason: str) -> LivedLife:
"""Honest absence — no always-on run has been persisted yet."""
return LivedLife(
schema_version="lived_life_v1",
status="missing_evidence",
missing_reason=reason,
identity=None,
heartbeats=0,
closure_observed=False,
closure_held=False,
closure_ceiling=CLOSURE_CEILING,
final_checkpoint_ok=False,
converged=False,
total_facts_consolidated=0,
total_proposals_created=0,
current_identity=None,
resume_status="unknown",
resume_summary=_RESUME_SUMMARY["unknown"],
records=[],
artifact=None,
)
def validate(record: LivedLife) -> None:
"""Fail-closed honesty gate for a recorded lived-life surface.
Every claim the surface makes must agree EXACTLY with the per-beat measurements it is
built from, so the continuity card can never overstate the life:
* each beat's ``field_valid`` agrees with ``versor_condition (None or < ceiling)``;
* ``closure_observed`` agrees with "some beat observed a field";
* ``closure_held`` agrees with "every OBSERVED versor_condition < ceiling";
* ``heartbeats`` and the learning totals agree with the records;
* ``converged`` agrees with "records exist and the final beat did no work".
This is the wrong=0 analogue for the continuity surface: a tampered artifact (a beat
whose ``field_valid`` lies about a breached ceiling, an inflated ``closure_held``, a
miscounted total) makes ``validate`` raise rather than render a false claim.
"""
if record.status != "recorded":
return
for beat in record.records:
expected_valid = (
beat.versor_condition is None
or beat.versor_condition < record.closure_ceiling
)
if beat.field_valid != expected_valid:
raise ValueError(
f"lived-life beat {beat.tick}: field_valid={beat.field_valid} disagrees "
f"with versor_condition vs ceiling "
f"({beat.versor_condition} / {record.closure_ceiling:.3e})"
)
observed = [
b.versor_condition for b in record.records if b.versor_condition is not None
]
if record.closure_observed != bool(observed):
raise ValueError(
"lived-life closure_observed disagrees with the per-beat measurements"
)
if record.closure_held != all(vc < record.closure_ceiling for vc in observed):
raise ValueError(
"lived-life closure_held disagrees with the per-beat measurements"
)
if record.heartbeats != len(record.records):
raise ValueError("lived-life heartbeats disagrees with the record count")
if record.total_facts_consolidated != sum(
b.facts_consolidated for b in record.records
):
raise ValueError(
"lived-life total_facts_consolidated disagrees with the records"
)
if record.total_proposals_created != sum(
b.proposals_created for b in record.records
):
raise ValueError(
"lived-life total_proposals_created disagrees with the records"
)
expected_converged = bool(record.records) and not record.records[-1].did_work
if record.converged != expected_converged:
raise ValueError("lived-life converged disagrees with the final beat")
expected_resume = _resume_status(record.identity, record.current_identity)
if record.resume_status != expected_resume:
raise ValueError(
"lived-life resume_status disagrees with identity vs current_identity"
)
if record.resume_summary != _RESUME_SUMMARY[record.resume_status]:
raise ValueError("lived-life resume_summary disagrees with resume_status")
def _coerce_heartbeat(raw: Any) -> LivedLifeHeartbeat:
if not isinstance(raw, dict):
raise ValueError("lived-life record must be an object")
versor_condition = raw.get("versor_condition")
return LivedLifeHeartbeat(
tick=int(raw["tick"]),
versor_condition=(
None if versor_condition is None else float(versor_condition)
),
field_valid=bool(raw["field_valid"]),
facts_consolidated=int(raw["facts_consolidated"]),
proposals_created=int(raw["proposals_created"]),
pending_proposals=int(raw["pending_proposals"]),
did_work=bool(raw["did_work"]),
)
def lived_life_from_payload(
raw: Any,
*,
artifact: ArtifactRef | None = None,
current_identity: str | None = None,
) -> LivedLife:
"""Project a persisted ``lived_life.json`` payload into the validated read model.
An unrecognized ``schema_version`` is honest absence (a forward/old artifact), not an
error. ``converged`` and ``resume_status`` are DERIVED here (not trusted from the
artifact) ``resume_status`` from the persisted ``identity`` vs the caller-supplied
``current_identity`` (the live substrate identity); ``validate`` then re-checks every
artifact-sourced claim against the records.
"""
if not isinstance(raw, dict):
raise ValueError("lived_life artifact must be an object")
if raw.get("schema_version") != LIVED_LIFE_SCHEMA_VERSION:
return missing_lived_life(
f"unrecognized lived_life schema_version: {raw.get('schema_version')!r}"
)
records = [_coerce_heartbeat(item) for item in raw.get("records", [])]
identity = str(raw["identity"]) if raw.get("identity") else None
resume_status = _resume_status(identity, current_identity)
record = LivedLife(
schema_version="lived_life_v1",
status="recorded",
missing_reason=None,
identity=identity,
heartbeats=int(raw.get("heartbeats", len(records))),
closure_observed=bool(raw["closure_observed"]),
closure_held=bool(raw["closure_held"]),
closure_ceiling=float(raw.get("closure_ceiling", CLOSURE_CEILING)),
final_checkpoint_ok=bool(raw["final_checkpoint_ok"]),
converged=bool(records) and not records[-1].did_work,
total_facts_consolidated=int(raw["total_facts_consolidated"]),
total_proposals_created=int(raw["total_proposals_created"]),
current_identity=current_identity,
resume_status=resume_status,
resume_summary=_RESUME_SUMMARY[resume_status],
records=records,
artifact=artifact,
)
validate(record)
return record

View file

@ -11,6 +11,7 @@ from dataclasses import dataclass
from pathlib import Path, PurePosixPath
from typing import Any, Callable, cast, get_args
from chat.always_on import LIVED_LIFE_FILENAME
from core.config import RuntimeConfig
from core.engine_identity import EngineIdentityError, engine_identity_for_config
from engine_state import EngineStateStore, get_git_revision
@ -35,6 +36,7 @@ from workbench.schemas import (
IdentityContinuity,
IdentityContinuityStatus,
IdentityLineageRelation,
LivedLife,
MathProposalDetail,
MathProposalSummary,
MathRatifyResult,
@ -50,6 +52,7 @@ from workbench.schemas import (
VaultEntry,
VaultSummary,
)
from workbench.lived_life import lived_life_from_payload, missing_lived_life
REPO_ROOT = Path(__file__).resolve().parents[1]
SAFE_EVAL_LANES = frozenset({"contemplation_quality"})
@ -326,6 +329,8 @@ def _artifact_kind(path: Path) -> str:
rel = _relative(path)
if rel == "engine_state/manifest.json":
return "engine_state_manifest"
if rel == f"engine_state/{LIVED_LIFE_FILENAME}":
return "lived_life"
if rel.startswith("teaching/proposals/"):
return "proposal"
if rel.startswith("evals/") and "/results/" in rel:
@ -1735,6 +1740,32 @@ def _identity_continuity_from_manifest(
)
def lived_life() -> LivedLife:
"""Read the persisted always-on run (``engine_state/lived_life.json``) as the L10
lived-life surface.
Honest absence (``missing_evidence``) when no always-on run has been persisted yet
the heartbeat (``chat.always_on.run_continuous`` + ``write_lived_life``) is what
produces the artifact; until a continuous-life run lands one, the surface says so
rather than fabricating a life."""
path = ENGINE_STATE_ROOT / LIVED_LIFE_FILENAME
if not path.exists():
return missing_lived_life("no always-on run has been persisted yet")
payload = _read_json_object(path)
artifact = _artifact_ref_for_path(path, "lived_life")
# The resume verdict: would a reboot resume THIS life? Recompute the current substrate
# identity with the canonical function (fail-soft -> "unknown", like IdentityContinuity).
try:
current_identity: str | None = engine_identity_for_config(
RuntimeConfig(), get_git_revision()
)
except EngineIdentityError:
current_identity = None
return lived_life_from_payload(
payload, artifact=artifact, current_identity=current_identity
)
def _journal_entries(journal: Any) -> list[Any]:
path = getattr(journal, "path", None)
if isinstance(path, Path) and path.exists():

View file

@ -173,6 +173,67 @@ class FieldEvidence:
transition_inner_product: float | None
@dataclass(frozen=True, slots=True)
class LivedLifeHeartbeat:
"""One beat of the continuous life (read-only telemetry).
Mirrors ``chat.always_on.HeartbeatRecord`` across the firewall: the closure of the
live field that beat (``versor_condition``, READ never repaired), whether it held the
``< ceiling`` invariant, and what the life learned that beat (Step-D facts +
proposal-only proposals)."""
tick: int
versor_condition: float | None
field_valid: bool
facts_consolidated: int
proposals_created: int
pending_proposals: int
did_work: bool
@dataclass(frozen=True, slots=True)
class LivedLife:
"""L10 lived-life surface — evidence that CORE is ONE continuous life.
A read-only projection of the persisted always-on run
(``chat.always_on.write_lived_life`` -> ``engine_state/lived_life.json``): the engine
holds itself alive over uptime with no user turn, learns while idle (Step-D
consolidation + proposal-only proposals), and holds closure BY CONSTRUCTION (the
heartbeat reads ``versor_condition`` as evidence, never repairs it).
``closure_held`` is consistency-checked at construction against the per-beat
measurements (``workbench.lived_life.validate``) the surface can NEVER claim the
field stayed valid while a beat breached the ceiling (the wrong=0 analogue for the
continuity surface). ``converged`` is honest telemetry: a saturated life stops
churning (the final beat did no work).
The two halves of "one continuous life" are both here: ``records`` are the lived
experience over uptime (T-experience), and ``resume_status`` is the resume guarantee
(T-resume) it compares the life's content ``identity`` to the ``current_identity``
recomputed from the live substrate. That is exactly the check the runtime load guard
makes on reboot (``would_resume`` a reboot resumes THIS life; ``substrate_changed``
it would raise ``IdentityContinuityError``). The per-run lineage chain stays owned by
Runs ``IdentityContinuity``; this is the self-contained substrate verdict."""
schema_version: Literal["lived_life_v1"]
status: PipelineEvidenceStatus
missing_reason: str | None
identity: str | None
heartbeats: int
closure_observed: bool
closure_held: bool
closure_ceiling: float
final_checkpoint_ok: bool
converged: bool
total_facts_consolidated: int
total_proposals_created: int
current_identity: str | None
resume_status: Literal["would_resume", "substrate_changed", "unknown"]
resume_summary: str
records: list[LivedLifeHeartbeat] = field(default_factory=list)
artifact: ArtifactRef | None = None
@dataclass(frozen=True, slots=True)
class EvidenceBundle:
"""D3 shareable evidence bundle — a turn's deterministic evidence, citable.