Skip to content

Release 2.0 — LinkBar - #49

Merged
gowtham0992 merged 38 commits into
mainfrom
develop
Jul 28, 2026
Merged

Release 2.0 — LinkBar#49
gowtham0992 merged 38 commits into
mainfrom
develop

Conversation

@gowtham0992

Copy link
Copy Markdown
Owner

Link 2.0.0 — the memory layer gets a face

LinkBar puts the review gate in your macOS menu bar. The memory layer is unchanged in shape (plain Markdown, review-gated writes, no LLM in the write path) — it's just no longer only a CLI and an MCP server.

No breaking changes. Every CLI command, MCP tool, hook, and memory file from 1.7 works as before. The major version marks LinkBar's debut, not an API break.

LinkBar 1.0 (macOS, apps/LinkBar — Swift/SwiftUI over lnk --json)

  • Memory Palette — global hotkey (⌥⌘M) opens a floating panel over any app: type to recall, + to remember
  • Capture notifications — native banner with a one-tap Accept when a session capture lands (works unsigned; no Apple Developer certificate)
  • Live agent pulse — see which agent sessions are writing right now; menu-bar icon carries a quiet green dot
  • Memory browser — every memory file, searchable/filterable, with supersede lineage and archive/restore
  • Status dashboard — health of CLI, workspace, MCP, hooks, recall tier, and viewer, each with a one-click fix that verifies its outcome
  • Ships as an unsigned cask with a postflight quarantine-strip: brew install --cask gowtham0992/link/linkbar

Also

  • Fixed: lnk semantic reported "Indexed 16 of 6" — the denominator counted active-only while the index embeds every memory
  • Homepage: LinkBar section, version banner, per-agent onboard picker, origin story, alternating demo layout
  • prepare_release.py now bumps the homepage release banner with the version files
  • Repo history scrubbed of 465 MB of accidentally-committed Swift build artifacts

Verification

  • 910 tests + 44 subtests green; type ratchet 385 ≤ 387; memory hygiene 0% junk
  • LinkBar builds clean; palette hotkey and notification banner both confirmed working on macOS 26

Squashed reintroduction on a clean base (earlier branch history had
swept-in build artifacts). SwiftUI MenuBarExtra over `lnk --json`:

- Live kqueue watchers on the workspace — the badge and popover update
  the moment a session hook writes a capture; verified live.
- One field, two verbs: Enter asks memory, ⌘↩ remembers (review-gated).
- Capture rows show "Will save: <first proposal>" via capture-inbox
  previews; timestamps disambiguate same-titled sessions.
- Recall always answers: results, honest abstention, or "no matches".
- Secret refusals from the new remember gate surface as a friendly
  flash; stale-runtime warnings show a banner with one-click Fix.
- Launch at login (SMAppService), settings sheet, reveal-in-Finder on
  every row, auto-fading toned flashes, ⌘R/⌘Q, version footer.
- LINKBAR_SNAPSHOT=/path.png renders the popover to PNG through an
  offscreen AppKit window for screenshot verification.
Direction: a native macOS inbox with Link's editorial soul — system
materials and SF Pro do the structure, rust does the opinion, one
serif wordmark is the signature.

- DesignSystem.swift: LinkBrand tokens (rust with a lifted dark-mode
  variant, 4/8 spacing rhythm), SectionHeader (tracked uppercase
  labels with count badges — rust when work is pending), HoverRow,
  and the serif Wordmark.
- Rust replaces default-blue everywhere an action lives: Accept,
  review checkmark, the remember ⊕, settings toggle, Fix button.
- Real hierarchy: titles at 12.5 medium, metadata in tertiary,
  memory type in rust, timestamps inline; search field with an
  embedded magnifier; two-tone "Will save:" previews.
- Designed idle state (rust seal, "All reviewed.") instead of empty
  sections; flash is a toned pill that slides in and fades.
- LINKBAR_APPEARANCE=light|dark forces the snapshot appearance so
  both modes are verified from the command line.
…Extra windows (Done dismissed the popover, state stuck)
Research into how the hook grabs session context surfaced three
misalignments, now fixed:

- Standing rules survived: extract_transcript_text gains keep_head, and
  the hook mines a head+tail window (9k) instead of recency-only 6k. A
  rule stated at the start of a long session no longer falls off the
  front. Verified live on an 82-turn session.
- Correct attribution at accept time: the capture records a
  ## Proposal Source block (the user's own turns); accept-capture and
  the inbox preview mine from it, so the assistant's prose beneath the
  notes is never re-proposed as the user's preference. Closes a
  regression the earlier hook-time fix didn't cover.
- The pipeline is reviewable: session-end persists a decision trail
  (## How Link Read This Session), surfaced on the dashboard Captures
  page (proposals + collapsible trail) and in capture-inbox --json
  with a mined_from_user_turns flag.
# Conflicts:
#	CHANGELOG.md
#	tests/test_capture_core.py
Inch-by-inch review of every surface plus RepoBar-inspired features.

Bugs fixed:
- start() ran on every popover open, stacking a 5-min timer and
  rebuilding watchers each time; now guarded to run once per launch.
- Watchers for raw/memory-captures failed silently on a fresh
  workspace (directory not yet created) and stayed blind until
  restart; they now self-heal after the first capture creates the dir.
- LogEntry.id was timestamp+operation, which collides when one command
  writes twice in a second and made ForEach drop rows; id now includes
  the description.
- memory-log emits oldest-first; "Recent activity" and the "Latest:"
  line wanted newest-first — now reversed.
- Dashboard viewer probe trusted any responder on :3000; it now
  requires the Link viewer page (200 + "Link" in body) so a foreign
  dev server on that port isn't mistaken for ours.
- Bundle CFBundleShortVersionString was 0.1.0 while the UI said 0.5;
  both are now 0.6.0 from one LinkBrand.version constant.

Features:
- Idle state replaced with a living overview: active/total memories,
  wiki pages, and to-review counts as stat chips, plus a 14-day
  activity sparkline and the latest operation with relative time.
- Multi-proposal captures get an Accept menu (pick which proposal);
  single-proposal stays a one-click Accept.
- Recall rows gain Copy text; the search field gains a clear button.
- Capture timestamps show local relative time ("2h ago") instead of
  raw UTC.
- Menu-bar icon shows "!" when the workspace runtime is stale (repair
  is one click) even when nothing is pending.

Verified via light/dark snapshots against both released lnk (graceful
fallback: no proposals/trail) and dev lnk (full 1.7 rendering: "Will
save" preview, decision-trail disclosure, provenance). Installed and
running as 0.6.0.
Cold-user walkthrough found the automatic loop's worst first impression:
a one-click Accept (LinkBar) and accept-capture --index 1 landed on
whichever proposal came first in the transcript, which is often a
throat-clearing preamble ("I want to set some conventions…") rather
than the rule ("From now on I only deploy on Fridays…"). Both classify
as preferences at score 90, so confidence alone can't separate them.

- memory_durability_rank scores concrete directives (an action verb, or
  only/always/never/by default) above statements that are merely about
  making rules (want/need to set/establish + conventions/guidelines/…).
  propose_memories_from_text stable-sorts by it, so index 1 is the
  substance. Bare temporal phrases ("from now on", "going forward")
  don't count as concrete — they attach to preambles just as easily.
  Ordering only; every proposal still appears for review.
- README Quick Start collapses three parallel entry points (proof / try
  + serve / onboard x5) into one two-command hero path.
- lnk onboard collapses a fresh workspace's dozen scaffold lines into a
  one-line summary; targeted repairs on an existing workspace still list.
LinkBar showed your memory but was silent about Link's own health —
so a stale MCP runtime, unwired hooks, or a missing semantic tier
would quietly degrade recall with no signal. New Status tab makes the
whole plumbing visible and self-healing.

- Tabbed shell: Inbox · Status · Settings (slim rust segmented bar;
  Inbox carries the pending badge, Status shows an amber dot when a
  surface needs attention). Settings moves from a sheet-like pane to a
  proper tab.
- Status dashboard: a health row per surface — CLI, Workspace, MCP,
  Hooks (Claude Code), Recall power (semantic tier + rerank), Viewer —
  each a colored dot + one-line state, fed by status/verify-mcp/
  semantic --json plus a direct read of the agent's hook config. Heavy
  probes (verify-mcp, semantic) are gated to once/15s and run after the
  fast data paints, so the popover stays instant.
- One-click remediation on every unhealthy row: Refresh (stale
  runtime), Fix (MCP version drift), Wire (Claude Code hooks), Enable
  (semantic recall), Open (viewer).
- Menu-bar icon shows a subtle amber dot when any surface is unhealthy
  even with an empty review inbox — Link tells you before recall
  quietly gets worse.

Verified via light/dark snapshots against a real workspace: it
correctly flags this machine's stale MCP (1.5.0 ≠ 1.6.0) with a Fix
button and lexical-only recall with an Enable button.
Clicking "Enable" on the Recall row flashed "Semantic recall ready."
and then the row stayed "Lexical only" — because the fix flashed
success on exit 0 without checking whether anything changed. On a
released (pre-1.7) CLI, `semantic --setup` only prints the manual pip
steps and exits 0, so nothing was installed.

Every remediation now confirms the real outcome and flashes the truth:
- Enable (semantic): runs --setup, re-reads `semantic --json`, and
  reports "ready — <tier>" only if it actually enabled, else the exact
  manual command to run.
- Fix (MCP): runs the precise upgrade command verify-mcp emits (venv
  pip install --upgrade link-mcp==<version>) via a new LinkCLI.runRaw,
  re-checks verify-mcp, and reports success only if it's ready — not a
  workspace init that never touched the venv.
- Wire (hooks): re-reads the settings file to confirm the hook landed.

No more optimistic flashes; the dot and the message always agree.
The three How-it-works demos stacked as full-width centered figures ran
~1800px of scroll, with captions as afterthought lines. Each demo is
now a flex row — terminal beside its caption as real side prose with a
rust kicker (REMEMBERS / RECALLS BY MEANING / STAYS TRUE) — zigzagging
left/right. ~40% less scroll, editorial rhythm, and the side text keeps
a row alive during the animations' brief between-scene gaps. Narrow
viewports wrap back to the stacked layout (flex-wrap, no media queries
needed inside the template).

Goes live with the next develop→main merge.
The first ambient feature: LinkBar's memory is no longer trapped behind
the menu-bar icon. Press ⌥⌘M anywhere and a floating panel opens over
whatever you're in.

- Type to recall — results stream as you type (debounced), Enter copies
  the top hit to the clipboard, Esc closes. Confidence chips and the
  honest "don't know" abstention carry over from core recall.
- Prefix "+" to remember — "+ staging moved to port 4000" saves a
  review-gated proposal without leaving your editor. Secret-refusal and
  duplicate/conflict feedback shown inline.
- Carbon RegisterEventHotKey needs no permissions (unlike global event
  monitors that require Input Monitoring), so it works in the unsigned/
  ad-hoc build. Non-activating NSPanel floats over full-screen apps and
  all Spaces. Same lnk --json backend — no new surface.

This turns LinkBar from a menu-bar inbox into a system capability:
Spotlight, but for your agent memory.
Second ambient feature. LinkBar now detects live agent sessions (a
Claude Code project whose newest transcript was written in the last
5 minutes) and shows the pulse:

- A breathing green dot + "N agents active · project names" row atop
  the inbox, with the last memory activity's relative time.
- The menu-bar icon gains a quiet green dot when agents are working
  and nothing needs review — memory being made, no action required.
  Priority order in the label: pending count > active pulse > amber
  health warning.
- Zero polling loops: computed during the existing refresh pass from
  transcript mtimes (they stream continuously while a session runs —
  verified live). Codex/Cursor roots can join the same scan later.

Verified via snapshot against the real workspace: the pulse correctly
detected the very session that wrote this commit.
Third v2.0 feature: when a session capture lands, post a native banner
with the "Will save:" proposal preview and an Accept action, so the
review gate meets you the instant memory is proposed. Full
UNUserNotificationCenter wiring: capture category, Accept/Review
actions, accept-by-path from the banner, present-while-frontmost.

FINDING (the reason this ships dormant): tested notification
authorization on the installed ad-hoc-signed bundle, launched properly
via LaunchServices, on macOS 26.5.2 — result:

  granted=false status=denied "Notifications are not allowed for this
  application"

macOS ties notification permission to a stable code signature; an
unsigned/ad-hoc app is denied outright and can't even prompt. So the
feature is gated on the real authorization result: on the current free
unsigned build it stays completely inert (no dead API calls, no
console spam), and it lights up automatically the day LinkBar ships
signed + notarized — which is now the single concrete thing the $99
Apple Developer enrollment buys. Everything else in v2.0 (palette,
pulse, browser) works free.
Fourth v2.0 feature. New Memory tab between Inbox and Status:

- Reads wiki/memories/*.md directly (the local-first move: the browser
  shows your actual files, no intermediary), parsing only the
  frontmatter the rows display; refreshed with the normal refresh pass
  and the existing directory watchers.
- Search-as-you-filter, type chips (preference/decision/note/project/
  procedure/fact), and an archived toggle; superseded and needs-review
  states surface inline, supersede lineage on hover.
- Row actions: copy the claim, reveal in Finder (double-click too),
  archive/restore via the CLI.

Snapshot-verified against the real workspace (6 active memories render
with correct types, scopes, projects, and dates).
Three liveliness upgrades (pattern-inspired, not copied):

- Version banner above the header: "New · Link 1.7.0 is out — secret
  gate, capture provenance, ranked proposals →" linking to the GitHub
  release. One line that says the project is alive.
- The agent picker now pays its rent: each agent tab swaps in the real
  one-command setup (lnk onboard --agent <x> --hooks --write for
  hook-capable agents, --write otherwise) instead of the legacy
  bash integrations/<x>/install.sh scripts that predate 1.7's
  self-provisioning onboard.
- New § ORIGIN section between Benchmarks and Setup: "It started with
  a Karpathy gist." — the LLM-wiki post, what Link grew from it, and
  the honest kinship line ("Other branches of the pattern graph your
  code. Link remembers you."), linking the original gist.

Verified rendering locally (banner, origin, and live per-agent command
swap all present; legacy install.sh commands gone; JSON template valid).
…is total not active (was the 16-of-6 nonsense)
The banner advertises a download and links the release tag, so a stale
version points visitors at a tag that does not exist yet. It now moves
with the other 5 version files instead of relying on someone
remembering it at release time.
Made the release script hard-fail on minimal trees (its own tests build
a fake repo without docs/). The homepage is presentation, not a package
artifact — update it when present, skip it otherwise.
The 1.7 hardening and 2.0 work removed two type errors; locking the
lower number in means they can't quietly come back.
@gowtham0992
gowtham0992 merged commit 250c98d into main Jul 28, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant