Skip to content

feat(web): rebuild the landing page as a marketing page, split from /login - #679

Merged
mthines merged 7 commits into
mainfrom
feat/landing-page-rework
Oct 11, 2026
Merged

mthines merged 7 commits into
mainfrom
feat/landing-page-rework

Conversation

@dash0-dev

@dash0-dev dash0-dev Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

/ redirected every anonymous visitor to /login, so the front door was an auth route titled Sign in. This PR makes / a marketing page and leaves /login doing only the job its URL names. The second pass turns that page from accurate into persuasive: it leads with the problem, shows the product in the first screen, and makes the install command the one obvious action. Copy is still held to what the product does today.

Baseline it has to beat (Dash0 RUM, web, 2026-09-11 → 2026-10-11, production /login): 134 landing sessions, 30 (22%) started sign-in, 11 (8%) opened docs, 0 recorded install_command.copied (the command sat at the bottom of /login). No copy event has ever been recorded, so a broken event is not fully ruled out; the first copies after deploy will confirm it.

Changes

Structure — / renders the landing page; /login keeps only the auth form plus a "See what LoreKit does" link. Signed-in redirect to /lore and the query-string auth-callback rescue are unchanged. AuthHashCatcher is mounted on / as well as /login (comment corrected: it was not moved). main from #685 is merged; its Blog link now lives in the shared LandingHeader.

Reading order — hero → live demo (the hero's product shot, peeking above the fold) → 01 why not just a CLAUDE.md? (one lesson's month — learns → recalls → promotes → prunes — then a CLAUDE.md vs LoreKit table) → 02 how it works (setup and team sharing, not a second telling of the loop: connect each agent → lessons stay with their repo via scopes → bind a scope to the org for one shared copy; CI reads with a read-only token) → 03 what you get (bento: memory cost, review-comment learning, every lesson in plain sight, grooming) → 04 where your lore lives → 05 what LoreKit doesn't do → closing call to action.

Persuasion, by barrier

  • The differentiator, up front: headline Your coding agents forget. LoreKit makes them learn. A rules file can hold a convention someone already knew; it can't learn what nobody knew, hand it back when the same error recurs, promote what keeps recurring, or retire what nobody uses. The hero lede, section 01 and the demo's Promotion tab all tell that loop, and section 01 answers the "why not just CLAUDE.md?" objection by name — positioning LoreKit as how a team finds out what earns a place in its CLAUDE.md. Each beat is a shipped mechanic (friction-gated write nudge, error-matched recall on a failing tool call, recurrence-ranked injection + lorekit-setup promotion, retention-policy archive); the scenario's numbers are labelled as a story.
  • One obvious action: the install command gets the amber frame and the page's only filled button (Von Restorff); it repeats at full size in the closing card (peak-end).
  • Safe to try: the trust points move from above the headline to under the command, where "is this safe?" is actually asked. No star counts (18 today — that would not help), no urgency, no testimonials we don't have.

Copy corrected against the CLI — install with a blank token still writes the hosted MCP entry (packages/cli/src/commands/install.mjs); offline needs the local MCP entry plus "mode": "local" (/docs/offline steps 3 and 6). So "Works offline with no account" directly under the command, and the old step 2 "your agent starts remembering", promised a setup one command does not produce. The hero and closing card now name both real paths at equal weight: Hosted (sign in, paste a token) and Offline (skip the token, switch to local mode). The webhook cell says review comments become candidate lessons that expire (supabase/functions/mcp/webhook.ts), not "durable lessons automatically". The demo caption no longer lists Codex as supported.

Visual system — one SectionHeading (mono numbered eyebrow, 30–36px title, 16px lede) and exactly two repeated signature moves: lk-glow-frame (amber hairline + glow, reserved for the product and its actions) and lk-gradient-text (the payoff phrase per heading). Sticky blurred header (main now uses overflow-x-clip so sticky works). New token --color-accent-bright. MemoryCost is folded into the bento's widest cell.

Motion — CSS only, transform/opacity only, resting state = finished state: lk-rise (hero stagger), lk-reveal (sections, view() timeline), new lk-tilt (the demo window lies back and lifts flat by cover 35%). Safari/Firefox and reduced-motion visitors get the static page.

Review findings applied — AuthHashCatcher comment; LandingBackdrop uses tokens instead of hex; StepBadge replaces the duplicated class; one GitHubMark replaces four inline copies of the SVG path (header, hero, footer, LoginButton). Not done: a CopyCommand size test (see Verification).

Telemetry — the page answers "how far do they scroll, what do they see, what do they click" with the blog's own model, not a second one:

  • Reading: ReadingTelemetry (the blog's component) mounts on / with content.type=landing, slug=home, measured hero → closing card. Same content.scroll_depth (25/50/75/100), content.section_read (per-section engaged dwell) and content.read (one summary per view) as a blog post, so one dashboard splits the two by lorekit.content.type. Section ids live in components/landing/sections.ts and every heading imports its id from there, so a renamed heading can't silently drop out of the data (sections.spec.ts).
  • Clicks: landing.cta_clicked with closed-union cta (get-token/offline-guide/sign-in/docs/blog/github) × placement (header/hero/get-started), through one LandingLink for every link on the page. get-token vs offline-guide from the hero is the direct read on which path visitors want.
  • Demo: landing.demo_tab_selected — which use case a visitor picks (the auto-playing tab isn't counted).
  • Copy: install_command.copied with landing-hero / landing-get-started, kept apart so "did the command alone convert" and "did the whole page convert" stay separable.
  • Funnel: page view → depth milestones → section dwell → copy / CTA. Success = copy sessions ÷ landing sessions rising from 0, with the hosted/offline split and sign-ins read alongside. Blog comparison (30 days): 24 sessions reached 25 % of a post, 18 reached 100 %.
  • docs/otel.md documents the new events; its Content section no longer claims /docs is tracked (it never mounted the component).

Verification

  • Typecheck: scoped tsc --noEmit over the changed files and their imports (55 source files) — clean. The full nx typecheck web exceeds this sandbox's memory; CI's Typecheck, Test & Lint (affected) is the authoritative run.
  • ESLint on all changed files — 0 errors (2 pre-existing warnings in SiteFooter on untouched lines).
  • Vitest: track (incl. the new landing.* and content.type=landing wire shapes), lore-events, reading, sdk-event-callers, analytics-id-literals, landing/sections — 84/84 pass.
  • globals.css compiled through @tailwindcss/postcss — new utilities and signature classes generate.
  • Not run here: Storybook visual tests (no Playwright browser in the sandbox; no landing stories exist — worth a follow-up once baselines can be generated), a real-browser look (use the Vercel preview), and the repo's /polish → review-loop pipeline — this was authored by Agent0 outside Claude Code, so treat it as a draft for review.

Context

  • Docs obligation: none applied — no MCP tool, REST route, CLI flag, limit or config key changed. The page now states the offline path the way /docs/offline already does. Separately, README.md still calls webhook lessons "durable"; that is a follow-up.
  • Product follow-up (not in this PR): if install with a blank token offered to set up local mode, the no-account promise would be true in one command, and the hero could say so.

…login

`/` redirected every anonymous visitor to `/login`, so the front door was an
auth route titled "Sign in": a form before an explanation, with the product's
strongest verifiable claims — one command, works with no account, MIT,
self-hostable — below the fold of a page nobody had a reason to scroll.

`/` is now the marketing page and `/login` does only the job its URL names.
The hero's primary action is the install command rather than sign-in, because
the CLI's offline mode needs no account and an auth-first ordering described a
requirement that does not exist.

Three overstated claims are corrected: "never asks the same question twice"
(an absolute the retrieval model cannot guarantee), a bare "Free" badge (now
"Free · 5,000 memories", the actual free-plan cap), and a flat Claude Code /
Cursor / Codex list (Codex is feature-flagged and experimental). Two new
sections state what the page was missing: where lore physically lives, and
what LoreKit does not do.
@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

The dashboard preview for this PR — redeployed on each push that changes the web app.

Project Deployment Actions Updated
lorekit Ready Ready Preview Oct 11, 2026 6:09am UTC

Preview always points at this PR's latest commit; Deployment is the immutable build of 356c095. · Comment /web-preview to force a redeploy. · Workflow logs

@dash0-dev

dash0-dev Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

/review

dash0-dev Bot pushed a commit to mthines/agent-skills that referenced this pull request Sep 21, 2026
…stop scoring grep collisions as blast radius

Both found by the first fanned-out review run against mthines/lorekit#679.

The workspace was materialized under os.tmpdir(). The host's file tools are
scoped to the agent workspace, so `/tmp/prr-clone-*` was not merely awkward —
the standards finder's sub-agent had `read`, `glob` and `cat` all REFUSED
against it, returned zero findings, and had to disclose that its empty result
meant "could not open the governing docs" rather than "the diff conforms".
A checkout now lands under $PR_REVIEWER_SCRATCH / /tmp/workspace, with
os.tmpdir() kept as the last rung for a host that has no workspace.

The impact graph resolved consumers by word-boundary grep alone. On #679 that
gave `metadata` — the Next.js route-segment export of app/page.tsx, which
nothing can import — 87 consuming files across 8 packages, and `wait`, a
non-exported helper the diff does not even change, another 27. Fourteen of
fourteen sampled hits were collisions: an audit record's `metadata:` property,
the English word in a comment, an unrelated `wait` method. blast_radius scored
260 / band high on that, which routes Phase C to `deep` — the most expensive
tier — on pure noise. gateConsumers() now intersects the grep hits with the
import edges importersOf() already resolves, for ES modules only (a Go or
Python same-package reference needs no import and is left alone), and records
`consumer_gate` on any symbol where it bit so an empty list is never misread as
"nothing depends on this".
dash0-dev Bot pushed a commit to mthines/agent-skills that referenced this pull request Sep 21, 2026
…te deletes real edges

A monorepo declares `"@/*": ["./src/*"]` in packages/<name>/tsconfig.json, not
at the root, and a paths target is relative to the config that declares it.
aliasMap read the root only, so every aliased import stayed unresolved — which
was survivable while importers were merely informational and is not now that
gateConsumers intersects consumers against them: an unresolvable alias reads as
"no file imports this module" and deletes real consumers.

Measured on mthines/lorekit#679, same commit, three runs:
  before the gate      band high, score 260 — 87 fake consumers on `metadata`
  gate, root alias only band low,  score 2   — real importers deleted too
  gate + this fix      band medium, score 17 — CopyCommand back to its 3 real
                       consumers (LandingHero, GetStartedCard, BlogPostCta),
                       every landing component back to page.tsx, and 192
                       `metadata` + 60 `wait` collisions still dropped
@mthines

mthines commented Sep 22, 2026

Copy link
Copy Markdown
Owner

/review

@dash0-dev

dash0-dev Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

⚡ Running Agent Reviewer | Review…
View Agent Reviewer | Review in Agent0

@dash0-dev

dash0-dev Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

🟡 4 findings

Splits the marketing landing page from the login-only auth page, sharing header/backdrop between them and adding an install-command-first hero.

Warnings: description omits AuthHashCatcher duplication; 4 non-blocking finding(s)

1 advisory finding below the confidence bar — see Less certain below.

Finding Where Severity
AuthHashCatcher comment claims a move that didn't happen packages/web/src/app/page.tsx:63 🟡 medium
Raw hex colors in shared LandingBackdrop packages/web/src/components/landing/LandingBackdrop.tsx:15 🟡 medium
Step-badge class duplicated between siblings packages/web/src/components/landing/HowItWorks.tsx:53 ⚪ low
No test coverage for CopyCommand's new size branch packages/web/src/components/landing/CopyCommand.tsx:32 🟡 medium
Less certain (1) — advisory, below the confidence bar
  • packages/web/src/components/landing/LandingHero.tsx:39 — suggestion: GitHub-mark SVG path is inlined again here (also in LandingHeader, LoginButton, SiteFooter); extract one icon component. (confidence 88)
Review details

Needs attention

Gate Status Details
Description vs. code ⚠️ Says AuthHashCatcher 'moves' to /; it's duplicated — login/page.tsx still renders it unchanged.
Prior review feedback ✅ Earlier review comments are resolved.
Documentation ✅ The change is documented well enough to follow.
Self-review signals ✅ No debug logs, leftover TODOs, or unreviewed stubs.
Code review ⚠️ 4 non-blocking finding(s) (see inline).
Impact — 4 changed exports · 8 consumers checked
  • CopySurface (packages/web/src/lib/analytics/track.ts) — signature change · 1 consumer file · 1 verified unaffected
  • CopyCommand (packages/web/src/components/landing/CopyCommand.tsx) — body change · 3 consumer files · 3 verified unaffected
  • LandingHeader (packages/web/src/components/landing/LandingHeader.tsx) — added change · 2 consumer files · 2 verified unaffected
  • LandingBackdrop (packages/web/src/components/landing/LandingBackdrop.tsx) — added change · 2 consumer files · 2 verified unaffected

Found

Quality — produced 7 → posted inline 4 (1 consolidated at dedupe, 1 contradicted and dropped, 1 deferred below confidence bar)
Severity — 🟡 3 medium · ⚪ 1 low
Standards — ran — 2 doc(s) loaded, 1 finding(s)

Run

full · 904 lines in delta · tier deep · depth checkout · blast_radius=medium, semver_delta=none, high_stakes=0, risky_shapes=none
CI — all checks green (Typecheck/Test/Lint, Storybook interaction+visual, Vercel preview)
Memories — 25 indexed · 0 used

Nothing to report — optimality, measurability (1 paths classified), integrations (not activated), 0 files skipped.

pr-reviewer · commit d38c6e4 · full review · how these findings are produced · updated Sep 22, 2026 5:10am UTC

mthines added a commit to mthines/agent-skills that referenced this pull request Sep 23, 2026
…dle, prepared context (#201)

* feat(pr-reviewer): Agent0 fast path — workspace install, compiled bundle, prepared context

The review pipeline runs on three harnesses. In a Dash0 Agent0 Automation
sandbox, four host facts make the CLI's assumptions false, and all four are paid
before Step 0 runs:

  1. the native file reader is scoped to the workspace, so an install under
     $HOME/.claude degrades every read to a sed slice against a ~50 KB cap —
     ~16 sequential calls to ingest a 277 KB agent definition;
  2. the host's skill tool resolves a fixed enum of its own built-ins and never
     the filesystem, so no install ordering can make a repo-owned lens visible
     to it (20/29 runs in one week hit this; the mandated retry recovered 0/26
     across two weeks);
  3. custom agent types are not dispatchable and delegation is one level deep;
  4. the GitHub credential is repo-scoped, so `gh api /user` 401s and Step 0.5's
     identity read can never succeed.

Three new pieces, none of which changes a phase, finding, gate or verdict:

- scripts/agent0-setup.sh — the source of truth for an automation's
  sandbox.setupScript. Installs the agent tree, the six lenses as files, and the
  compiled bundle INSIDE the workspace, then writes RUN-CONSTRAINTS.md and
  exports the resolved paths. Runs once and is cached between runs, replacing an
  in-session install re-executed on all 34 runs of a measured week. Fails closed.

- scripts/build-agent0-bundle.mjs — compiles pr-reviewer.md plus the mandatory
  core rules into one file, so no run pays a per-phase read: 16 bash slices
  become 3 native reads. A concatenation with a preamble, never a paraphrase —
  a compiler that rewrote the pipeline would be a second pipeline to keep in
  sync. Fails closed on a missing core rule.

- scripts/prepare-review.mjs — executes the deterministic half (Steps 0, 0.5,
  0.7's GitHub fallback rung, 0.8, 1.1, 1.1b, 1.2, shape classification, Phase B)
  in one process, ~6 s measured, and emits a ~12 KB index plus sidecars. Closes
  the torn-state window by construction: head, base, diff, patch list and impact
  graph are bound from one metadata read. It does no LoreKit read, makes no
  judgment and writes nothing to GitHub, and the artifact says so.

A degraded rung is never an exit code — it is an entry in anomalies[], because a
review that could not materialize a checkout is a narrower review, not a failed
one.

rules/agent0-runtime.md documents the harness and is referenced from the agent's
Imports; it is inert on every other harness. Both scripts carry --self-test
(9 and 19 cases).

* fix(pr-reviewer): fold the three spellings of one GitHub App login before deciding REVIEW_RELATION

`gh pr view --json author` reports an App author as `app/dash0-dev`, the REST
comment and review payloads report the same actor as `dash0-dev[bot]`, and a
human configuring the automation types `dash0-dev`. A raw comparison therefore
reads the agent's own PR as `cross` — which is not cosmetic, since that flag
decides whether findings carry context-asymmetry hedging.

* fix(pr-reviewer): three bugs the first live run against lorekit#679 found

- prepare-review.mjs creates the sidecar directory. `--out` names a file in a
  directory the caller has not necessarily made, and the first write into it is
  a sidecar, so an absent dir surfaced as `ENOENT … pr-files.json` — which
  reads as a missing input rather than an absent output dir, and aborted the
  whole prepare step.

- agent0-setup.sh no longer dies on an unset $DASH0_AGENT_ENV. That variable is
  not set in every sandbox, and under `set -u` the expansion exits bash at a
  line sitting BEFORE the verification block — an install that printed a bundle
  summary and then stopped one step short of the check that exists to catch it.
  The resolved paths are now written to $PR_REVIEWER_ROOT/env.sh unconditionally
  and appended to the env channel only when one is present.

- impactSummary is derived from the keys build-impact-graph.mjs actually emits.
  It read `impact.changed_exports`, which does not exist; the graph's own name
  is `symbols[]`. Every run reported `0 changed exports` — on lorekit#679, a
  diff whose graph holds 23 symbols (13 exported) and scores band: high. Adds
  changedSymbols, blastScore and the band's own `why` lines, so a `high` earned
  by a common identifier is distinguishable from one earned by a real export.

* fix(pr-reviewer): put the checkout where sub-agents can read it, and stop scoring grep collisions as blast radius

Both found by the first fanned-out review run against mthines/lorekit#679.

The workspace was materialized under os.tmpdir(). The host's file tools are
scoped to the agent workspace, so `/tmp/prr-clone-*` was not merely awkward —
the standards finder's sub-agent had `read`, `glob` and `cat` all REFUSED
against it, returned zero findings, and had to disclose that its empty result
meant "could not open the governing docs" rather than "the diff conforms".
A checkout now lands under $PR_REVIEWER_SCRATCH / /tmp/workspace, with
os.tmpdir() kept as the last rung for a host that has no workspace.

The impact graph resolved consumers by word-boundary grep alone. On #679 that
gave `metadata` — the Next.js route-segment export of app/page.tsx, which
nothing can import — 87 consuming files across 8 packages, and `wait`, a
non-exported helper the diff does not even change, another 27. Fourteen of
fourteen sampled hits were collisions: an audit record's `metadata:` property,
the English word in a comment, an unrelated `wait` method. blast_radius scored
260 / band high on that, which routes Phase C to `deep` — the most expensive
tier — on pure noise. gateConsumers() now intersects the grep hits with the
import edges importersOf() already resolves, for ES modules only (a Go or
Python same-package reference needs no import and is left alone), and records
`consumer_gate` on any symbol where it bit so an empty list is never misread as
"nothing depends on this".

* fix(pr-reviewer): read per-package tsconfig paths, or the consumer gate deletes real edges

A monorepo declares `"@/*": ["./src/*"]` in packages/<name>/tsconfig.json, not
at the root, and a paths target is relative to the config that declares it.
aliasMap read the root only, so every aliased import stayed unresolved — which
was survivable while importers were merely informational and is not now that
gateConsumers intersects consumers against them: an unresolvable alias reads as
"no file imports this module" and deletes real consumers.

Measured on mthines/lorekit#679, same commit, three runs:
  before the gate      band high, score 260 — 87 fake consumers on `metadata`
  gate, root alias only band low,  score 2   — real importers deleted too
  gate + this fix      band medium, score 17 — CopyCommand back to its 3 real
                       consumers (LandingHero, GetStartedCard, BlogPostCta),
                       every landing component back to page.tsx, and 192
                       `metadata` + 60 `wait` collisions still dropped

---------

Co-authored-by: mads.thines <[email protected]>
mthines and others added 6 commits October 11, 2026 04:57
# Conflicts:
#	packages/web/src/app/(auth)/login/page.tsx
…nto, honest next steps

Raises the PR's honest copy to a marketing page that sells:

- Hero leads with the problem and resolves it in one fixation
  ("Your coding agents forget. LoreKit remembers."), the README's own framing.
  The install command gets the amber frame and the page's only filled button;
  trust points move under it, to the moment of the click.
- The live demo becomes the hero's product shot, directly below it, and tilts
  flat as it scrolls in (CSS view() timeline, transform-only, flat at rest).
- New "01 / the problem" before/after, and a "03 / what you get" bento that
  absorbs MemoryCost and adds review-comment learning, one store for every
  tool, and grooming — each with a small picture of the behaviour.
- One heading system (mono numbered eyebrow, 30-36px title) and two repeated
  signature moves (lk-glow-frame, lk-gradient-text) across every section.
- Sticky blurred header; the Blog link from #685 now lives in the shared
  LandingHeader (the merge kept the slim /login).

Copy corrected against the CLI: install with a blank token still writes the
hosted MCP entry, so "works offline with no account" directly under the
command promised a setup one command does not produce. The hero and the
closing card now name both real paths — hosted (sign in, paste a token) and
offline (skip the token, switch to local mode) — at equal weight. Webhook
lessons are described as candidates that expire, matching webhook.ts.

Review findings applied: AuthHashCatcher comment no longer claims a move;
LandingBackdrop uses tokens, not hex; StepBadge replaces the duplicated
class; one GitHubMark replaces four inline copies of the SVG path.

Co-authored-by: dash0-dev[bot] <257284812+dash0-dev[bot]@users.noreply.github.com>
…flow

From review of the preview:

- Before/after: the speaker column was 44px, so "agent ›" wrapped its chevron
  onto a second line on every agent row, and the long memory.write row wrapped
  too — the two transcripts drifted out of day-for-day alignment. Columns are
  now sized in ch (nowrap), the rows are short enough to stay on one line, and
  the cards sit side by side only from lg.
- How it works: the README ASCII box rendered with its top-right corner one
  column short of the right edge, left-aligned in a frame twice its width, and
  the step cards' connecting rule showed only as stubs in the gaps. Replaced
  both with one flow — session A → memory.write → store → memory.list →
  session B — where each step is a node and the calls label the arrows
  (vertical below lg). Uses the same fix/ssr-window lesson as the live demo.
- Two-sentence headings put the gradient payoff on its own line instead of
  breaking mid-sentence ("…starts from / zero. Yours…").

Co-authored-by: dash0-dev[bot] <257284812+dash0-dev[bot]@users.noreply.github.com>
… CTA

Reuses the blog's reading model rather than inventing a second one:
ReadingTelemetry now mounts on / with contentType 'landing' (slug 'home'),
measured against the hero-to-closing-card wrapper. The home page therefore
emits the same content.scroll_depth / content.section_read / content.read
events as a blog post, split by lorekit.content.type.

- sections.ts is the single source of the eight section heading ids; every
  section imports its id from it and the page hands the ordered list to the
  telemetry, so a renamed heading cannot silently drop out of the data
  (sections.spec.ts pins the list).
- landing.cta_clicked (cta x placement, both closed unions) via one
  LandingLink for every link on the page: header, hero GitHub pill, the
  hero's hosted/offline choice, the closing card. get-token vs offline-guide
  from the hero is the direct read on which path visitors want.
- landing.demo_tab_selected: which demo use case a visitor picks (the
  auto-playing first tab is not counted).
- GetStartedButton (only caller was the closing card) folds into it as a
  tracked link.
- docs/otel.md: new landing.* table; the Content section no longer claims
  /docs is tracked — it never mounted ReadingTelemetry.

Co-authored-by: dash0-dev[bot] <257284812+dash0-dev[bot]@users.noreply.github.com>
…AUDE.md

The "01" example ("Zod, not Yup" written once, read back) argued for a
rules-file line, not for LoreKit. Replaced it with the thing a rules file
cannot do:

- "01 / why not just a CLAUDE.md?" — Your CLAUDE.md is frozen. Your lore
  keeps learning. A month in the life of one lesson, in four beats, each a
  shipped mechanic: LEARNS (agent writes it on friction, unprompted),
  RECALLS (a teammate's failing call gets it matched by the error text),
  PROMOTES (seen 3x -> permanent rule), PRUNES (unopened 90 days ->
  archived, restorable). Tries go 4 -> 1 -> 0, the loop closes back to the
  start, then a CLAUDE.md vs LoreKit table states it plainly — and positions
  LoreKit as how you find out what earns a place in your CLAUDE.md.
- Hero: "LoreKit remembers." -> "LoreKit makes them learn."; the lede now
  names the loop (write on friction, recall on the error, promote, archive).
- Live demo: the static "Code conventions" tab becomes "Promotion" — a CI
  flake seen for the third time gets promoted to a rule; next session is
  green first time. Tab telemetry id code-conventions -> promotion.
- Scroll-staggered card rise (lk-step) and a rail drawn as the section
  enters (lk-draw); transform-only, finished at rest.
- Section id the-problem -> learning-loop (sections.ts, docs/otel.md).

Co-authored-by: dash0-dev[bot] <257284812+dash0-dev[bot]@users.noreply.github.com>
…up + team

From the preview review:

- 01 visual bugs: the rail through the stage icons ran between each
  stage's day label and verb (labels sat beside the icon on the rail's
  line) — labels now sit under the icon. Transcripts get a fixed four-line
  height so outcomes line up across cards (no more bottom-pinned text with
  gaps). The "and round again" label no longer masks the dashed line with
  an opaque box that didn't match the glow; it sits under the line.
- 02 retold 01's loop (write -> store -> read). Now it answers how the day-4
  teammate got the lesson: connect each agent (install's real status lines;
  Cursor is three copied files), lessons stay with their repo (narrow ->
  broad scope ladder in the scope colours), one shared set for the team
  (bind repo::acme/* to the org; members read+write one copy, CI reads
  with an lk_ro_ token, unbound stays personal). "Wire it once. The whole
  team learns." No arrow labels to cramp.
- Bento: "One store for every tool" duplicated the new team step; replaced
  with "Every lesson in plain sight" (Lore Explorer + greppable markdown).

Co-authored-by: dash0-dev[bot] <257284812+dash0-dev[bot]@users.noreply.github.com>
@mthines
mthines marked this pull request as ready for review October 11, 2026 06:22
@mthines
mthines self-requested a review as a code owner October 11, 2026 06:22
@mthines
mthines merged commit f7a8f65 into main Oct 11, 2026
19 checks passed
@dash0-dev

dash0-dev Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor Author

Darkplane did not approve this pull request. Score 54.12 of 100, threshold 75. Blast radius 66, Evidence quality 66, Change footprint 30.

Darkplane did not approve this pull request. It scored 54.12 of 100, and 75 was required.

  • 🟡 Blast radius scored 66.
    The change is confined to the web package: new landing/* components, CSS, and additive analytics types in track.ts. It touches the public root route page.tsx, which used to redirect to /login, and the shared SiteFooter.tsx, LoginButton.tsx and CopyCommand.tsx. Revert is a plain git revert, with no migrations or backend changes. The size (about 2,250 source lines) and the auth-callback handling kept on / raise the risk, and I did not read the /login page or SiteFooter.tsx diffs.
  • 🟡 Evidence quality scored 66.
    CI is green on the head commit: Typecheck, Test & Lint (affected), Storybook interaction and visual tests, and the Vercel preview all succeeded. The PR adds tests for track.ts (track.spec.ts) and for the section ids (sections.spec.ts), and an automated review's findings were reportedly addressed. Against that, there are no human reviews, no tests for the many new landing UI components or for CopyCommand's size branch, and no landing Storybook stories. The author says a real-browser look was not done.
  • 🔴 Change footprint scored 30.
    This is a large hand-written change: 26 files and about 2,500 lines, including 12 new landing components and a rewrite of app/page.tsx and login/page.tsx. Most of it is presentational UI. The riskier parts are small: app/page.tsx keeps its auth-callback forwarding and signed-in redirect and adds an AuthHashCatcher, and track.ts gets new event types with tests. Nothing in it is mechanical.

An AI evaluator produced these scores from the diff, the repository history, and the pull request text. The pull request text is author-controlled, so treat the scores as signals rather than proof. Reviewed for commit 356c095.

Was this decision right? Give feedback

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