Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,13 @@ confidently-negative signal are different things. Keyman extraction,
entity-relationship classification, post summary, in-popup chat, and
commitment derivation go through contextual-orchestrator the same way
adjudication does -- never a raw LLM API. Demo TEPP seed goes through
`tepp_client` the same way: a missing transport or an unused accepted
envelope is Failed (`tepp_not_available` / `tepp_result_not_persisted`),
never a fabricated theta or a local psychometric substitute.
`tepp_client` the same way: a missing transport is Failed
(`tepp_not_available`). A strict accepted v1 envelope persists to
`analysis_run_tepp_receipt` and the local run stays Running (ADR 0219);
an invalid or unpublished envelope is Failed
(`tepp_result_not_persisted`). Never a fabricated theta or a local
psychometric substitute. Automatic polling stays unavailable until TEPP
publishes its status route.

The lineage `text` channel follows [ADR 0190](docs/adr/0190-lineage-text-channel-embedding-swap.md):
when an embedding provider is configured, `reconstruct()` precomputes
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.d/2.29.0-tepp-accepted-seed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 2.29.0 — Seeded TEPP accepted receipt stays Running

After `make seed`, Demo Corp includes a Running TEPP measurement whose
strict accepted v1 receipt is transport evidence (ADR 0219). Open that
run: measurement request accepted — refresh to check whether results are
ready. The missing-transport TEPP row stays Failed / `tepp_not_available`.
Acceptance is not a calibrated result. Never invent a theta. No polling
until TEPP publishes its status route.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ All notable changes to this project are documented here. Format follows

### Added

- After `make seed`, Demo Corp now includes a Running TEPP measurement
whose strict accepted v1 receipt is transport evidence (ADR 0219 /
v2.29.0). Open that run: measurement request accepted — refresh to
check whether results are ready. The missing-transport TEPP row stays
Failed / `tepp_not_available`. Acceptance is not a calibrated result
and the UI does not expose the receipt's transport `run_id`. Never
invent a theta. No polling until TEPP publishes its status route.
Issue #277 stays open.

- Period leftover pairs now caption leftover-map graphic-display pair
segments with persisted leftover-map distance `d` (ADR 0271 /
v2.28.0). After `make seed`, closest and farthest leftover pairs sit
Expand Down
15 changes: 10 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,19 @@ sits on a public HTTP route.

## Analysis-run seed and run states (ADR 0013 / 0014 / 0024)

`make seed` writes a Demo Corp lineage run, a TEPP run, and a Succeeded
period-report run on one snapshot. The TEPP path goes through
`tepp_client`: a missing transport or an unused accepted envelope is
Failed (`tepp_not_available` / `tepp_result_not_persisted`). Never
invent a theta or a local psychometric substitute.
`make seed` writes a Demo Corp lineage run, a Failed TEPP run
(missing transport), a Running TEPP run with a persisted accepted
receipt, and a Succeeded period-report run on one snapshot. The TEPP
path goes through `tepp_client`: a missing transport is Failed
(`tepp_not_available`); a strict accepted v1 envelope persists as
transport evidence and stays Running (ADR 0219). An invalid envelope
is Failed (`tepp_result_not_persisted`). Never invent a theta or a
local psychometric substitute.

- Failed TEPP is terminal -- open that row and connect a live TEPP
transport from it.
- A Running TEPP with an accepted receipt is not a calibrated result --
refresh that run to check whether results are ready.
- A failed lineage row retries reconstruction and does not mention TEPP;
a failed period-report row rebuilds the report.
- Pending rows claim nothing: pending TEPP is not a calibrated
Expand Down
20 changes: 14 additions & 6 deletions backend/app/analysis_run_start.py
Comment thread
seonghobae marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,14 @@ def _tepp_submission(
client: TeppClient,
request: AnalysisRunRequest,
) -> tuple[str, str, dict[str, Any] | None]:
"""Submit through ``tepp_client`` and require a completed result envelope.

TEPP's target HTTP contract is asynchronous. An ``accepted`` response is
therefore not a measurement and remains ``tepp_result_not_persisted``.
Only a provider-authoritative completed envelope can enter the database.
"""Submit through ``tepp_client`` and classify the provider envelope.

TEPP's target HTTP contract is asynchronous. A strict accepted v1
response is transport evidence (ADR 0219), not a measurement: the
caller persists ``analysis_run_tepp_receipt`` and leaves the local
run Running. Only a provider-authoritative completed envelope can
enter ``analysis_run_tepp_result``. An invalid or unpublished shape
stays ``tepp_result_not_persisted``.
Comment thread
seonghobae marked this conversation as resolved.
"""
try:
response = client.submit_analysis_run(request)
Expand All @@ -271,12 +274,17 @@ def _tepp_submission(
return _FAILED, "tepp_result_not_persisted", None
if not isinstance(response, dict):
return _FAILED, "tepp_result_not_persisted", None
state = response.get("status") or response.get("run_state")
status = response.get("status")
run_state = response.get("run_state")
if status is not None and run_state is not None and status != run_state:
return _FAILED, "tepp_result_not_persisted", None
state = status or run_state
remote_run_id = response.get("analysis_run_id") or response.get("run_id")
if state == "accepted":
if (
set(response)
== {"contract_version", "run_id", "run_state", "idempotency_key"}
and type(response["contract_version"]) is int
and response["contract_version"] == 1
and response["idempotency_key"] == request.idempotency_key
and isinstance(remote_run_id, str)
Expand Down
6 changes: 5 additions & 1 deletion docs/adr/0219-tepp-terminal-result-lifecycle.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR 0219 — Persist TEPP acceptance and consume terminal results

**Decision status:** Accepted on this active PR; not protected-main truth until merge
**Decision status:** Accepted; seed visibility on this PR; polling remains blocked on TEPP #249
**Date:** 2026-08-26
**Depends on:** ADR 0022, ADR 0023, ADR 0204; TEPP PR #157
**Refs:** LineageWeave issue #277; TEPP issues #156 and #249
Expand Down Expand Up @@ -66,6 +66,10 @@ sequenceDiagram
LineageWeave owns transport and provenance persistence only. TEPP retains all
statistical, psychometric, CPU, and GPU arithmetic. Automatic polling remains
unavailable until the owning service publishes its route and retry policy.
`make seed` writes one Demo Corp TEPP run that stays Failed /
`tepp_not_available` (missing transport) and one that stays Running with a
persisted accepted receipt so the buyer copy is visible without inventing a
theta.

## References — APA 7th

Expand Down
2 changes: 1 addition & 1 deletion docs/doctoring/ANALYSIS_RUN_REGISTRY_REFERENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ provenance, retention, and immutable evidence rather than blanket masking.
| Idempotency is actor-scoped | Permit identical opaque keys for two accounts and reject reuse by the same account. |
| Lifecycle is ordered | Require pending first, contiguous ordinals, monotonic time, legal transitions, terminal finality, and append-only rows. |
| Rollback does not erase audit data silently | Reject 0018 rollback with any registry rows. A run-bearing registry empties only through an unrevoked `analysis_run_retention_grant` plus `analysis_run_retention_admin`, then `purge_analysis_run_registry('approved-retention-purge')`; a wrong token, a raw `DELETE`, and a runtime role that only knows the public phrase stay rejected. Export then delete `analysis_run_retention_event` before 0020 rollback. |
| Start reconstruction recovers the designed tree | Persist edges from `lineage_edge_specs` on the A-100 fixture bag via `records_from_source_posts`; the pricing follow-up must parent both the revised quote and the delivery question. A period-report start must 422 without a theta. TEPP start submits through `tepp_client` and stays Failed (`tepp_not_available` / `tepp_result_not_persisted`) without a theta. Snapshot members exclude a later backfill. A concurrent or Running start is 409. A Succeeded retry returns the stored digest. |
| Start reconstruction recovers the designed tree | Persist edges from `lineage_edge_specs` on the A-100 fixture bag via `records_from_source_posts`; the pricing follow-up must parent both the revised quote and the delivery question. A period-report start must 422 without a theta. TEPP start submits through `tepp_client`: missing transport is Failed (`tepp_not_available`); a strict accepted v1 envelope persists to `analysis_run_tepp_receipt` and stays Running; an invalid envelope is Failed (`tepp_result_not_persisted`) without a theta. Snapshot members exclude a later backfill. A concurrent or Running start is 409. A Succeeded retry returns the stored digest. |

## APA 7th references

Expand Down
44 changes: 44 additions & 0 deletions docs/product-technical-gap-baseline.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Product & Technical Gap Baseline

> Exact-head observation overlay: 2026-09-02 KST. Protected `main` is
> `3f61c8242b9c02dec307a7396e83e28f7cdd9f3d`. PR #897 is
> implemented through behavior-changing head
> `419d099af60df2f275fd058bf42149700709f628`, mergeable, and protected by
Comment thread
seonghobae marked this conversation as resolved.
> normal squash auto-merge; exact-head Checks are queued and no qualifying
> independent APPROVE exists. The following documentation-only commit records
> that observation; it does not claim its own recursively unknowable commit
> identifier as the observed implementation head. All implementation review
Comment thread
seonghobae marked this conversation as resolved.
> threads were resolved at the observation.
> Its accepted-receipt seed now also fails closed
> when a reseed encounters an existing Running history and a conflicting
> receipt: it appends `analysis_status_failed` /
> `tepp_result_not_persisted` unless a terminal event already exists, then
> appends the missing Delivered event to any existing claimed outbox so a
> terminal run cannot be retried. Focused regression evidence is 55 passing
> tests. This remains candidate evidence,
> not a protected-main release or authenticated PostgreSQL/UI runtime claim.
> The queue currently contains 107 open PRs and 15 open Issues; stacked PRs
> retain their declared bases until each parent is protected-merged. Canonical
> remote names are `ContextualWisdomLab/LineageWeave`, `RankWeave`,
> `ThreadWeave`, lowercase `disksage`, `TEPP`, `contextual-orchestrator`, and
> `fast-mlsirm`. The largest buyer increment in this slice remains an honest
> visible Running state after a persisted accepted receipt; producer status
> polling stays unavailable under issue #277. TEPP PR #266 protected-merged
> the strict HTTPS GET exchange builder, but neither that library contract nor
> a closed provider issue proves a configured live service, authenticated
> PostgreSQL lifecycle, evidence-based polling cadence, or rendered UI here.

> Exact-head loop overlay: 2026-09-01 KST. Protected `main` is
> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` (v2.24.0 leftover-map
> coordinates, #782). Package/pyproject versions on that head are 2.28.0.
> Open ready PRs still lack independent APPROVE. Leftover-map stacked
> heads through v2.106 are gold-plating and are not this cycle's buyer
> increment. #96 stays closed as a weaker duplicate of #91. Copilot
> review is not independent APPROVE. Do not self-approve. Do not merge
> stacked leftover PRs onto an unprotected leftover base. Issues #79
> and #87 stay OPEN. Issue #277 stays OPEN: consumer receipt persist is
> on `main`; producer status HTTP remains unavailable.
> Next buyer increment on this cycle: seed a Demo Corp Running TEPP
> accepted receipt (ADR 0219 / v2.29.0) so `make seed` shows
> "Measurement request accepted. Refresh this run to check whether
> results are ready." Missing-transport Failed remains. Never invent a
> GET URL, retry interval, leftover score, or theta.

Comment thread
seonghobae marked this conversation as resolved.
> Exact-head loop overlay: 2026-08-29 13:20 KST. Protected `main` is
> `fc13acaa20adca11968238e398d4aafcf62b6cee` (v2.23.0 leftover-map
> explained leftover share, #775). Open ready PRs still lack independent
Expand Down
1 change: 1 addition & 0 deletions docs/storybook-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ operator-facing control you can click before changing product CSS.
| `Evidence/OrganizationAliasChip` | Click a cataloged org; the parenthetical is the unique corroborated SKOS companion. | `--color-chip-border`, `--radius-chip`, `OrganizationAliasChip` |
| `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation, while `CombinedVoiceEvidence` covers primary-plus-additional Voice assignments and focuses the evidence action distinct from the carrying-Post action. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0251 states. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` |
| `Evidence/OntologyExplorer` | Distinguish Event Lineage from typed ontology facts, inspect Post/Person/Organization/Team/Project/Work-evidence shapes, token-backed secondary cues, and truth labels, then open authorized evidence. The populated scene includes one assertion-backed occupational construct without a person-trait promotion. The named exact-values region supports keyboard scrolling; `LongLabelsAndEvidenceTable` proves complete labels wrap without character-count truncation. Desktop, narrow, drawers, legend/filter, empty, truncated, partial, denied, stale, and rejected scenes cover ADR 0184/0222/0255 states. | `OntologyExplorer`, `ontologyLayout`, `--ontology-node-*-fill`, `--color-table-border` |
| `Analysis/TeppAcceptedReceipt` | Read that TEPP accepted the measurement request, then refresh the run to check whether results are ready. Acceptance is not a calibrated result and does not name a remote run id, TEPP, or Succeeded. | `TeppAcceptedReceipt`, `post-meta` |
| `AnalysisRun/CutoffKnownBody` | Read the cutoff-known sentence, then compare it with the live body below. | `--color-accent-border`, `--space-panel-block`, `--radius-panel`, `CutoffKnownBody` |
| `Analysis/LineageEntityPicker` | Choose which corp to reconstruct, then click Request a lineage reconstruction. | `--space-control-gap`, `--size-control-min`, `--radius-control`, `LineageEntityPicker` |
| `Admin/AdminPanel` | Change the tenant brand name, then verify the saved or failed state before leaving settings. | `--surface`, `--border`, `--space-panel-block`, `AdminPanel` |
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
"version": "2.28.0",
"version": "2.29.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
56 changes: 50 additions & 6 deletions frontend/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ describe("App, authenticated", () => {
succeededReportRun?: boolean;
succeededTeppRun?: boolean;
pendingTeppRun?: boolean;
runningTeppRun?: boolean;
pluralAffiliations?: boolean;
deferMe?: boolean;
deferPostOne?: boolean;
Expand Down Expand Up @@ -408,12 +409,16 @@ describe("App, authenticated", () => {
? "analysis_status_succeeded"
: options?.pendingTeppRun
? "analysis_status_pending"
: "analysis_status_failed";
: options?.runningTeppRun
? "analysis_status_running"
: "analysis_status_failed";
const teppLabel = options?.succeededTeppRun
? "Succeeded"
: options?.pendingTeppRun
? "Pending"
: "Failed";
: options?.runningTeppRun
? "Running"
: "Failed";
return Promise.resolve(
jsonResponse({
analysis_run_id: "run-demo-tepp",
Expand All @@ -426,7 +431,7 @@ describe("App, authenticated", () => {
status_label: teppLabel,
knowledge_cutoff: "2026-01-12T12:00:00Z",
requested_at: "2026-01-12T12:34:00Z",
...(options?.succeededTeppRun
...(options?.runningTeppRun
? {
tepp_accepted_receipt: {
remote_run_id: "tepp-remote-run-1",
Expand All @@ -452,6 +457,21 @@ describe("App, authenticated", () => {
occurred_at: "2026-01-12T12:35:00Z",
},
]
: options?.runningTeppRun
? [
{
status_ordinal: 1,
status_code: "analysis_status_pending",
status_label: "Pending",
occurred_at: "2026-01-12T12:35:00Z",
},
{
status_ordinal: 2,
status_code: "analysis_status_running",
status_label: "Running",
occurred_at: "2026-01-12T12:36:00Z",
},
]
: [
{
status_ordinal: 1,
Expand Down Expand Up @@ -779,12 +799,16 @@ describe("App, authenticated", () => {
? "analysis_status_succeeded"
: options?.pendingTeppRun
? "analysis_status_pending"
: "analysis_status_failed",
: options?.runningTeppRun
? "analysis_status_running"
: "analysis_status_failed",
status_label: options?.succeededTeppRun
? "Succeeded"
: options?.pendingTeppRun
? "Pending"
: "Failed",
: options?.runningTeppRun
? "Running"
: "Failed",
knowledge_cutoff: "2026-01-12T12:00:00Z",
requested_at: "2026-01-12T12:34:00Z",
source_counts: [
Expand Down Expand Up @@ -3971,11 +3995,31 @@ describe("App, authenticated", () => {
expect(
await screen.findByText("These posts are the cutoff corpus this TEPP run measured."),
).toBeInTheDocument();
expect(screen.queryByLabelText("Measurement request accepted")).not.toBeInTheDocument();
expect(screen.queryByText("tepp-remote-run-1")).not.toBeInTheDocument();
expect(screen.queryByText(/replace Failed/i)).not.toBeInTheDocument();
});

it("names a running TEPP accepted receipt as transport evidence, not a result", async () => {
stubBackend({ runningTeppRun: true });
render(<App showLabPanels />);

await userEvent.click(
await screen.findByRole("button", {
name: "Open analysis run: TEPP measurement · Running · Demo Corp",
}),
);
expect(screen.getByLabelText("Measurement request accepted")).toHaveTextContent(
"Refresh this run to check whether results are ready.",
);
expect(
screen.getAllByText(
"Refresh this run. Start already queued the work on the durable outbox.",
).length,
).toBeGreaterThan(0);
expect(screen.queryByText("tepp-remote-run-1")).not.toBeInTheDocument();
expect(screen.queryByText(/replace Failed/i)).not.toBeInTheDocument();
expect(screen.queryByText(/theta/i)).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Start TEPP measurement" })).not.toBeInTheDocument();
});

it("records a pending lineage run and opens the authorized detail", async () => {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3368,7 +3368,8 @@ function AnalysisRunsPanel({
{" · "}
Requested {selected.requested_at.slice(0, 10)}
</p>
{selected.tepp_accepted_receipt && (
{selected.tepp_accepted_receipt &&
selected.status_code === "analysis_status_running" && (
<TeppAcceptedReceipt />
)}
<AnalysisRunReproducibilityDigests
Expand Down
2 changes: 1 addition & 1 deletion lineageweave/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,4 @@
"serialize_lineage_analysis_result",
]

__version__ = "2.20.0"
__version__ = "2.29.0"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "lineageweave"
version = "2.28.0"
version = "2.29.0"
description = "Reconstructs git-branch-style lineage DAGs from scattered short records using multi-channel score fusion and LLM adjudication."
readme = "README.md"
license = { text = "MIT" }
Expand Down
Loading
Loading