diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..3b2deb73d --- /dev/null +++ b/docs/index.md @@ -0,0 +1,30 @@ +# LineageWeave + +LineageWeave reconstructs evidence-bound lineage, project journeys, and relationship context from scattered enterprise records so people can inspect how events, claims, posts, and decisions relate over time. + +## Start here + +Use LineageWeave when source systems contain related records without reliable explicit cross-record links and you need a browsable, evidence-preserving view of branching histories rather than a flat search result. + +The product combines deterministic lineage assembly with bounded retrieval/fusion and optional adjudication through shared ContextualWisdomLab components. It keeps source authority, authentication, tenant scope, measurement, and model-provider routing in their owning products and contracts. + +## Product surfaces + +- lineage reconstruction and project journeys; +- operations/dashboard views over governed records; +- evidence-aware Global Ask and related context navigation; +- authenticated API and web client over durable PostgreSQL state; +- integration with ThreadWeave, RankWeave, TEPP, contextual-orchestrator, and shared context contracts through explicit boundaries. + +## Documentation + +- [Repository overview and local stack](../README.md) +- [Architecture](../ARCHITECTURE.md) +- [Product requirements](product-requirements.md) +- [Product/technical gap baseline](product-technical-gap-baseline.md) +- [Architecture decisions](adr/) +- [Research notes](lineage-bi-research-notes.md) + +## Status and evidence + +The repository has progressed beyond its original synthetic reconstruction demo into a broader authenticated product stack, while synthetic fixtures remain important for safe examples and tests. Treat protected-main behavior, current release evidence, and repository verification as authoritative; do not infer production readiness from a documentation page or an open pull request alone. diff --git a/frontend/src/leftoverMapPlotSmallCanvas.test.ts b/frontend/src/leftoverMapPlotSmallCanvas.test.ts new file mode 100644 index 000000000..75d18ab13 --- /dev/null +++ b/frontend/src/leftoverMapPlotSmallCanvas.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from "vitest"; +import { layoutLeftoverMapPlot, type LeftoverMapPlottablePair } from "./leftoverMapPlotLayout"; + +const completeCaptionPair: LeftoverMapPlottablePair = { + pair_kind: "closest", + post_id: "post-small-canvas", + post_title: "Small canvas post", + criterion_code: "sales_lead_quality", + leftover_distance: 0.12, + leftover_map_reconstruction: 0.25, + leftover_map_explained_share: 0.76, + leftover_map_person_axis_1: -1, + leftover_map_person_axis_2: -1, + leftover_map_item_axis_1: 1, + leftover_map_item_axis_2: -1, +}; + +describe("layoutLeftoverMapPlot small-canvas caption bounds", () => { + it("keeps a complete three-caption stack inside the requested 20px height", () => { + const layout = layoutLeftoverMapPlot( + [completeCaptionPair], + (criterionCode) => criterionCode, + { height: 20 }, + ); + + expect(layout).not.toBeNull(); + expect(layout?.height).toBe(20); + const segment = layout?.segments[0]; + expect(segment).toBeDefined(); + expect(segment?.labelY).toBeGreaterThanOrEqual(12); + expect(segment?.reconstructionY).toBeGreaterThanOrEqual(segment?.labelY ?? 0); + expect(segment?.explainedShareY).toBeGreaterThanOrEqual(segment?.reconstructionY ?? 0); + expect(segment?.explainedShareY).toBeLessThanOrEqual(16); + }); +}); diff --git a/frontend/src/leftoverMapPlotVietnameseCopy.test.ts b/frontend/src/leftoverMapPlotVietnameseCopy.test.ts new file mode 100644 index 000000000..16d29d5db --- /dev/null +++ b/frontend/src/leftoverMapPlotVietnameseCopy.test.ts @@ -0,0 +1,27 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { setLocale, tf } from "./i18n"; + +const GRAPHIC_DISPLAY_COPY = + "Leftover map after IRT main effects. Axis ticks name persisted leftover-map coordinates. Pair segments name leftover-map distance d, leftover-map reconstruction R̂, leftover-map explained leftover share e, leftover-map unexplained leftover share s, leftover-map cross share x, leftover-map unexplained leftover U, leftover residual R, leftover observed Y, leftover expected E, and leftover-map rank. Click a post marker to open that post. The plot does not invent a leftover score."; + +afterEach(() => { + setLocale("en"); +}); + +describe("leftover-map Vietnamese copy inheritance", () => { + it("keeps explained leftover share terminology as an explicit share", () => { + setLocale("vi"); + + expect( + tf("leftover-map explained leftover share {label}", { label: "R̂²/R² 0.76" }), + ).toBe("tỷ phần phần dư được giải thích trên bản đồ phần dư R̂²/R² 0.76"); + }); + + it("keeps the expanded graphic description explicit about explained share e", () => { + setLocale("vi"); + + expect(tf(GRAPHIC_DISPLAY_COPY, {})).toContain( + "tỷ phần phần dư được giải thích e", + ); + }); +}); diff --git a/lineageweave/__init__.py b/lineageweave/__init__.py index 45c371fa7..226794a62 100644 --- a/lineageweave/__init__.py +++ b/lineageweave/__init__.py @@ -130,4 +130,4 @@ "serialize_lineage_analysis_result", ] -__version__ = "2.20.0" +__version__ = "2.41.0" diff --git a/tests/test_package_version.py b/tests/test_package_version.py new file mode 100644 index 000000000..cb85f136e --- /dev/null +++ b/tests/test_package_version.py @@ -0,0 +1,20 @@ +"""Release identity stays consistent across Python and frontend artifacts.""" + +from __future__ import annotations + +import json +import tomllib +from pathlib import Path + +from lineageweave import __version__ + + +def test_release_versions_are_synchronized() -> None: + """Runtime provenance must use the same version as shipped package metadata.""" + repository_root = Path(__file__).resolve().parents[1] + project = tomllib.loads((repository_root / "pyproject.toml").read_text(encoding="utf-8")) + frontend = json.loads( + (repository_root / "frontend" / "package.json").read_text(encoding="utf-8") + ) + + assert __version__ == project["project"]["version"] == frontend["version"]