Repository navigation
Note-taker: honest chrome + walkable session-history drill-down (Closes #247) - #250
Merged
Merged
Conversation
Remove the dead Notes/Summary/Search nav tabs and the dead Home button (affordances with no live handler); the session-history list is the pad's real navigation now. The Search view stays tracked by #230. Remove the hard-coded machine "Enrichments" header from the right column; its blocks self-label, symmetric with the left column — never a bold header over possibly-empty content. Make session-history rows clickable: selecting a past session shows that session's read-only record in the center (its session-level summary + its moments) under a "Past session" header with an always-visible Back-to-live control. It is read-only navigation — no capture start/stop, the consent boundary is untouched. Mechanism: a generic Hud.mapQuery seam remaps a block's query before it is hydrated; the note-taker's NotetakerView re-points the center session-scoped blocks from session:'current' to the selected past-session id, so a plain hud.refresh() re-hydrates the center against it. The engine already honors an explicit sessionId over 'current' (query.ts) — locked by a new test. The seeded surface document is unchanged (the binding is applied at query time), so no migration is needed. Honest states: a past session with no summary/moments says "Nothing was captured in this session.", never a blank center. New nav/decoration classes are non-selectable in the stylesheet (selection-hygiene stays derived from it). Driven proof: notetaker-history.test.ts drives the real Hud + mapQuery + mount-layer click delegation + renderNotetaker — a synthesized click on the rendered session-open button flows through to a real re-query + re-render, asserts the center shows that session (not the live one), clicks back-to-live, asserts the live view returns, and covers the empty-detail honest state. A served-DOM Electron harness (scripts/notetaker-history-e2e.mjs) mirrors it. Closes #247
Ambisphaeric
added a commit
that referenced
this pull request
Jul 18, 2026
Fresh-eyes repairs on the correction slice: - Focus/caret theft (the #225 pattern): SummaryEditSession now snapshots the editor focus + caret before a destructive live re-render and restores them after (rerenderInto), scoped to .sum-edit-text, with IME-safe wipe deferral. dev-entry nests it around the input block rerenderInto so both fields survive one wipe. Driven test asserts draft + focus + caret survive a background re-render (the probe that returned focused=false is now green). - NUL bytes: the summaryCorrectionKey and correctSummary id-hash separators used raw 0x00 bytes; replaced with the backslash-u-0000 escape (byte-identical runtime, matching resolveClaimHeads). Zero raw NULs remain in the diff. - Pad correction (unblocked by #250): renderNotetaker threads the summaryEdit context through renderZonePanel, so the pad center summary gets the pencil. A correction targets a summary identity (not session current), so the write path works on any session, live and past-session views alike; a read-only past view still forbids capture but allows correcting derived prose. Driven pad e2e covers the live-view open/type/save/persist flow.
Ambisphaeric
added a commit
that referenced
this pull request
Jul 18, 2026
) * feat(summaries): make summary prose correctable in place (sovereign user revisions) Closes #246 The summaries why-line promised "a draft you can correct" but no edit affordance existed. This makes summary prose correctable in place, stored as a sovereign, append-only user revision that outranks any machine revision on read and survives re-derivation. Contract (shared/contracts): - Summary gains source ('model'|'user', optional — absent ⇒ model for pre-#246 rows), a correction stamp, and a corrects link; proposal relaxed to boolean (a user correction is proposal:false). New SummaryCorrection shape and CorrectSummaryRequest payload; POST /summaries/correct route. Schemas regen'd. Engine: - store.correctSummary mints a source:'user' revision carrying the target's identity (level/window/session/children/bound), confidence 1, a correction stamp, and only STRUCTURAL provenance (no model-invoke fields — human prose is never attributed to a model). resolveSummaryHeads resolves supersession + sovereignty in one pass, keyed by a stable window/level identity so a later re-derivation cannot defeat the correction. The producer excludes user rows from the machine chain. A degraded target is refused. Purely local write. Client: - A pencil affordance on live rows (opt-in via a threaded correction context; degraded/empty rows get none) swaps the row to an inline editor; save posts the correction, the row re-renders with the corrected prose and an honest "edited by you" marker (user-select:none). SummaryEditSession controller dispatches the verbs (unioned into the interaction lint); a refused save surfaces a calm visible line with the raw reason on hover. Tests: engine sovereignty proof (correct → re-run producer → user text wins, incl. a new machine revision), served route e2e, egress seam unchanged; client driven served e2e (click/type/save renders + persists; refused save shows error), block + selection-hygiene + interaction-lint coverage. * fix(summaries): keep resolveSummaryHeads in window read-order A collected user correction was appended at the tail of the resolved list; sort the result by (windowStart, createdAt, id) so a correction reads in its window's place, matching the append-only order the SQL query establishes. * fix(summaries): focus/caret survival, NUL escapes, and pad correction Fresh-eyes repairs on the correction slice: - Focus/caret theft (the #225 pattern): SummaryEditSession now snapshots the editor focus + caret before a destructive live re-render and restores them after (rerenderInto), scoped to .sum-edit-text, with IME-safe wipe deferral. dev-entry nests it around the input block rerenderInto so both fields survive one wipe. Driven test asserts draft + focus + caret survive a background re-render (the probe that returned focused=false is now green). - NUL bytes: the summaryCorrectionKey and correctSummary id-hash separators used raw 0x00 bytes; replaced with the backslash-u-0000 escape (byte-identical runtime, matching resolveClaimHeads). Zero raw NULs remain in the diff. - Pad correction (unblocked by #250): renderNotetaker threads the summaryEdit context through renderZonePanel, so the pad center summary gets the pencil. A correction targets a summary identity (not session current), so the write path works on any session, live and past-session views alike; a read-only past view still forbids capture but allows correcting derived prose. Driven pad e2e covers the live-view open/type/save/persist flow.
This was referenced Jul 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #247.
What changed
Dead chrome removed. The left rail's disabled Notes / Summary / Search feature-nav tabs and the disabled Home button are gone — affordances with no live handler, per the standing interaction-honesty policy. The ◆ is now a non-interactive brand mark, not a button. The Search VIEW stays tracked by #230 (a disclosed follow-up, not silently dropped). The pad's navigation is now the real, walkable session-history list.
Machine header removed. The hard-coded "Enrichments" header on the right column is gone; its blocks self-label (Transcript / Actions / Fields), symmetric with the left column's Pinned + Sessions — never a bold machine word painted over possibly-empty content.
Session-history drill-down (headline). History rows are clickable nav controls (the wired
session-openverb). Selecting a past session shows that session's read-only record in the CENTER column — its session-level summary and its moments — under a "Past session" header with an always-visible "Back to live" control. It is read-only navigation: it starts/stops no capture and never touches session lifecycle (consent boundary intact).Mechanism
Hud.mapQuery(block)seam remaps a block's query before hydration; the controller stays layout-agnostic.NotetakerView(client-local, session-ephemeral) holds the selection and, viamapQuery, re-points the CENTER session-scoped blocks fromsession: 'current'to the selected past-session id, so a plainhud.refresh()re-hydrates the center against it. Row clicks route through the real mount-layer delegation toopen/backToLive.sessionIdovercurrent(query.ts) — locked by a new unit test. The seeded surface document is unchanged (the binding is applied at query time), so no migration is needed.Proof
notetaker-history.test.ts(in-gate, driven): synthesizes a real click on the renderedsession-openbutton → the real delegated listener → the realNotetakerView→ a realmapQueryre-query → a real re-render; asserts the center shows THAT session's summary + moments (not the live one's), clicks back-to-live, asserts the live view returns, and covers the empty-detail honest state.scripts/notetaker-history-e2e.mjs(served-DOM, Electron, GUI-only like the other e2e scripts): mirrors the flow against real hud.html + preload + a fake engine, driving DOM clicks and asserting the served center.notetaker-layout.test.tsandsessions.test.tsto pin the new chrome/behavior.Gate
pnpm -r buildgreen. Fullpnpm -r testgreen except one pre-existing timing flake insummaries-surface-e2e(the #241 chronic-flake pair) — confirmed 3/3 green isolated and unrelated to this change (engine query logic is unchanged; only a comment + a test were added there). Schema regen: zero drift.