graph: the MINIMAL home — the no-graph home, take two (release polish 2.2)
The chains-as-home experiment is retired (owner, 2026-10-06): dragging the table out of its overlay home caused every mess we saw — checkboxes by default, the bar/pill collision, the clearance band. The eventual plan is the DATA VIEW as home; until that is designed and built, the rendering-off home is deliberately minimal: - The SAME composer blob home already floats — teach/practice switcher and pick pill untouched. - The graph chrome's survivors in the graph view's OWN places: the top-right column — actions row (Chains + Import, the same 36px band pills) with the cost pill BELOW it. Import always renders (the entry-point law). No node search, no render gear (canvas things). - A quiet centered summary (KnowledgeSummary, a pure body — pinned by the render suite): propositions · chains, teaching · practice session counts, the imported-sources list as truncated muted rows; the empty knowledge base says so and names the import entry point. Biased up off the composer (pb-40), pointer-events-none. - NO recent sessions (the sidebar owns that, owner ruling). The chain table returns to overlay-only duty: ChainTableBody's onClose-optional and topBarExtra experiment hooks are reverted, and components/chains-home.tsx is deleted. MinimalHome renders the STANDARD ChainTableOverlay behind its Chains button — the pick flow mirrors GraphView's contract verbatim (chainSelectOpen raises the overlay in select mode; Done reports the lifted pick set down). Smoke-verified live, twice: the summary shows real counts (262 props · 160 chains, 195 teaching · 17 practice, 4 source paths); overlay open/close via button + X; pick flow — cluster check → bar "23 nodes → 17 chains · Clear · Done" → uncheck 2 props → Done → chip "21 propositions selected"; practice session starts from the composer; settings restore returns the canvas home. (First run's "select mode missing" was a tester artifact: the bar is selection-gated and prop checkboxes render only when expanded — both confirmed working.) 1417 tests (new KnowledgeSummary pins); tsc, lint, build green.
This commit is contained in:
@@ -82,31 +82,12 @@ const BASE = {
|
||||
onGenerate: () => {},
|
||||
onDelete: () => {},
|
||||
onClose: () => {},
|
||||
topBarExtra: undefined as React.ReactNode,
|
||||
};
|
||||
|
||||
function render(props: Partial<typeof BASE> = {}) {
|
||||
return renderToStaticMarkup(React.createElement(ChainTableBody, { ...BASE, ...props }));
|
||||
}
|
||||
|
||||
describe("ChainTableBody — the HOME variant (graph rendering off, 2026-10-06)", () => {
|
||||
it("onClose ABSENT = the page, not the overlay: no close X, everything else intact", () => {
|
||||
const html = render({ onClose: undefined });
|
||||
assert.ok(!html.includes('data-testid="chain-table-close"'), "nothing to close — the table IS the page");
|
||||
assert.ok(html.includes('data-testid="chain-table-search"'), "the search row stays");
|
||||
assert.ok(html.includes("chain"), "the counts stay");
|
||||
assert.ok(html.includes("lh-drag"), "the window-drag band stays (same bar as every surface)");
|
||||
});
|
||||
|
||||
it("topBarExtra injects into the bar's right cluster — import + cost ride the TOP BAR (owner, 2026-10-06)", () => {
|
||||
const html = render({ onClose: undefined, topBarExtra: React.createElement("b", { "data-testid": "tbx" }, "X") });
|
||||
assert.ok(html.includes('data-testid="tbx"'), "the extra renders inside the bar");
|
||||
assert.ok(html.includes("lh-no-drag"), "the cluster carves out of the drag band");
|
||||
const overlay = render();
|
||||
assert.ok(!overlay.includes('data-testid="tbx"'), "absent by default — the overlay variant injects nothing");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ChainTableBody — clusters (the outermost layer)", () => {
|
||||
it("collapsed by default: cluster rows render, chain rows do not", () => {
|
||||
const html = render();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/** The minimal home's KnowledgeSummary — the quiet centered summary of
|
||||
* the knowledge base (owner, 2026-10-06: "very quiet, very minimal").
|
||||
* Pure body: props in, markup out. */
|
||||
import assert from "node:assert/strict";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import React from "react";
|
||||
import { describe, it } from "node:test";
|
||||
import { KnowledgeSummary } from "../components/minimal-home.tsx";
|
||||
|
||||
function render(props: Partial<Parameters<typeof KnowledgeSummary>[0]> = {}) {
|
||||
return renderToStaticMarkup(
|
||||
React.createElement(KnowledgeSummary, {
|
||||
propositions: 12,
|
||||
chains: 5,
|
||||
teachSessions: 3,
|
||||
practiceSessions: 2,
|
||||
sources: [],
|
||||
...props,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
describe("KnowledgeSummary — the quiet home summary (2026-10-06)", () => {
|
||||
it("renders the knowledge base in numbers: propositions · chains, teaching · practice sessions", () => {
|
||||
const html = render();
|
||||
assert.ok(html.includes("12 propositions"), "propositions count");
|
||||
assert.ok(html.includes("5 chains"), "chains count");
|
||||
assert.ok(html.includes("3 teaching sessions"), "teaching count (plural)");
|
||||
assert.ok(html.includes("2 practice sessions"), "practice count (plural)");
|
||||
assert.ok(!html.includes("import notes"), "no empty-state hint when there is content");
|
||||
});
|
||||
|
||||
it("singularizes: one of each reads as single, not '1 sessions'", () => {
|
||||
const html = render({ propositions: 1, chains: 1, teachSessions: 1, practiceSessions: 1 });
|
||||
assert.ok(html.includes("1 proposition ·"));
|
||||
assert.ok(html.includes("1 chain"));
|
||||
assert.ok(html.includes("1 teaching session"));
|
||||
assert.ok(html.includes("1 practice session"));
|
||||
});
|
||||
|
||||
it("lists the imported sources — quiet truncated rows (owner: 'a list of sources that have been imported')", () => {
|
||||
const html = render({ sources: ["/notes/databases.md", "/notes/laravel.md"] });
|
||||
assert.ok(html.includes("/notes/databases.md"));
|
||||
assert.ok(html.includes("/notes/laravel.md"));
|
||||
assert.ok(html.includes('class="w-full truncate'), "each row truncates — long paths never blow the column");
|
||||
});
|
||||
|
||||
it("the empty knowledge base says so, quietly — import is the entry point", () => {
|
||||
const html = render({ propositions: 0, chains: 0, teachSessions: 0, practiceSessions: 0 });
|
||||
assert.ok(html.includes("Nothing here yet"));
|
||||
assert.ok(html.includes("import notes"), "the hint names the entry point");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user