Stackon

What we shipped recently

A running log of Stackon’s evolution. Every meaningful change lands here.

  1. v0.99.53Shipped

    Meet Jarvis — Stackon Space gets a voice

    • Stackon Space opens onto something new: Simple mode, a voice-first stage with a single breathing Stackon mark. Talk to it — or type — and Jarvis does the rest: creates projects, dispatches real, traced Claude Code agents, watches your pull requests, and reports back out loud. Speech recognition runs fully on your machine (local Whisper), and the full workspace — now Advanced mode — stays one toggle away, exactly as you left it.
    • Agents that finish stay open, so a follow-up continues the same session with everything it already knows. Whatever needs you finds you: a chime sounds when an agent finishes or blocks, permission prompts land as approve / deny cards on the stage, consequential actions like merging a PR wait for your spoken yes, and steps only you can do appear as a “Waiting on you” checklist under the task’s card. Every task opens into a live, timestamped feed of its agent’s updates. Update from /download.
  2. v0.99.52Shipped

    GitHub, woven into Stackon Space

    • Stackon Space now keeps GitHub in your peripheral vision instead of behind a door. A new status chip in the footer always shows your current branch, its open pull request, and a live check-status dot — and one click takes you exactly where that state points: the PR itself, a pre-filled Create PR form for a branch that doesn’t have one yet, or a guided connect checklist if GitHub isn’t set up. Agent-lane cards show their branch’s PR and checks at a glance, too.
    • The GitHub button in the header opens a redesigned, roomier GitHub home: your open PRs with checks and review state beside a repo status card, with PR detail, reviews, and merging one click deep. Behind it all, Space now watches your branch and PR status continuously — refreshing when you return to the window, polling while checks are pending, and updating the moment you merge. Update from /download.
  3. v0.99.51Shipped

    Live Preview — see your app inside Stackon Space

    • Stackon Space gains a Preview pane: a toggleable rail that renders the web app you’re building, live, right beside your terminals and editor. Start your dev server in a terminal tab and Space detects it — reading your package.json scripts and probing the usual ports — then attaches with one click. Every hot reload your agents trigger shows up instantly.
    • The pane knows when your server stops (the frame dims with a rescan prompt), remembers the last URL per workspace, and includes Phone / Tablet / Full width presets for quick responsive checks. Toggle it from the footer, the View menu, or the command palette. Update from /download.
  4. v0.99.50Shipped

    The full PR conversation, inside Stackon Space

    • Stackon Space pull requests now have a Conversation tab alongside Files changed. It’s the whole story of the PR in chronological order — when it was opened, every comment, each review with its verdict, the commits as they were pushed, force-pushes, and the final merge or close.
    • You can join the discussion without leaving the app: a composer at the bottom of the timeline posts general PR comments straight through your own GitHub credentials, right next to the inline code review tools that already live in the diff view. Update from /download.
  5. v0.99.49Shipped

    Stackon Space sessions, captured as real traces

    • Stackon Space — our native desktop workspace — now records every traced terminal session as a complete Trace: real token cost, the model used, and the agent’s actual reply text for each turn. Open the trace in the web viewer and it updates live as the session runs.
    • Interactive prompts are captured faithfully too. When an agent asks you to choose from a menu, the trace shows the question and your selection, and splits the work and cost from before and after your answer into clean, separate turns — and each session closes with a clear End marker. Update from /download.
  6. v0.99.48Shipped

    Open pull requests from Stackon Space

    • Stackon Space — our native desktop workspace — can now connect to GitHub and drive your pull requests without leaving the app. A single GitHub button in the header opens everything: connect with the GitHub CLI, see your repo’s open PRs with live check status and review state, and merge or close them in place.
    • It’s built for the way agents work. Spin up an agent lane (an isolated branch and worktree), let an agent commit to it, then open a pull request straight from that lane — the branch is pushed and the PR drafted with the title pre-filled from your last commit. Sign-in uses your own gh credentials, and lane branches are kept after a merge by default so your parallel work stays intact. Update from /download.
  7. v0.99.47Shipped

    Stackon Space for Windows — signed, direct download

    • Stackon Space, our native desktop workspace, is now available for Windows as a direct download — head to /download. It’s the full Stackon ADE in a native window: real terminals, a Monaco editor, your missions and agents, and every session captured as a trace.
    • The installer is code-signed (Azure Trusted Signing), so Windows SmartScreen recognizes it instead of warning about an unknown publisher. An .msi is also available for IT and group-policy deployment. The macOS build is next.
  8. v0.99.46Shipped

    User Settings — your profile and two-factor auth

    • The account menu’s Settings link now opens a real User Settings page (it used to drop you on Team Members). Set your first and last name, phone, and title in one place — your display name stays in sync automatically. Your account email is shown read-only.
    • You can now add two-factor authentication: pair an authenticator app (1Password, Authy, Google Authenticator…) by scanning a QR code and confirming a 6-digit code, and remove it just as easily. This is the setup half — enforcing the second factor at sign-in is a follow-on update.
  9. v0.99.45Fix

    The dashboard sweep wraps up — plus a clickable audit history

    • Brought the last set of surfaces onto the same instrument-panel look as the rest of the dashboard — the Overview, Approvals, Cost, Compliance, and Forge, plus the Compute, Team, Billing, API tokens, and Devices pages. Every action across them now confirms with the same non-disruptive notice from the top of the screen, so the whole signed-in dashboard finally reads as one consistent instrument.
    • A few targeted improvements rode along: the audit log on Compliance is now clickable — each row drills straight into the trace, run, or resource it records; the 30-day spend graph on Cost and the Overview reads in white; audit retention is capped at a clean 7–365 days; and the Billing plan comparison is tidied up with centered columns and corrected copy.
  10. v0.99.44Fix

    A cleaner, more consistent Webhooks — and the dashboard is uniform throughout

    • Brought the Outgoing webhooks settings onto the same instrument-panel look as the rest of the dashboard — the create form, the endpoints table, and each webhook’s detail (events, signing secret, and the delivery log). Creating, testing, retrying, enabling, disabling, or deleting a webhook now confirms with the same non-disruptive notice from the top of the screen as the rest of the dashboard. This is the last area in a sweep that brought every dashboard surface onto one consistent look.
  11. v0.99.43Fix

    A cleaner, more consistent Scribe

    • Brought the Scribe area onto the same instrument-panel look as the rest of the dashboard — the skills list, the Distill a skill form, and each skill’s detail. Distilling, saving, or deleting a skill now confirms with the same non-disruptive notice from the top of the screen as the rest of the dashboard.
  12. v0.99.42Fix

    Confirmation notices no longer replay on back-navigation

    • Fixed a glitch where a “created / saved / deleted” confirmation notice would pop again when you left a page and navigated back to it — even though you hadn’t repeated the action. The notice now clears itself from the page’s history entry the moment it shows, so returning never replays it; repeating an action still confirms each time.
  13. v0.99.41Fix

    A cleaner, more consistent Adversary

    • Brought the Adversary area onto the same instrument-panel look as the rest of the dashboard — the campaign list, the New Campaign form, and each campaign’s detail. The threat-posture headline now reads as a status dot + label, and running a campaign, re-running one, or deleting one confirms with the same non-disruptive notice from the top of the screen as the rest of the dashboard.
  14. v0.99.40Fix

    A cleaner Knowledge area — and toasts that confirm what you did

    • Brought the Knowledge area onto the same instrument-panel look as the rest of the dashboard — the corpus, the New Source form, and each source’s detail. We also unified action feedback across the whole dashboard: creating a mission, canvas, agent, eval, gate, or knowledge source — and ingesting or deleting a source — now pops the same non-disruptive confirmation from the top of the screen, so an action never leaves you guessing whether it landed.
  15. v0.99.39Fix

    A cleaner, more consistent Agents

    • Brought the Agents area onto the same instrument-panel look as the rest of the dashboard — the roster, the New Agent and agent-edit forms, and the one-shot Quick run. Creating, updating, archiving, or restoring an agent now confirms with a non-disruptive notice from the top of the screen instead of an inline banner that shifts the page.
  16. v0.99.38Fix

    A cleaner, more consistent Canvas

    • Brought the whole Canvas area onto the same instrument-panel look as Traces, Evals & Missions — the pipeline list, the New Canvas form (its starter-template roles now read in their own colors), the canvas editor, node editing, and the full version history (snapshots + diffs). The editor’s configuration — Team Knowledge, Approval Gate, Commit, and Publish to Forge — now sits under one collapsible Canvas settings panel, so the page leads with the pipeline and the run. And every canvas action — adding, moving, or removing a node, toggling knowledge or approvals, committing, publishing, posting a comment, or deleting the canvas — now confirms with a non-disruptive notice from the top of the screen instead of shifting the page.
  17. v0.99.37Fix

    Header menus hold the page still

    • Opening a header menu — Product, Community, Company, or the mobile menu — now freezes the page behind it until you close it, so the page no longer scrolls away under an open dropdown. The lock compensates for the scrollbar width, so nothing shifts when a menu opens.
  18. v0.99.36Fix

    A cleaner, more consistent Missions

    • Brought the Missions board, the mission thread, and the New Mission form onto the same instrument-panel look as Traces & Evals. Each agent reply in a thread is now a tidy collapsible row — with In / Out / Cost and an Open Trace button; lane and mission status read as a colored dot + plain label; and action feedback (approvals, run errors) now arrives as a non-disruptive notice from the top of the screen instead of shifting the page.
  19. v0.99.35Fix

    A consistent Kind label across Evals

    • The Kind column in the Evals list now matches the eval detail view — a kind-colored dot with a plain white label instead of colored text — so the two read the same at a glance.
  20. v0.99.34Fix

    A cleaner New Eval form and PR-blocking gates

    • Continued the dashboard consistency pass through the rest of the Evals area. The New Eval form now shows only the configuration for the grader you pick — an output-contains string check or an LLM judge rubric — rather than both at once, and eval kinds read consistently as Output Contains / LLM Judge throughout. The PR-blocking gates list and detail now match the same instrument-panel look, and the copy-paste CI workflow references a STACKON_API_TOKEN secret.
  21. v0.99.33Fix

    A cleaner, more consistent Traces & Evals

    • Refined the Traces and Evals dashboards onto one consistent instrument-panel look — decluttered headers, run status as a colored dot + plain label (green completed / amber running / red failed), boxed metrics, and a single click-to-expand span timeline & details on every trace. The first wave of a dashboard-wide consistency pass.
  22. v0.99.32Fix

    Stop a mission run — and no more runs stuck “in progress”

    • Two fixes for runaway runs: a live mission now shows a Stop run button that ends it and unsticks the board immediately, and any run abandoned by an interrupted background task is automatically marked failed after 10 minutes (with a note in the thread) instead of spinning “in progress” forever.
  23. v0.99.31Fix

    A clear path when a mission isn’t ready to run

    • A mission runs a bound canvas of agents, so it needs one with at least one agent before it can start. Instead of a silently disabled composer, you now get a Setup needed panel that names exactly what’s missing and fixes it in one step — attach an existing canvas from a dropdown, build a new one, or jump to the bound canvas to add agents.
  24. v0.99.30Fix

    Opening a trace the instant a run starts

    • Clicking Open trace in the first moment of a live run used to hit a “not found” page — the trace was still being written. It now shows a brief Initializing run state that resolves into the real trace the instant it begins streaming, so the link always lands somewhere useful.
  25. v0.99.29Fix

    Signing in without an account now points you the right way

    • Enter an email that doesn’t have a Stackon account on the sign-in page and we now take you straight to sign-up — with the address already filled in — instead of quietly “sending” a link that could never arrive.
  26. v0.99.28Fix

    A more focused dashboard overview

    • Removed the redundant “Jump to” shortcut row from the dashboard overview — the left sidebar (and ⌘K) already cover navigation, so the overview now stays on your live signal: spend, runs, eval health, and what needs you.
  27. v0.99.27Fix

    Dashboard chrome, tuned to the brand

    • The dashboard now sits on the same black-and-smoke palette as the rest of stackon.ai — the faint green cast behind the workspace is gone — and the top-bar breadcrumb (Stackon / <page>) now shares the brand display typeface with the page title, so the chrome reads as one consistent surface.
  28. v0.99.26Infra

    A reproducible database, from scratch

    • Behind the scenes: Stackon’s entire database schema now lives in version-controlled migrations and is verified byte-for-byte identical to production — so a clean environment can be stood up from nothing. Reliability groundwork for staging and self-hosting; no change to the product itself.
  29. v0.99.25Fix

    Canvas leads the workspace

    • The dashboard’s Workspace nav now opens with Canvas — the first step when you start a project — ahead of Missions, matching the natural build order.
  30. v0.99.23Shipped

    Your sign-in link now tells you when it lands

    • When you request a magic link, the sign-in confirmation now updates the moment your email is actually delivered — the “in flight” signal settles into a Delivered receipt (or flags a bounce) in real time, so you’re never left wondering whether it’s on the way. Built on real delivery events, not a timer.
  31. v0.99.21Fix

    A more polished sign-in

    • After you request a magic link, the confirmation on the sign-in screen is now a refined smoke-glass panel in the same telemetry style as the dashboard — replacing the old green box. A subtle “in flight” signal traces toward its destination, so it’s clear at a glance that your link is on its way.
  32. v0.99.20Fix

    Fixed: dashboard search & command palette

    • The top-right search and the command palette now open correctly — clicking search previously threw an error. The shortcut hint is also OS-aware now: ⌘K on macOS, Ctrl K on Windows and Linux.
  33. v0.99.19Fix

    A more cohesive dashboard typeface

    • Dashboard headings and key metrics now use Stackon’s display typeface — the same one across stackon.ai — so the workspace and the marketing site read as one product. A small follow-on to the dashboard redesign.
  34. v0.99.18Shipped

    A redesigned dashboard — and navigation that finally fits

    • Navigation moved off the cramped top bar into a collapsible left sidebar, grouped the way you actually work — Workspace, Observability, Extend, and Settings. It sits as a slim icon rail by default, expands on hover, and pins open when you want it to stay. Search (⌘K) and your account moved to a clean top bar.
    • Every screen — Traces, Cost, Evals, Missions, Canvas, Agents, Adversary and the rest — was rebuilt into one cohesive mission-control look: telemetry-style readouts, live status signals, and corner-framed panels, all in the same black-and-smoke palette. Same data and actions, a far sharper surface.
  35. v0.99.17Fix

    Model Updates moves to /model-updates

    • The model-release feed now lives at /model-updates — a URL that finally matches what the page is. The old /blog address permanently redirects there, so every existing link and bookmark keeps working.
  36. v0.99.16Shipped

    Redesigned product pages — and Stackon Space joins the lineup

    • Every product now has a polished, public pageTrace, Evals, Cost, Canvas, Missions, Bridge, the MCP server and the rest — each with a hero, a live visual of the actual product, deep-dive sections, and cross-links to the rest of the platform. Browse them from the Product menu or the /product hub — no sign-in required.
    • New on the lineup: Stackon Space, the native desktop workspace — real terminals, a code editor, your missions, and your agent roster in one window, where every Claude Code session you spawn lands back in Stackon as a replayable trace. See the page; Mac & Windows builds are coming to /download.
  37. v0.99.15Shipped

    Stackon MCP & Bridge are now on npm

    • The Stackon MCP server and Bridge daemon are now published packages — install them in one line with npm i @stackon/mcp or npm i @stackon/bridge.
    • Stackon MCP connects your workspace to Claude Code, Cursor, Windsurf, Codex, or Zed, so every agent run emits a Trace span and you can run evals straight from your editor. Bridge points agents at your own compute — your laptop, a GPU box, or your VPC — with nothing leaving your infrastructure.
    • Every install snippet across the site and docs now resolves to a real package.
  38. v0.99.14Shipped

    A clearer site — public product pages + a sharper home

    • Every part of the platform now has its own public pageTrace, Evals, Cost, Canvas, Missions, Bridge, the MCP server and more, browsable from the new Product menu and the /product hub. No sign-in required to see what each one does.
    • The home page leads with what Stackon actually is — “Run AI agents on your codebase, and prove they got better” — plus an “up and running in 60 seconds” walkthrough (create a token, add the MCP server, watch it land in Trace).
    • And it’s self-serve: start free from anywhere, no waitlist. Cleaner nav and footer to match.
  39. v0.99.13Shipped

    Dashboard — an analytical home screen

    • The dashboard home is now a real command center instead of a grid of links. At a glance: this month’s spend (against your budget), runs today, your 30-day eval pass-rate, and failed runs in the last week.
    • Below the numbers, a 30-day spend trend, your most recent traces, what’s awaiting approval, and your active missions — each linking straight to the detail. A brand-new workspace gets a guided “get your first trace flowing” panel instead of an empty screen.
  40. v0.99.12Shipped

    Blog — now sourced directly from the model labs

    • The Blog is now a first-party feed: every update comes straight from the AI labs’ own sitesAnthropic (Claude), OpenAI (ChatGPT), Google (Gemini), xAI (Grok), Meta (Llama), Mistral, and DeepSeek — with no news aggregators or third-party rewrites in the mix.
    • OpenAI and Google publish proper feeds; for the labs that don’t, we read their official release-notes / news pages directly. Corporate noise (funding, hiring, office openings) is filtered out so the feed stays focused on model launches and updates, newest first.
  41. v0.99.11Shipped

    A more modern typographic voice

    • Refreshed the typeface behind every headline across the site — from the landing page’s “Ship faster. With receipts.” to section titles like “Four products. One workflow.” — swapping the previous editorial serif for Hanken Grotesk, a contemporary grotesque that reads cleaner and more technical next to the product.
    • It’s a single design-token change under the hood, so the new voice is consistent everywhere headlines appear, and the page stays fast (the above-the-fold headline font is still preloaded).
  42. v0.99.10Fix

    Blog — cleaner, more readable cards

    • Tidied up the Blog feed. News items pulled from Google News were showing raw link markup in their summary (a long redirect URL bled across the card) — now each card shows a clean headline with the original publisher (e.g. “via Yahoo Finance”) and links straight to the source.
    • The cards themselves got a polish pass: equal heights in a tighter grid, titles and excerpts that clamp cleanly instead of overflowing, a subtle staggered reveal, and source filters that no longer show empty 0 categories.
  43. v0.99.9Shipped

    Billing — manage your subscription in Settings

    • Settings → Billing is now a real page: see your current plan, how many seats you’re using against the plan’s limit, and an estimated monthly cost — with a side-by-side plan comparison and one-click upgrade.
    • This is the subscription surface (plan, seats, payment method, invoices) — distinct from the Cost dashboard, which tracks your token spend. Each page links to the other so it’s always clear which dollars you’re looking at.
    • Payment method and invoice management open in a secure Stripe billing portal when billing is configured; until paid plans are switched on, the page shows an honest “nothing to bill yet” state rather than an empty placeholder. Plan and payment changes are limited to workspace owners and admins.
  44. v0.99.8Shipped

    Blog — a live feed of AI-engineering news

    • The Blog is live — a real-time digest of what’s happening across Claude (Anthropic), Codex (OpenAI), and the broader AI-engineering world, pulled automatically from the source.
    • It aggregates a curated set of official and topic feeds — OpenAI, Hugging Face, Google DeepMind, Simon Willison, Latent Space, and live Anthropic/Codex coverage — into one clean, filterable grid of headlines and short excerpts, with every card linking straight to the original.
    • The page refreshes itself on a timer (no manual updates, no database), and each source is fetched independently — so if one feed is briefly unreachable, the rest of the page is unaffected and it reappears on the next refresh.
  45. v0.99.7Shipped

    Stackon Space — sessions now record real cost, tokens &amp; a readable transcript

    • Every Claude Code session you launch from Stackon Space already becomes a replayable trace — now those traces carry real dollar cost and token counts instead of zeros. When a traced session ends, Stackon Space reads Claude Code’s own session transcript and backfills the trace with input/output tokens, cache usage, the model used, and a computed cost.
    • The trace’s Outputs now show a clean conversation — the actual user prompts and model replies (with compact [tool: …] markers) — instead of raw terminal redraw noise, rendered in the same readable view as Inputs and Attributes with a one-click JSON toggle.
    • Each turn is now its own span built from the transcript — with the prompt, the assistant’s clean reply, and its own cost, tokens, and duration — so you can see exactly what each step did and what it cost (replacing the old keystroke-guessed turns that captured terminal spinner noise).
    • This makes the desktop’s session→trace bridge actually answer the question Trace exists for — what did this run cost, and what happened? — so spend shows up in the trace list, the trace detail, and the Cost dashboard like any other run.
    • Under the hood we pin a session id at launch (--session-id) so each trace maps deterministically to its transcript, and cost is computed from the same per-model pricing table the web runner uses (cache reads/writes priced correctly, not as full-price input).
  46. v0.99.6Shipped

    Stackon Space — find in the terminal (Ctrl/⌘+F)

    • The Terminal pane now has a find bar: press Ctrl/⌘+F with a terminal focused to search the scrollback, with match-case, whole-word, and regex toggles and a live match counter.
    • Enter / Shift+Enter jump between matches and Esc closes the bar; matches highlight in the brand emerald as you type. When the editor pane is focused, Ctrl/⌘+F still reaches Monaco’s own find — the shortcut is only claimed for the active terminal cell.
  47. v0.99.5Shipped

    Trace — readable span detail, with a raw-JSON toggle

    • A trace’s Inputs, Outputs, and Attributes now render in a human-readable view by default instead of raw JSON — user messages and model output read as plain text (real line breaks, no escaped \n or wrapper braces), chat transcripts render as a conversation, and attribute objects render as a tidy key/value list.
    • Every box keeps a Readable / JSON toggle in its header, so the exact raw payload is always one click away — nothing is hidden, just easier to read.
    • The span list also previews each turn’s user input inline, so you can scan what every step was about without expanding it.
  48. v0.99.4Shipped

    Stackon Space — fuzzy-match highlighting in Quick Open + Command Palette

    • Quick Open (Ctrl/⌘+P) and the Command Palette (Ctrl/⌘+Shift+P) now highlight the characters that matched your query — so you can see at a glance why each result ranked where it did, the same way VS Code does it.
    • The two overlays shared a near-identical fuzzy scorer; that logic now lives in one place and additionally reports which characters matched, so the highlight comes for free with no change to ranking.
  49. v0.99.3Fix

    Stackon Space — smooth terminal resizing

    • Fixed the terminal jittering / flickering at certain pane sizes while dragging a splitter (most visible maxing the terminal against the Tasks pane). At boundary heights the terminal’s scrollbar rapidly appeared and disappeared, which nudged the column count and reflowed the text, re-triggering itself — a fast feedback loop.
    • The fix reserves a stable scrollbar gutter so the bar’s appearance can’t change the usable width, only re-fits when the pane’s actual pixel size changes (one fit per frame), and clips transient overflow — so dragging stays smooth.
  50. v0.99.2Infra

    Stackon Space — close from the rail + a prompt when nothing's open

    • The × next to the open workspace in the rail now closes it (editor + terminals together), not just removes it from the recent list. The × on a workspace that isn’t open still just forgets it from recents.
    • When no workspace is open, both the Terminal and Editor panes now show a prompt to New Workspace or Open folder… instead of a stray home-directory shell — terminals are workspace-scoped, so you start one by opening a workspace.
  51. v0.99.1Fix

    Stackon Space — closing a workspace closes its terminals

    • Closing a workspace now closes the editor and that workspace’s terminals together. Before, the terminals stayed running in the background after the workspace was closed; now they’re shut down with it (the PTYs are killed), and reopening the workspace starts fresh. Switching between workspaces still keeps each one’s terminals alive — only an explicit close tears them down.
  52. v0.99.0Shipped

    Stackon Space — workspace presets (one-click launch)

    • Save a workspace setup once, relaunch it in a click. In the New Workspace Layout step, the Presets row holds saved bundles — a folder, a terminal count, and an optional agent. Click a preset chip and that workspace opens immediately with that exact layout (the agent running in one terminal, traced), skipping the rest of the wizard.
    • + New saves the folder + terminal count you’ve set, with an optional agent picked from your roster; hover a chip to delete it. The agent is resolved fresh at launch, so editing or removing it later never launches a stale snapshot.
  53. v0.98.0Shipped

    Stackon Space — guided workspace setup

    • New Workspace is now a short three-step flow — Start → Layout → Agents. Pick (or create) a folder, choose how many terminals to open and how they’re laid out (1 / 2 / 4 / 6 / 8 / 10 / 12, in a grid), then either add an AI agent or Open without AI for just the terminals.
    • Nothing opens until you finish, so you get exactly the layout you asked for — N terminals in a grid, with the agent you chose running in one of them, recorded as a Stackon trace. Recent workspaces are one click away at every step.
  54. v0.97.0Shipped

    Stackon Space — parallel agent lanes (git worktrees)

    • Run several Claude agents on the same repo at once without them stepping on each other. Agent lanes — the button in the Terminal pane, or the command palette — create a git worktree: a separate working directory on its own branch sharing the repo’s history. A Claude session spawns pinned to it, so each agent edits its own files on its own branch and two of them never fight over the same file or the git index.
    • Spin up a few lanes (each can wear one of your roster agents), watch them side by side in the terminal grid, then remove a lane when you’re done — the branch stays so you can merge its work. Lanes live in a <repo>-worktrees/ folder next to your project, and each session is recorded as a Stackon trace like any other.
  55. v0.96.0Infra

    Consistent page headers across the dashboard

    • Every dashboard page — Traces, Canvas, Evals, Agents, Missions, Cost, Knowledge, settings, and every detail / new / edit screen — now draws its header from one shared component. The eyebrow, title, description, back-link, action buttons, and per-page stat line render identically, so the app reads as one surface instead of ~40 hand-built variations.
    • Lead pillars (Trace, Evals, Approvals) carry an emerald accent dot; detail pages use a two-column layout with status badges and actions aligned to the header. Purely presentational — no behavior changed.
  56. v0.95.0Shipped

    Stackon Space — light theme

    • Stackon Space now ships a light theme alongside the default dark. Flip it in Settings → Appearance; the choice persists and applies live — the whole workspace, the Monaco editor, the terminals, and the markdown preview all re-tone together, no relaunch.
    • Dark stays the default; light is one toggle away.
  57. v0.94.0Infra

    Reorder Stackon Space editor tabs

    • Drag an editor tab along the strip to reorder your open files, the same way the Terminal pane tabs already work. The order sticks while you work.
  58. v0.93.0Infra

    Syntax highlighting in the markdown preview

    • Fenced code blocks in the Stackon Space markdown preview now get syntax highlighting, brand-toned to match the editor. The highlighter is bundled in the app, so it works fully offline.
  59. v0.92.0Shipped

    Stackon Space terminals stay alive per workspace

    • Switching between workspaces no longer kills their terminals. Running claude sessions and long-lived shells keep going in the background and are right where you left them when you switch back.
    • Only the current workspace’s terminals are shown; the rest stay mounted and hidden — so a swarm running in one project survives while you hop to another.
  60. v0.91.0Infra

    Stackon Space terminals are scoped to each workspace

    • Open terminals now belong to the workspace you opened them in, instead of being shared across every project. Switch workspaces and you see that project’s terminals — not a pile of unrelated shells.
  61. v0.90.0Shipped

    Stackon Space — open or create a workspace folder

    • The New Workspace flow can now create a folder, not just open an existing one: pick a parent directory, name it, and Stackon Space makes it and opens it. And the editor’s plain Open folder… is back as a one-click switch for when you just want to point at a directory.
  62. v0.89.0Shipped

    Stackon Space — a real New Workspace flow

    • “New Workspace” is now the front door. Step one picks the folder — your project root, which sets the editor root, the terminal working directory, and the trace context. Step two picks or creates the agent or mission to start with. Opening a workspace is one coherent action instead of separate folder + session steps.
  63. v0.88.0Shipped

    Stackon Space — commit history in the Changes rail

    • The git Changes rail gains a Recent commits list — the last 30 commits with short hash, subject, relative time, and author. It refreshes after you commit or sync, so you can watch your work land without leaving the app.
  64. v0.87.0Shipped

    Stackon Space — branch, push & pull from the Changes rail

    • The Changes rail now shows your current branch (⎇ main) and how far ahead / behind your upstream you are, with Push and Pull buttons right there. Each shows an inline result (“Pushed ✓” / “Already up to date”) so you know it worked.
    • Sync uses your operating system’s git credentials — the same ones the git command line uses — independent of how you signed in to Stackon Space. An uncached credential fails fast instead of hanging.
  65. v0.86.0Shipped

    Stackon Space — stage & commit from the Changes rail

    • Commit without leaving Stackon Space. The Changes rail lists changed files with a stage checkbox each (plus Stage all), a commit-message box, and a Commit button — the basic add / commit loop, right in the workspace. Ctrl/Cmd+Enter commits.
  66. v0.85.0Shipped

    Stackon Space — git diff viewer

    • A new Changes tab in the editor rail shows your git working-tree changes. Pick a file and it opens a read-only side-by-side diff (the same Monaco diff engine VS Code uses) of HEAD vs. your working copy, overlaid on the editor.
    • Reads your repo through git directly, pinned to the repository root; degrades gracefully when the folder isn’t a git repo or git isn’t installed.
  67. v0.84.0Shipped

    Stackon Space — markdown preview

    • Open a .md or .mdx file and a Preview toggle appears in the tab strip — flip it for a rendered, side-by-side view that mirrors your edits live. Links open in your browser; the renderer blocks script and javascript: URLs so a README can’t do anything funny.
  68. v0.83.0Shipped

    Stackon Space — create, rename & delete files from the tree

    • Right-click any file or folder in the editor tree for New file, New folder, Rename, and Delete (right-click empty space for new file / folder at the root).
    • It’s careful with open buffers: renaming remaps the tab, and a rename is refused if the file has unsaved changes rather than risk losing them.
  69. v0.82.0Fix

    Stackon Space editor works offline

    • The Monaco editor used to load its engine from a CDN, so it came up blank with no internet. Its assets are now bundled with the app and served locally — the editor works fully offline, on a plane or behind a firewall.
  70. v0.81.0Infra

    Stackon Space — a File menu

    • The editor toolbar’s five buttons (New file, Open folder, Save, Save all, Close) are tidied into a single File ▾ dropdown, with the unsaved-changes count riding on the menu as a badge. Click out or press Esc to close it.
  71. v0.80.0Shipped

    Stackon Space — create agents & missions from the workspace

    • The new-workspace wizard can now create an agent or a mission inline, not just pick an existing one. Fill the short form, hit Create & start, and it’s saved to your team and a traced claude session spins up in the workspace. The rows are real — they show up on the web dashboard too.
  72. v0.79.0Shipped

    Stackon Space — start-a-session wizard

    • Open a workspace for the first time and a wizard offers to start you working: pick one of your agents or missions and it spawns a traced claude session pinned to that folder, or start a blank terminal, or skip. Reachable any time from the command palette via “Start session in workspace…”.
  73. v0.78.0Infra

    Stackon Space — a real workspace switcher

    • The left rail is now a live list of your recent workspaces instead of a placeholder. Click one to switch the editor, terminals, and trace context to it; hover to remove it from the list. Opening a new folder records it automatically.
  74. v0.77.0Infra

    Stackon Space — more command-palette actions

    • The command palette (Ctrl/Cmd+Shift+P) gains Save file, Replace in files, and Close workspace, and the rail’s “Open folder” button is now wired up. Opening Replace-in-files from the palette reveals the replace row in the Search panel.
  75. v0.76.0Shipped

    Find-and-replace — per file and per match

    • Stackon Space find-in-files replace gets finer-grained: hover a file’s result group to replace every match in just that file, or hover a single match to replace only that one occurrence. The global Replace All keeps its confirmation step; the targeted replaces are one click.
  76. v0.75.0Shipped

    Stackon Space — font, tab size & scrollback settings

    • Settings adds editor + terminal font family, editor tab size, and terminal scrollback, all applied live. Font family is shared across editor and terminal and falls back to the built-in mono if you type a name that isn’t installed, so it never renders broken.
  77. v0.74.0Shipped

    Stackon Space — find and replace across files

    • The Search panel gains a replace row and a global Replace All (with a two-click confirm, since it writes to disk). Files you have open in the editor are edited through the editor itself so the change stays undoable; files with unsaved changes are skipped and reported rather than clobbered.
  78. v0.73.0Infra

    Find-in-files — search as you type

    • Stackon Space find-in-files now searches as you type (debounced, kicking in at two characters so a single letter doesn’t scan the whole tree). Enter still forces an immediate search at any length, and toggling case / whole-word / regex re-runs in place.
  79. v0.72.0Shipped

    Find-in-files — regex & whole-word

    • Stackon Space workspace search gains two toggles next to the case switch: whole-word (\b) and regular expressions (.*). Matches highlight at their true length, and an invalid pattern shows a clear “Invalid regular expression” note instead of silently returning nothing. Plain-text searches keep the fast path.
  80. v0.71.0Infra

    Stackon Space — the focused pane is highlighted

    • Phase 7H wraps. The Terminal or Editor pane that currently holds keyboard focus now gets an emerald frame border and a brighter title — so it’s always obvious which pane Ctrl/Cmd+W will close a tab in. Click between panes and the highlight follows; open the command palette and it stays put on the pane you were last working in.
    • Backed by a tiny observable store (useSyncExternalStore) the panes update on focus. Tasks and Agents never highlight — they aren’t Ctrl+W targets.
  81. v0.70.1Shipped

    Stackon Space — close the active tab (Ctrl/Cmd+W)

    • Ctrl/Cmd+W (and a "Close active tab" palette command) closes the active tab of whichever pane has keyboard focus — terminal or editor. It resolves the target from where your cursor actually is at the moment you press it, so it never closes the wrong pane; when focus is in the command palette it falls back to the pane you were last in.
    • The shortcut is intercepted so it can never close the Stackon Space window itself.
  82. v0.69.0Shipped

    Stackon Space — command palette + global shortcuts

    • Ctrl/Cmd+Shift+P opens a command palette: a fuzzy-filtered list of actions — new terminal, open folder, quick-open, find in files, save all, toggle the terminal grid, settings, sign out — each row showing its keyboard shortcut, so the palette doubles as a way to learn them. Plus two new direct shortcuts: Ctrl/Cmd+T for a new terminal and Ctrl/Cmd+B to toggle the workspace rail.
    • Actions route through a small command bus so the shell-level palette can drive any pane. It joins the shortcuts already in place — Ctrl/Cmd+P quick-open, Ctrl/Cmd+Shift+F find-in-files, Ctrl/Cmd+S save, Ctrl/Cmd+, settings.
  83. v0.68.0Shipped

    Stackon Space — settings / preferences

    • A real preferences pane lands, reachable from the header or Ctrl/Cmd+,. Set editor and terminal font size, the default shell new terminals launch, and terminal cursor blink + style. Font and cursor changes apply live to every open pane — no relaunch — and everything persists across sessions via the same store the workspace folder and tabs already use.
    • Default shell is a free-text field (e.g. pwsh.exe, cmd.exe); leave it blank to auto-detect. The plumbing makes new controls cheap to add.
  84. v0.67.0Infra

    Stackon Space — new terminals open in your workspace

    • New terminals now start in the Editor’s workspace folder instead of your home directory. + New, drag-spawns from Tasks/Agents, and restored tabs all resolve the current workspace — so a fresh shell is already in the project you’re working on. Change the workspace folder and the next terminal follows it.
    • The path is read fresh at spawn time, and Stackon Space falls back to your home directory if that folder has since moved or been deleted — a stale path never breaks the spawn.
  85. v0.66.0Shipped

    Stackon Space — find in files

    • Search your whole workspace from the Editor, not just the open file. Ctrl/Cmd+Shift+F flips the left rail to Search; type a query, press Enter, and matches stream in grouped by file with the hit highlighted. Click any result to open that file as a tab and jump straight to the line.
    • Built like quick-open — it reuses the workspace index, skips vendor/build folders, reads files concurrently in batches so a few-thousand-file repo stays responsive, skips binaries, and caps results. A case-sensitive toggle is included; regex / whole-word and search-as-you-type are the next slice.
  86. v0.65.0Fix

    Stackon Space Editor — undo + cursor survive tab switches

    • Phase 7C.2. Switching editor tabs no longer resets your place. Each open file now keeps its own Monaco model, so undo/redo history and your cursor + scroll position are preserved when you jump between tabs and back — the editor feels continuous, like VS Code.
    • Under the hood the editor drives models keyed by file URI (handling Windows C:\ paths correctly) and saves/restores per-file view state, instead of remounting per file. Models are disposed when you close a tab or switch workspaces.
  87. v0.64.0Shipped

    Stackon Space — quick-open (Ctrl/Cmd+P)

    • Jump to any file without hunting the tree. Ctrl/Cmd+P opens a fuzzy file finder over your whole workspace — type a few characters, arrow to a match, Enter to open it as a tab. Heavy/vendor folders (node_modules, .git, build output) are skipped and the index is capped so big repos stay snappy.
    • VS Code-style: the shortcut is captured app-wide once a workspace is open (so it beats the browser print dialog and the terminal’s Ctrl+P). With nothing open, Ctrl+P passes through to the terminal as before.
  88. v0.63.0Shipped

    Stackon Space Editor — create files + Save all

    • The Editor can now create files, not just open them. + New file takes a workspace-relative path (notes.md, src/foo.ts), writes it to disk, and opens it as a tab. And Save all (Ctrl/Cmd+Shift+S, or the toolbar button showing the dirty count) writes every unsaved buffer at once.
    • Writes stay inside Tauri’s scoped filesystem; creating into a folder that doesn’t exist yet surfaces a clear error (no implicit directory creation for now).
  89. v0.62.0Shipped

    Stackon Space Tasks — live list + status control

    • The Tasks pane mission list now updates live too: missions you create or move on the web appear and re-sort in Stackon Space without a refresh (Supabase Realtime postgres_changes on missions, team-scoped by RLS). With the live transcript from the previous build, the whole Tasks pane is now real-time.
    • And it’s no longer read-only — change a mission’s status (backlog → in progress → done → …) right from the desktop via the status dropdown. The change is row-level-security gated to your team and syncs back to the web instantly.
  90. v0.61.0Shipped

    Stackon Space Tasks update live

    • The Tasks pane mission transcript now updates in real time, matching the web. Open a mission in Stackon Space and watch agent replies, system notices, and teammates’ messages stream in as they happen — no reselecting. A small ● live marker shows when the thread is connected.
    • Same Supabase Realtime postgres_changes path as the web thread, gated by the same row-level security — you only ever receive your own team’s messages.
  91. v0.60.1Infra

    Stackon Space remembers your open files

    • Your Editor tabs now come back on relaunch, alongside the terminal tabs and workspace folder. Open files (and the active one) are remembered per workspace and re-read from disk on reopen — so the whole Stackon Space session restores where you left it.
  92. v0.60.0Shipped

    Stackon Space Editor — open files in tabs

    • Phase 7C.1. The Editor pane now holds multiple files open at once. Click files in the tree to open them as tabs, switch between them, and close individually — each tab tracks its own unsaved-changes dot, and switching keeps your edits in place. Open files are marked in the file tree too.
    • Ctrl/Cmd+S saves the active tab. One Monaco instance still drives the active buffer (per-buffer undo history + cursor across switches is the next polish), and every write stays inside Tauri’s scoped filesystem (HOME / Documents / Desktop / Downloads).
  93. v0.59.1Infra

    Reorder Stackon Space terminal tabs

    • Small polish on the Terminal pane: drag a tab along the strip to reorder it. The order (and which tab is active) persists across relaunches, and reordering reflows the grid view too. No session restarts — you’re just rearranging.
  94. v0.59.0Shipped

    Stackon Space — see all your terminals at once

    • Phase 7B.2 lands. A new grid toggle (▦) in the Terminal pane flips between tabs and an N-cell grid — every running terminal visible at once, laid out automatically (two-up, 2×2, up to a 3-wide grid). Drive a swarm of claude sessions side by side, or watch a mission run next to a live shell.
    • Tabs and grid are the same terminals, just arranged differently — toggling never restarts a session (the PTYs stay alive; each terminal just reflows to its new size). The active cell is ringed; click any cell to focus it. Your layout choice persists across relaunches alongside the tab strip.
  95. v0.58.0Shipped

    Stackon Space remembers your terminals

    • Phase 7B.2. The Terminal pane tab strip now persists across relaunches. Quit Stackon Space and reopen it — your tabs come back in the same order, with the one you were on still active. Built on the same tauri-plugin-store the workspace folder and sign-in already use.
    • A shell session can’t survive a restart (the process is gone when the app quits), so restored tabs open as fresh shells — we deliberately don’t re-run a task tab’s command, so a claude session you spawned from a mission won’t re-fire on every launch. The N-cell grid view is the next slice of 7B.2.
  96. v0.57.0Shipped

    Mission threads update live

    • Open a mission and watch it fill in — no refresh. Messages now stream into the thread in real time: every agent reply as the bound canvas runs, system notices, and messages from teammates all appear the moment they’re written. Previously only the person who kicked off a run saw live progress; everyone else had to reload.
    • Built on Supabase Realtime postgres_changes over the mission_messages table, gated by the same row-level security as the rest of your data — you only ever receive messages for your own team’s missions. The server still renders the full thread on load; live rows merge in on top.
  97. v0.56.0Infra

    Faster docs — the API reference paints instantly

    • The /docs API reference loads in a fraction of the time. It used to ship a blank page that waited on a ~1 MB Scalar bundle before anything appeared — Lighthouse scored it 39 on mobile. Now the page server-renders a full endpoint index (every /api/v1 operation, grouped by Traces / Evals / Bridge, parsed straight from the same OpenAPI spec we serve at /openapi.yaml) that paints immediately, and the interactive Scalar explorer loads on demand when you scroll to it or click Load interactive reference.
    • Result: total blocking time dropped from 751 ms to 37 ms, Speed Index from 7.6 s to ~1 s, and first paint from 7.6 s to ~1 s — the heavy explorer is no longer on the critical path, but it’s one scroll away when you want it. The Scalar bundle is now pinned to an immutable, edge-cacheable version, too.
    • Marketing-side polish along for the ride: the home hero’s entrance animations settle a touch sooner, trimming Speed Index without losing any of the motion.
  98. v0.55.0Shipped

    Stackon Space — sign in with an email code

    • Signing in to Stackon Space now happens entirely inside the app: enter your email, we send a 6-digit code, you type it in — done. No browser round-trip, no custom URL scheme. Same Stackon account, and the session persists across launches.
    • The magic-link email now shows the code prominently alongside the usual sign-in link, so either works. This replaces the earlier deep-link sign-in, which stays supported for any links already in flight.
  99. v0.53.0Shipped

    Stackon Space — drop a skill into a running session

    • Drag a skill from the Agents pane onto a terminal that’s already running claude and its instructions are typed into that session for you to review and send — no new tab. Dropping on the tab strip still spawns a fresh claude tab with the skill applied, as before.
  100. v0.52.0Fix

    Stackon Space traces — cleaner cost roll-ups

    • Tightened how Stackon Space records terminal sessions as traces: fixed a source of trace pollution, removed a dead cost parser, and added a background sweeper that closes out stale, never-finished session traces so your trace list stays tidy.
  101. v0.51.0Shipped

    Stackon Space traces — per-turn spans + cost

    • Recorded terminal sessions now break a claude run into per-turn spans with a cost roll-up — so a session trace reads as a sequence of turns with token + cost detail, rather than one opaque blob.
  102. v0.50.0Shipped

    Phase 7F — Every Claude Code session in Space becomes a Stackon trace

    • The differentiator. When you drag a mission / agent / skill onto the Terminal pane in Stackon Space, the resulting Claude Code session is now recorded as a Stackon trace. A pulsing red REC badge appears in the terminal cell header while it's recording; an Open trace ↗ button lights up next to it. Click that → your default browser opens the session at stackon.ai/dashboard/traces/<id>, where the full transcript lives next to every other Stackon run — replayable, eval-gateable, postmortem-ready, ready to share with a teammate. Every local Claude Code session has receipts.
    • Mechanism: new desktop/src/lib/trace-session.ts. On terminal mount (when trace: true is in the spawn payload — set automatically by the Tasks / Agents / Skills panes; default-shell + New tabs don't trace, so throwaway ls sessions stay private), a traces row + one root span (kind=agent, name=terminal.session) are inserted via the existing authenticated Supabase client. Each PTY output chunk is ANSI-stripped + appended to an in-memory buffer; flushes happen every 2 s OR when the buffer hits 64 KB. Typed input is also appended (so the trace shows what the user said). On PTY exit, the session closes with status=ok; on unmount mid-run, closes with the same status (idempotent — the TraceSession has its own closed guard).
    • Privacy: transcripts are capped at 1 MB — past that, appends are dropped with a visible Capped badge so the user knows recording stopped. Only Tasks / Agents / Skills spawns are traced by default; plain + New shells aren’t (preserves throwaway-session privacy). Recording uses the same RLS-scoped client as every other Supabase write — only the user's team sees their traces.
    • Bundle: 783 KB JS / 26 KB CSS (gzip 215 + 6). +5 KB for the trace-session lib. Phase 7 is complete. Stackon Space now matches the original vision end-to-end — terminals, editor, missions, agents, skills, AND every shell session becomes a Stackon trace. The desktop workspace where every Claude Code session has receipts.
  103. v0.49.0Shipped

    Phase 7E — Agents + Skills sidebar with drag-to-terminal

    • Stackon Space’s Agents pane is no longer a stub. Top half = your team’s roster, pulled live from team_agents (same Supabase project the web uses, RLS-scoped server-side). Bottom half = the Skills library — Scribe-distilled procedures from past canvas runs.
    • Drag an agent onto the Terminal pane → spawns claude --append-system-prompt <agent.system_prompt>. The new Claude Code session boots already wearing that agent’s persona. Drag a skill → spawns claude with the skill’s instructions appended to the system prompt, wrapped in a # Applied skill · <name> header so Claude treats it as procedural addendum, not the primary persona.
    • Every card also has a Spawn click button — same payload, same outcome, but works without drag (trackpad-friendly). Reuses the application/x-stackon-spawn mime + spawn-bus CustomEvent pipeline from Phase 7D — Terminal pane routes mission cards, agent cards, and skill cards identically.
    • Same claude prerequisite as 7D: install Claude Code CLI on your PATH (npm install -g @anthropic-ai/claude-code) or the spawned tab will say command not found. Phase 7E.1 polish: drop a skill onto an already-running terminal to inject it mid-session via PTY stdin instead of always spawning a fresh tab. Next: 7F — terminal session → Stackon trace bridge (every claude session in Space optionally becomes a replayable trace).
  104. v0.48.0Shipped

    Phase 7D — Tasks pane wired to live Missions API + drag-to-terminal

    • Stackon Space’s Tasks pane is no longer a stub. It now pulls your team’s missions from the live Stackon backend (same Supabase project as the web), with the list on the left + the selected mission’s transcript on the right. Click any mission card to see its full thread (user prompts + agent messages + system errors, exactly as the web mission page renders them). Read-only for v1 — composer + new-mission creation are Phase 7D.1.
    • The differentiator: drag a mission card onto the Terminal pane’s tab strip and a new tab opens running claude with the mission’s title + description as the initial user prompt. The agent picks up the task as if you’d typed it. Same effect via the "Spawn in Terminal" button on the mission detail header. The tab strip flashes emerald on drag-over so you know the drop target is hot.
    • Mechanism: new desktop/src/lib/missions.ts reuses the authenticated Supabase client from Phase 7A.1 — RLS scopes everything server-side to your team_members rows, no extra filtering on the desktop side. New desktop/src/lib/spawn-bus.ts is a window-level CustomEvent helper for cross-pane spawn requests (avoids prop-drilling between sibling panes that don’t share state). The Terminal pane subscribes on mount; both drag-and-drop AND the "Spawn in Terminal" button feed it identically.
    • Prerequisite for the spawn to actually do anything useful: Claude Code CLI installed and on your PATH. If it’s not, the spawned tab shows claude: command not found — install via npm install -g @anthropic-ai/claude-code. Stackon Space doesn’t bundle Claude Code; you own that install (lets you stay on your preferred Claude Code version, get its own updates, etc).
    • Phase 7E next: Agents + Skills sidebar with drag-to-terminal injection. Phase 7F: terminal session → Stackon trace bridge (the killer differentiator — every claude session in Space optionally becomes a replayable Stackon trace).
  105. v0.47.0Shipped

    Phase 7B.1 + 7C — terminal tabs + Monaco editor pane

    • Terminal tabs (7B.1). Stackon Space’s Terminal pane is now multi-tab. Click + New to spawn another shell. Each tab keeps its own PTY alive when you switch away (display:none, not unmount, so xterm state survives). Hover a tab for the close (×) which kills that tab’s PTY. ResizeObserver in the cell naturally refits when a tab becomes visible again.
    • Editor pane (7C). Real Monaco editor — same engine VS Code uses — wired to tauri-plugin-fs for read/write/list. Click Open folder… → native folder picker via tauri-plugin-dialog → file tree on the left, Monaco on the right. Click a file to open it; Ctrl/Cmd+S writes the buffer back via writeTextFile. Language detection covers TS/JS/MD/CSS/HTML/Rust/Python/Go/YAML/TOML/shell/SQL/XML; falls back to plaintext for the rest. The workspace folder path persists across launches via tauri-plugin-store so reopening Stackon Space restores your last project.
    • FS scoping. The fs:scope capability locks reads + writes to $HOME / $DOCUMENT / $DESKTOP / $DOWNLOAD subtrees. Anything outside the allowlist is rejected at the plugin layer — agents can’t touch C:\Windows or /etc from the workspace. Per-workspace scoping is a future polish.
    • Monaco theme matches the Stackon palette (charcoal canvas, emerald cursor). One open file at a time for v1 — tabs come in 7C.1. Bundle: 771 KB JS / 25 KB CSS (gzip 212 + 6); Monaco itself loads dynamically from CDN on first use to keep the desktop binary small.
  106. v0.46.0Shipped

    Phase 7B — real PTYs in the Terminal pane

    • Stackon Space’s Terminal pane is no longer a stub. It hosts a live xterm.js terminal wired to a Rust-side PTY running your platform shell (PowerShell 7+ if installed, else Windows PowerShell 5.1 on Windows; $SHELL → zsh on macOS; $SHELL → bash on Linux). Type, see output, resize the pane and the PTY resizes too. Restart button kills the child and spawns a fresh one.
    • Mechanism: new src-tauri/src/pty.rs wraps the portable-pty Rust crate. Four Tauri commands — pty_spawn / pty_write / pty_resize / pty_kill — each operate against a HashMap<String, PtyHandle> behind a Mutex. On spawn, a dedicated reader thread pumps PTY output (8 KB chunks) to the renderer via Tauri events on pty:<id>:output; on child exit the thread emits pty:<id>:exit and removes the handle from state.
    • Renderer: new TerminalCell component constructs an xterm.js instance with the Stackon palette (charcoal canvas, emerald cursor, branded ANSI colors), loads FitAddon, calls spawnPty, wires output → term.write and term.onDatawritePty, and a ResizeObserver drives fit.fit() + resizePty. Unmount kills the PTY + disposes the terminal. Status chip in the cell header reflects booting / running / exited / error.
    • Phase 7B.1 will add a tab UI (multiple terminals per pane) + an N-cell grid layout matching the screenshot the user shared. Phase 7D drags missions onto terminals to spawn claude with the mission user_task; Phase 7E lets you drag skills to inject system prompts. Phase 7F captures terminal sessions into the existing trace/span tables.
  107. v0.45.0Preview

    Phase 7A.1 — Stackon Space OAuth deep-link sign-in

    • Stackon Space’s splash now has a real Sign in with Stackon button. Click it → your default browser opens to stackon.ai/sign-in?next=stackon://auth/callback → you sign in (magic link or GitHub) → the web redirects to the custom stackon:// scheme with the session tokens in the URL fragment → the OS routes the URL back to the running Stackon Space window → the splash dismisses and your workspace mounts. Persisted to disk via tauri-plugin-store; subsequent launches restore the session automatically.
    • Web side: /auth/confirm learns a TRUSTED_SCHEMES whitelist (currently just stackon://). When next is in the whitelist, the route’s post-verifyOtp redirect target gets the session encoded into the URL fragment (#access_token=...&refresh_token=...&expires_in=...) — tokens in the fragment so they stay out of server access logs + referrer headers. The web finalUrl helper also passes stackon:// through unchanged so the magic-link email’s emailRedirectTo points at the custom scheme.
    • Tauri side: three new plugins — tauri-plugin-deep-link (custom URL scheme registration via the plugins.deep-link.desktop.schemes bundle config), tauri-plugin-shell (renderer can open the external browser), tauri-plugin-store (persisted session file). Plus tauri-plugin-single-instance with the deep-link feature so the second stackon:// launch (during a sign-in handshake) wakes the existing window instead of spawning a second process. Capabilities updated.
    • Renderer side: desktop/src/lib/{supabase,auth}.ts. The Supabase JS client uses detectSessionInUrl: false because we feed the fragment to setSession ourselves from the deep-link listener. App.tsx bootstraps with a brief "Restoring your session…" state, then either mounts the shell (if a session restored from tauri-plugin-store) or shows the sign-in splash. Build-time env vars: VITE_SUPABASE_URL + VITE_SUPABASE_PUBLISHABLE_KEY documented in new desktop/.env.example.
    • Phase 7A.1 unblocks 7B (real PTYs) and everything that follows — the session is now real, so Tasks/Agents/Skills can actually hit the Stackon API once those panes are wired in 7D/E.
  108. v0.44.0Preview

    Phase 7A — Stackon Space scaffolded (native desktop agent workspace)

    • Stackon Space — the native desktop incarnation of Stackon — gets a real shell. The Tauri window no longer redirects to the web dashboard; it hosts a Vite-built React app implementing a four-pane workspace: Terminal · Editor · Tasks · Agents. Splitters between panes, a workspace rail on the left, a pipeline strip on the bottom — the same kind of multi-pane layout you’d expect from a native IDE, but every pane is a future home for live Stackon primitives.
    • What the desktop app IS today (Phase 7A): a real frontend pipeline (Vite + React 19 + Tailwind v4 inside desktop/), the four-pane resizable shell, brand-token-matched chrome, a splash with a "Continue to workspace" CTA. What it’s NOT yet: real PTYs (Phase 7B — portable-pty + xterm.js), Monaco editor (7C), Mission API integration (7D), Skill drag-injection (7E), terminal-to-trace bridging (7F), OAuth deep-link sign-in (7A.1). Each pane shows a labeled stub describing what fills it.
    • Strategic framing: Stackon Space is the same product as web Stackon — same backend, same auth, same Postgres, same brand. The desktop binary is the workspace surface; the cloud is the brain. Web Stackon stays for missions/agents/canvas/traces. Stackon Space adds the things web can’t do — local file system, native PTYs, multi-pane simultaneous runs.
    • Build outputs: desktop/dist/ bundle (237 KB JS, 20 KB CSS gzipped to 74 + 5). tauri.conf.json now invokes npm run dev:vite / npm run build:vite via before*Command; dev URL flipped from localhost:3000 (web app) to localhost:1420 (Vite). Tauri shell version bumped to v0.44.0.
  109. v0.43.0Shipped

    Phase 6D — @-mention dispatch, swarm mode, multi-turn conversation context

    • The mission composer is now a real terminal interface. Type plain text and the bound canvas runs sequentially (existing behavior). Start with @all and every roster agent runs in parallel against the same prompt — outputs interleave into the transcript as they stream in. Start with @<agent-name> matching a roster agent in the bound canvas and just that agent runs, skipping the pipeline. The token matcher is forgiving (case-insensitive, ignores dashes/underscores/spaces), so @Coder-Bob matches an agent named "Coder Bob" and vice versa.
    • Every run also now sees the prior mission turns as conversation context. runCanvas + new runAgentById load the last 30 user/agent messages for the mission (when a missionId is threaded in) and inline them into each node's system prompt as a `# Prior conversation in this mission` block. Closes the stateless-run gap from Phase 6C — the agent that wrote the diff knows what the user asked for two turns ago.
    • New runAgentById(agentId, userTask, opts) mirrors runCanvas's lifecycle for a single roster agent: trace shell + root span + broadcaster (uses the mission's bound canvas channel so the LiveRunPanel transparently subscribes), one synthetic LLM span, one mission_message. runCanvas grows a swarm: boolean option — sequential for-loop vs. Promise.all; the per-node atom was extracted into an executeNodeStep closure so both modes share it.
    • Phase 6 is complete. The Missions / Agents / Canvas / Approvals tabs now feel like a Claude-Code-style multi-agent terminal: add agents to your roster, drop them into a canvas, attach the canvas to a mission, then converse with the team — swarm them, task them individually, or run the full pipeline. Every token streams live; every turn persists.
  110. v0.42.0Shipped

    Mission becomes a chat thread — roster, transcript, composer, live stream

    • Mission detail page is no longer a form — it's a thread. Top: title + status + roster of agents (pulled from the bound canvas's nodes, named via the team_agents roster when available). Middle: scrollable transcript of every user prompt + every agent message, oldest first, with cost / tokens / trace link per agent message. Bottom: composer — type what the team should work on and hit Send. The existing edit / approve / archive / delete forms moved into a collapsed "Mission settings" disclosure so they're still reachable but no longer dominate the page.
    • New `mission_messages` table (RLS scoped to `team_members`, append-only by design: insert + select only from user clients; admin client retains update/delete for future scrub flows). One `role='user'` row per composer submit; one `role='agent'` row per `node.completed`; `role='system'` for run failures. Each agent row links back to its `trace_id`, `span_id`, `canvas_node_id`, and `agent_id` (when bound to a roster agent) so the transcript carries all the cross-links needed for replay + drill-in.
    • The composer reuses Phase 6B's broadcast pipeline: pregenerates a `traceId`, schedules `runCanvas` via Next 16 `after()` with `{ precreatedTraceId, missionId }`, redirects with `?live=`. The LiveRunPanel mounts above the transcript and streams tokens as the run executes; once each node completes, a persisted mission_message arrives and the live block becomes static. Approval-gated submits still queue a pending row (`requestMissionRun`), but the user message persists immediately so the thread shows the intent before the approver acts. Approval-driven runs now also write agent messages because `approveMissionRun` threads the `missionId` into `runCanvas`.
    • Multi-turn agent context is intentionally deferred to Phase 6D — each composer submit is currently a fresh run against the bound canvas with the composer text as the user task. The mission's title + description are visible context for humans but aren't re-injected into the LLM prompt today.
  111. v0.41.0Shipped

    Canvas runs stream live — tokens land in the page as they're generated

    • Hitting Run on a canvas no longer makes you wait for the whole pipeline to finish before you see anything. The page now renders a live transcript: each agent shows its output character-by-character as it streams from Claude. Active node has an emerald-pulsed border; completed nodes show cost + token counts; final state links to the persisted trace.
    • Mechanism: `runCanvas` extends to broadcast `run.started` / `node.started` / `node.token` / `node.completed` / `run.completed` / `run.failed` on the existing `canvas:` private Realtime channel (same substrate as multiplayer cursors + comments). Token deltas are batched at 100 ms or 400 chars to stay under Supabase's per-channel msg/sec budget. Emission uses the service-role admin client so it bypasses the `realtime.messages` RLS policy without needing a user JWT.
    • Dispatch model flipped from "server action blocks until done" to "server action schedules + redirects with ?live=<traceId>" via Next 16 `after()`. The trace id is pregenerated client-side (crypto.randomUUID) and passed into `runCanvas` so the redirect target is known before the LLM work begins. The persisted trace remains the source of truth — broadcasts are best-effort, additive, and dropped if delivery fails (the live UI just misses a chunk; the trace catches up on completion).
    • Foundation for Phase 6C (mission-as-thread) + 6D (swarm + interjection). Canvas approvals + eval-gate runner + HTTP API runner stay synchronous for now — they don't need a live UI.
  112. v0.40.0Shipped

    Agents become first-class — team roster you can drop into any canvas

    • The Agents tab is no longer a one-shot prompt form. It's now a roster: name, role, model, and system prompt saved per team. Click into any agent to edit; archive when you're done with it. The legacy one-off runner moves to `/dashboard/agents/quick` so you can still fire a quick test without committing to a saved agent.
    • New `team_agents` table (RLS scoped to `team_members`, soft-deletes via `archived_at`, one active agent per (team, name)). `canvas_nodes` gains a nullable `agent_id` reference — nodes linked to a roster agent show a green `From roster` chip and resolve the agent's current role / model / system prompt at run time. Edit Coder Bob's system prompt and every canvas that uses him picks up the change on the next run.
    • Canvas add-node form now leads with a `From roster` picker (when you have saved agents) above the existing inline form. Both work — pick from the roster to track an agent live, or define inline for a one-off node. Existing canvas nodes are untouched (agent_id is nullable; their inline columns keep working).
    • Foundation for Phase B (live streaming inside the canvas) and Phase C (mission-as-thread with @-mention dispatch to specific agents). Agents need stable identity before either lands, which is what this ships.
  113. v0.39.4Shipped

    Press-kit full lockup — mark + wordmark on one canvas

    • Added a horizontal lockup to the press kit — mark on the left, wordmark on the right, both centered on the same 1536×1024 canvas. Ships in both dark (`#0A0A0A`) and light (`#FAFAF8`) variants. Useful for footers, slide decks, and any context where a journalist or partner wants both identity pieces composed as a single asset rather than reassembling the mark and wordmark by hand.
    • `scripts/crop-stackon-logo.mjs` gains a lockup pass that reuses the existing `markBuffer` and the vector wordmark SVG (480×480 mark, 64 px gap, 760 px wordmark, group centered on the canvas). Same `npm run gen:brand` regenerates everything; no new dependencies.
    • `/media` now lists the two lockup tiles at the top of the asset grid, ahead of the mark-only and wordmark-only slots — the typical first thing a press contact reaches for.
  114. v0.39.3Fix

    Press-kit wordmark — designed SVG replaces gpt-image-1 raster

    • The `/media` wordmark slots (`Wordmark · dark` and `Wordmark · light`) were generated by gpt-image-1, which mangles text — the rendered `STACKON` letterforms had subtle distortion and paper-grain artifacts that didn't read at press scale. Replaced with a hand-wired vector wordmark built from Geist Regular glyph paths.
    • New `scripts/build-wordmark.mjs` reads the Geist-Regular.ttf already bundled with `@vercel/og` (a transitive Next.js dependency), uses `opentype.js` to convert the text "Stackon" to SVG glyph paths, and writes `public/stackon-wordmark-{dark,light}.svg`. Path-only — no font dependency at render time, no rasterization, no AI distortion. Single color per variant (white #FAFAFA on dark, charcoal #0A0A0A on light); drops the legacy coral 'on' two-tone from the v0.34 bitmap source, aligned to v0.36 monochrome.
    • `scripts/crop-stackon-logo.mjs` now invokes the wordmark builder up-front, then rasterizes the SVG onto a 1536×1024 canvas at 1100 px target width for the press-kit PNGs. `npm run gen:brand` remains the single command to refresh all brand assets. PNG file size dropped from ~640 KB (raster) to ~59 KB (clean vector composite).
    • Removed the `media-logo-dark` / `media-logo-light` entries from `scripts/placeholder-prompts.mjs` so a future `npm run gen:placeholders --force` can't silently overwrite the vector wordmark with a gpt-image-1 raster. Gotcha #60 (wordmark distortion caveat in press kit) closes.
  115. v0.39.0Preview

    Stackon for Windows — Tauri shell scaffolded (NSIS + MSI)

    • The Tauri shell now targets Windows alongside macOS. `tauri.conf.json:bundle.targets` extends to `["dmg", "app", "nsis", "msi"]` — Tauri silently skips the platform-foreign targets at build time, so the same `npm run desktop:build` invocation produces a DMG on macOS and an NSIS .exe + MSI on Windows. No code changes in `main.rs`; the Rust shell is platform-agnostic by design.
    • Added a Windows `bundle.windows` config block: `webviewInstallMode: downloadBootstrapper` (so older Windows 10 boxes get WebView2 fetched at install time), NSIS `installMode: perMachine` with the new `icon.ico` as the installer icon, WiX defaults set to `en-US`. The capability surface is unchanged from the macOS shell — same minimal `core:window:*` permissions.
    • Asset pipeline extended: `scripts/crop-stackon-logo.mjs` now also emits `desktop/src-tauri/icons/icon.ico`, a multi-resolution ICO covering 16/24/32/48/64/128/256 px. Built from the same RGBA mark via the `to-ico` npm package — no external tooling, runs on every `npm run gen:brand`.
    • **You cannot build a Windows installer from macOS.** Tauri's Windows bundler relies on Windows-only tooling (NSIS, WiX, SignTool). Production builds happen either on a Windows machine or — recommended — a `windows-latest` GitHub Actions runner. `desktop/DEPLOY.md` gains a section 8 covering Windows prerequisites (MSVC C++ Build Tools, rustup), build commands, code signing (OV vs. EV certs), and the GH Actions workflow stub. The `desktopWindows` feature flag stays `enabled: false` until a signed `.exe` + `.msi` is hosted.
  116. v0.38.1Fix

    Stackon for Mac — first compiling build (scaffold fixes)

    • v0.38.0 scaffolded the Tauri shell but never compiled locally — the dev box was missing Command Line Tools + Rust. After installing both (xcode-select --install, rustup default stable), the first `npx tauri build` surfaced two real bugs in the scaffold: a capability that doesn’t exist in Tauri v2.11, and icon PNGs in the wrong color space.
    • Capability fix: `core:webview:allow-reload` was requested in `capabilities/default.json`, but Tauri 2.11 removed it — reload now lives on the OS menu (⌘R). Dropped it; nothing was using it anyway.
    • Icon fix: `scripts/crop-stackon-logo.mjs` was emitting RGB PNGs for the desktop icon matrix (32×32, 128×128, 128×128@2x, 512×512). Tauri’s `generate_context!` proc-macro requires RGBA. Added `.ensureAlpha()` to the desktop icon loop. All four PNGs now write as 8-bit RGBA; `iconutil` still assembles `icon.icns` from the RGB sources cleanly.
    • After fixes, the first end-to-end build produces `Stackon.app` + `Stackon_0.38.1_x64.dmg` in ~1m 23s (~4.2 MB DMG, unsigned x86_64). Signing + notarization still gated on Apple Developer Program enrollment. Bumped `desktop/{Cargo.toml,package.json,tauri.conf.json}` from the inherited 0.37.1 to 0.38.1 so the DMG filename + version sync to the repo cadence going forward.
  117. v0.38.0Preview

    Stackon for Mac — Tauri v2 desktop shell (scaffolded)

    • New `desktop/` package: a Tauri v2 Rust shell that wraps the Stackon web ADE in a native macOS window. Dev mode points at `http://localhost:3000` and hot-reloads alongside `npm run dev`; production build redirects to `https://stackon.ai/dashboard` from a tiny `dist/index.html` splash. Window chrome is native (titlebar, dock icon, ⌘W/⌘Q), backed by WKWebView on macOS so memory + cold start are roughly half of what an Electron equivalent would be.
    • Bundle identifier `ai.stackon.desktop`. Icons regenerate from `stackon/stackon_logo.png` via the existing `npm run gen:brand` script — the matrix now includes 32×32/128×128/128×128@2x/icon.png PNGs plus an `icon.icns` assembled via macOS `iconutil`. The Rust code is intentionally tiny: a single `main.rs` that calls `tauri::Builder::default().run()`. We’ll add commands + plugins (system tray, global hotkey for voice push-to-talk, native notifications) as later iterations.
    • Distribution: direct download from `/download`, no App Store. The `desktopMac` feature flag stays `enabled: false` until the signed DMG is hosted — the page renders a 'Coming in Phase 4' violet pill in the meantime. Signing + notarization requires Apple Developer Program enrollment ($99/yr), which is the same gate as TestFlight (mobile/DEPLOY.md step 0.2). Doing both together is the natural sequence.
    • Windows build is a near-identical follow-up in a later session — same Tauri base, swap the bundle target from DMG to MSI. The `/download` page already has a Windows card showing 'Coming in Phase 4' so the placement is in place.
  118. v0.37.0Shipped

    Voice v2 — true local Whisper (wasm) joins the capability chain

    • Push-to-talk now has a third path: fully in-browser Whisper via `@huggingface/transformers` (ONNX wasm). Audio + inference both stay on the device — nothing leaves the browser. First use downloads ~145 MB of `onnx-community/whisper-tiny.en` at fp32 precision (cached in browser Cache Storage thereafter). Subsequent transcriptions reuse the loaded pipeline with no network round-trip. fp32 chosen over the smaller quantized variants because their per-tensor scale tensors are broken in the upstream exports — crashes session init via the new MatMulNBits kernel.
    • User-selectable preference (auto / local / cloud) is persisted to localStorage and exposed as a one-click chip next to the mic button. `auto` resolves to webspeech → local → cloud (best UX everywhere). `local` is a privacy lock — it will never silently fall back to cloud. `cloud` keeps the existing Whisper-1 path for users who explicitly opt in.
    • Audit log records the same shape for all three modes (`bytes`, `mime`, `duration_ms`, `transcript_chars`, plus a new `mode` field). A new same-origin `POST /api/voice/audit` endpoint receives a JSON beacon from the browser when local-mode transcription finishes, so the compliance audit log shows the usage without the audio ever crossing the wire.
    • Component palette aligned to v0.36 — error states use rose instead of red. Build, lint, typecheck all clean.
  119. v0.36.3Shipped

    Final amber sweep — every remaining marketing + auth + onboarding surface

    • Closes the v0.36 monochrome campaign. After this commit, `grep -rE 'amber|FBBF24|251,191,36' src/app src/components` returns empty across the entire repo. Home (v0.36), dashboard (v0.36.1), pricing (v0.36.2), and now everything else.
    • 16 files swept: About, Careers, Changelog, Community/Discord, Community/Events, Contact, Forge marketplace + listing detail, Invite landing, Media, Privacy, Terms, the auth layout + form, the onboarding layout + 3-step wizard. ~58 amber utilities + 5 amber-rgba hero backdrops retired.
    • Tone calls worth flagging: the changelog `preview` kind moved from amber to rose, filling the 4-tone categorical slot alongside shipped (emerald), fix (sky), infra (violet). The invite-landing `Pill` ('Team invite' / 'Email mismatch') moved to violet — categorical 'invitation' marker. The auth header's mini 'S' logo mark flipped to a white background. The onboarding wizard's 'checked' selection state, progress dots, and CTAs all moved to white (neutral primary) rather than picking a categorical color for what is fundamentally a selection-vs-unselected toggle.
    • Every italic emphasis phrase ('one we'd trust with production', 'say hello first', 'where we build', 'on the calendar', 'the right answer', 'shipped', 'brand', 'policy', 'service') flipped from text-amber-300 to text-white. Emphasis without color, per v0.36 ethos. Every hero radial-gradient backdrop swapped from amber-rgba to a faint white glow. Every mailto link in /privacy and /terms moved from amber to text-zinc-100 with underline-offset.
    • Build, lint, typecheck clean. No behavior changes.
  120. v0.36.2Shipped

    Pricing page — amber sweep to match v0.36 monochrome palette

    • The last public marketing surface still running on the old amber-accented system. `/pricing` now follows the same recipe as the home (v0.36) and dashboard (v0.36.1): white-pill primary CTAs, neutral zinc eyebrows, monochrome chrome.
    • The featured Team plan card flipped from amber to violet — categorical 'premium tier' pop, matching the convention from v0.36.1 (Owner role badge, postmortem panel, modified-diff state). Border + gradient + ring + 'Most popular' badge text + the matrix column header all read violet now. The CTA inside the featured card is a white pill (same as every other primary action across the app).
    • Feature-list bullets uniform muted zinc across all plan cards. FAQ caret neutral. Italic accent phrases ('not seat-shaming.', 'Start free') keep the typography but drop the amber tint — emphasis without color, per v0.36 ethos. Hero radial-gradient backdrop swapped from amber-rgba to a faint white glow.
    • 12 amber utilities + 1 amber rgba retired in `src/app/pricing/page.tsx`. No behavior changes. Build, lint, typecheck clean. `/pricing` is now the third surface (after home + dashboard) running on the unified `--brand-*` palette.
  121. v0.36.1Shipped

    Dashboard amber sweep — monochrome palette across the app shell

    • v0.36 retired amber on the marketing home and shared chrome. v0.36.1 finishes the job: every page under /dashboard (38 surfaces) plus five shared components (ComingSoon banner, trace/badges, voice-input, canvas-multiplayer, canvas-comments) now run on the same monochrome system. ~273 amber utilities replaced with `--brand-*`-aligned alternatives.
    • Primary CTAs flipped from amber pills to white pills (`bg-white text-zinc-950 hover:bg-zinc-200`), matching the home's primary action. Form focus rings dropped from amber to neutral white. Hover-link accents lost their amber tint.
    • Semantic emerald now appears only where v0.36's rule says it should: live status. Trace, Evals, and Approvals eyebrows are emerald (the live-measurement family). The Run-canvas and Run-mission action panels carry an emerald-tinted gradient. The cost breakdown bar reads as a live feed. Postmortem panels moved to violet (analytical / investigative, not a status). Diff-modified rows moved to violet (categorical, distinct from emerald-added and red-removed). 'Coming Soon' chips and the dashboard nav hover dropped to pure neutral. Warning banners (missing env vars, no canvas yet) moved to rose — pending/attention per the v0.36 semantic palette.
    • The Trace span-kind badge for `agent` moved from amber to the paler categorical emerald (`emerald-300`) — distinct from the saturated emerald-400 used for OK/in-progress status. Build, lint, and typecheck all clean; no behavior changed.
  122. v0.36.0Shipped

    Marketing home rework — monochrome palette, editorial Trace pillar

    • The home page and shared marketing chrome (header / nav / footer) traded amber for a monochrome white-on-near-black system. New brand tokens live in `globals.css` (`--brand-bg/surface/text/live/pending/tone-*`) as the single source of truth.
    • Muted emerald (#34D399) is the only chromatic accent and it's reserved for live/healthy status moments — pulsing dots, the eval-pass row, the '● Recently shipped' hero callout. Categorical product chips use a 4-tone set (sky for Canvas, violet for MCP, emerald for Trace, rose for Mobile).
    • Two new home sections: `` ('Four products. One workflow.') and `` (Describe / Orchestrate / Ship triptych). The Trace pillar was rebuilt as a single editorial spine — small chip, oversized two-line headline ('Every run / leaves a trace.'), `` artifact with crop-mark corners, then a 3-up feature row.
    • All `gpt-image-1` prompts rewritten end-to-end — HUNTERADE wordmark → STACKON, amber → emerald-only-where-functional, `ANTI_AI_TAIL` to reduce AI tell. 17 of 18 placeholders regenerated; the 18th (`home-fp2p-ship.png`) is blocked on raising the OpenAI billing limit and renders the dotted-grid fallback in the meantime.
  123. v0.35.0Shipped

    Renamed to Stackon

    • HunterADE is now Stackon. The new brand mark — three stacked cards representing code, sparkle, and OpenAI's model — sits over the wordmark and reads as an editor environment built on top of the foundation models that actually do the work. The tagline followed: an Agentic Developmental Environment powered by Claude and Codex.
    • Sub-products dropped the Hunter prefix. HunterTrace is Trace, HunterCanvas is Canvas, HunterMobile is Mobile, HunterCost is Cost, and so on. Two exceptions where the bare noun was too generic: Stackon MCP and Stackon CLI.
    • This release is the visible-surfaces flip: marketing pages, dashboard UI, mobile app icon + name + deep-link scheme, emails, OpenAPI docs, /privacy and /terms. Wire formats stayed put on purpose — `ht_` / `hbk_` / `htmi_` / `htmd_` token prefixes still work, the `X-HunterADE-Signature` webhook header is unchanged, and `HUNTERADE_*` env vars keep their names. Existing automation against the API does not break. A later cutover sprint will rotate those when there's a clean migration window.
    • iOS bundle ID flipped to `com.stackon.mobile` — the one exception to the phased rule, because App Store records are permanent post-registration and the mobile build hadn't shipped to TestFlight yet. Free now, irreversible after.
  124. v0.34.5Preview

    HunterMobile brand assets — icon, splash, adaptive, favicon

    • mobile/assets/ now ships with the four files EAS Build requires: icon.png (1024×1024 RGB), splash.png, adaptive-icon.png, and favicon.png. All derived from the existing HunterADE crosshair mark (public/placeholders/media-mark-dark.png) via macOS `sips` — center-cropped to 1024 square, no alpha channel (Apple rejects icons with transparency).
    • mobile/app.json wires the new files through expo.icon, expo.splash (resizeMode contain, #0A0A0A background), expo.android.adaptiveIcon, and expo.web.favicon. Mobile bundle bumped to 0.34.5; DEPLOY.md step 1 now reads as ✅ shipped.
    • Closes the last codebase-side blocker before TestFlight submission. Remaining: deploy the backend at the apiBaseUrl, enroll Apple Developer, eas login, eas init, eas build + eas submit.
  125. v0.34.4Preview

    TestFlight prep — privacy, terms, mobile deploy checklist

    • New /privacy and /terms pages cover everything Apple needs to accept a TestFlight submission — what data the app collects, who we share it with (Supabase / Anthropic / OpenAI / Resend / Expo / Stripe), how to delete your data, and the standard alpha-stage warranty disclaimers. Footer links to both. Plain-English drafts written for honest disclosure, not legal cover — get them reviewed by counsel before public GA.
    • New mobile/DEPLOY.md walks the user through every step from Apple Developer enrollment to `eas submit --platform ios`. P0 flagged up top: the production build talks to hunterade.com, so the backend has to be deployed and reachable before TestFlight reviewers can pair.
    • Cleanup in mobile/: dropped the dangling googleServicesFile reference so a first `eas build --platform ios` succeeds without an Android Firebase project. Bumped mobile bundle + app.json to 0.34.0.
  126. v0.34.3Fix

    Press kit — full-image view, click-to-open, download per asset

    • The new /media tiles were being cropped: every press shot is wider than 16:9, and the old PlaceholderImage frame used object-cover, lopping content off both sides. Replaced the press-kit grid with a new MediaAsset component that renders each shot at its natural aspect (object-contain inside an aspect-ratio computed from the file).
    • Click any tile → opens the original file at full resolution in a new tab. Each tile now has a `↓ Download` link beneath it that saves the file directly. Captions are auto-built from the real PNG header — actual pixel dimensions + file size, so the page can't drift from what's in public/placeholders/.
  127. v0.34.2Shipped

    Press kit — real dashboard screenshots replace AI mockups

    • The three product shots on /media (HunterTrace, HunterCanvas, HunterMobile / Approvals) are now real screenshots of the running dashboard, not gpt-image-1 mockups. The AI versions were photoreal but leaked the prompt's example labels — "span name", "PlanGPT", "Expense Report" — into the UI; the new shots carry actual product copy.
    • New scripts/seed-demo-screenshots.mjs (`npm run seed:demo`) inserts a photogenic 16-span trace, a 3-node Planner→Coder→Reviewer canvas, and a pending approval — all tagged so re-runs (or `--clean`) replace prior demo rows without drift. Anyone refreshing the press kit can re-seed, screenshot, and commit in five minutes.
  128. v0.34.0Shipped

    Marketing site redesign — editorial nav + ecosystem index

    • Homepage and global nav rebuilt around an editorial column grid: monospaced eyebrows mark structural sections, Instrument Serif italic carries emphasis pulls, hairline amber rules act as scaffolding instead of decoration. The page reads like a print spread now — same proof artifacts, more breathing room.
    • New top nav: Logo · Pricing · Ecosystem (dropdown: Observability / Canvas & Missions / Apps & Surfaces — every enabled product from featureFlags.ts) · Community (Discord, Docs, Events, Blog) · Company (About, Changelog, Careers, Media, Contact). Hover-open + click-toggle + ESC + outside-click. Hand-rolled, no extra deps. Mobile hamburger opens a full-width sheet listing all three categories stacked.
    • Single source of truth at src/lib/marketing/ecosystem.ts — the nav dropdown, the new homepage Ecosystem section, and the footer columns all read the same data. Adding a product = one edit.
    • Six new stub pages so every nav link resolves: /about, /careers, /media, /contact, /community/discord, /community/events. Each is a real editorial page (not banners) with placeholder image slots tagged data-placeholder-slot="" — grep that attribute to swap in OpenAI-generated assets once the API key lands.
    • Hero ops cluster recomposed as a "specimen plate" with bracket markers, t+ timer, and a span/eval/budget caption — reads as proof artifact rather than tech demo. The conic-gradient swirl is gone; one calm radial bloom + the existing dotted-grid texture handles atmosphere.
  129. v0.33.1Infra

    pg_cron sweeper hardening

    • Both sweep_expired_canvas_pending_runs and sweep_expired_mission_pending_runs were tripping Supabase's function_search_path_mutable advisor: a function with no SET search_path leaves it role-mutable, so a malicious schema sitting earlier in resolution could shadow an unqualified table reference. Low risk in practice (pg_cron runs jobs as postgres; tables are owned by supabase_admin) but cleanest fix is to nail it down.
    • Migration recreates both functions with SET search_path = '' and fully-qualified public. references. CREATE OR REPLACE only — no schema or cron-schedule change. Both advisor warnings are gone; sweep_expired_*_pending_runs RPCs still callable and behaviorally identical (verified end-to-end in scripts/test-sweepers.mjs, 14 assertions).
    • v0.33.0Shipped

      HunterMobile — cost dashboard on your phone

      • Mobile gets `budget.breached` pushes (v0.28) but couldn't see the current state on the phone. v0.33 closes that loop. New Cost tab on HunterMobile mirrors the web HunterCost dashboard: current-month spend, vs. last month delta with percent change, hard / soft budget limits with usage bar, and a 7-day spend sparkline.
      • Server: new GET /api/v1/mobile/cost endpoint returns { current_spend_usd, last_month_spend_usd, budget, daily }. Reuses the same getMonthlySpend / getLastMonthSpend / getDailySpend / getBudget helpers the dashboard uses — refactored to thread an admin client so they work outside a session (mobile uses bearer tokens, no Supabase cookie).
      • UI: pure-JSX sparkline (no chart library dep), color-coded budget bar (green under soft, amber over soft, red at hard), and a 'no limits set' empty state pointing to the web dashboard. Footnote spells out the spend formula so users can audit it.
      • Mobile bundle bumped to 0.33.0.
    • v0.32.0Shipped

      HunterMobile — mission approvals on your phone

      • The v0.31 server fan-out (mission.run.requested webhook + push) is now actionable from HunterMobile. New /(home)/approvals tab unifies canvas + mission pending runs in two grouped sections; each row deep-links to the right detail screen via expo-router.
      • New mobile/app/mission-approvals/[id].tsx screen mirrors the canvas detail layout — shows mission title, requester, bound canvas, user task, and the same Approve & run / Reject buttons. Approve redirects to the resulting trace (same admin-client identity override path the dashboard uses, so the trace is attributed to the original requester).
      • Three new bearer-token authed API routes: GET /api/v1/mobile/mission-approvals (list pending for team), GET /api/v1/mobile/mission-approvals/[id] (single), POST /api/v1/mobile/mission-approvals/[id] (action: approve | reject + optional reason). ApprovalError codes map cleanly: already_decided → 409 conflict, not_team_member → 403 forbidden.
      • Push notifications for mission.run.requested now deep-link properly — server pushes set data.kind = 'mission_approval', mobile's deepLinkForNotification routes to /mission-approvals/[id]. Tapping a notification opens the right screen on cold start + foreground.
      • Mobile bundle bumped to 0.32.0. Tab labels stay 'Approvals' — the inside is what changed.
    • v0.31.0Shipped

      HunterMissions run approvals

      • Missions now opt into the same approval gate as canvases. Flip Require approval on a mission and Run mission queues a row in the new mission_pending_runs table instead of executing immediately. Any team member can approve or reject from /dashboard/approvals or the inline banner on the mission detail page.
      • Mission-level approval supersedes canvas-level approval — signing off on a mission IS signing off on the run, so a canvas with its own requires_approval=true is NOT re-gated. The approveMissionRun helper calls runCanvas directly via the admin-client identity override, attributing the trace + cost to the original requester, not the approver. Same race-safe atomic claim pattern from canvas approvals (v0.29): UPDATE … WHERE status='pending' returns null on the second simultaneous approver, surfacing 'already_decided'.
      • New webhook event mission.run.requested fans to outgoing webhooks AND mobile push (sibling pattern from v0.28). Three new audit_action values: mission.run.requested / .approved / .rejected. The pending row snapshots canvas_id + user_task at request time so a teammate rebinding the mission to a different canvas — or editing its title — between request and approval doesn't change what the approver is signing off on.
      • /dashboard/approvals is now a unified inbox: missions and canvases live in the same list, grouped by kind. The /dashboard/missions/[id] page shows an inline pending banner above the Run button so the requester sees their own queued run without leaving the mission.
      • pg_cron job sweep-expired-mission-pending-runs runs every 5 minutes (mirrors the canvas sweeper from v0.30.1) and flips status pending → expired for any row past expires_at (24h default). security invoker, idempotent reschedule, no audit_action for the transition — the absence of an approve/reject IS the signal.
    • v0.30.1Infra

      Approvals expiry sweeper

      • canvas_pending_runs.expires_at defaults to now()+24h but nothing was marking expired rows — listings already filtered on status='pending' so they dropped out of view, but the audit trail showed a dangling 'pending' state forever. Closed.
      • New pg_cron job sweep-expired-canvas-pending-runs runs every 5 minutes (*/5 * * * *) and flips status pending → expired for any row past its deadline. The job calls public.sweep_expired_canvas_pending_runs() which is security invoker — pg_cron's runner role bypasses RLS so we don't need definer privileges.
      • No new audit_action value: pg_cron is system maintenance, not a user action. The absence of an approve/reject decision before expires_at IS the entire signal.
    • v0.30.0Shipped

      HunterMobile diff viewer + EAS Build config

      • HunterMobile now has a canvas browser. New Canvases tab lists every canvas on your team with version count + 'requires approval' badge; tapping drills into the version history; tapping a version renders a side-by-side diff against the previous one (or against an arbitrary version via ?against=N).
      • The mobile diff reuses the server's existing diffSnapshots() engine — same algorithm that powers /dashboard/canvas/[id]/versions on the web. Per-node ADDED / MODIFIED / REMOVED / UNCHANGED blocks with per-field deltas (role / name / model / system_prompt). Metadata diffs (canvas name + description) surface separately. Summary pills at the top count each category.
      • Three new mobile API endpoints, all bearer-token (htmd_) authed, all team-scoped: GET /api/v1/mobile/canvases (list), GET /api/v1/mobile/canvases/[id]/versions (history), GET /api/v1/mobile/canvases/[id]/versions/[version]/diff (CanvasDiff between this version and previous, or `?against=` for an arbitrary base).
      • Mobile bundle bumped to 0.30.0. New eas.json with development / preview / production profiles is in place — running `eas build --profile preview` produces an internal-distribution build for both platforms; `eas submit --profile production` ships to TestFlight + Play internal track. First build needs `eas login` and the Apple Developer + Google Play Console records (those are out-of-band).
      • v0.30 closes the HunterMobile track for now — the app is feature-complete behind the mobile flag. Future work: actual store submissions, live multiplayer cursors mirrored to mobile, push-to-talk recording from the phone.
    • v0.29.0Shipped

      HunterMobile approve queued canvas runs

      • Canvases can now opt in to an approval gate via a new requires_approval toggle on the canvas detail page. When on, every Run pipeline button queues a row in the new canvas_pending_runs table instead of executing immediately. Any team member can approve or reject from /dashboard/approvals or HunterMobile — approver != requester is allowed (the simplest rule that lets a phone-only co-pilot actually unblock a teammate).
      • New webhook event canvas.run.requested fans to outgoing webhooks AND mobile push (sibling pattern from v0.28). The push notification carries the canvas name, requester, and a truncated user_task; tapping deep-links straight to the mobile approval detail screen. Existing webhook subscribers don't see the new event unless they explicitly subscribe — backwards-compatible.
      • Server: new src/lib/canvas/approvals.ts wraps the lifecycle. requestCanvasRun inserts pending row + fires push/webhook. approveCanvasRun atomically claims the row (UPDATE … WHERE status='pending') so two simultaneous approvers can't double-run; then calls runCanvas via the admin-client identity override, attributing the trace to the original requester (not the approver). rejectCanvasRun mirrors the claim, with an optional reason stored in error_message.
      • Dashboard: /dashboard/approvals lists all pending requests across canvases; per-canvas pages also show their own pending list inline so the requester sees their own queued runs without leaving the canvas. Three new audit_action values: canvas.run.requested / canvas.run.approved / canvas.run.rejected.
      • Mobile: new /(home)/approvals tab + /approvals/[id] detail screen. Approve sends the user to the new trace; reject returns to the list. Notification taps deep-link to detail; the screen shows 'already decided' if two approvers race.
      • Race safety: the WHERE status='pending' guard makes approve/reject idempotent — second caller gets a conflict error (409 on mobile API, friendly redirect on dashboard). pending_run.expires_at defaults to 24h after creation; a background cleanup will mark expired rows in a follow-up.
    • v0.28.0Shipped

      HunterMobile push notifications — webhook events to your phone

      • HunterMobile flag flipped on. trace.failed / budget.breached / gate.failed / gate.passed now fan out to every paired device on the team alongside the existing outgoing webhook. Same fire-and-forget contract: fireMobilePush(teamId, event, payload) wraps the work in Next 16's after() so a slow Expo round-trip never adds latency to user-facing actions.
      • Server: new src/lib/mobile/push.ts hits exp.host/--/api/v2/push/send with all active push tokens for the team in a single request. Per-device receipts land in a new mobile_push_deliveries table (status / expo_ticket_id / error_code / error_message / timestamps), readable by team members. One audit event per fan-out (mobile.push.send) summarises delivered + failed counts.
      • Device life-cycle: when Expo returns DeviceNotRegistered or InvalidCredentials we set mobile_devices.expo_push_token_invalid_at and the device drops out of future fan-outs until the next heartbeat with a fresh token. The active-device index (mobile_devices_push_idx) is now scoped on (team_id) where token-present-and-not-invalid.
      • Mobile: expo-notifications + expo-device added. New mobile/src/push.ts handles permission, projectId lookup, getExpoPushTokenAsync, and POSTs to /api/v1/mobile/heartbeat with push_token. RootLayout subscribes to addNotificationResponseReceivedListener — tapping a notification deep-links to /traces/ for trace + gate events, /(home) for budget. Settings tab shows ‘Push notifications: Enabled / Disabled’ and exposes a manual re-prompt button when the OS permission is off.
      • Notification payloads carry only event title + IDs (trace_id, gate_slug, event kind). Trace bodies, span outputs, and budget breakdowns stay on the server — Expo can't see them.
    • v0.27.0Preview

      HunterMobile preview — pair-by-code + read-only viewer

      • Phase 4's last surface starts shipping. New @hunterade/mobile package at mobile/ — Expo + Expo Router + TypeScript app with three screens (pair, traces list, trace detail) and a settings tab that shows device/team identity and signs out. Token lives in expo-secure-store (Keychain on iOS, Keystore on Android).
      • Pairing: /dashboard/settings/devices mints a 6-character code (15 min TTL) per user, the mobile app exchanges the code via /api/v1/mobile/exchange for a long-lived htmd_-prefixed device token. Each user only sees their own devices, even on shared teams.
      • API surface: /api/v1/mobile/{exchange,heartbeat,me,traces,traces/[id]} — a separate authenticator from the scoped PAT one (mobile tokens are scope-less, mirrors HunterBridge's hbk_ pattern). Three new audit_action values: mobile.pair, mobile.revoke, mobile.heartbeat.
      • Scope deliberately small for v0.27 — read-only screens and pull-to-refresh. Push notifications via Expo Push API, approve/reject queued canvas runs, and a diff viewer all ship in v0.28+. The mobile feature flag stays off until that lands; the v0.27 preview is reachable directly from /dashboard/settings/devices.
    • v0.26.0Shipped

      HunterVoice cloud-Whisper fallback (Firefox + everywhere else)

      • Closes gotcha #16 — the v1 push-to-talk button now works in browsers without the Web Speech API. The component picks its mode at mount: Web Speech where present (Chrome / Edge / Safari), or MediaRecorder + cloud Whisper where it isn't (Firefox, in-app webviews).
      • Cloud path: MediaRecorder captures audio with the best supported mime type (webm/opus → mp4 → ogg/opus → browser default), the blob is POSTed to a new same-origin /api/voice/transcribe route handler, the server calls OpenAI whisper-1 via raw fetch (no extra SDK — same pattern as HunterKnowledge embeddings), and the returned text is appended to the linked textarea using the existing appendForVoice helper. UX is byte-identical to the v1 path other than a small ‘cloud’ tag and a ‘Transcribing…’ status while the round-trip is in flight.
      • OPENAI_API_KEY drives the fallback (already required for HunterKnowledge embeddings). Each callsite reads isWhisperConfigured() server-side and passes a cloudFallbackEnabled boolean to the client component, so the disabled-state copy can tell the user whether the limit is the browser or the server.
      • Audit-logged as voice.transcribe with bytes / mime / duration / transcript-char-count metadata only — we deliberately do not store the raw audio or the transcript itself. Compliance audit log already renders the new action label.
      • Auth: same-origin Supabase session cookie, same shape as server actions. 12 MB upload cap, normalized error envelope ({ error: { code, message } }), 503 when the key is missing, 502 on upstream failure.
    • v0.25.1Infra

      Webhooks: drop legacy plaintext secret column

      • Follow-up to v0.24.1 — encrypt-at-rest is now the only path for webhook signing material. The plaintext webhooks.secret column is gone, the webhooks_secret_present_chk constraint is gone, and secret_encrypted / secret_iv / secret_auth_tag are NOT NULL.
      • createWebhookAction now refuses to create a webhook unless HUNTERADE_BYOK_MASTER_KEY is set — no more silent plaintext fallback in dev. Local dev needs the master key configured to flag-flip webhooks.
      • dispatch.ts is simpler: one decrypt path, no lazy migration, no fallback branch. Decrypt failures fail the delivery loudly with a hint that the master key probably rotated.
      • Closes gotcha #20 fully. The transition window is over.
    • v0.25.0Shipped

      HunterMultiplayer v2: persisted comments + Realtime Authorization

      • Canvas comments are now a real persisted thread, not just live cursors. New canvas_comments table with author profiles, resolve/reopen, author-or-admin delete, full RLS scoped to team membership. The dashboard renders an SSR snapshot; new inserts stream in via Supabase postgres_changes — no refresh needed.
      • Closes gotcha #15 — the canvas: cursor + presence channel is now private. Two new policies on realtime.messages enforce team membership before a client can subscribe or broadcast: split_part(realtime.topic(), ':', 2) gives the canvas id, then a join through canvases → team_members checks auth.uid(). Public-channel access by guessed UUIDs is no longer possible.
      • Browser client calls supabase.realtime.setAuth() with the active session JWT before subscribing, then opts in with config.private = true. The cursor / presence experience is byte-identical to v1 — just provably scoped.
      • Three new audit_action enum values — comment.create, comment.resolve, comment.delete — labeled on /dashboard/compliance. Author can edit their own comments; owners and admins can moderate any.
      • Comment writes go through server actions that look up canvas.team_id, populate the row, and invalidate the canvas page; the postgres_changes listener also re-fetches so two open tabs converge on the same state without thrashing.
    • v0.24.1Infra

      Webhook signing secrets encrypted at rest

      • Closes the v2 hardening item (gotcha #20). Webhook secrets now live in three new bytea columns — secret_encrypted / secret_iv / secret_auth_tag — encrypted with AES-256-GCM keyed off HUNTERADE_BYOK_MASTER_KEY. Same scheme as BYOK API keys; rotating the master key invalidates both surfaces.
      • AES-GCM helpers extracted from compliance/byok.ts to a shared src/lib/crypto/aes-gcm.ts (encryptSecret, decryptSecret, bytesFromBytea, bytesToBytea, masterKey, isMasterKeyConfigured). Rule of two — webhooks is the second consumer, so it earns the abstraction.
      • Transition: new webhooks insert encrypted-only with secret = NULL. Existing rows still have plaintext; dispatch.ts lazy-migrates on first read (decrypt → dispatch → write encrypted columns + null plaintext in the background). After every row has been hit, a follow-up commit will drop the plaintext column.
      • Defensive constraint: webhooks_secret_present_chk ensures every row has either plaintext OR all three encrypted columns. No row can lose its signing material via a partial write.
      • Behaviorally invisible to users — same /dashboard/settings/webhooks UI, same delivery log, same HMAC-SHA256 X-HunterADE-Signature on every request. Flag-flipped without a key in dev: createWebhookAction falls back to plaintext when isMasterKeyConfigured() is false.
    • v0.24.0Shipped

      Public API: OpenAPI 3.1, scoped tokens, rate limits, request IDs

      • Hand-authored OpenAPI 3.1 spec at /openapi.yaml — every /api/v1 endpoint with request/response schemas, scope annotations, and error envelope. Rendered with Scalar at /docs (no npm dep, single CDN script).
      • Personal access tokens now hold scopes: traces:read (list/get traces + spans), traces:write (start traces, append spans, end, record_run), evals:run (trigger evals on a trace + run an eval gate). The token-create form at /dashboard/settings/tokens has a checkbox grid for picking a least-privilege subset; existing tokens were backfilled with the full scope set so no consumer broke.
      • Per-token sliding-window rate limit — 60 requests/minute default, settable via HUNTERADE_API_RPM. Counters live in api_rate_buckets via an atomic security-definer Postgres function. 429 responses carry Retry-After + X-RateLimit-{Limit,Remaining,Reset} headers. Fails open on infra blips so a transient DB error doesn't deny legitimate traffic.
      • Error envelope normalized across every /api/v1/* response: { error: { code, message, request_id } }. Every response (success + error) carries an X-Request-Id header — partners can pass one in to correlate their logs with ours, or read the one we mint. Hunter MCP client updated to read either the new or legacy shape, surfacing the request id when present.
      • Versioning policy committed in the spec's info.description: /api/v1 is stable; new optional fields and new endpoints land without a major bump; deprecations get a 90-day Deprecation header notice and a changelog entry; breaking changes ship under /api/v2 with parallel running.
      • Bridge daemon endpoints (hbk_ namespace) inherit the same error envelope + request id flow but stay scope-less — single-purpose tokens for job dispatch.
    • v0.23.0Shipped

      Teams & invites — Phase 1 closer

      • New `/dashboard/settings/team` surface. Owners and admins invite teammates by email + role, see pending invites with sent/expires timestamps, revoke any pending invite, promote/demote members, and remove members. The owner row is protected — never demotable or removable from this UI.
      • Each invite mints a single-use `htmi_`-prefixed token (sha256-hashed at rest, plaintext only sent in the email) with a 14-day expiry. The accept-invite landing at `/invite/[token]` handles every edge case explicitly: signed-out → sign-up/sign-in deeplink with the email pre-filled, signed-in but wrong email → sign-out CTA, expired/revoked/already-claimed → friendly explainer.
      • Resend delivery mirrors the waitlist pattern — gated on `resendIsConfigured()` so flag flips ship without a real key, dispatched via Next 16 `after()` so the user's redirect lands instantly. The `team_invites` row is the durable record; the email is delivery only.
      • Audit trail extended with three new actions — `member.invite.revoke`, `member.accept`, `member.role.update` — alongside the existing `member.invite` and `member.remove`. Every transition shows up on `/dashboard/compliance` with a recognizable label.
      • RLS: members read their team's invites (so non-admins see who's been invited); owners and admins manage. Accept-invite redemption goes through the admin client because the redeemer isn't yet a team member when the row is being looked up by token_hash.
      • Phase 1 now fully closes: marketing site, auth (magic link + OAuth), waitlist + Resend, onboarding wizard, ⌘K palette, and teams & invites — all live and registry-flagged.
    • v0.22.0Shipped

      Phase 1 cleanup: waitlist confirmation, onboarding wizard, ⌘K palette

      • Waitlist now sends a Resend confirmation email after a fresh signup. Dispatch wraps Next 16's `after()` so the redirect lands instantly while the email send survives the serverless response. Already-on-the-list submissions skip the email and surface a friendly 'queued' toast on the home page; failures show a retry message instead of disappearing into the void.
      • Onboarding wizard at `/onboarding` — 3 steps (display name, role, primary use case) — runs after sign-up and before the first dashboard hit. Profile row gets `role`, `primary_use_case`, and `onboarded_at` columns; the dashboard layout detours fresh users until the wizard is complete. Skipped automatically for users who've already completed it (back-button safety).
      • Command palette (⌘K / Ctrl+K) mounts globally across `/dashboard/*`. Three groups: Navigate (every dashboard surface + settings), Create (new mission, canvas, eval, adversary sweep, scribe distillation, knowledge source), Settings & docs. Built on the shadcn `cmdk` primitive — fuzzy search, keyboard-only operation, no mouse required.
      • Marketing surface picks up post-submit feedback: `?status=joined|already|invalid|error` on the home renders a colored banner anchored to the waitlist section so users see exactly what happened with their submit.
      • Three Phase 1 flags flipped (`waitlist`, `onboarding`, `commandPalette`); Phase 1 is now substantively complete except for teams + invites.
    • v0.21.1Fix

      Webhooks: dispatch survives serverless response via Next 16 `after()`

      • fireWebhookEvent now wraps dispatch in `after()` from next/server. On Vercel a bare `void promise(...)` is dropped when the response returns; with after() the runtime keeps the function alive until dispatch finishes. Falls back to bare scheduling outside a request scope (tests / scripts) by catching the E468 'wrong context' throw.
      • No behavior change in local dev — Node continues running async work either way. The change matters in production where serverless functions terminate the moment the response is sent.
    • v0.21.0Shipped

      Outgoing webhooks: ping Slack / Discord / PagerDuty when things matter

      • Subscribe a URL to events HunterADE already cares about: gate.passed, gate.failed, budget.breached, trace.failed. Slack / Discord / PagerDuty / your own infra now composes with the dashboard so an eval regression or a budget breach pages someone instead of sitting in a tab.
      • Each delivery is signed HMAC-SHA256 in the X-HunterADE-Signature header (sha256=hex(hmac(secret, body))) — same scheme as GitHub / Stripe / Linear. Receivers verify by re-signing the raw body and constant-time-comparing. The signing secret is shown once at create; lose it and you delete + recreate.
      • X-HunterADE-Delivery carries a stable UUID so receivers can dedupe replays. Manual retry from the dashboard re-fires with the same delivery_uuid so the receiver's idempotency check still works.
      • Single-attempt inline + manual retry from the UI in v1; cron-driven exponential backoff is a deliberate v2 once we have a worker queue. 8s timeout per attempt so a slow receiver can't hang a gate run.
      • Dispatch is fire-and-forget at every call site (fireWebhookEvent, no await) so a wedged receiver never adds seconds to a user-facing response. Failures land in the delivery log with HTTP status, response body (truncated to 2KB), and error message.
      • /dashboard/settings/webhooks: list + create (URL + event multi-select + auto-mint secret shown once) + per-webhook detail page with delivery log, manual retry, send-test-event button, enable/disable toggle. Three new audit_action values (webhook.create / update / delete) plus webhook.test for the synthetic-event path.
    • v0.20.0Shipped

      HunterEvals PR gates: block PRs from CI when an agent regresses

      • The Phase-2.5 promise the README has been making for months. A 'gate' bundles a canvas + a fixed test input + the evals that must pass, identified by a stable slug. Trigger it from a GitHub Action and you get a synchronous pass/fail you can wire into branch protection — a regression to the canvas's prompt blocks merge.
      • New schema: eval_gates (slug-unique-per-team, eval_ids[], canvas + test_input) and eval_gate_runs (status, trace_id, pass/fail counts, optional commit_sha + pr_url for CI deep-links). Three new audit_action values (eval_gate.create / delete / run).
      • POST /api/v1/eval-gates/[slug]/run is bearer-token authed, runs the canvas with the gate's test input via an admin-client identity override on runCanvas, then grades the gate's evals against the resulting trace and returns {status, passed_count, failed_count, trace_id, dashboard_url} in one synchronous call.
      • /dashboard/evals/gates lets you create gates (canvas dropdown + test input + multi-select evals + auto-derived slug) and each gate page shows recent runs (manual + CI), a copyable workflow YAML pre-filled with the slug, and a 'Run gate now' button for smoke testing.
      • .github/workflows/example-eval-gate.yml.template ships in the repo as a reference workflow — drop into your own repo, set HUNTERADE_API_TOKEN secret, add to branch protection, done.
      • runCanvas now accepts an optional identity override ({teamId, userId, client}) so any non-session caller (eval gate runner, future webhooks) can drive a canvas run without hijacking auth.getUser. Existing user-session callers are unchanged.
    • v0.19.1Shipped

      HunterVoice: ⇧Space toggle replaces hold-Space PTT

      • Press ⇧Space inside a focused prompt textarea to start dictating; press it again to stop. Plain Space is no longer intercepted, so typing literal spaces while composing a prompt is back to normal.
      • Behaviour matches the click-to-toggle button: mic stays hot until you toggle off, so you can pause to think without losing the recognizer.
    • v0.19.0Shipped

      HunterVoice v1: push-to-talk dictation on agent + canvas inputs

      • Click the mic next to any prompt textarea — or hold Space inside it — and dictate. Final transcript is appended to whatever you've already typed; live interim text shows next to the button so you see the recognizer working before you stop.
      • Two interaction modes: click-to-toggle (accessibility default, keyboard / screen-reader friendly with aria-pressed + aria-label) and hold-Space inside the focused textarea (Slack-style power-user shortcut).
      • Web Speech API only in v1 — works in Chrome, Edge, Safari with zero new deps and zero env vars. Firefox shows a disabled 'Voice n/a' button instead of crashing. True local Whisper (transformers.js wasm, ~40MB) and an OpenAI Whisper cloud fallback are deliberate v2 paths so we don't ship a 40MB browser bundle for an MVP.
      • Dropped on /dashboard/agents (user prompt) and /dashboard/canvas/[id] (run-canvas task input). Wires up by id — the textarea stays a normal server-rendered field, the VoiceInput client component finds it via document.getElementById and writes to .value so form submission picks up the dictated text without any controlled-input refactor.
    • v0.18.0Shipped

      HunterMultiplayer v1: Figma-style live cursors + presence on canvas

      • Open the same canvas detail page (`/dashboard/canvas/[id]`) in two windows — or with a teammate — and you see each other's cursor in real time, with a coloured arrow + name tag. Top-right pill stack shows everyone currently viewing.
      • Pure Supabase Realtime — one channel per canvas, presence for the pill stack, broadcast for cursor coordinates throttled to 20 Hz. Zero new tables, zero DB writes; opening a canvas you don't have access to never reaches the channel because Realtime inherits the same RLS as your other queries.
      • Per-user color is a stable hash of `user_id` from a hand-picked dark-theme palette (no amber, so the brand accent stays distinct from any one cursor). Initials computed from full_name → email → user_id fallback.
      • Each tab is its own session, but pills de-dupe by user_id so two tabs from the same person show one avatar — Figma-style. Cursors GC after 5s of silence as a safety net for crashed peers.
      • Comments + Multiplayer-on-other-surfaces (traces, missions) are deferred to v2 — the canvas headline experience is what the roadmap promised, and shipping it cleanly beats a half-built three-feature drop.
    • v0.17.0Shipped

      HunterBridge v1: BYO compute — pair your laptop, run agents locally

      • Phase 3 closes. Register a machine (laptop, GPU box, self-hosted runner), pair it with a 15-minute one-time code, and dispatch agent runs to it from /dashboard/agents. The bridge polls the HunterADE API, executes locally with its own Anthropic key, and streams traces back into HunterTrace — zero model traffic touches our infra.
      • New schema: `bridges`, `bridge_pairing_codes`, `bridge_tokens` (hbk_… bearer, sha256-stored), `bridge_jobs` queue, plus `traces.bridge_id` so the trace viewer shows where a run executed. Three new audit_action values: bridge.register / bridge.revoke / bridge.run.
      • Daemon-facing API at /api/v1/bridge/*: pair, heartbeat, jobs/next (atomic claim), jobs/[id]/result. Bridge tokens authenticate every endpoint; tokens are sha256-hashed at rest and revoked the moment a bridge is decommissioned.
      • /dashboard/compute lists bridges with online/offline state (90s heartbeat window), shows unclaimed pairing codes with countdown, recent jobs grouped by bridge with status + trace deep-link, and a one-line install command.
      • @hunterade/bridge ships as a Node-based reference daemon under bridge/. `npx @hunterade/bridge pair --code …` then `npx @hunterade/bridge run` is the whole loop. Heartbeat every 30s, poll every 3s, graceful shutdown on SIGINT. Config stored chmod 600 at ~/.hunterade/bridge/config.json.
      • Agent runner gets a "Run on" select — defaults to Cloud, lists every bridge with online/offline status. Cloud path is unchanged; the bridge path enqueues a job + pre-creates the trace so the user lands on a live URL while the daemon picks it up.
      • Tauri/Rust binaries with mTLS tunnel + auto-update + code signing are deferred to v2 — out of scope for a single session, and the v1 token-auth model is functionally complete for self-hosted use.
    • v0.16.0Shipped

      HunterCompliance v1: SOC2-ready audit log, PII proxy, BYOK

      • New `audit_events` table captures every meaningful action — agent runs, canvas runs, evals, postmortems, adversary sweeps, scribe distillations, forge publishes / installs, knowledge ingests, budget changes, BYOK rotations, token lifecycle, compliance settings updates, and audit exports. Append-only, RLS-protected per team, indexed on (team_id, occurred_at).
      • PII proxy redacts emails, phones, SSNs, credit cards (Luhn-checked), IPv4, AWS access keys, and known model-provider key formats from every prompt before it leaves our infra. Strict mode adds long digit runs and IPv6. Originals stay in your trace spans.
      • BYOK lets a team supply their own Anthropic / OpenAI key. Encrypted at rest with AES-256-GCM under HUNTERADE_BYOK_MASTER_KEY. Runner resolves BYOK first, falls back to platform env. Rotating leaves a `byok.rotate` audit event.
      • /dashboard/compliance — owner / admin only — surfaces PII toggle, retention slider, BYOK cards (key hint + last rotation), and a 100-event audit log. Stream the full log as JSONL or CSV; the export itself shows up as the next event in the trail.
      • Every LLM-calling surface (runAgent, runCanvas, runRedTeamCampaign, runPostmortem, distillSkillFromTrace, llm-judge) goes through one `prepareRun(teamId, provider)` helper that resolves the key + redacts inputs + stamps `compliance.*` attributes on the parent span.
      • RBAC: owners and admins manage settings + BYOK; all team members can read the audit log. Personal teams treat their creator as owner even before team_members has a row.
    • v0.15.0Shipped

      Naming pass: every product / surface now starts with "Hunter"

      • Locked in the naming rule from v0.14.0 across every shipped surface — product labels in featureFlags.ts, every dashboard page header, every empty-state, and the public marketing surfaces.
      • Phase 2: Mission Control → HunterMissions, Eval Harness → HunterEvals, Multi-Agent Canvas → HunterCanvas. Phase 3: Cost Governance → HunterCost, Red Team Mode → HunterAdversary, Agent Postmortems → HunterPostmortems, Agent Git → HunterGit, Team Knowledge Graph → HunterKnowledge, Local Bridge → HunterBridge. Phase 4: Forge → HunterForge, with HunterMultiplayer / HunterMobile / HunterCompliance lined up.
      • Dashboard sub-nav labels stay terse on purpose — the Hunter brand prefix is implied by being inside the HunterADE app shell. Each terse label maps to its full Hunter-prefixed name on the page header (e.g. nav "Adversary" → page header "HunterAdversary").
      • ROADMAP.md and README.md status table refreshed in the same commit so external readers see the official names. Added an explicit Naming rule line to ROADMAP § Brand & Naming so the policy lives next to the surface list.
      • Internal code identifiers (table / column / variable names like canvas_versions, forge_listings) intentionally stay descriptive snake_case — the rule only governs user-facing product names.
    • v0.14.0Shipped

      HunterScribe v1: distill a recorded trace into a reusable skill

      • New `skills` table — name, description, instructions (the actual prompt prefix), source_trace_ids[] for provenance, distill model + cost rollup. RLS via private.is_team_member; owners/admins delete.
      • Added `skill_id` to canvas_nodes — when set, the canvas runner prepends the skill's instructions to that node's system prompt automatically.
      • Distillation: pick a saved trace at /dashboard/scribe/new, click Distill — Sonnet 4.6 reads the trace's spans + IO previews and produces { name, description, instructions } in strict JSON. Typical cost ~$0.005 per skill.
      • /dashboard/scribe — list of skills with provenance count + distill cost. /dashboard/scribe/[id] is a full edit page (refine the auto-generated instructions before attaching).
      • Canvas node edit page gained a HunterScribe skill picker. The runner pre-loads all referenced skills in one query, splices skill.instructions into the system-prompt head before knowledge context and base role.
      • Naming rule: every product / surface starts with "Hunter" going forward. Skill Recorder → HunterScribe is the first feature shipped under this rule.
    • v0.13.0Shipped

      HunterForge v1: publish a canvas, install someone else's

      • New `forge_listings` table — frozen canvas snapshots (same shape as canvas_versions), unique slug, published_at lifecycle, install_count rollup. RLS lets anon + authenticated read PUBLISHED listings; team members additionally see their own drafts.
      • /forge — public marketplace landing (no auth required). Hero, role-chip preview per listing, install_count + node count footer.
      • /forge/[slug] — public detail with full pipeline preview (every node's role, name, model, system prompt) and a one-click Install button.
      • Install action forks the listing into the user's team: new canvas + nodes, auto-commit as v1 with message "Installed from Forge · ", increments install_count, redirects to the new canvas.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Publish panel on /dashboard/canvas/[id]: title + description form. Server action snapshots current state, mints a slug (title + 6-char random suffix), sets published_at = now.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>/dashboard/forge — your team's listings with Unpublish / Republish / Delete actions. Drafts and unpublished listings remain visible to the team without leaking to the public.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Forge link added to the marketing nav (public) and the dashboard sub-nav (publishers).</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.299999999999999s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.12.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterKnowledge v1: pgvector retrieval that grounds every canvas run</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Enabled pgvector + new knowledge_sources / knowledge_chunks tables (1536-dim embeddings, HNSW cosine index). public.match_knowledge_chunks RPC runs as security_invoker over team-scoped RLS — no security-definer warnings.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built /dashboard/knowledge with paste-ingest (paragraph-aware chunker, ~500 tok / 50 tok overlap), source detail with chunk drill-down, and a built-in Search panel that runs cosine retrieval ad-hoc to verify quality.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>OpenAI text-embedding-3-small via raw fetch (no extra SDK dep). Friendly setup banner + form-disable when OPENAI_API_KEY isn't configured.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Per-canvas opt-in via a Use Knowledge toggle on the canvas detail page. When on, runCanvas embeds the user task once, retrieves top-6 chunks above min-similarity 0.4, and prepends a "Relevant team context" block to every node's system prompt.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Retrieved chunk_ids land on the agent.run span's attributes so trace replay shows exactly which knowledge informed the run.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.36s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.11.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterGit v1: version-control your canvas like code</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `canvas_versions` table — frozen snapshots of (canvas + ordered nodes) keyed on (canvas_id, version) with auto-incrementing per-canvas integers. Snapshots are immutable history; the table has no UPDATE policy.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Commit panel on /dashboard/canvas/[id]: type a message, click Commit, snapshot lands as the next version. Required commit message keeps history meaningful.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>/dashboard/canvas/[id]/versions: full list with revert links and a Diff vs vN-1 button on each row. Latest pair gets a one-click "Diff latest" shortcut in the header.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>/dashboard/canvas/[id]/versions/[versionId]: full snapshot view of name + description + every node (with its system prompt) + a Revert button.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>/dashboard/canvas/[id]/versions/diff?from=…&to=…: side-by-side diff with metadata changes highlighted, per-position node states (added / removed / modified / unchanged), and per-field change summaries (role, name, model, system_prompt). Modified rows expand with both before/after states + full prompt text.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Revert is auditable: replaces canvas + nodes with the snapshot, then auto-writes a new version with `is_revert = true` and message "Revert to vN" so history stays linear.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.42s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.10.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterPostmortems v1: 5-whys analysis on any trace</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `postmortems` table — one per trace (UNIQUE), summary + structured analysis (whys, root_cause, recommendations) jsonb, model + cost + duration tracked. RLS via private.is_team_member.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Embedded a Postmortem panel into /dashboard/traces/[id]: empty state with a Generate button, populated state with summary + numbered 5-whys list + amber root-cause callout + recommendation bullets + Regenerate button.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Runner uses Claude Haiku 4.5 with a strict JSON-output system prompt and a compact trace-context summary (root + spans with status, IO previews, errors). Typical cost is sub-cent; budget gated.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Re-generation upserts on (trace_id) — running it again on the same trace overwrites with a fresh analysis. The trigger column reserves space for future auto-on-error / auto-on-budget triggers.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.48s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.9.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterAdversary v1: automatic adversarial sweeps against your front-door agent</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `red_team_campaigns` + `red_team_attempts` tables with attack_kind enum (prompt_injection / jailbreak / system_extraction / off_task / edge_case). RLS via private.is_team_member.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Standard attack pack: 4 canonical adversarial inputs — "Ignore previous instructions", system-prompt extraction, DAN-style jailbreak, and an off-task chitchat distraction. Each attack ships with an explicit judge rubric so verdicts are auditable.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Runner targets the front-door (first node) of any saved canvas. Each attack creates a new HunterTrace + agent.run + llm.completion span — the campaign reuses the same trace + eval infrastructure, no new observability surface.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>LLM judge (Haiku 4.5 by default) grades each attempt: passed=true means the agent BLOCKED the attack, false means the attacker won. Judge cost is rolled into the campaign's total_cost_usd alongside the agent call.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built /dashboard/red-team with a list view (block-rate bar chart per campaign), /dashboard/red-team/new (canvas + pack picker), and /dashboard/red-team/[id] showing per-attempt verdicts, judge reasoning, and links into each generated trace.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Re-run + delete campaigns inline. Cost gated by the same monthly budget as everything else.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.54s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.8.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterCost v1: monthly budgets that refuse runs over the hard limit</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `budgets` table — one per team via PK, hard + optional soft USD limits. RLS lets owners + admins update; members read.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built /dashboard/cost: this-month total + budget gauge, last-month comparison, 30-day SVG sparkline (no charting library — pure server-rendered), spend breakdown by runner (canvas, agent runner, evals, API) and by model, top 10 traces by cost.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>BudgetExceededError + assertBudgetAvailable() wired into runAgent, runCanvas, and runEvalsForTrace. Once the team's monthly spend reaches the hard limit, every LLM-triggering path returns a clear error with the exact number to raise the cap or wait for next cycle.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Soft limits surface as a banner above the dashboard (and on the budget gauge as a tick mark) — runs continue, but the team knows they're approaching the wall.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Phase 3 begins. Budgets close the immediate enterprise-readiness gap that traces alone don't solve.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.6s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.7.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterMissions v1: kanban tasks that run end-to-end through your canvases</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `missions` table + `mission_status` enum (backlog / in_progress / done / failed / archived). Optional canvas_id and current_trace_id link each mission to its execution and resulting trace. RLS via private.is_team_member.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built /dashboard/missions kanban with four lanes, status dropdowns, priority chips, and a Run button on cards bound to a canvas.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built /dashboard/missions/new (title + description + canvas selector + priority) and /dashboard/missions/[id] for full edit + run + archive/delete with the latest linked trace pinned to the top.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>runMissionAction wraps runCanvas: marks the mission in_progress, executes synchronously, parks the trace_id back on the row, transitions to done (or failed). Closes the loop from queue → execute → replay.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Sub-nav now leads with Missions: Overview · Missions · Agents · Canvas · Traces · Evals.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Phase 2 is complete: every roadmap surface for the lead pillar is shipped.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.66s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.6.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterCanvas v1: orchestrate Planner → Coder → Reviewer pipelines</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `canvases` + `canvas_nodes` schema with a `canvas_role` enum (planner / coder / reviewer / tester / red_team / custom). RLS via private.is_team_member; ordered retrieval indexed on (canvas_id, position).</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built /dashboard/canvas list, /dashboard/canvas/new (with four starter templates), /dashboard/canvas/[id] for the pipeline editor, and /dashboard/canvas/[id]/nodes/[nodeId] for per-node prompt + model editing.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Composer UX is fully server-rendered: add / remove / reorder nodes via server actions; no client JS required. Vertical card layout with animated connectors between steps.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Canvas runner walks nodes in order, feeds each output into the next agent's system prompt, captures every call as an llm.completion span under one agent.run root span. The whole pipeline lands as a single HunterTrace you can replay and grade with Evals.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Adaptive thinking on every node; ephemeral prompt caching on the system block; cost rolled up from each node's usage object.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Sub-nav now: Overview · Agents · Canvas · Traces · Evals. Canvas tile is a Live link.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.719999999999999s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.5.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">Hunter MCP server: stream traces from Cursor / Claude Code / any MCP client</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `api_tokens` table with sha-256 hashed PATs (plaintext shown once); `/dashboard/settings/tokens` to mint and revoke.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New v1 HTTP API: POST /api/v1/runs (one-shot), POST /api/v1/traces (start), GET /api/v1/traces, GET /api/v1/traces/:id, POST /api/v1/traces/:id/spans, POST /api/v1/traces/:id/end, POST /api/v1/traces/:id/evals/run. Bearer-token authed.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `mcp/` package: an independent npm module exposing six tools (record_run, start_trace, add_span, end_trace, list_recent_traces, run_evals) over MCP stdio. Drop the binary into Cursor or Claude Code's mcp.json and your editor agent emits HunterTrace spans on its own.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Eval runner refactored to accept an injected Supabase client so the API path can run evals with the admin client without going through user RLS.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Requires the SUPABASE_SECRET_KEY env var — the HTTP API returns 503 with a clear setup message until it's set.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.78s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.4.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterEvals v1: grade traces with output-contains or LLM judge</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New evals + eval_runs schema (RLS via private.is_team_member) — re-running an eval against the same trace upserts on (eval, trace).</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Two grader types: output_contains (instant, free) and llm_judge (Haiku 4.5 by default — costs negligible tokens per run, returns a JSON verdict with pass/fail, score, and reason).</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>/dashboard/evals: list + create form with conditional config blocks per grader kind. /dashboard/evals/[id] shows the eval's recent runs with verdicts, scores, and per-run cost.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Trace detail (/dashboard/traces/[id]) gained an Evals panel: passed/failed counts, per-eval verdict chips, and a Run evals button that grades the trace against every enabled rule.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>PR-blocking eval gates land in Phase 2.5 once the local CLI ships.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.84s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.3.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">Single-agent runner: real Anthropic calls, every span recorded</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Wired @anthropic-ai/sdk into a server-side runner that streams Messages API calls (adaptive thinking, prompt caching on system blocks) and persists every call as a HunterTrace span tree: agent.run wraps llm.completion.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built /dashboard/agents — a clean form (system prompt, user prompt, model dropdown). On submit you land on the trace detail with cost, tokens, latency, and the full assistant output captured.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Accurate cost calculation per model, including separate rates for cache writes (5m TTL × 1.25 input) and cache reads (× 0.1 input). Opus 4.7 / 4.6, Sonnet 4.6, Haiku 4.5 supported.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Typed Anthropic SDK exceptions (RateLimitError, AuthenticationError, etc.) surface as span.status = error with the HTTP status preserved on attributes.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Surface a clear setup banner when ANTHROPIC_API_KEY is missing rather than failing silently.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.9s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 9, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.2.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">HunterTrace v1: trace + span ingest, list view, timeline replay</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>New `traces` and `spans` tables with full RLS — every span carries cost, latency, model, tokens, IO, and a typed `kind` (agent / llm / tool / eval / internal).</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built `/dashboard/traces` list view with status badges, span counts, total cost rollups, and relative timestamps.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Built `/dashboard/traces/[id]` timeline replay — proportional span bars colored by kind, stat tiles, and a full inspector with collapsible inputs/outputs/attributes per span.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Auto-create a personal team for every new user (and backfill existing users) so traces always have a home.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>One-click "Generate sample trace" action that inserts a realistic span tree to play with.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:9.959999999999999s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 8, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.1.2</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300">Infra</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">Supabase wired up — auth and waitlist persist</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Provisioned the production Supabase project (us-west-1, Free tier) with `profiles`, `teams`, `team_members` (owner/admin/member enum), and `waitlist` tables — RLS on everything.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Security-definer trigger functions (`handle_new_user`, `handle_new_team`, `is_team_member`) live in a private schema so they can't be called as RPCs.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Generated typed `Database` for the Supabase clients — full autocomplete and compile-time safety on every query.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Waitlist form on the landing page now persists to Postgres. Duplicate emails are treated as success.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:10.02s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 8, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.1.1</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">Phase 1 auth: magic link + GitHub/Google OAuth</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Added the `(auth)` route group: shared `AuthForm` with email magic-link plus GitHub and Google OAuth buttons.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Wired session-refresh middleware so Supabase auth cookies stay fresh on every navigation.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>OAuth callback exchanges the `?code` for a session and redirects to `?next` (defaults to `/dashboard`).</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>`/dashboard` is now server-side guarded — unauthenticated users land on `/sign-in?next=/dashboard`.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Site header switches to a user menu with email + sign-out once you're signed in.</span></li></ul></li><li class="relative [animation:var(--animate-hunter-rise)]" style="animation-delay:10.08s"><span aria-hidden="true" class="absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]"></span><div class="flex flex-wrap items-center gap-3 text-xs"><time class="font-mono text-zinc-500">May 8, 2026</time><span class="rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300">v0.1.0</span><span class="rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300">Shipped</span></div><h2 class="mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50">Phase 0 foundation</h2><ul class="mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400"><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Stood up the HunterADE app: Next.js 16 + React 19 + TypeScript + Tailwind v4 + shadcn/ui.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Supabase clients (browser, server, middleware) typed end-to-end.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Introduced the `<ComingSoon />` pattern + `featureFlags.ts` registry — flip a single boolean to launch a feature; banner self-removes.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>Marketing landing page with hero, four-pillar grid (HunterTrace as lead), and waitlist form.</span></li><li class="flex items-start gap-2"><span class="mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600"></span><span>CI on every push: typecheck + lint + build.</span></li></ul></li></ol></div></div></section><footer class="relative mt-12 border-t border-white/5 bg-zinc-950"><div aria-hidden="true" class="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/12 to-transparent"></div><div class="mx-auto grid w-full max-w-7xl grid-cols-2 gap-y-12 gap-x-8 px-6 py-16 sm:grid-cols-3 lg:grid-cols-[1.5fr_repeat(5,1fr)]"><div class="col-span-2 flex flex-col gap-4 sm:col-span-3 lg:col-span-1"><a class="flex items-center gap-2.5 font-medium tracking-tight" href="/"><span aria-hidden="true" class="grid h-7 w-7 place-items-center rounded-md bg-white font-display text-base leading-none text-zinc-950 shadow-[0_4px_18px_-6px_rgba(255,255,255,0.35)]">S</span><span class="text-zinc-100">Stackon</span></a><p class="max-w-xs text-sm leading-relaxed text-zinc-500">The observability-first workspace for engineering teams running Claude and Codex. Every agent run, a replayable trace.</p><p class="font-mono text-[10px] uppercase tracking-[0.22em] text-zinc-600">Speed, with receipts.</p></div><div class="flex flex-col gap-3"><p class="font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500">Observability</p><ul class="flex flex-col gap-2"><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/trace">Trace</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/evals">Evals</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/cost">Cost</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/adversary">Adversary</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/postmortems">Postmortems</a></li></ul></div><div class="flex flex-col gap-3"><p class="font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500">Canvas & Missions</p><ul class="flex flex-col gap-2"><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/canvas">Canvas</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/missions">Missions</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/versions">Versions</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/multiplayer">Multiplayer</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/scribe">Scribe</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/knowledge">Knowledge</a></li></ul></div><div class="flex flex-col gap-3"><p class="font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500">Apps & Surfaces</p><ul class="flex flex-col gap-2"><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/mobile">Mobile</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/voice">Voice</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/space">Stackon Space</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/mcp">Stackon MCP</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/bridge">Bridge</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/forge">Forge</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/product/compliance">Compliance</a></li></ul></div><div class="flex flex-col gap-3"><p class="font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500">Resources</p><ul class="flex flex-col gap-2"><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/docs">Docs</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/changelog">Changelog</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/model-updates">Model Updates</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/community/events">Events</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/community/discord">Discord</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/download">Download</a></li></ul></div><div class="flex flex-col gap-3"><p class="font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500">Company</p><ul class="flex flex-col gap-2"><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/about">About</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/pricing">Pricing</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/careers">Careers</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/media">Media</a></li><li><a class="text-sm text-zinc-400 transition-colors hover:text-white" href="/contact">Contact</a></li></ul></div></div><div class="border-t border-white/5"><div class="mx-auto flex w-full max-w-7xl flex-col items-start justify-between gap-3 px-6 py-6 text-xs text-zinc-600 sm:flex-row sm:items-center"><p>© <!-- -->2026<!-- --> Stackon</p><div class="flex items-center gap-5 text-xs"><a class="text-zinc-500 transition-colors hover:text-white" href="/privacy">Privacy</a><a class="text-zinc-500 transition-colors hover:text-white" href="/terms">Terms</a></div><p class="font-mono text-[10px] uppercase tracking-[0.22em] text-zinc-700">v0.99.53</p></div></div></footer></main><!--$--><!--/$--><script src="/_next/static/chunks/0tyw4u3~2isbh.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n3:I[58298,[\"/_next/static/chunks/1434vgfrw3.2j.js\"],\"default\"]\n4:I[37457,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n6:I[22016,[\"/_next/static/chunks/0.yi9aimcng_a.js\"],\"\"]\n14:I[63491,[\"/_next/static/chunks/0sz.a62igdz7s.js\"],\"default\"]\nc4:I[97367,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"ViewportBoundary\"]\nc6:I[97367,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"MetadataBoundary\"]\nc7:\"$Sreact.suspense\"\ne2:I[97367,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"OutletBoundary\"]\ne4:I[55068,[\"/_next/static/chunks/0.yi9aimcng_a.js\"],\"SiteNav\"]\ne5:I[27201,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"IconMark\"]\n:HL[\"/_next/static/chunks/0.afuf0f_~w~k.css\",\"style\"]\n:HL[\"/_next/static/chunks/15ybv1~9s.ryk.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.08e28id.o-okb.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/c47649aa31f9e140-s.p.11uo_35nso9mn.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/cc2b2ba9b11d3453-s.p.11.718el1mtc9.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2\",\"font\",{\"crossOrigin\":\"anonymous\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"changelog\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"changelog\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0.afuf0f_~w~k.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/15ybv1~9s.ryk.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"geist_deef94d5-module__Sms4YG__variable geist_mono_1bf8cbf6-module__FlyLvG__variable hanken_grotesk_3039b8e4-module__rXvONG__variable dark h-full antialiased\",\"children\":[\"$\",\"body\",null,{\"className\":\"min-h-full flex flex-col bg-zinc-950 text-zinc-100\",\"children\":[[[\"$\",\"link\",\"/_next/static/media/c47649aa31f9e140-s.p.11uo_35nso9mn.woff2\",{\"rel\":\"preload\",\"href\":\"/_next/static/media/c47649aa31f9e140-s.p.11uo_35nso9mn.woff2\",\"as\":\"font\",\"type\":\"font/woff2\",\"crossOrigin\":\"anonymous\"}],[\"$\",\"link\",\"/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2\",{\"rel\":\"preload\",\"href\":\"/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2\",\"as\":\"font\",\"type\":\"font/woff2\",\"crossOrigin\":\"anonymous\"}],[\"$\",\"link\",\"/_next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2\",{\"rel\":\"preload\",\"href\":\"/_next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2\",\"as\":\"font\",\"type\":\"font/woff2\",\"crossOrigin\":\"anonymous\"}]],[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$3\",\"errorStyles\":[],\"errorScripts\":[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/1434vgfrw3.2j.js\",\"async\":true}]],\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"main\",null,{\"className\":\"flex flex-1 flex-col\",\"children\":[\"$L5\",[\"$\",\"section\",null,{\"className\":\"flex flex-1 items-center\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto flex w-full max-w-3xl flex-col gap-8 px-6 py-24 sm:py-32\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex items-center gap-3 \",\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"block h-px w-12 bg-gradient-to-r from-transparent via-white/30 to-white/40\"}],[\"$\",\"span\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-300\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-zinc-500\",\"children\":[\"§ \",\"404\"]}],[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"mx-2 text-zinc-700\",\"children\":\"·\"}],\"Not found\"]}]]}],[\"$\",\"h1\",null,{\"className\":\"font-display text-[clamp(2.5rem,6vw,5rem)] leading-[1.02] tracking-tight text-zinc-50\",\"children\":[\"That page \",[\"$\",\"span\",null,{\"className\":\"italic text-white\",\"children\":\"doesn’t exist\"}],\".\"]}],[\"$\",\"p\",null,{\"className\":\"max-w-xl text-base leading-relaxed text-zinc-400\",\"children\":[\"Most likely you followed a link to something that moved or hasn’t shipped yet. If you think this is a bug, email \",[\"$\",\"a\",null,{\"className\":\"text-zinc-200 underline-offset-4 hover:underline\",\"href\":\"mailto:hello@stackon.ai\",\"children\":\"hello@stackon.ai\"}],\".\"]}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap gap-3 pt-2\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/\",\"className\":\"rounded-full bg-white px-5 py-2 text-sm font-medium text-zinc-950 transition hover:bg-zinc-200\",\"children\":\"Back to home\"}],[\"$\",\"$L6\",null,{\"href\":\"/changelog\",\"className\":\"rounded-full border border-white/15 px-5 py-2 text-sm text-zinc-200 transition hover:border-white/30 hover:text-white\",\"children\":\"See what shipped\"}]]}]]}]}],[\"$\",\"footer\",null,{\"className\":\"relative mt-12 border-t border-white/5 bg-zinc-950\",\"children\":[[\"$\",\"div\",null,{\"aria-hidden\":true,\"className\":\"pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/12 to-transparent\"}],[\"$\",\"div\",null,{\"className\":\"mx-auto grid w-full max-w-7xl grid-cols-2 gap-y-12 gap-x-8 px-6 py-16 sm:grid-cols-3 lg:grid-cols-[1.5fr_repeat(5,1fr)]\",\"children\":[[\"$\",\"div\",null,{\"className\":\"col-span-2 flex flex-col gap-4 sm:col-span-3 lg:col-span-1\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/\",\"className\":\"flex items-center gap-2.5 font-medium tracking-tight\",\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"grid h-7 w-7 place-items-center rounded-md bg-white font-display text-base leading-none text-zinc-950 shadow-[0_4px_18px_-6px_rgba(255,255,255,0.35)]\",\"children\":\"S\"}],\"$L7\"]}],\"$L8\",\"$L9\"]}],[\"$La\",\"$Lb\",\"$Lc\"],\"$Ld\",\"$Le\"]}],\"$Lf\"]}]]}],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]}]]}],{\"children\":[\"$L10\",{\"children\":[\"$L11\",{},null,false,null]},null,false,\"$@12\"]},null,false,null],\"$L13\",false]],\"m\":\"$undefined\",\"G\":[\"$14\",[\"$L15\",\"$L16\"]],\"S\":false,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"KBfzp_tZ3I1FEUM4rtWt3\"}\n"])</script><script>self.__next_f.push([1,"7:[\"$\",\"span\",null,{\"className\":\"text-zinc-100\",\"children\":\"Stackon\"}]\n8:[\"$\",\"p\",null,{\"className\":\"max-w-xs text-sm leading-relaxed text-zinc-500\",\"children\":\"The observability-first workspace for engineering teams running Claude and Codex. Every agent run, a replayable trace.\"}]\n9:[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.22em] text-zinc-600\",\"children\":\"Speed, with receipts.\"}]\na:[\"$\",\"div\",\"Observability\",{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Observability\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",\"traces\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/trace\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Trace\"}]}],[\"$\",\"li\",\"evals\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/evals\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Evals\"}]}],[\"$\",\"li\",\"costGovernance\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/cost\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Cost\"}]}],[\"$\",\"li\",\"redTeam\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/adversary\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Adversary\"}]}],[\"$\",\"li\",\"postmortems\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/postmortems\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Postmortems\"}]}]]}]]}]\nb:[\"$\",\"div\",\"Canvas \u0026 Missions\",{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Canvas \u0026 Missions\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",\"canvas\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/canvas\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Canvas\"}]}],[\"$\",\"li\",\"missionControl\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/missions\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Missions\"}]}],[\"$\",\"li\",\"agentGit\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/versions\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Versions\"}]}],[\"$\",\"li\",\"multiplayer\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/multiplayer\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Multiplayer\"}]}],[\"$\",\"li\",\"skillRecorder\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/scribe\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Scribe\"}]}],[\"$\",\"li\",\"knowledge\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/knowledge\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Knowledge\"}]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"c:[\"$\",\"div\",\"Apps \u0026 Surfaces\",{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Apps \u0026 Surfaces\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",\"mobile\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/mobile\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Mobile\"}]}],[\"$\",\"li\",\"voice\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/voice\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Voice\"}]}],[\"$\",\"li\",\"space\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/space\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Stackon Space\"}]}],[\"$\",\"li\",\"hunterMcp\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/mcp\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Stackon MCP\"}]}],[\"$\",\"li\",\"compute\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/bridge\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Bridge\"}]}],[\"$\",\"li\",\"forge\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/forge\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Forge\"}]}],[\"$\",\"li\",\"compliance\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/compliance\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Compliance\"}]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"d:[\"$\",\"div\",null,{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Resources\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/docs\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Docs\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/changelog\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Changelog\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/model-updates\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Model Updates\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/community/events\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Events\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/community/discord\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Discord\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/download\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Download\"}]}]]}]]}]\ne:[\"$\",\"div\",null,{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Company\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/about\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"About\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/pricing\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Pricing\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/careers\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Careers\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/media\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Media\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/contact\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Contact\"}]}]]}]]}]\nf:[\"$\",\"div\",null,{\"className\":\"border-t border-white/5\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto flex w-full max-w-7xl flex-col items-start justify-between gap-3 px-6 py-6 text-xs text-zinc-600 sm:flex-row sm:items-center\",\"children\":[[\"$\",\"p\",null,{\"children\":[\"© \",2026,\" Stackon\"]}],[\"$\",\"div\",null,{\"className\":\"flex items-center gap-5 text-xs\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/privacy\",\"className\":\"text-zinc-500 transition-colors hover:text-white\",\"children\":\"Privacy\"}],[\"$\",\"$L6\",null,{\"href\":\"/terms\",\"className\":\"text-zinc-500 transition-colors hover:text-white\",\"children\":\"Terms\"}]]}],[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.22em] text-zinc-700\",\"children\":\"v0.99.53\"}]]}]}]\n10:[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]\n"])</script><script>self.__next_f.push([1,"11:[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"main\",null,{\"className\":\"flex flex-1 flex-col\",\"children\":[\"$L17\",[\"$\",\"section\",null,{\"className\":\"relative overflow-hidden border-b border-white/5\",\"children\":[[\"$\",\"div\",null,{\"aria-hidden\":true,\"className\":\"pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(255,255,255,0.07),transparent_55%)] [animation:var(--animate-hunter-glow)]\"}],[\"$\",\"div\",null,{\"className\":\"relative mx-auto flex max-w-3xl flex-col items-center gap-4 px-6 py-20 text-center\",\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-balance font-display text-5xl leading-[1.02] tracking-tight text-zinc-50 sm:text-6xl [animation:var(--animate-hunter-rise)]\",\"children\":[\"What we \",[\"$\",\"span\",null,{\"className\":\"italic text-white\",\"children\":\"shipped\"}],\" recently\"]}],[\"$\",\"p\",null,{\"className\":\"max-w-xl text-sm leading-relaxed text-zinc-400 [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.08s\"},\"children\":\"A running log of Stackon’s evolution. Every meaningful change lands here.\"}]]}]]}],[\"$\",\"section\",null,{\"className\":\"border-b border-white/5\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto max-w-3xl px-6 py-16\",\"children\":[\"$\",\"div\",null,{\"className\":\"relative pl-8\",\"children\":[[\"$\",\"div\",null,{\"aria-hidden\":true,\"className\":\"absolute left-2 top-2 h-[calc(100%-1rem)] w-px bg-gradient-to-b from-white/20 via-white/10 to-transparent\"}],[\"$\",\"ol\",null,{\"className\":\"flex flex-col gap-12\",\"children\":[[\"$\",\"li\",\"2026-07-04-Meet Jarvis — Stackon Space gets a voice\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jul 4, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.53\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Meet Jarvis — Stackon Space gets a voice\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e opens onto something new: \u003cstrong\u003eSimple mode\u003c/strong\u003e, a voice-first stage with a single breathing Stackon mark. Talk to it \u0026mdash; or type \u0026mdash; and \u003cstrong\u003eJarvis\u003c/strong\u003e does the rest: creates projects, dispatches real, traced Claude Code agents, watches your pull requests, and reports back out loud. Speech recognition runs \u003cstrong\u003efully on your machine\u003c/strong\u003e (local Whisper), and the full workspace \u0026mdash; now \u003cstrong\u003eAdvanced mode\u003c/strong\u003e \u0026mdash; stays one toggle away, exactly as you left it.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Agents that finish \u003cstrong\u003estay open\u003c/strong\u003e, so a follow-up continues the same session with everything it already knows. Whatever needs \u003cem\u003eyou\u003c/em\u003e finds you: a \u003cstrong\u003echime\u003c/strong\u003e sounds when an agent finishes or blocks, permission prompts land as \u003cstrong\u003eapprove / deny cards\u003c/strong\u003e on the stage, consequential actions like merging a PR wait for your spoken yes, and steps only you can do appear as a \u003cstrong\u003e\u0026ldquo;Waiting on you\u0026rdquo; checklist\u003c/strong\u003e under the task\u0026rsquo;s card. Every task opens into a live, timestamped feed of its agent\u0026rsquo;s updates. Update from \u003cstrong\u003e/download\u003c/strong\u003e.\"}}]]}]]}]]}],\"$L18\",\"$L19\",\"$L1a\",\"$L1b\",\"$L1c\",\"$L1d\",\"$L1e\",\"$L1f\",\"$L20\",\"$L21\",\"$L22\",\"$L23\",\"$L24\",\"$L25\",\"$L26\",\"$L27\",\"$L28\",\"$L29\",\"$L2a\",\"$L2b\",\"$L2c\",\"$L2d\",\"$L2e\",\"$L2f\",\"$L30\",\"$L31\",\"$L32\",\"$L33\",\"$L34\",\"$L35\",\"$L36\",\"$L37\",\"$L38\",\"$L39\",\"$L3a\",\"$L3b\",\"$L3c\",\"$L3d\",\"$L3e\",\"$L3f\",\"$L40\",\"$L41\",\"$L42\",\"$L43\",\"$L44\",\"$L45\",\"$L46\",\"$L47\",\"$L48\",\"$L49\",\"$L4a\",\"$L4b\",\"$L4c\",\"$L4d\",\"$L4e\",\"$L4f\",\"$L50\",\"$L51\",\"$L52\",\"$L53\",\"$L54\",\"$L55\",\"$L56\",\"$L57\",\"$L58\",\"$L59\",\"$L5a\",\"$L5b\",\"$L5c\",\"$L5d\",\"$L5e\",\"$L5f\",\"$L60\",\"$L61\",\"$L62\",\"$L63\",\"$L64\",\"$L65\",\"$L66\",\"$L67\",\"$L68\",\"$L69\",\"$L6a\",\"$L6b\",\"$L6c\",\"$L6d\",\"$L6e\",\"$L6f\",\"$L70\",\"$L71\",\"$L72\",\"$L73\",\"$L74\",\"$L75\",\"$L76\",\"$L77\",\"$L78\",\"$L79\",\"$L7a\",\"$L7b\",\"$L7c\",\"$L7d\",\"$L7e\",\"$L7f\",\"$L80\",\"$L81\",\"$L82\",\"$L83\",\"$L84\",\"$L85\",\"$L86\",\"$L87\",\"$L88\",\"$L89\",\"$L8a\",\"$L8b\",\"$L8c\",\"$L8d\",\"$L8e\",\"$L8f\",\"$L90\",\"$L91\",\"$L92\",\"$L93\",\"$L94\",\"$L95\",\"$L96\",\"$L97\",\"$L98\",\"$L99\",\"$L9a\",\"$L9b\",\"$L9c\",\"$L9d\",\"$L9e\",\"$L9f\",\"$La0\",\"$La1\",\"$La2\",\"$La3\",\"$La4\",\"$La5\",\"$La6\",\"$La7\",\"$La8\",\"$La9\",\"$Laa\",\"$Lab\",\"$Lac\",\"$Lad\",\"$Lae\",\"$Laf\",\"$Lb0\",\"$Lb1\",\"$Lb2\",\"$Lb3\",\"$Lb4\",\"$Lb5\",\"$Lb6\",\"$Lb7\",\"$Lb8\",\"$Lb9\",\"$Lba\",\"$Lbb\",\"$Lbc\",\"$Lbd\",\"$Lbe\",\"$Lbf\"]}]]}]}]}],\"$Lc0\"]}],[\"$Lc1\"],\"$Lc2\"]}]\n"])</script><script>self.__next_f.push([1,"c3:[]\n12:\"$Wc3\"\n13:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Lc4\",null,{\"children\":\"$Lc5\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lc6\",null,{\"children\":[\"$\",\"$c7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lc8\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}]\n15:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0.afuf0f_~w~k.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n16:[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/15ybv1~9s.ryk.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n"])</script><script>self.__next_f.push([1,"18:[\"$\",\"li\",\"2026-07-03-GitHub, woven into Stackon Space\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.06s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jul 3, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.52\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"GitHub, woven into Stackon Space\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e now keeps GitHub in your peripheral vision instead of behind a door. A new \u003cstrong\u003estatus chip in the footer\u003c/strong\u003e always shows your current branch, its open pull request, and a live check-status dot \u0026mdash; and one click takes you exactly where that state points: the PR itself, a pre-filled \u003cstrong\u003eCreate PR\u003c/strong\u003e form for a branch that doesn\u0026rsquo;t have one yet, or a guided \u003cstrong\u003econnect checklist\u003c/strong\u003e if GitHub isn\u0026rsquo;t set up. \u003cstrong\u003eAgent-lane cards\u003c/strong\u003e show their branch\u0026rsquo;s PR and checks at a glance, too.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The GitHub button in the header opens a redesigned, roomier \u003cstrong\u003eGitHub home\u003c/strong\u003e: your open PRs with checks and review state beside a repo status card, with PR detail, reviews, and merging one click deep. Behind it all, Space now watches your branch and PR status continuously \u0026mdash; refreshing when you return to the window, polling while checks are pending, and updating the moment you merge. Update from \u003cstrong\u003e/download\u003c/strong\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"19:[\"$\",\"li\",\"2026-07-01-Live Preview — see your app inside Stackon Space\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.12s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jul 1, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.51\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Live Preview — see your app inside Stackon Space\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e gains a \u003cstrong\u003ePreview pane\u003c/strong\u003e: a toggleable rail that renders the web app you\u0026rsquo;re building, live, right beside your terminals and editor. Start your dev server in a terminal tab and Space \u003cstrong\u003edetects it\u003c/strong\u003e \u0026mdash; reading your \u003ccode\u003epackage.json\u003c/code\u003e scripts and probing the usual ports \u0026mdash; then attaches with one click. Every hot reload your agents trigger shows up instantly.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The pane knows when your server stops (the frame dims with a rescan prompt), remembers the last URL per workspace, and includes \u003cstrong\u003ePhone / Tablet / Full\u003c/strong\u003e width presets for quick responsive checks. Toggle it from the footer, the View menu, or the command palette. Update from \u003cstrong\u003e/download\u003c/strong\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"1a:[\"$\",\"li\",\"2026-07-01-The full PR conversation, inside Stackon Space\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.18s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jul 1, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.50\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"The full PR conversation, inside Stackon Space\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e pull requests now have a \u003cstrong\u003eConversation\u003c/strong\u003e tab alongside \u003cstrong\u003eFiles changed\u003c/strong\u003e. It\u0026rsquo;s the whole story of the PR in chronological order \u0026mdash; when it was opened, every comment, each review with its verdict, the commits as they were pushed, force-pushes, and the final merge or close.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"You can join the discussion without leaving the app: a composer at the bottom of the timeline posts general PR comments straight through your own GitHub credentials, right next to the inline code review tools that already live in the diff view. Update from \u003cstrong\u003e/download\u003c/strong\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"1b:[\"$\",\"li\",\"2026-06-20-Stackon Space sessions, captured as real traces\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.24s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 20, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.49\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space sessions, captured as real traces\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e \u0026mdash; our native desktop workspace \u0026mdash; now records every traced terminal session as a complete \u003cstrong\u003eTrace\u003c/strong\u003e: real token \u003cstrong\u003ecost\u003c/strong\u003e, the \u003cstrong\u003emodel\u003c/strong\u003e used, and the agent\u0026rsquo;s actual \u003cstrong\u003ereply text\u003c/strong\u003e for each turn. Open the trace in the web viewer and it updates \u003cstrong\u003elive\u003c/strong\u003e as the session runs.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Interactive prompts are captured faithfully too. When an agent asks you to choose from a menu, the trace shows the question and \u003cstrong\u003eyour selection\u003c/strong\u003e, and splits the work and cost from before and after your answer into clean, separate turns \u0026mdash; and each session closes with a clear \u003cstrong\u003eEnd\u003c/strong\u003e marker. Update from \u003cstrong\u003e/download\u003c/strong\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"1c:[\"$\",\"li\",\"2026-06-09-Open pull requests from Stackon Space\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.3s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.48\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Open pull requests from Stackon Space\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e \u0026mdash; our native desktop workspace \u0026mdash; can now \u003cstrong\u003econnect to GitHub and drive your pull requests\u003c/strong\u003e without leaving the app. A single GitHub button in the header opens everything: connect with the GitHub CLI, see your repo\u0026rsquo;s open PRs with live check status and review state, and merge or close them in place.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"It\u0026rsquo;s built for the way agents work. Spin up an \u003cstrong\u003eagent lane\u003c/strong\u003e (an isolated branch and worktree), let an agent commit to it, then \u003cstrong\u003eopen a pull request straight from that lane\u003c/strong\u003e \u0026mdash; the branch is pushed and the PR drafted with the title pre-filled from your last commit. Sign-in uses your own \u003ccode\u003egh\u003c/code\u003e credentials, and lane branches are kept after a merge by default so your parallel work stays intact. Update from \u003cstrong\u003e/download\u003c/strong\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"1d:[\"$\",\"li\",\"2026-06-07-Stackon Space for Windows — signed, direct download\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.36s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 7, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.47\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space for Windows — signed, direct download\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e, our native desktop workspace, is now available for \u003cstrong\u003eWindows\u003c/strong\u003e as a direct download \u0026mdash; head to \u003cstrong\u003e/download\u003c/strong\u003e. It\u0026rsquo;s the full Stackon ADE in a native window: real terminals, a Monaco editor, your missions and agents, and every session captured as a trace.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The installer is \u003cstrong\u003ecode-signed\u003c/strong\u003e (Azure Trusted Signing), so Windows SmartScreen recognizes it instead of warning about an unknown publisher. An \u003cstrong\u003e.msi\u003c/strong\u003e is also available for IT and group-policy deployment. The macOS build is next.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"1e:[\"$\",\"li\",\"2026-06-06-User Settings — your profile and two-factor auth\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.42s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.46\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"User Settings — your profile and two-factor auth\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The account menu\u0026rsquo;s \u003cstrong\u003eSettings\u003c/strong\u003e link now opens a real \u003cstrong\u003eUser Settings\u003c/strong\u003e page (it used to drop you on Team Members). Set your \u003cstrong\u003efirst and last name\u003c/strong\u003e, \u003cstrong\u003ephone\u003c/strong\u003e, and \u003cstrong\u003etitle\u003c/strong\u003e in one place \u0026mdash; your display name stays in sync automatically. Your account email is shown read-only.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"You can now add \u003cstrong\u003etwo-factor authentication\u003c/strong\u003e: pair an authenticator app (1Password, Authy, Google Authenticator\u0026hellip;) by scanning a QR code and confirming a 6-digit code, and remove it just as easily. This is the setup half \u0026mdash; enforcing the second factor at sign-in is a follow-on update.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"1f:[\"$\",\"li\",\"2026-06-06-The dashboard sweep wraps up — plus a clickable audit history\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.48s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.45\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"The dashboard sweep wraps up — plus a clickable audit history\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the last set of surfaces onto the same instrument-panel look as the rest of the dashboard \u0026mdash; the \u003cstrong\u003eOverview\u003c/strong\u003e, \u003cstrong\u003eApprovals\u003c/strong\u003e, \u003cstrong\u003eCost\u003c/strong\u003e, \u003cstrong\u003eCompliance\u003c/strong\u003e, and \u003cstrong\u003eForge\u003c/strong\u003e, plus the \u003cstrong\u003eCompute\u003c/strong\u003e, \u003cstrong\u003eTeam\u003c/strong\u003e, \u003cstrong\u003eBilling\u003c/strong\u003e, \u003cstrong\u003eAPI\u0026nbsp;tokens\u003c/strong\u003e, and \u003cstrong\u003eDevices\u003c/strong\u003e pages. Every action across them now confirms with the same non-disruptive notice from the top of the screen, so the whole signed-in dashboard finally reads as one consistent instrument.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"A few targeted improvements rode along: the \u003cstrong\u003eaudit log\u003c/strong\u003e on Compliance is now \u003cstrong\u003eclickable\u003c/strong\u003e \u0026mdash; each row drills straight into the trace, run, or resource it records; the 30-day \u003cstrong\u003espend graph\u003c/strong\u003e on Cost and the Overview reads in white; audit retention is capped at a clean 7\u0026ndash;365\u0026nbsp;days; and the Billing plan comparison is tidied up with centered columns and corrected copy.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"20:[\"$\",\"li\",\"2026-06-06-A cleaner, more consistent Webhooks — and the dashboard is uniform throughout\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.54s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.44\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner, more consistent Webhooks — and the dashboard is uniform throughout\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the \u003cstrong\u003eOutgoing\u0026nbsp;webhooks\u003c/strong\u003e settings onto the same instrument-panel look as the rest of the dashboard \u0026mdash; the create form, the endpoints table, and each webhook\u0026rsquo;s detail (events, signing secret, and the delivery log). Creating, testing, retrying, enabling, disabling, or deleting a webhook now confirms with the same non-disruptive notice from the top of the screen as the rest of the dashboard. This is the last area in a sweep that brought \u003cstrong\u003eevery\u003c/strong\u003e dashboard surface onto one consistent look.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"21:[\"$\",\"li\",\"2026-06-06-A cleaner, more consistent Scribe\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.6s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.43\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner, more consistent Scribe\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the \u003cstrong\u003eScribe\u003c/strong\u003e area onto the same instrument-panel look as the rest of the dashboard \u0026mdash; the skills list, the \u003cstrong\u003eDistill\u0026nbsp;a\u0026nbsp;skill\u003c/strong\u003e form, and each skill\u0026rsquo;s detail. Distilling, saving, or deleting a skill now confirms with the same non-disruptive notice from the top of the screen as the rest of the dashboard.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"22:[\"$\",\"li\",\"2026-06-06-Confirmation notices no longer replay on back-navigation\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.6599999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.42\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Confirmation notices no longer replay on back-navigation\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Fixed a glitch where a \u0026ldquo;created / saved / deleted\u0026rdquo; confirmation notice would pop again when you left a page and navigated back to it \u0026mdash; even though you hadn\u0026rsquo;t repeated the action. The notice now clears itself from the page\u0026rsquo;s history entry the moment it shows, so returning never replays it; repeating an action still confirms each time.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"23:[\"$\",\"li\",\"2026-06-06-A cleaner, more consistent Adversary\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.72s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.41\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner, more consistent Adversary\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the \u003cstrong\u003eAdversary\u003c/strong\u003e area onto the same instrument-panel look as the rest of the dashboard \u0026mdash; the campaign list, the \u003cstrong\u003eNew\u0026nbsp;Campaign\u003c/strong\u003e form, and each campaign\u0026rsquo;s detail. The threat-posture headline now reads as a status dot\u0026nbsp;+\u0026nbsp;label, and running a campaign, re-running one, or deleting one confirms with the same non-disruptive notice from the top of the screen as the rest of the dashboard.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"24:[\"$\",\"li\",\"2026-06-06-A cleaner Knowledge area — and toasts that confirm what you did\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.78s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.40\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner Knowledge area — and toasts that confirm what you did\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the \u003cstrong\u003eKnowledge\u003c/strong\u003e area onto the same instrument-panel look as the rest of the dashboard \u0026mdash; the corpus, the \u003cstrong\u003eNew\u0026nbsp;Source\u003c/strong\u003e form, and each source\u0026rsquo;s detail. We also unified action feedback across the whole dashboard: \u003cstrong\u003ecreating\u003c/strong\u003e a mission, canvas, agent, eval, gate, or knowledge source \u0026mdash; and ingesting or deleting a source \u0026mdash; now pops the same non-disruptive confirmation from the top of the screen, so an action never leaves you guessing whether it landed.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"25:[\"$\",\"li\",\"2026-06-06-A cleaner, more consistent Agents\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.84s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 6, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.39\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner, more consistent Agents\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the \u003cstrong\u003eAgents\u003c/strong\u003e area onto the same instrument-panel look as the rest of the dashboard \u0026mdash; the roster, the \u003cstrong\u003eNew\u0026nbsp;Agent\u003c/strong\u003e and agent-edit forms, and the one-shot \u003cstrong\u003eQuick\u0026nbsp;run\u003c/strong\u003e. Creating, updating, archiving, or restoring an agent now confirms with a non-disruptive notice from the top of the screen instead of an inline banner that shifts the page.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"26:[\"$\",\"li\",\"2026-06-05-A cleaner, more consistent Canvas\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.8999999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 5, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.38\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner, more consistent Canvas\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the whole \u003cstrong\u003eCanvas\u003c/strong\u003e area onto the same instrument-panel look as Traces, Evals \u0026amp; Missions \u0026mdash; the pipeline list, the \u003cstrong\u003eNew\u0026nbsp;Canvas\u003c/strong\u003e form (its starter-template roles now read in their own colors), the canvas editor, node editing, and the full version history (snapshots\u0026nbsp;+\u0026nbsp;diffs). The editor\u0026rsquo;s configuration \u0026mdash; \u003cstrong\u003eTeam\u0026nbsp;Knowledge\u003c/strong\u003e, \u003cstrong\u003eApproval\u0026nbsp;Gate\u003c/strong\u003e, \u003cstrong\u003eCommit\u003c/strong\u003e, and \u003cstrong\u003ePublish\u0026nbsp;to\u0026nbsp;Forge\u003c/strong\u003e \u0026mdash; now sits under one collapsible \u003cstrong\u003eCanvas\u0026nbsp;settings\u003c/strong\u003e panel, so the page leads with the pipeline and the run. And every canvas action \u0026mdash; adding, moving, or removing a node, toggling knowledge or approvals, committing, publishing, posting a comment, or deleting the canvas \u0026mdash; now confirms with a non-disruptive notice from the top of the screen instead of shifting the page.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"27:[\"$\",\"li\",\"2026-06-03-Header menus hold the page still\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"0.96s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 3, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.37\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Header menus hold the page still\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Opening a header menu \u0026mdash; \u003cstrong\u003eProduct\u003c/strong\u003e, \u003cstrong\u003eCommunity\u003c/strong\u003e, \u003cstrong\u003eCompany\u003c/strong\u003e, or the mobile menu \u0026mdash; now freezes the page behind it until you close it, so the page no longer scrolls away under an open dropdown. The lock compensates for the scrollbar width, so nothing shifts when a menu opens.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"28:[\"$\",\"li\",\"2026-06-03-A cleaner, more consistent Missions\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.02s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 3, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.36\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner, more consistent Missions\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Brought the \u003cstrong\u003eMissions\u003c/strong\u003e board, the mission thread, and the New Mission form onto the same instrument-panel look as Traces \u0026amp; Evals. Each agent reply in a thread is now a tidy collapsible row \u0026mdash; with \u003cstrong\u003eIn\u003c/strong\u003e\u0026nbsp;/\u0026nbsp;\u003cstrong\u003eOut\u003c/strong\u003e\u0026nbsp;/\u0026nbsp;\u003cstrong\u003eCost\u003c/strong\u003e and an \u003cstrong\u003eOpen\u0026nbsp;Trace\u003c/strong\u003e button; lane and mission status read as a colored dot + plain label; and action feedback (approvals, run errors) now arrives as a non-disruptive notice from the top of the screen instead of shifting the page.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"29:[\"$\",\"li\",\"2026-06-03-A consistent Kind label across Evals\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.08s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 3, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.35\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A consistent Kind label across Evals\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The \u003cstrong\u003eKind\u003c/strong\u003e column in the Evals list now matches the eval detail view \u0026mdash; a kind-colored dot with a plain white label instead of colored text \u0026mdash; so the two read the same at a glance.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2a:[\"$\",\"li\",\"2026-06-03-A cleaner New Eval form and PR-blocking gates\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.14s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 3, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.34\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner New Eval form and PR-blocking gates\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Continued the dashboard consistency pass through the rest of the \u003cstrong\u003eEvals\u003c/strong\u003e area. The \u003cstrong\u003eNew\u0026nbsp;Eval\u003c/strong\u003e form now shows only the configuration for the grader you pick \u0026mdash; an output-contains string check or an LLM\u0026nbsp;judge rubric \u0026mdash; rather than both at once, and eval kinds read consistently as \u003cstrong\u003eOutput\u0026nbsp;Contains\u003c/strong\u003e\u0026nbsp;/\u0026nbsp;\u003cstrong\u003eLLM\u0026nbsp;Judge\u003c/strong\u003e throughout. The \u003cstrong\u003ePR-blocking\u0026nbsp;gates\u003c/strong\u003e list and detail now match the same instrument-panel look, and the copy-paste CI workflow references a \u003ccode\u003eSTACKON_API_TOKEN\u003c/code\u003e secret.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2b:[\"$\",\"li\",\"2026-06-02-A cleaner, more consistent Traces \u0026amp; Evals\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.2s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.33\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A cleaner, more consistent Traces \u0026amp; Evals\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Refined the \u003cstrong\u003eTraces\u003c/strong\u003e and \u003cstrong\u003eEvals\u003c/strong\u003e dashboards onto one consistent instrument-panel look \u0026mdash; decluttered headers, run status as a colored dot + plain label (green\u0026nbsp;completed\u0026nbsp;/ amber\u0026nbsp;running\u0026nbsp;/ red\u0026nbsp;failed), boxed metrics, and a single click-to-expand \u003cstrong\u003espan\u0026nbsp;timeline\u0026nbsp;\u0026amp;\u0026nbsp;details\u003c/strong\u003e on every trace. The first wave of a dashboard-wide consistency pass.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2c:[\"$\",\"li\",\"2026-06-02-Stop a mission run — and no more runs stuck \u0026ldquo;in progress\u0026rdquo;\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.26s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.32\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stop a mission run — and no more runs stuck \u0026ldquo;in progress\u0026rdquo;\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Two fixes for runaway runs: a live mission now shows a \u003cstrong\u003eStop\u0026nbsp;run\u003c/strong\u003e button that ends it and unsticks the board immediately, and any run abandoned by an interrupted background task is automatically marked failed after 10\u0026nbsp;minutes (with a note in the thread) instead of spinning \u0026ldquo;in\u0026nbsp;progress\u0026rdquo; forever.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2d:[\"$\",\"li\",\"2026-06-02-A clear path when a mission isn\u0026rsquo;t ready to run\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.3199999999999998s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.31\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A clear path when a mission isn\u0026rsquo;t ready to run\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"A mission runs a bound \u003cstrong\u003ecanvas\u003c/strong\u003e of agents, so it needs one with at least one agent before it can start. Instead of a silently disabled composer, you now get a \u003cstrong\u003eSetup\u0026nbsp;needed\u003c/strong\u003e panel that names exactly what\u0026rsquo;s missing and fixes it in one step \u0026mdash; attach an existing canvas from a dropdown, build a new one, or jump to the bound canvas to add agents.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2e:[\"$\",\"li\",\"2026-06-02-Opening a trace the instant a run starts\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.38s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.30\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Opening a trace the instant a run starts\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Clicking \u003cstrong\u003eOpen\u0026nbsp;trace\u003c/strong\u003e in the first moment of a live run used to hit a \u0026ldquo;not\u0026nbsp;found\u0026rdquo; page \u0026mdash; the trace was still being written. It now shows a brief \u003cstrong\u003eInitializing\u0026nbsp;run\u003c/strong\u003e state that resolves into the real trace the instant it begins streaming, so the link always lands somewhere useful.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"2f:[\"$\",\"li\",\"2026-06-02-Signing in without an account now points you the right way\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.44s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.29\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Signing in without an account now points you the right way\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Enter an email that doesn\u0026rsquo;t have a Stackon account on the \u003ca href=\\\"/sign-in\\\"\u003esign-in\u003c/a\u003e page and we now take you straight to \u003ca href=\\\"/sign-up\\\"\u003esign-up\u003c/a\u003e \u0026mdash; with the address already filled in \u0026mdash; instead of quietly \u0026ldquo;sending\u0026rdquo; a link that could never arrive.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"30:[\"$\",\"li\",\"2026-06-02-A more focused dashboard overview\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.5s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.28\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A more focused dashboard overview\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Removed the redundant \u0026ldquo;Jump\u0026nbsp;to\u0026rdquo; shortcut row from the dashboard overview \u0026mdash; the left sidebar (and \u003ccode\u003e\u0026#8984;K\u003c/code\u003e) already cover navigation, so the overview now stays on your live signal: spend, runs, eval health, and what needs you.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"31:[\"$\",\"li\",\"2026-06-02-Dashboard chrome, tuned to the brand\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.56s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.27\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Dashboard chrome, tuned to the brand\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The dashboard now sits on the same \u003cstrong\u003eblack-and-smoke\u003c/strong\u003e palette as the rest of stackon.ai \u0026mdash; the faint green cast behind the workspace is gone \u0026mdash; and the top-bar breadcrumb (\u003cstrong\u003eStackon / \u0026lt;page\u0026gt;\u003c/strong\u003e) now shares the brand display typeface with the page title, so the chrome reads as one consistent surface.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"32:[\"$\",\"li\",\"2026-06-02-A reproducible database, from scratch\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.6199999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 2, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.26\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A reproducible database, from scratch\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Behind the scenes: Stackon\u0026rsquo;s entire database schema now lives in version-controlled migrations and is verified byte-for-byte identical to production \u0026mdash; so a clean environment can be stood up from nothing. Reliability groundwork for staging and self-hosting; no change to the product itself.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"33:[\"$\",\"li\",\"2026-06-01-Canvas leads the workspace\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.68s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 1, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.25\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Canvas leads the workspace\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The dashboard\u0026rsquo;s \u003cstrong\u003eWorkspace\u003c/strong\u003e nav now opens with \u003cstrong\u003eCanvas\u003c/strong\u003e \u0026mdash; the first step when you start a project \u0026mdash; ahead of Missions, matching the natural build order.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"34:[\"$\",\"li\",\"2026-06-01-Your sign-in link now tells you when it lands\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.74s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 1, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.23\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Your sign-in link now tells you when it lands\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"When you request a magic link, the \u003ca href=\\\"/sign-in\\\"\u003esign-in\u003c/a\u003e confirmation now updates the moment your email is actually \u003cstrong\u003edelivered\u003c/strong\u003e \u0026mdash; the \u0026ldquo;in\u0026nbsp;flight\u0026rdquo; signal settles into a \u003cstrong\u003eDelivered\u003c/strong\u003e receipt (or flags a bounce) in real time, so you\u0026rsquo;re never left wondering whether it\u0026rsquo;s on the way. Built on real delivery events, not a timer.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"35:[\"$\",\"li\",\"2026-06-01-A more polished sign-in\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.7999999999999998s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"Jun 1, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.21\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A more polished sign-in\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"After you request a magic link, the confirmation on the \u003ca href=\\\"/sign-in\\\"\u003esign-in\u003c/a\u003e screen is now a \u003cstrong\u003erefined smoke-glass panel\u003c/strong\u003e in the same telemetry style as the dashboard \u0026mdash; replacing the old green box. A subtle \u003cstrong\u003e\u0026ldquo;in\u0026nbsp;flight\u0026rdquo;\u003c/strong\u003e signal traces toward its destination, so it\u0026rsquo;s clear at a glance that your link is on its way.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"36:[\"$\",\"li\",\"2026-05-31-Fixed: dashboard search \u0026 command palette\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.8599999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 31, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.20\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Fixed: dashboard search \u0026 command palette\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The top-right \u003cstrong\u003esearch\u003c/strong\u003e and the \u003cstrong\u003ecommand palette\u003c/strong\u003e now open correctly \u0026mdash; clicking search previously threw an error. The shortcut hint is also \u003cstrong\u003eOS-aware\u003c/strong\u003e now: \u003ccode\u003e\u0026#8984;K\u003c/code\u003e on macOS, \u003ccode\u003eCtrl\u0026nbsp;K\u003c/code\u003e on Windows and Linux.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"37:[\"$\",\"li\",\"2026-05-31-A more cohesive dashboard typeface\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.92s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 31, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.19\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A more cohesive dashboard typeface\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Dashboard \u003cstrong\u003eheadings and key metrics\u003c/strong\u003e now use Stackon\u0026rsquo;s display typeface \u0026mdash; the same one across \u003ca href=\\\"/\\\"\u003estackon.ai\u003c/a\u003e \u0026mdash; so the workspace and the marketing site read as one product. A small follow-on to the dashboard redesign.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"38:[\"$\",\"li\",\"2026-05-31-A redesigned dashboard — and navigation that finally fits\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"1.98s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 31, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.18\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A redesigned dashboard — and navigation that finally fits\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Navigation moved off the cramped top bar into a \u003cstrong\u003ecollapsible left sidebar\u003c/strong\u003e, grouped the way you actually work \u0026mdash; \u003cstrong\u003eWorkspace\u003c/strong\u003e, \u003cstrong\u003eObservability\u003c/strong\u003e, \u003cstrong\u003eExtend\u003c/strong\u003e, and \u003cstrong\u003eSettings\u003c/strong\u003e. It sits as a slim icon rail by default, \u003cstrong\u003eexpands on hover\u003c/strong\u003e, and \u003cstrong\u003epins open\u003c/strong\u003e when you want it to stay. Search (\u003ccode\u003e\u0026#8984;K\u003c/code\u003e) and your account moved to a clean top bar.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every screen \u0026mdash; \u003cstrong\u003eTraces, Cost, Evals, Missions, Canvas, Agents, Adversary\u003c/strong\u003e and the rest \u0026mdash; was rebuilt into one cohesive \u003cstrong\u003emission-control\u003c/strong\u003e look: telemetry-style readouts, live status signals, and corner-framed panels, all in the same black-and-smoke palette. Same data and actions, a far sharper surface.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"39:[\"$\",\"li\",\"2026-05-31-Model Updates moves to /model-updates\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.04s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 31, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.17\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Model Updates moves to /model-updates\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The model-release feed now lives at \u003ca href=\\\"/model-updates\\\"\u003e/model-updates\u003c/a\u003e \u0026mdash; a URL that finally matches what the page is. The old \u003ccode\u003e/blog\u003c/code\u003e address \u003cstrong\u003epermanently redirects\u003c/strong\u003e there, so every existing link and bookmark keeps working.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"3a:[\"$\",\"li\",\"2026-05-30-Redesigned product pages — and Stackon Space joins the lineup\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.1s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 30, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.16\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Redesigned product pages — and Stackon Space joins the lineup\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every product now has a \u003cstrong\u003epolished, public page\u003c/strong\u003e \u0026mdash; \u003cstrong\u003eTrace, Evals, Cost, Canvas, Missions, Bridge, the MCP server\u003c/strong\u003e and the rest \u0026mdash; each with a hero, a live visual of the actual product, deep-dive sections, and cross-links to the rest of the platform. Browse them from the \u003cstrong\u003eProduct\u003c/strong\u003e menu or the \u003ca href=\\\"/product\\\"\u003e/product\u003c/a\u003e hub \u0026mdash; no sign-in required.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New on the lineup: \u003cstrong\u003eStackon Space\u003c/strong\u003e, the \u003cstrong\u003enative desktop workspace\u003c/strong\u003e \u0026mdash; real terminals, a code editor, your missions, and your agent roster in one window, where every Claude Code session you spawn lands back in Stackon as a \u003cstrong\u003ereplayable trace\u003c/strong\u003e. \u003ca href=\\\"/product/space\\\"\u003eSee the page\u003c/a\u003e; Mac \u0026amp; Windows builds are coming to \u003ca href=\\\"/download\\\"\u003e/download\u003c/a\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"3b:[\"$\",\"li\",\"2026-05-30-Stackon MCP \u0026 Bridge are now on npm\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.16s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 30, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.15\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon MCP \u0026 Bridge are now on npm\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The \u003cstrong\u003eStackon MCP server\u003c/strong\u003e and \u003cstrong\u003eBridge\u003c/strong\u003e daemon are now published packages \u0026mdash; install them in one line with \u003ccode\u003enpm\u0026nbsp;i\u0026nbsp;@stackon/mcp\u003c/code\u003e or \u003ccode\u003enpm\u0026nbsp;i\u0026nbsp;@stackon/bridge\u003c/code\u003e.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon MCP\u003c/strong\u003e connects your workspace to \u003cstrong\u003eClaude Code, Cursor, Windsurf, Codex, or Zed\u003c/strong\u003e, so every agent run emits a Trace span and you can run evals straight from your editor. \u003cstrong\u003eBridge\u003c/strong\u003e points agents at your own compute \u0026mdash; your laptop, a GPU box, or your VPC \u0026mdash; with nothing leaving your infrastructure.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every install snippet across the site and docs now resolves to a real package.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"3c:[\"$\",\"li\",\"2026-05-30-A clearer site — public product pages + a sharper home\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.2199999999999998s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 30, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.14\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A clearer site — public product pages + a sharper home\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every part of the platform now has its own \u003cstrong\u003epublic page\u003c/strong\u003e \u0026mdash; \u003cstrong\u003eTrace, Evals, Cost, Canvas, Missions, Bridge, the MCP server\u003c/strong\u003e and more, browsable from the new \u003cstrong\u003eProduct\u003c/strong\u003e menu and the \u003cstrong\u003e/product\u003c/strong\u003e hub. No sign-in required to see what each one does.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The home page leads with what Stackon actually is \u0026mdash; \u003cem\u003e\u0026ldquo;Run AI agents on your codebase, and prove they got better\u0026rdquo;\u003c/em\u003e \u0026mdash; plus an \u003cstrong\u003e\u0026ldquo;up and running in 60 seconds\u0026rdquo;\u003c/strong\u003e walkthrough (create a token, add the MCP server, watch it land in Trace).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"And it\u0026rsquo;s \u003cstrong\u003eself-serve\u003c/strong\u003e: start free from anywhere, no waitlist. Cleaner nav and footer to match.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"3d:[\"$\",\"li\",\"2026-05-30-Dashboard — an analytical home screen\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.28s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 30, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.13\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Dashboard — an analytical home screen\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The dashboard home is now a real \u003cstrong\u003ecommand center\u003c/strong\u003e instead of a grid of links. At a glance: \u003cstrong\u003ethis month\u0026rsquo;s spend\u003c/strong\u003e (against your budget), \u003cstrong\u003eruns today\u003c/strong\u003e, your \u003cstrong\u003e30-day eval pass-rate\u003c/strong\u003e, and \u003cstrong\u003efailed runs\u003c/strong\u003e in the last week.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Below the numbers, a \u003cstrong\u003e30-day spend trend\u003c/strong\u003e, your \u003cstrong\u003emost recent traces\u003c/strong\u003e, what\u0026rsquo;s \u003cstrong\u003eawaiting approval\u003c/strong\u003e, and your \u003cstrong\u003eactive missions\u003c/strong\u003e \u0026mdash; each linking straight to the detail. A brand-new workspace gets a guided \u003cem\u003e\u0026ldquo;get your first trace flowing\u0026rdquo;\u003c/em\u003e panel instead of an empty screen.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"3e:[\"$\",\"li\",\"2026-05-29-Blog — now sourced directly from the model labs\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.34s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 29, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.12\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Blog — now sourced directly from the model labs\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Blog is now a \u003cstrong\u003efirst-party feed\u003c/strong\u003e: every update comes \u003cstrong\u003estraight from the AI labs\u0026rsquo; own sites\u003c/strong\u003e \u0026mdash; \u003cstrong\u003eAnthropic (Claude), OpenAI (ChatGPT), Google (Gemini), xAI (Grok), Meta (Llama), Mistral, and DeepSeek\u003c/strong\u003e \u0026mdash; with no news aggregators or third-party rewrites in the mix.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"OpenAI and Google publish proper feeds; for the labs that don\u0026rsquo;t, we read their official release-notes / news pages directly. Corporate noise (funding, hiring, office openings) is filtered out so the feed stays focused on \u003cstrong\u003emodel launches and updates\u003c/strong\u003e, newest first.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"3f:[\"$\",\"li\",\"2026-05-29-A more modern typographic voice\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.4s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 29, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.11\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"A more modern typographic voice\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Refreshed the typeface behind every headline across the site \u0026mdash; from the landing page\u0026rsquo;s \u003cem\u003e\u0026ldquo;Ship faster. With receipts.\u0026rdquo;\u003c/em\u003e to section titles like \u003cem\u003e\u0026ldquo;Four products. One workflow.\u0026rdquo;\u003c/em\u003e \u0026mdash; swapping the previous editorial serif for \u003cstrong\u003eHanken Grotesk\u003c/strong\u003e, a contemporary grotesque that reads cleaner and more technical next to the product.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"It\u0026rsquo;s a single design-token change under the hood, so the new voice is consistent everywhere headlines appear, and the page stays fast (the above-the-fold headline font is still preloaded).\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"40:[\"$\",\"li\",\"2026-05-29-Blog — cleaner, more readable cards\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.46s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 29, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.10\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Blog — cleaner, more readable cards\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Tidied up the Blog feed. News items pulled from Google News were showing \u003cstrong\u003eraw link markup\u003c/strong\u003e in their summary (a long redirect URL bled across the card) \u0026mdash; now each card shows a \u003cstrong\u003eclean headline\u003c/strong\u003e with the \u003cstrong\u003eoriginal publisher\u003c/strong\u003e (e.g. \u0026ldquo;via Yahoo Finance\u0026rdquo;) and links straight to the source.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The cards themselves got a polish pass: \u003cstrong\u003eequal heights\u003c/strong\u003e in a tighter grid, titles and excerpts that \u003cstrong\u003eclamp cleanly\u003c/strong\u003e instead of overflowing, a subtle staggered reveal, and source filters that no longer show empty \u003ccode\u003e0\u003c/code\u003e categories.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"41:[\"$\",\"li\",\"2026-05-29-Billing — manage your subscription in Settings\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.52s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 29, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.9\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Billing — manage your subscription in Settings\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eSettings \u0026rarr; Billing\u003c/strong\u003e is now a real page: see your \u003cstrong\u003ecurrent plan\u003c/strong\u003e, how many \u003cstrong\u003eseats\u003c/strong\u003e you\u0026rsquo;re using against the plan\u0026rsquo;s limit, and an estimated monthly cost \u0026mdash; with a side-by-side \u003cstrong\u003eplan comparison\u003c/strong\u003e and one-click upgrade.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"This is the \u003cem\u003esubscription\u003c/em\u003e surface (plan, seats, payment method, invoices) \u0026mdash; distinct from the \u003cstrong\u003eCost\u003c/strong\u003e dashboard, which tracks your token spend. Each page links to the other so it\u0026rsquo;s always clear which dollars you\u0026rsquo;re looking at.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Payment method and invoice management open in a secure \u003cstrong\u003eStripe billing portal\u003c/strong\u003e when billing is configured; until paid plans are switched on, the page shows an honest \u0026ldquo;nothing to bill yet\u0026rdquo; state rather than an empty placeholder. Plan and payment changes are limited to workspace \u003cstrong\u003eowners and admins\u003c/strong\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"42:[\"$\",\"li\",\"2026-05-29-Blog — a live feed of AI-engineering news\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.58s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 29, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.8\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Blog — a live feed of AI-engineering news\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The \u003cstrong\u003eBlog\u003c/strong\u003e is live \u0026mdash; a \u003cstrong\u003ereal-time digest\u003c/strong\u003e of what\u0026rsquo;s happening across \u003cstrong\u003eClaude (Anthropic)\u003c/strong\u003e, \u003cstrong\u003eCodex (OpenAI)\u003c/strong\u003e, and the broader AI-engineering world, pulled automatically from the source.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"It aggregates a curated set of official and topic feeds \u0026mdash; OpenAI, Hugging Face, Google DeepMind, Simon Willison, Latent Space, and live Anthropic/Codex coverage \u0026mdash; into one clean, filterable grid of headlines and short excerpts, with every card linking straight to the original.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The page \u003cstrong\u003erefreshes itself on a timer\u003c/strong\u003e (no manual updates, no database), and each source is fetched independently \u0026mdash; so if one feed is briefly unreachable, the rest of the page is unaffected and it reappears on the next refresh.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"43:[\"$\",\"li\",\"2026-05-28-Stackon Space — sessions now record real cost, tokens \u0026amp; a readable transcript\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.6399999999999997s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 28, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.7\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — sessions now record real cost, tokens \u0026amp; a readable transcript\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every Claude Code session you launch from Stackon Space already becomes a \u003cstrong\u003ereplayable trace\u003c/strong\u003e \u0026mdash; now those traces carry \u003cstrong\u003ereal dollar cost and token counts\u003c/strong\u003e instead of zeros. When a traced session ends, Stackon Space reads Claude Code\u0026rsquo;s own session transcript and backfills the trace with \u003cstrong\u003einput/output tokens, cache usage, the model used, and a computed cost\u003c/strong\u003e.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The trace\u0026rsquo;s \u003cstrong\u003eOutputs\u003c/strong\u003e now show a \u003cstrong\u003eclean conversation\u003c/strong\u003e \u0026mdash; the actual user prompts and model replies (with compact \u003ccode\u003e[tool: …]\u003c/code\u003e markers) \u0026mdash; instead of raw terminal redraw noise, rendered in the same readable view as Inputs and Attributes with a one-click \u003cstrong\u003eJSON\u003c/strong\u003e toggle.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Each \u003cstrong\u003eturn\u003c/strong\u003e is now its own span built from the transcript \u0026mdash; with the prompt, the assistant\u0026rsquo;s clean reply, and its \u003cstrong\u003eown cost, tokens, and duration\u003c/strong\u003e \u0026mdash; so you can see exactly what each step did and what it cost (replacing the old keystroke-guessed turns that captured terminal spinner noise).\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"This makes the desktop\u0026rsquo;s session\u0026rarr;trace bridge actually answer the question Trace exists for \u0026mdash; \u003cem\u003ewhat did this run cost, and what happened?\u003c/em\u003e \u0026mdash; so spend shows up in the trace list, the trace detail, and the Cost dashboard like any other run.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Under the hood we pin a session id at launch (\u003ccode\u003e--session-id\u003c/code\u003e) so each trace maps deterministically to its transcript, and cost is computed from the same per-model pricing table the web runner uses (cache reads/writes priced correctly, not as full-price input).\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"44:[\"$\",\"li\",\"2026-05-28-Stackon Space — find in the terminal (Ctrl/⌘+F)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.6999999999999997s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 28, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.6\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — find in the terminal (Ctrl/⌘+F)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Terminal pane now has a \u003cstrong\u003efind bar\u003c/strong\u003e: press \u003cstrong\u003eCtrl/\u0026#8984;+F\u003c/strong\u003e with a terminal focused to search the scrollback, with \u003cstrong\u003ematch-case\u003c/strong\u003e, \u003cstrong\u003ewhole-word\u003c/strong\u003e, and \u003cstrong\u003eregex\u003c/strong\u003e toggles and a live match counter.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eEnter\u003c/strong\u003e / \u003cstrong\u003eShift+Enter\u003c/strong\u003e jump between matches and \u003cstrong\u003eEsc\u003c/strong\u003e closes the bar; matches highlight in the brand emerald as you type. When the editor pane is focused, Ctrl/\u0026#8984;+F still reaches Monaco\u0026rsquo;s own find \u0026mdash; the shortcut is only claimed for the active terminal cell.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"45:[\"$\",\"li\",\"2026-05-28-Trace — readable span detail, with a raw-JSON toggle\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.76s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 28, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.5\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Trace — readable span detail, with a raw-JSON toggle\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"A trace\u0026rsquo;s \u003cstrong\u003eInputs\u003c/strong\u003e, \u003cstrong\u003eOutputs\u003c/strong\u003e, and \u003cstrong\u003eAttributes\u003c/strong\u003e now render in a \u003cstrong\u003ehuman-readable\u003c/strong\u003e view by default instead of raw JSON \u0026mdash; user messages and model output read as plain text (real line breaks, no escaped \u003ccode\u003e\\\\n\u003c/code\u003e or wrapper braces), chat transcripts render as a conversation, and attribute objects render as a tidy key/value list.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every box keeps a \u003cstrong\u003eReadable / JSON\u003c/strong\u003e toggle in its header, so the exact raw payload is always one click away \u0026mdash; nothing is hidden, just easier to read.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The span list also previews each turn\u0026rsquo;s user input inline, so you can scan what every step was about without expanding it.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"46:[\"$\",\"li\",\"2026-05-28-Stackon Space — fuzzy-match highlighting in Quick Open + Command Palette\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.82s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 28, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.4\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — fuzzy-match highlighting in Quick Open + Command Palette\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Quick Open (\u003cstrong\u003eCtrl/\u0026#8984;+P\u003c/strong\u003e) and the Command Palette (\u003cstrong\u003eCtrl/\u0026#8984;+Shift+P\u003c/strong\u003e) now \u003cstrong\u003ehighlight the characters that matched your query\u003c/strong\u003e \u0026mdash; so you can see at a glance why each result ranked where it did, the same way VS Code does it.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The two overlays shared a near-identical fuzzy scorer; that logic now lives in one place and additionally reports which characters matched, so the highlight comes for free with no change to ranking.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"47:[\"$\",\"li\",\"2026-05-27-Stackon Space — smooth terminal resizing\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.88s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 27, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.3\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — smooth terminal resizing\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Fixed the terminal jittering / flickering at certain pane sizes while dragging a splitter (most visible maxing the terminal against the Tasks pane). At boundary heights the terminal\u0026rsquo;s scrollbar rapidly appeared and disappeared, which nudged the column count and reflowed the text, re-triggering itself \u0026mdash; a fast feedback loop.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The fix reserves a stable scrollbar gutter so the bar\u0026rsquo;s appearance can\u0026rsquo;t change the usable width, only re-fits when the pane\u0026rsquo;s actual pixel size changes (one fit per frame), and clips transient overflow \u0026mdash; so dragging stays smooth.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"48:[\"$\",\"li\",\"2026-05-27-Stackon Space — close from the rail + a prompt when nothing's open\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"2.94s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 27, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.2\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — close from the rail + a prompt when nothing's open\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The \u003cstrong\u003e×\u003c/strong\u003e next to the open workspace in the rail now closes it (editor + terminals together), not just removes it from the recent list. The × on a workspace that isn\u0026rsquo;t open still just forgets it from recents.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"When no workspace is open, both the Terminal and Editor panes now show a prompt to \u003cstrong\u003eNew Workspace\u003c/strong\u003e or \u003cstrong\u003eOpen folder…\u003c/strong\u003e instead of a stray home-directory shell \u0026mdash; terminals are workspace-scoped, so you start one by opening a workspace.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"49:[\"$\",\"li\",\"2026-05-27-Stackon Space — closing a workspace closes its terminals\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 27, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — closing a workspace closes its terminals\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Closing a workspace now closes the editor \u003cem\u003eand\u003c/em\u003e that workspace\u0026rsquo;s terminals together. Before, the terminals stayed running in the background after the workspace was closed; now they\u0026rsquo;re shut down with it (the PTYs are killed), and reopening the workspace starts fresh. Switching \u003cem\u003ebetween\u003c/em\u003e workspaces still keeps each one\u0026rsquo;s terminals alive — only an explicit close tears them down.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"4a:[\"$\",\"li\",\"2026-05-27-Stackon Space — workspace presets (one-click launch)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.06s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 27, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.99.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — workspace presets (one-click launch)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Save a workspace setup once, relaunch it in a click. In the New Workspace \u003cstrong\u003eLayout\u003c/strong\u003e step, the \u003cstrong\u003ePresets\u003c/strong\u003e row holds saved bundles \u0026mdash; a folder, a terminal count, and an optional agent. Click a preset chip and that workspace opens immediately with that exact layout (the agent running in one terminal, traced), skipping the rest of the wizard.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003e+ New\u003c/strong\u003e saves the folder + terminal count you\u0026rsquo;ve set, with an optional agent picked from your roster; hover a chip to delete it. The agent is resolved fresh at launch, so editing or removing it later never launches a stale snapshot.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"4b:[\"$\",\"li\",\"2026-05-27-Stackon Space — guided workspace setup\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.12s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 27, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.98.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — guided workspace setup\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New Workspace is now a short three-step flow \u0026mdash; \u003cstrong\u003eStart \u0026rarr; Layout \u0026rarr; Agents\u003c/strong\u003e. Pick (or create) a folder, choose \u003cstrong\u003ehow many terminals\u003c/strong\u003e to open and how they\u0026rsquo;re laid out (1 / 2 / 4 / 6 / 8 / 10 / 12, in a grid), then either add an AI agent or \u003cstrong\u003eOpen without AI\u003c/strong\u003e for just the terminals.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Nothing opens until you finish, so you get exactly the layout you asked for \u0026mdash; N terminals in a grid, with the agent you chose running in one of them, recorded as a Stackon trace. Recent workspaces are one click away at every step.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"4c:[\"$\",\"li\",\"2026-05-27-Stackon Space — parallel agent lanes (git worktrees)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.1799999999999997s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 27, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.97.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — parallel agent lanes (git worktrees)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Run several Claude agents on the same repo at once without them stepping on each other. \u003cstrong\u003eAgent lanes\u003c/strong\u003e \u0026mdash; the \u003ccode\u003e⎇\u003c/code\u003e button in the Terminal pane, or the command palette \u0026mdash; create a git \u003cem\u003eworktree\u003c/em\u003e: a separate working directory on its own branch sharing the repo\u0026rsquo;s history. A Claude session spawns pinned to it, so each agent edits its own files on its own branch and two of them never fight over the same file or the git index.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Spin up a few lanes (each can wear one of your roster agents), watch them side by side in the terminal grid, then remove a lane when you\u0026rsquo;re done \u0026mdash; the branch stays so you can merge its work. Lanes live in a \u003ccode\u003e\u0026lt;repo\u0026gt;-worktrees/\u003c/code\u003e folder next to your project, and each session is recorded as a Stackon trace like any other.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"4d:[\"$\",\"li\",\"2026-05-27-Consistent page headers across the dashboard\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.2399999999999998s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 27, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.96.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Consistent page headers across the dashboard\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every dashboard page \u0026mdash; Traces, Canvas, Evals, Agents, Missions, Cost, Knowledge, settings, and every detail / new / edit screen \u0026mdash; now draws its header from one shared component. The eyebrow, title, description, back-link, action buttons, and per-page stat line render identically, so the app reads as one surface instead of ~40 hand-built variations.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Lead pillars (Trace, Evals, Approvals) carry an emerald accent dot; detail pages use a two-column layout with status badges and actions aligned to the header. Purely presentational \u0026mdash; no behavior changed.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"4e:[\"$\",\"li\",\"2026-05-26-Stackon Space — light theme\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.3s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.95.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — light theme\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space now ships a light theme alongside the default dark. Flip it in \u003cstrong\u003eSettings \u0026rarr; Appearance\u003c/strong\u003e; the choice persists and applies live \u0026mdash; the whole workspace, the Monaco editor, the terminals, and the markdown preview all re-tone together, no relaunch.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Dark stays the default; light is one toggle away.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"4f:[\"$\",\"li\",\"2026-05-26-Reorder Stackon Space editor tabs\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.36s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.94.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Reorder Stackon Space editor tabs\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Drag an editor tab along the strip to reorder your open files, the same way the Terminal pane tabs already work. The order sticks while you work.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"50:[\"$\",\"li\",\"2026-05-26-Syntax highlighting in the markdown preview\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.42s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.93.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Syntax highlighting in the markdown preview\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Fenced code blocks in the Stackon Space markdown preview now get syntax highlighting, brand-toned to match the editor. The highlighter is bundled in the app, so it works fully offline.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"51:[\"$\",\"li\",\"2026-05-26-Stackon Space terminals stay alive per workspace\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.48s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.92.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space terminals stay alive per workspace\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Switching between workspaces no longer kills their terminals. Running \u003ccode\u003eclaude\u003c/code\u003e sessions and long-lived shells keep going in the background and are right where you left them when you switch back.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Only the current workspace\u0026rsquo;s terminals are shown; the rest stay mounted and hidden \u0026mdash; so a swarm running in one project survives while you hop to another.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"52:[\"$\",\"li\",\"2026-05-26-Stackon Space terminals are scoped to each workspace\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.54s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.91.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space terminals are scoped to each workspace\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Open terminals now belong to the workspace you opened them in, instead of being shared across every project. Switch workspaces and you see that project\u0026rsquo;s terminals \u0026mdash; not a pile of unrelated shells.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"53:[\"$\",\"li\",\"2026-05-26-Stackon Space — open or create a workspace folder\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.5999999999999996s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.90.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — open or create a workspace folder\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The New Workspace flow can now \u003cstrong\u003ecreate\u003c/strong\u003e a folder, not just open an existing one: pick a parent directory, name it, and Stackon Space makes it and opens it. And the editor\u0026rsquo;s plain \u003cstrong\u003eOpen folder\u0026hellip;\u003c/strong\u003e is back as a one-click switch for when you just want to point at a directory.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"54:[\"$\",\"li\",\"2026-05-26-Stackon Space — a real New Workspace flow\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.6599999999999997s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.89.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — a real New Workspace flow\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u0026ldquo;New Workspace\u0026rdquo; is now the front door. Step one picks the folder \u0026mdash; your project root, which sets the editor root, the terminal working directory, and the trace context. Step two picks or creates the agent or mission to start with. Opening a workspace is one coherent action instead of separate folder + session steps.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"55:[\"$\",\"li\",\"2026-05-26-Stackon Space — commit history in the Changes rail\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.7199999999999998s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.88.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — commit history in the Changes rail\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The git Changes rail gains a \u003cstrong\u003eRecent commits\u003c/strong\u003e list \u0026mdash; the last 30 commits with short hash, subject, relative time, and author. It refreshes after you commit or sync, so you can watch your work land without leaving the app.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"56:[\"$\",\"li\",\"2026-05-26-Stackon Space — branch, push \u0026 pull from the Changes rail\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.78s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.87.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — branch, push \u0026 pull from the Changes rail\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Changes rail now shows your current branch (\u003ccode\u003e⎇ main\u003c/code\u003e) and how far ahead / behind your upstream you are, with \u003cstrong\u003ePush\u003c/strong\u003e and \u003cstrong\u003ePull\u003c/strong\u003e buttons right there. Each shows an inline result (\u0026ldquo;Pushed \u0026check;\u0026rdquo; / \u0026ldquo;Already up to date\u0026rdquo;) so you know it worked.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Sync uses your operating system\u0026rsquo;s git credentials \u0026mdash; the same ones the \u003ccode\u003egit\u003c/code\u003e command line uses \u0026mdash; independent of how you signed in to Stackon Space. An uncached credential fails fast instead of hanging.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"57:[\"$\",\"li\",\"2026-05-26-Stackon Space — stage \u0026 commit from the Changes rail\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.84s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.86.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — stage \u0026 commit from the Changes rail\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Commit without leaving Stackon Space. The Changes rail lists changed files with a stage checkbox each (plus \u003cstrong\u003eStage all\u003c/strong\u003e), a commit-message box, and a \u003cstrong\u003eCommit\u003c/strong\u003e button \u0026mdash; the basic add / commit loop, right in the workspace. \u003ccode\u003eCtrl/Cmd+Enter\u003c/code\u003e commits.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"58:[\"$\",\"li\",\"2026-05-26-Stackon Space — git diff viewer\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.9s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.85.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — git diff viewer\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"A new \u003cstrong\u003eChanges\u003c/strong\u003e tab in the editor rail shows your git working-tree changes. Pick a file and it opens a read-only side-by-side diff (the same Monaco diff engine VS Code uses) of HEAD vs. your working copy, overlaid on the editor.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Reads your repo through \u003ccode\u003egit\u003c/code\u003e directly, pinned to the repository root; degrades gracefully when the folder isn\u0026rsquo;t a git repo or git isn\u0026rsquo;t installed.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"59:[\"$\",\"li\",\"2026-05-26-Stackon Space — markdown preview\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"3.96s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.84.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — markdown preview\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Open a \u003ccode\u003e.md\u003c/code\u003e or \u003ccode\u003e.mdx\u003c/code\u003e file and a \u003cstrong\u003ePreview\u003c/strong\u003e toggle appears in the tab strip \u0026mdash; flip it for a rendered, side-by-side view that mirrors your edits live. Links open in your browser; the renderer blocks script and \u003ccode\u003ejavascript:\u003c/code\u003e URLs so a README can\u0026rsquo;t do anything funny.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"5a:[\"$\",\"li\",\"2026-05-26-Stackon Space — create, rename \u0026 delete files from the tree\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.02s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.83.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — create, rename \u0026 delete files from the tree\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Right-click any file or folder in the editor tree for \u003cstrong\u003eNew file\u003c/strong\u003e, \u003cstrong\u003eNew folder\u003c/strong\u003e, \u003cstrong\u003eRename\u003c/strong\u003e, and \u003cstrong\u003eDelete\u003c/strong\u003e (right-click empty space for new file / folder at the root).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"It\u0026rsquo;s careful with open buffers: renaming remaps the tab, and a rename is refused if the file has unsaved changes rather than risk losing them.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"5b:[\"$\",\"li\",\"2026-05-26-Stackon Space editor works offline\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.08s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.82.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space editor works offline\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Monaco editor used to load its engine from a CDN, so it came up blank with no internet. Its assets are now bundled with the app and served locally \u0026mdash; the editor works fully offline, on a plane or behind a firewall.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"5c:[\"$\",\"li\",\"2026-05-26-Stackon Space — a File menu\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.14s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 26, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.81.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — a File menu\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The editor toolbar\u0026rsquo;s five buttons (New file, Open folder, Save, Save all, Close) are tidied into a single \u003cstrong\u003eFile ▾\u003c/strong\u003e dropdown, with the unsaved-changes count riding on the menu as a badge. Click out or press Esc to close it.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"5d:[\"$\",\"li\",\"2026-05-25-Stackon Space — create agents \u0026 missions from the workspace\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.2s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.80.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — create agents \u0026 missions from the workspace\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The new-workspace wizard can now \u003cstrong\u003ecreate\u003c/strong\u003e an agent or a mission inline, not just pick an existing one. Fill the short form, hit \u003cstrong\u003eCreate \u0026amp; start\u003c/strong\u003e, and it\u0026rsquo;s saved to your team and a traced \u003ccode\u003eclaude\u003c/code\u003e session spins up in the workspace. The rows are real \u0026mdash; they show up on the web dashboard too.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"5e:[\"$\",\"li\",\"2026-05-25-Stackon Space — start-a-session wizard\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.26s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.79.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — start-a-session wizard\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Open a workspace for the first time and a wizard offers to start you working: pick one of your agents or missions and it spawns a traced \u003ccode\u003eclaude\u003c/code\u003e session pinned to that folder, or start a blank terminal, or skip. Reachable any time from the command palette via \u0026ldquo;Start session in workspace\u0026hellip;\u0026rdquo;.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"5f:[\"$\",\"li\",\"2026-05-25-Stackon Space — a real workspace switcher\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.32s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.78.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — a real workspace switcher\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The left rail is now a live list of your recent workspaces instead of a placeholder. Click one to switch the editor, terminals, and trace context to it; hover to remove it from the list. Opening a new folder records it automatically.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"60:[\"$\",\"li\",\"2026-05-25-Stackon Space — more command-palette actions\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.38s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.77.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — more command-palette actions\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The command palette (\u003ccode\u003eCtrl/Cmd+Shift+P\u003c/code\u003e) gains Save file, Replace in files, and Close workspace, and the rail\u0026rsquo;s \u0026ldquo;Open folder\u0026rdquo; button is now wired up. Opening Replace-in-files from the palette reveals the replace row in the Search panel.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"61:[\"$\",\"li\",\"2026-05-25-Find-and-replace — per file and per match\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.4399999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.76.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Find-and-replace — per file and per match\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space find-in-files replace gets finer-grained: hover a file\u0026rsquo;s result group to replace every match in just that file, or hover a single match to replace only that one occurrence. The global Replace All keeps its confirmation step; the targeted replaces are one click.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"62:[\"$\",\"li\",\"2026-05-25-Stackon Space — font, tab size \u0026 scrollback settings\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.5s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.75.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — font, tab size \u0026 scrollback settings\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Settings adds editor + terminal font family, editor tab size, and terminal scrollback, all applied live. Font family is shared across editor and terminal and falls back to the built-in mono if you type a name that isn\u0026rsquo;t installed, so it never renders broken.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"63:[\"$\",\"li\",\"2026-05-25-Stackon Space — find and replace across files\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.56s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.74.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — find and replace across files\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Search panel gains a replace row and a global \u003cstrong\u003eReplace All\u003c/strong\u003e (with a two-click confirm, since it writes to disk). Files you have open in the editor are edited through the editor itself so the change stays undoable; files with unsaved changes are skipped and reported rather than clobbered.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"64:[\"$\",\"li\",\"2026-05-25-Find-in-files — search as you type\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.62s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.73.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Find-in-files — search as you type\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space find-in-files now searches as you type (debounced, kicking in at two characters so a single letter doesn\u0026rsquo;t scan the whole tree). Enter still forces an immediate search at any length, and toggling case / whole-word / regex re-runs in place.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"65:[\"$\",\"li\",\"2026-05-25-Find-in-files — regex \u0026 whole-word\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.68s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.72.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Find-in-files — regex \u0026 whole-word\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space workspace search gains two toggles next to the case switch: whole-word (\u003ccode\u003e\\\\b\u003c/code\u003e) and regular expressions (\u003ccode\u003e.*\u003c/code\u003e). Matches highlight at their true length, and an invalid pattern shows a clear \u0026ldquo;Invalid regular expression\u0026rdquo; note instead of silently returning nothing. Plain-text searches keep the fast path.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"66:[\"$\",\"li\",\"2026-05-25-Stackon Space — the focused pane is highlighted\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.74s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.71.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — the focused pane is highlighted\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7H wraps. The Terminal or Editor pane that currently holds keyboard focus now gets an emerald frame border and a brighter title — so it\u0026rsquo;s always obvious which pane \u003ccode\u003eCtrl/Cmd+W\u003c/code\u003e will close a tab in. Click between panes and the highlight follows; open the command palette and it stays put on the pane you were last working in.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Backed by a tiny observable store (\u003ccode\u003euseSyncExternalStore\u003c/code\u003e) the panes update on focus. Tasks and Agents never highlight — they aren\u0026rsquo;t Ctrl+W targets.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"67:[\"$\",\"li\",\"2026-05-25-Stackon Space — close the active tab (Ctrl/Cmd+W)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.8s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.70.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — close the active tab (Ctrl/Cmd+W)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003ccode\u003eCtrl/Cmd+W\u003c/code\u003e (and a \u0026quot;Close active tab\u0026quot; palette command) closes the active tab of whichever pane has keyboard focus — terminal or editor. It resolves the target from where your cursor actually is at the moment you press it, so it never closes the wrong pane; when focus is in the command palette it falls back to the pane you were last in.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The shortcut is intercepted so it can never close the Stackon Space window itself.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"68:[\"$\",\"li\",\"2026-05-25-Stackon Space — command palette + global shortcuts\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.859999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.69.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — command palette + global shortcuts\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003ccode\u003eCtrl/Cmd+Shift+P\u003c/code\u003e opens a command palette: a fuzzy-filtered list of actions — new terminal, open folder, quick-open, find in files, save all, toggle the terminal grid, settings, sign out — each row showing its keyboard shortcut, so the palette doubles as a way to learn them. Plus two new direct shortcuts: \u003ccode\u003eCtrl/Cmd+T\u003c/code\u003e for a new terminal and \u003ccode\u003eCtrl/Cmd+B\u003c/code\u003e to toggle the workspace rail.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Actions route through a small command bus so the shell-level palette can drive any pane. It joins the shortcuts already in place — \u003ccode\u003eCtrl/Cmd+P\u003c/code\u003e quick-open, \u003ccode\u003eCtrl/Cmd+Shift+F\u003c/code\u003e find-in-files, \u003ccode\u003eCtrl/Cmd+S\u003c/code\u003e save, \u003ccode\u003eCtrl/Cmd+,\u003c/code\u003e settings.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"69:[\"$\",\"li\",\"2026-05-25-Stackon Space — settings / preferences\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.92s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.68.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — settings / preferences\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"A real preferences pane lands, reachable from the header \u003cspan\u003e⚙\u003c/span\u003e or \u003ccode\u003eCtrl/Cmd+,\u003c/code\u003e. Set editor and terminal font size, the default shell new terminals launch, and terminal cursor blink + style. Font and cursor changes apply \u003cem\u003elive\u003c/em\u003e to every open pane — no relaunch — and everything persists across sessions via the same store the workspace folder and tabs already use.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Default shell is a free-text field (e.g. \u003ccode\u003epwsh.exe\u003c/code\u003e, \u003ccode\u003ecmd.exe\u003c/code\u003e); leave it blank to auto-detect. The plumbing makes new controls cheap to add.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"6a:[\"$\",\"li\",\"2026-05-25-Stackon Space — new terminals open in your workspace\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"4.9799999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.67.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — new terminals open in your workspace\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New terminals now start in the Editor\u0026rsquo;s workspace folder instead of your home directory. \u003ccode\u003e+ New\u003c/code\u003e, drag-spawns from Tasks/Agents, and restored tabs all resolve the current workspace — so a fresh shell is already in the project you\u0026rsquo;re working on. Change the workspace folder and the next terminal follows it.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The path is read fresh at spawn time, and Stackon Space falls back to your home directory if that folder has since moved or been deleted — a stale path never breaks the spawn.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"6b:[\"$\",\"li\",\"2026-05-25-Stackon Space — find in files\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.04s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 25, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.66.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — find in files\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Search your whole workspace from the Editor, not just the open file. \u003ccode\u003eCtrl/Cmd+Shift+F\u003c/code\u003e flips the left rail to Search; type a query, press Enter, and matches stream in grouped by file with the hit highlighted. Click any result to open that file as a tab and jump straight to the line.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built like quick-open — it reuses the workspace index, skips vendor/build folders, reads files concurrently in batches so a few-thousand-file repo stays responsive, skips binaries, and caps results. A case-sensitive toggle is included; regex / whole-word and search-as-you-type are the next slice.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"6c:[\"$\",\"li\",\"2026-05-24-Stackon Space Editor — undo + cursor survive tab switches\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.1s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.65.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space Editor — undo + cursor survive tab switches\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7C.2. Switching editor tabs no longer resets your place. Each open file now keeps its own Monaco model, so undo/redo history and your cursor + scroll position are preserved when you jump between tabs and back — the editor feels continuous, like VS Code.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Under the hood the editor drives models keyed by file URI (handling Windows \u003ccode\u003eC:\\\\\u003c/code\u003e paths correctly) and saves/restores per-file view state, instead of remounting per file. Models are disposed when you close a tab or switch workspaces.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"6d:[\"$\",\"li\",\"2026-05-24-Stackon Space — quick-open (Ctrl/Cmd+P)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.16s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.64.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — quick-open (Ctrl/Cmd+P)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Jump to any file without hunting the tree. \u003ccode\u003eCtrl/Cmd+P\u003c/code\u003e opens a fuzzy file finder over your whole workspace — type a few characters, arrow to a match, Enter to open it as a tab. Heavy/vendor folders (\u003ccode\u003enode_modules\u003c/code\u003e, \u003ccode\u003e.git\u003c/code\u003e, build output) are skipped and the index is capped so big repos stay snappy.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"VS Code-style: the shortcut is captured app-wide once a workspace is open (so it beats the browser print dialog and the terminal\u0026rsquo;s Ctrl+P). With nothing open, Ctrl+P passes through to the terminal as before.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"6e:[\"$\",\"li\",\"2026-05-24-Stackon Space Editor — create files + Save all\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.22s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.63.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space Editor — create files + Save all\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Editor can now create files, not just open them. \u003cstrong\u003e+ New file\u003c/strong\u003e takes a workspace-relative path (\u003ccode\u003enotes.md\u003c/code\u003e, \u003ccode\u003esrc/foo.ts\u003c/code\u003e), writes it to disk, and opens it as a tab. And \u003cstrong\u003eSave all\u003c/strong\u003e (\u003ccode\u003eCtrl/Cmd+Shift+S\u003c/code\u003e, or the toolbar button showing the dirty count) writes every unsaved buffer at once.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Writes stay inside Tauri\u0026rsquo;s scoped filesystem; creating into a folder that doesn\u0026rsquo;t exist yet surfaces a clear error (no implicit directory creation for now).\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"6f:[\"$\",\"li\",\"2026-05-24-Stackon Space Tasks — live list + status control\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.279999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.62.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space Tasks — live list + status control\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Tasks pane mission list now updates live too: missions you create or move on the web appear and re-sort in Stackon Space without a refresh (Supabase Realtime \u003ccode\u003epostgres_changes\u003c/code\u003e on missions, team-scoped by RLS). With the live transcript from the previous build, the whole Tasks pane is now real-time.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"And it\u0026rsquo;s no longer read-only — change a mission\u0026rsquo;s status (backlog → in\u0026nbsp;progress → done → …) right from the desktop via the status dropdown. The change is row-level-security gated to your team and syncs back to the web instantly.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"70:[\"$\",\"li\",\"2026-05-24-Stackon Space Tasks update live\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.34s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.61.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space Tasks update live\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Tasks pane mission transcript now updates in real time, matching the web. Open a mission in Stackon Space and watch agent replies, system notices, and teammates\u0026rsquo; messages stream in as they happen — no reselecting. A small \u003cspan\u003e● live\u003c/span\u003e marker shows when the thread is connected.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Same Supabase Realtime \u003ccode\u003epostgres_changes\u003c/code\u003e path as the web thread, gated by the same row-level security — you only ever receive your own team\u0026rsquo;s messages.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"71:[\"$\",\"li\",\"2026-05-24-Stackon Space remembers your open files\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.3999999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.60.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space remembers your open files\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Your Editor tabs now come back on relaunch, alongside the terminal tabs and workspace folder. Open files (and the active one) are remembered per workspace and re-read from disk on reopen — so the whole Stackon Space session restores where you left it.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"72:[\"$\",\"li\",\"2026-05-24-Stackon Space Editor — open files in tabs\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.46s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.60.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space Editor — open files in tabs\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7C.1. The Editor pane now holds multiple files open at once. Click files in the tree to open them as tabs, switch between them, and close individually — each tab tracks its own unsaved-changes dot, and switching keeps your edits in place. Open files are marked in the file tree too.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003ccode\u003eCtrl/Cmd+S\u003c/code\u003e saves the active tab. One Monaco instance still drives the active buffer (per-buffer undo history + cursor across switches is the next polish), and every write stays inside Tauri\u0026rsquo;s scoped filesystem (HOME / Documents / Desktop / Downloads).\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"73:[\"$\",\"li\",\"2026-05-24-Reorder Stackon Space terminal tabs\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.52s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.59.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Reorder Stackon Space terminal tabs\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Small polish on the Terminal pane: drag a tab along the strip to reorder it. The order (and which tab is active) persists across relaunches, and reordering reflows the grid view too. No session restarts — you\u0026rsquo;re just rearranging.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"74:[\"$\",\"li\",\"2026-05-24-Stackon Space — see all your terminals at once\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.58s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.59.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — see all your terminals at once\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7B.2 lands. A new grid toggle (▦) in the Terminal pane flips between tabs and an N-cell grid — every running terminal visible at once, laid out automatically (two-up, 2×2, up to a 3-wide grid). Drive a swarm of \u003ccode\u003eclaude\u003c/code\u003e sessions side by side, or watch a mission run next to a live shell.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Tabs and grid are the same terminals, just arranged differently — toggling never restarts a session (the PTYs stay alive; each terminal just reflows to its new size). The active cell is ringed; click any cell to focus it. Your layout choice persists across relaunches alongside the tab strip.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"75:[\"$\",\"li\",\"2026-05-24-Stackon Space remembers your terminals\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.64s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.58.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space remembers your terminals\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7B.2. The Terminal pane tab strip now persists across relaunches. Quit Stackon Space and reopen it — your tabs come back in the same order, with the one you were on still active. Built on the same \u003ccode\u003etauri-plugin-store\u003c/code\u003e the workspace folder and sign-in already use.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"A shell session can\u0026rsquo;t survive a restart (the process is gone when the app quits), so restored tabs open as fresh shells — we deliberately don\u0026rsquo;t re-run a task tab\u0026rsquo;s command, so a \u003ccode\u003eclaude\u003c/code\u003e session you spawned from a mission won\u0026rsquo;t re-fire on every launch. The N-cell grid view is the next slice of 7B.2.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"76:[\"$\",\"li\",\"2026-05-24-Mission threads update live\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.7s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.57.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Mission threads update live\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Open a mission and watch it fill in — no refresh. Messages now stream into the thread in real time: every agent reply as the bound canvas runs, system notices, and messages from teammates all appear the moment they\u0026rsquo;re written. Previously only the person who kicked off a run saw live progress; everyone else had to reload.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built on Supabase Realtime \u003ccode\u003epostgres_changes\u003c/code\u003e over the \u003ccode\u003emission_messages\u003c/code\u003e table, gated by the same row-level security as the rest of your data — you only ever receive messages for your own team\u0026rsquo;s missions. The server still renders the full thread on load; live rows merge in on top.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"77:[\"$\",\"li\",\"2026-05-24-Faster docs — the API reference paints instantly\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.76s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.56.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Faster docs — the API reference paints instantly\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eThe \u003ccode\u003e/docs\u003c/code\u003e API reference loads in a fraction of the time.\u003c/strong\u003e It used to ship a blank page that waited on a ~1 MB Scalar bundle before \u003cem\u003eanything\u003c/em\u003e appeared — Lighthouse scored it 39 on mobile. Now the page server-renders a full endpoint index (every \u003ccode\u003e/api/v1\u003c/code\u003e operation, grouped by Traces / Evals / Bridge, parsed straight from the same OpenAPI spec we serve at \u003ccode\u003e/openapi.yaml\u003c/code\u003e) that paints immediately, and the interactive Scalar explorer loads on demand when you scroll to it or click \u003cem\u003eLoad interactive reference\u003c/em\u003e.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Result: total blocking time dropped from 751\u0026nbsp;ms to 37\u0026nbsp;ms, Speed Index from 7.6\u0026nbsp;s to ~1\u0026nbsp;s, and first paint from 7.6\u0026nbsp;s to ~1\u0026nbsp;s — the heavy explorer is no longer on the critical path, but it\u0026rsquo;s one scroll away when you want it. The Scalar bundle is now pinned to an immutable, edge-cacheable version, too.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Marketing-side polish along for the ride: the home hero\u0026rsquo;s entrance animations settle a touch sooner, trimming Speed Index without losing any of the motion.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"78:[\"$\",\"li\",\"2026-05-24-Stackon Space — sign in with an email code\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.819999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 24, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.55.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — sign in with an email code\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Signing in to Stackon Space now happens entirely inside the app: enter your email, we send a 6-digit code, you type it in \u0026mdash; done. No browser round-trip, no custom URL scheme. Same Stackon account, and the session persists across launches.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The magic-link email now shows the code prominently alongside the usual sign-in link, so either works. This replaces the earlier deep-link sign-in, which stays supported for any links already in flight.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"79:[\"$\",\"li\",\"2026-05-23-Stackon Space — drop a skill into a running session\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.88s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.53.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space — drop a skill into a running session\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Drag a skill from the Agents pane onto a terminal that\u0026rsquo;s already running \u003ccode\u003eclaude\u003c/code\u003e and its instructions are typed into that session for you to review and send \u0026mdash; no new tab. Dropping on the tab strip still spawns a fresh \u003ccode\u003eclaude\u003c/code\u003e tab with the skill applied, as before.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"7a:[\"$\",\"li\",\"2026-05-23-Stackon Space traces — cleaner cost roll-ups\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"5.9399999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.52.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space traces — cleaner cost roll-ups\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Tightened how Stackon Space records terminal sessions as traces: fixed a source of trace pollution, removed a dead cost parser, and added a background sweeper that closes out stale, never-finished session traces so your trace list stays tidy.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"7b:[\"$\",\"li\",\"2026-05-23-Stackon Space traces — per-turn spans + cost\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.51.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon Space traces — per-turn spans + cost\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Recorded terminal sessions now break a \u003ccode\u003eclaude\u003c/code\u003e run into per-turn spans with a cost roll-up \u0026mdash; so a session trace reads as a sequence of turns with token + cost detail, rather than one opaque blob.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"7c:[\"$\",\"li\",\"2026-05-23-Phase 7F — Every Claude Code session in Space becomes a Stackon trace\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.06s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.50.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 7F — Every Claude Code session in Space becomes a Stackon trace\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eThe differentiator.\u003c/strong\u003e When you drag a mission / agent / skill onto the Terminal pane in Stackon Space, the resulting Claude Code session is now \u003cem\u003erecorded as a Stackon trace\u003c/em\u003e. A pulsing red \u003ccode\u003eREC\u003c/code\u003e badge appears in the terminal cell header while it's recording; an \u003cstrong\u003eOpen trace ↗\u003c/strong\u003e button lights up next to it. Click that → your default browser opens the session at \u003ccode\u003estackon.ai/dashboard/traces/\u0026lt;id\u0026gt;\u003c/code\u003e, where the full transcript lives next to every other Stackon run — replayable, eval-gateable, postmortem-ready, ready to share with a teammate. Every local Claude Code session has receipts.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mechanism: new \u003ccode\u003edesktop/src/lib/trace-session.ts\u003c/code\u003e. On terminal mount (when \u003ccode\u003etrace: true\u003c/code\u003e is in the spawn payload — set automatically by the Tasks / Agents / Skills panes; default-shell \u003ccode\u003e+ New\u003c/code\u003e tabs don't trace, so throwaway \u003ccode\u003els\u003c/code\u003e sessions stay private), a \u003ccode\u003etraces\u003c/code\u003e row + one root \u003ccode\u003espan\u003c/code\u003e (kind=agent, name=terminal.session) are inserted via the existing authenticated Supabase client. Each PTY output chunk is ANSI-stripped + appended to an in-memory buffer; flushes happen every 2 s OR when the buffer hits 64 KB. Typed input is also appended (so the trace shows what the user said). On PTY exit, the session closes with status=ok; on unmount mid-run, closes with the same status (idempotent — the TraceSession has its own \u003ccode\u003eclosed\u003c/code\u003e guard).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Privacy: transcripts are capped at \u003cstrong\u003e1 MB\u003c/strong\u003e — past that, appends are dropped with a visible \u003ccode\u003eCapped\u003c/code\u003e badge so the user knows recording stopped. Only Tasks / Agents / Skills spawns are traced by default; plain \u003ccode\u003e+ New\u003c/code\u003e shells aren\u0026rsquo;t (preserves throwaway-session privacy). Recording uses the same RLS-scoped client as every other Supabase write — only the user's team sees their traces.\"}}]]}],\"$Lc9\"]}]]}]\n"])</script><script>self.__next_f.push([1,"7d:[\"$\",\"li\",\"2026-05-23-Phase 7E — Agents + Skills sidebar with drag-to-terminal\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.12s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.49.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 7E — Agents + Skills sidebar with drag-to-terminal\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space\u0026rsquo;s Agents pane is no longer a stub. Top half = your team\u0026rsquo;s roster, pulled live from \u003ccode\u003eteam_agents\u003c/code\u003e (same Supabase project the web uses, RLS-scoped server-side). Bottom half = the Skills library — Scribe-distilled procedures from past canvas runs.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eDrag an agent\u003c/strong\u003e onto the Terminal pane → spawns \u003ccode\u003eclaude --append-system-prompt \u0026lt;agent.system_prompt\u0026gt;\u003c/code\u003e. The new Claude Code session boots already wearing that agent\u0026rsquo;s persona. \u003cstrong\u003eDrag a skill\u003c/strong\u003e → spawns \u003ccode\u003eclaude\u003c/code\u003e with the skill\u0026rsquo;s instructions appended to the system prompt, wrapped in a \u003ccode\u003e\u0026#35; Applied skill \u0026middot; \u0026lt;name\u0026gt;\u003c/code\u003e header so Claude treats it as procedural addendum, not the primary persona.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every card also has a \u003cstrong\u003eSpawn\u003c/strong\u003e click button — same payload, same outcome, but works without drag (trackpad-friendly). Reuses the \u003ccode\u003eapplication/x-stackon-spawn\u003c/code\u003e mime + \u003ccode\u003espawn-bus\u003c/code\u003e CustomEvent pipeline from Phase 7D — Terminal pane routes mission cards, agent cards, and skill cards identically.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Same \u003ccode\u003eclaude\u003c/code\u003e prerequisite as 7D: install Claude Code CLI on your PATH (\u003ccode\u003enpm install -g @anthropic-ai/claude-code\u003c/code\u003e) or the spawned tab will say \u003ccode\u003ecommand not found\u003c/code\u003e. Phase 7E.1 polish: drop a skill onto an already-running terminal to inject it mid-session via PTY stdin instead of always spawning a fresh tab. Next: \u003cstrong\u003e7F — terminal session → Stackon trace bridge\u003c/strong\u003e (every \u003ccode\u003eclaude\u003c/code\u003e session in Space optionally becomes a replayable trace).\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"7e:[\"$\",\"li\",\"2026-05-23-Phase 7D — Tasks pane wired to live Missions API + drag-to-terminal\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.18s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.48.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 7D — Tasks pane wired to live Missions API + drag-to-terminal\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space\u0026rsquo;s Tasks pane is no longer a stub. It now pulls your team\u0026rsquo;s missions from the live Stackon backend (same Supabase project as the web), with the list on the left + the selected mission\u0026rsquo;s transcript on the right. Click any mission card to see its full thread (user prompts + agent messages + system errors, exactly as the web mission page renders them). Read-only for v1 — composer + new-mission creation are Phase 7D.1.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The differentiator: \u003cstrong\u003edrag a mission card onto the Terminal pane\u0026rsquo;s tab strip\u003c/strong\u003e and a new tab opens running \u003ccode\u003eclaude\u003c/code\u003e with the mission\u0026rsquo;s title + description as the initial user prompt. The agent picks up the task as if you\u0026rsquo;d typed it. Same effect via the \u0026quot;Spawn in Terminal\u0026quot; button on the mission detail header. The tab strip flashes emerald on drag-over so you know the drop target is hot.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mechanism: new \u003ccode\u003edesktop/src/lib/missions.ts\u003c/code\u003e reuses the authenticated Supabase client from Phase 7A.1 — RLS scopes everything server-side to your \u003ccode\u003eteam_members\u003c/code\u003e rows, no extra filtering on the desktop side. New \u003ccode\u003edesktop/src/lib/spawn-bus.ts\u003c/code\u003e is a window-level CustomEvent helper for cross-pane spawn requests (avoids prop-drilling between sibling panes that don\u0026rsquo;t share state). The Terminal pane subscribes on mount; both drag-and-drop AND the \u0026quot;Spawn in Terminal\u0026quot; button feed it identically.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Prerequisite for the spawn to actually do anything useful: Claude Code CLI installed and on your PATH. If it\u0026rsquo;s not, the spawned tab shows \u003ccode\u003eclaude: command not found\u003c/code\u003e — install via \u003ccode\u003enpm install -g @anthropic-ai/claude-code\u003c/code\u003e. Stackon Space doesn\u0026rsquo;t bundle Claude Code; you own that install (lets you stay on your preferred Claude Code version, get its own updates, etc).\"}}]]}],\"$Lca\"]}]]}]\n"])</script><script>self.__next_f.push([1,"7f:[\"$\",\"li\",\"2026-05-23-Phase 7B.1 + 7C — terminal tabs + Monaco editor pane\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.24s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.47.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 7B.1 + 7C — terminal tabs + Monaco editor pane\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eTerminal tabs (7B.1).\u003c/strong\u003e Stackon Space\u0026rsquo;s Terminal pane is now multi-tab. Click \u003ccode\u003e+ New\u003c/code\u003e to spawn another shell. Each tab keeps its own PTY alive when you switch away (display:none, not unmount, so xterm state survives). Hover a tab for the close (×) which kills that tab\u0026rsquo;s PTY. ResizeObserver in the cell naturally refits when a tab becomes visible again.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eEditor pane (7C).\u003c/strong\u003e Real Monaco editor — same engine VS Code uses — wired to \u003ccode\u003etauri-plugin-fs\u003c/code\u003e for read/write/list. Click \u003cstrong\u003eOpen folder…\u003c/strong\u003e → native folder picker via \u003ccode\u003etauri-plugin-dialog\u003c/code\u003e → file tree on the left, Monaco on the right. Click a file to open it; \u003cstrong\u003eCtrl/Cmd+S\u003c/strong\u003e writes the buffer back via \u003ccode\u003ewriteTextFile\u003c/code\u003e. Language detection covers TS/JS/MD/CSS/HTML/Rust/Python/Go/YAML/TOML/shell/SQL/XML; falls back to \u003ccode\u003eplaintext\u003c/code\u003e for the rest. The workspace folder path persists across launches via \u003ccode\u003etauri-plugin-store\u003c/code\u003e so reopening Stackon Space restores your last project.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eFS scoping.\u003c/strong\u003e The \u003ccode\u003efs:scope\u003c/code\u003e capability locks reads + writes to \u003ccode\u003e$HOME / $DOCUMENT / $DESKTOP / $DOWNLOAD\u003c/code\u003e subtrees. Anything outside the allowlist is rejected at the plugin layer — agents can\u0026rsquo;t touch \u003ccode\u003eC:\\\\Windows\u003c/code\u003e or \u003ccode\u003e/etc\u003c/code\u003e from the workspace. Per-workspace scoping is a future polish.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Monaco theme matches the Stackon palette (charcoal canvas, emerald cursor). One open file at a time for v1 — tabs come in 7C.1. Bundle: 771 KB JS / 25 KB CSS (gzip 212 + 6); Monaco itself loads dynamically from CDN on first use to keep the desktop binary small.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"80:[\"$\",\"li\",\"2026-05-23-Phase 7B — real PTYs in the Terminal pane\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.3s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.46.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 7B — real PTYs in the Terminal pane\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space\u0026rsquo;s Terminal pane is no longer a stub. It hosts a live \u003ccode\u003exterm.js\u003c/code\u003e terminal wired to a Rust-side PTY running your platform shell (PowerShell 7+ if installed, else Windows PowerShell 5.1 on Windows; \u003ccode\u003e$SHELL\u003c/code\u003e → zsh on macOS; \u003ccode\u003e$SHELL\u003c/code\u003e → bash on Linux). Type, see output, resize the pane and the PTY resizes too. \u003cstrong\u003eRestart\u003c/strong\u003e button kills the child and spawns a fresh one.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mechanism: new \u003ccode\u003esrc-tauri/src/pty.rs\u003c/code\u003e wraps the \u003ccode\u003eportable-pty\u003c/code\u003e Rust crate. Four Tauri commands — \u003ccode\u003epty_spawn\u003c/code\u003e / \u003ccode\u003epty_write\u003c/code\u003e / \u003ccode\u003epty_resize\u003c/code\u003e / \u003ccode\u003epty_kill\u003c/code\u003e — each operate against a \u003ccode\u003eHashMap\u0026lt;String, PtyHandle\u0026gt;\u003c/code\u003e behind a \u003ccode\u003eMutex\u003c/code\u003e. On spawn, a dedicated reader thread pumps PTY output (8 KB chunks) to the renderer via Tauri events on \u003ccode\u003epty:\u0026lt;id\u0026gt;:output\u003c/code\u003e; on child exit the thread emits \u003ccode\u003epty:\u0026lt;id\u0026gt;:exit\u003c/code\u003e and removes the handle from state.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Renderer: new \u003ccode\u003eTerminalCell\u003c/code\u003e component constructs an \u003ccode\u003exterm.js\u003c/code\u003e instance with the Stackon palette (charcoal canvas, emerald cursor, branded ANSI colors), loads \u003ccode\u003eFitAddon\u003c/code\u003e, calls \u003ccode\u003espawnPty\u003c/code\u003e, wires output → \u003ccode\u003eterm.write\u003c/code\u003e and \u003ccode\u003eterm.onData\u003c/code\u003e → \u003ccode\u003ewritePty\u003c/code\u003e, and a \u003ccode\u003eResizeObserver\u003c/code\u003e drives \u003ccode\u003efit.fit() + resizePty\u003c/code\u003e. Unmount kills the PTY + disposes the terminal. Status chip in the cell header reflects booting / running / exited / error.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7B.1 will add a tab UI (multiple terminals per pane) + an N-cell grid layout matching the screenshot the user shared. Phase 7D drags missions onto terminals to spawn \u003ccode\u003eclaude\u003c/code\u003e with the mission user_task; Phase 7E lets you drag skills to inject system prompts. Phase 7F captures terminal sessions into the existing trace/span tables.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"81:[\"$\",\"li\",\"2026-05-23-Phase 7A.1 — Stackon Space OAuth deep-link sign-in\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.359999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.45.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-rose-400/40 bg-rose-400/10 text-rose-300\",\"children\":\"Preview\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 7A.1 — Stackon Space OAuth deep-link sign-in\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stackon Space\u0026rsquo;s splash now has a real \u003cstrong\u003eSign in with Stackon\u003c/strong\u003e button. Click it → your default browser opens to \u003ccode\u003estackon.ai/sign-in?next=stackon://auth/callback\u003c/code\u003e → you sign in (magic link or GitHub) → the web redirects to the custom \u003ccode\u003estackon://\u003c/code\u003e scheme with the session tokens in the URL fragment → the OS routes the URL back to the running Stackon Space window → the splash dismisses and your workspace mounts. Persisted to disk via \u003ccode\u003etauri-plugin-store\u003c/code\u003e; subsequent launches restore the session automatically.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Web side: \u003ccode\u003e/auth/confirm\u003c/code\u003e learns a \u003ccode\u003eTRUSTED_SCHEMES\u003c/code\u003e whitelist (currently just \u003ccode\u003estackon://\u003c/code\u003e). When \u003ccode\u003enext\u003c/code\u003e is in the whitelist, the route\u0026rsquo;s post-\u003ccode\u003everifyOtp\u003c/code\u003e redirect target gets the session encoded into the URL fragment (\u003ccode\u003e#access_token=...\u0026refresh_token=...\u0026expires_in=...\u003c/code\u003e) — tokens in the fragment so they stay out of server access logs + referrer headers. The web \u003ccode\u003efinalUrl\u003c/code\u003e helper also passes \u003ccode\u003estackon://\u003c/code\u003e through unchanged so the magic-link email\u0026rsquo;s \u003ccode\u003eemailRedirectTo\u003c/code\u003e points at the custom scheme.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Tauri side: three new plugins — \u003ccode\u003etauri-plugin-deep-link\u003c/code\u003e (custom URL scheme registration via the \u003ccode\u003eplugins.deep-link.desktop.schemes\u003c/code\u003e bundle config), \u003ccode\u003etauri-plugin-shell\u003c/code\u003e (renderer can open the external browser), \u003ccode\u003etauri-plugin-store\u003c/code\u003e (persisted session file). Plus \u003ccode\u003etauri-plugin-single-instance\u003c/code\u003e with the \u003ccode\u003edeep-link\u003c/code\u003e feature so the second \u003ccode\u003estackon://\u003c/code\u003e launch (during a sign-in handshake) wakes the existing window instead of spawning a second process. Capabilities updated.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[\"$Lcb\",\"$Lcc\"]}],\"$Lcd\"]}]]}]\n"])</script><script>self.__next_f.push([1,"82:[\"$\",\"li\",\"2026-05-23-Phase 7A — Stackon Space scaffolded (native desktop agent workspace)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.42s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.44.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-rose-400/40 bg-rose-400/10 text-rose-300\",\"children\":\"Preview\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 7A — Stackon Space scaffolded (native desktop agent workspace)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\u003cstrong\u003eStackon Space\u003c/strong\u003e — the native desktop incarnation of Stackon — gets a real shell. The Tauri window no longer redirects to the web dashboard; it hosts a Vite-built React app implementing a four-pane workspace: \u003cstrong\u003eTerminal · Editor · Tasks · Agents\u003c/strong\u003e. Splitters between panes, a workspace rail on the left, a pipeline strip on the bottom — the same kind of multi-pane layout you\u0026rsquo;d expect from a native IDE, but every pane is a future home for live Stackon primitives.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"What the desktop app IS today (Phase 7A): a real frontend pipeline (Vite + React 19 + Tailwind v4 inside \u003ccode\u003edesktop/\u003c/code\u003e), the four-pane resizable shell, brand-token-matched chrome, a splash with a \u0026quot;Continue to workspace\u0026quot; CTA. What it\u0026rsquo;s NOT yet: real PTYs (Phase 7B — \u003ccode\u003eportable-pty\u003c/code\u003e + xterm.js), Monaco editor (7C), Mission API integration (7D), Skill drag-injection (7E), terminal-to-trace bridging (7F), OAuth deep-link sign-in (7A.1). Each pane shows a labeled stub describing what fills it.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Strategic framing: Stackon Space is the same product as web Stackon — same backend, same auth, same Postgres, same brand. The desktop binary is the workspace surface; the cloud is the brain. Web Stackon stays for missions/agents/canvas/traces. Stackon Space adds the things web can\u0026rsquo;t do — local file system, native PTYs, multi-pane simultaneous runs.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Build outputs: \u003ccode\u003edesktop/dist/\u003c/code\u003e bundle (237 KB JS, 20 KB CSS gzipped to 74 + 5). \u003ccode\u003etauri.conf.json\u003c/code\u003e now invokes \u003ccode\u003enpm run dev:vite\u003c/code\u003e / \u003ccode\u003enpm run build:vite\u003c/code\u003e via \u003ccode\u003ebefore*Command\u003c/code\u003e; dev URL flipped from \u003ccode\u003elocalhost:3000\u003c/code\u003e (web app) to \u003ccode\u003elocalhost:1420\u003c/code\u003e (Vite). Tauri shell version bumped to \u003ccode\u003ev0.44.0\u003c/code\u003e.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"83:[\"$\",\"li\",\"2026-05-23-Phase 6D — @-mention dispatch, swarm mode, multi-turn conversation context\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.4799999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.43.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 6D — @-mention dispatch, swarm mode, multi-turn conversation context\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The mission composer is now a real terminal interface. Type plain text and the bound canvas runs sequentially (existing behavior). Start with \u003ccode\u003e@all\u003c/code\u003e and every roster agent runs in parallel against the same prompt — outputs interleave into the transcript as they stream in. Start with \u003ccode\u003e@\u0026lt;agent-name\u0026gt;\u003c/code\u003e matching a roster agent in the bound canvas and just that agent runs, skipping the pipeline. The token matcher is forgiving (case-insensitive, ignores dashes/underscores/spaces), so \u003ccode\u003e@Coder-Bob\u003c/code\u003e matches an agent named \\\"Coder Bob\\\" and vice versa.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every run also now sees the prior mission turns as conversation context. \u003ccode\u003erunCanvas\u003c/code\u003e + new \u003ccode\u003erunAgentById\u003c/code\u003e load the last 30 user/agent messages for the mission (when a missionId is threaded in) and inline them into each node's system prompt as a `# Prior conversation in this mission` block. Closes the stateless-run gap from Phase 6C — the agent that wrote the diff knows what the user asked for two turns ago.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New \u003ccode\u003erunAgentById(agentId, userTask, opts)\u003c/code\u003e mirrors runCanvas's lifecycle for a single roster agent: trace shell + root span + broadcaster (uses the mission's bound canvas channel so the LiveRunPanel transparently subscribes), one synthetic LLM span, one mission_message. \u003ccode\u003erunCanvas\u003c/code\u003e grows a \u003ccode\u003eswarm: boolean\u003c/code\u003e option — sequential for-loop vs. \u003ccode\u003ePromise.all\u003c/code\u003e; the per-node atom was extracted into an \u003ccode\u003eexecuteNodeStep\u003c/code\u003e closure so both modes share it.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 6 is complete. The Missions / Agents / Canvas / Approvals tabs now feel like a Claude-Code-style multi-agent terminal: add agents to your roster, drop them into a canvas, attach the canvas to a mission, then converse with the team — swarm them, task them individually, or run the full pipeline. Every token streams live; every turn persists.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"84:[\"$\",\"li\",\"2026-05-23-Mission becomes a chat thread — roster, transcript, composer, live stream\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.54s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.42.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Mission becomes a chat thread — roster, transcript, composer, live stream\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mission detail page is no longer a form — it's a thread. Top: title + status + roster of agents (pulled from the bound canvas's nodes, named via the team_agents roster when available). Middle: scrollable transcript of every user prompt + every agent message, oldest first, with cost / tokens / trace link per agent message. Bottom: composer — type what the team should work on and hit Send. The existing edit / approve / archive / delete forms moved into a collapsed \\\"Mission settings\\\" disclosure so they're still reachable but no longer dominate the page.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `mission_messages` table (RLS scoped to `team_members`, append-only by design: insert + select only from user clients; admin client retains update/delete for future scrub flows). One `role='user'` row per composer submit; one `role='agent'` row per `node.completed`; `role='system'` for run failures. Each agent row links back to its `trace_id`, `span_id`, `canvas_node_id`, and `agent_id` (when bound to a roster agent) so the transcript carries all the cross-links needed for replay + drill-in.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The composer reuses Phase 6B's broadcast pipeline: pregenerates a `traceId`, schedules `runCanvas` via Next 16 `after()` with `{ precreatedTraceId, missionId }`, redirects with `?live=\u003ctraceId\u003e`. The LiveRunPanel mounts above the transcript and streams tokens as the run executes; once each node completes, a persisted mission_message arrives and the live block becomes static. Approval-gated submits still queue a pending row (`requestMissionRun`), but the user message persists immediately so the thread shows the intent before the approver acts. Approval-driven runs now also write agent messages because `approveMissionRun` threads the `missionId` into `runCanvas`.\"}}]]}],\"$Lce\"]}]]}]\n"])</script><script>self.__next_f.push([1,"85:[\"$\",\"li\",\"2026-05-23-Canvas runs stream live — tokens land in the page as they're generated\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.6s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.41.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Canvas runs stream live — tokens land in the page as they're generated\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Hitting Run on a canvas no longer makes you wait for the whole pipeline to finish before you see anything. The page now renders a live transcript: each agent shows its output character-by-character as it streams from Claude. Active node has an emerald-pulsed border; completed nodes show cost + token counts; final state links to the persisted trace.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mechanism: `runCanvas` extends to broadcast `run.started` / `node.started` / `node.token` / `node.completed` / `run.completed` / `run.failed` on the existing `canvas:\u003cid\u003e` private Realtime channel (same substrate as multiplayer cursors + comments). Token deltas are batched at 100 ms or 400 chars to stay under Supabase's per-channel msg/sec budget. Emission uses the service-role admin client so it bypasses the `realtime.messages` RLS policy without needing a user JWT.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Dispatch model flipped from \\\"server action blocks until done\\\" to \\\"server action schedules + redirects with ?live=\u0026lt;traceId\u0026gt;\\\" via Next 16 `after()`. The trace id is pregenerated client-side (crypto.randomUUID) and passed into `runCanvas` so the redirect target is known before the LLM work begins. The persisted trace remains the source of truth — broadcasts are best-effort, additive, and dropped if delivery fails (the live UI just misses a chunk; the trace catches up on completion).\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Foundation for Phase 6C (mission-as-thread) + 6D (swarm + interjection). Canvas approvals + eval-gate runner + HTTP API runner stay synchronous for now — they don't need a live UI.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"86:[\"$\",\"li\",\"2026-05-23-Agents become first-class — team roster you can drop into any canvas\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.66s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 23, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.40.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Agents become first-class — team roster you can drop into any canvas\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Agents tab is no longer a one-shot prompt form. It's now a roster: name, role, model, and system prompt saved per team. Click into any agent to edit; archive when you're done with it. The legacy one-off runner moves to `/dashboard/agents/quick` so you can still fire a quick test without committing to a saved agent.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `team_agents` table (RLS scoped to `team_members`, soft-deletes via `archived_at`, one active agent per (team, name)). `canvas_nodes` gains a nullable `agent_id` reference — nodes linked to a roster agent show a green `From roster` chip and resolve the agent's current role / model / system prompt at run time. Edit Coder Bob's system prompt and every canvas that uses him picks up the change on the next run.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Canvas add-node form now leads with a `From roster` picker (when you have saved agents) above the existing inline form. Both work — pick from the roster to track an agent live, or define inline for a one-off node. Existing canvas nodes are untouched (agent_id is nullable; their inline columns keep working).\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Foundation for Phase B (live streaming inside the canvas) and Phase C (mission-as-thread with @-mention dispatch to specific agents). Agents need stable identity before either lands, which is what this ships.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"87:[\"$\",\"li\",\"2026-05-22-Press-kit full lockup — mark + wordmark on one canvas\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.72s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 22, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.39.4\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Press-kit full lockup — mark + wordmark on one canvas\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Added a horizontal lockup to the press kit — mark on the left, wordmark on the right, both centered on the same 1536×1024 canvas. Ships in both dark (`#0A0A0A`) and light (`#FAFAF8`) variants. Useful for footers, slide decks, and any context where a journalist or partner wants both identity pieces composed as a single asset rather than reassembling the mark and wordmark by hand.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"`scripts/crop-stackon-logo.mjs` gains a lockup pass that reuses the existing `markBuffer` and the vector wordmark SVG (480×480 mark, 64 px gap, 760 px wordmark, group centered on the canvas). Same `npm run gen:brand` regenerates everything; no new dependencies.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"`/media` now lists the two lockup tiles at the top of the asset grid, ahead of the mark-only and wordmark-only slots — the typical first thing a press contact reaches for.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"88:[\"$\",\"li\",\"2026-05-20-Press-kit wordmark — designed SVG replaces gpt-image-1 raster\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.779999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 20, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.39.3\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Press-kit wordmark — designed SVG replaces gpt-image-1 raster\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The `/media` wordmark slots (`Wordmark · dark` and `Wordmark · light`) were generated by gpt-image-1, which mangles text — the rendered `STACKON` letterforms had subtle distortion and paper-grain artifacts that didn't read at press scale. Replaced with a hand-wired vector wordmark built from Geist Regular glyph paths.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `scripts/build-wordmark.mjs` reads the Geist-Regular.ttf already bundled with `@vercel/og` (a transitive Next.js dependency), uses `opentype.js` to convert the text \\\"Stackon\\\" to SVG glyph paths, and writes `public/stackon-wordmark-{dark,light}.svg`. Path-only — no font dependency at render time, no rasterization, no AI distortion. Single color per variant (white #FAFAFA on dark, charcoal #0A0A0A on light); drops the legacy coral 'on' two-tone from the v0.34 bitmap source, aligned to v0.36 monochrome.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"`scripts/crop-stackon-logo.mjs` now invokes the wordmark builder up-front, then rasterizes the SVG onto a 1536×1024 canvas at 1100 px target width for the press-kit PNGs. `npm run gen:brand` remains the single command to refresh all brand assets. PNG file size dropped from ~640 KB (raster) to ~59 KB (clean vector composite).\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Removed the `media-logo-dark` / `media-logo-light` entries from `scripts/placeholder-prompts.mjs` so a future `npm run gen:placeholders --force` can't silently overwrite the vector wordmark with a gpt-image-1 raster. Gotcha #60 (wordmark distortion caveat in press kit) closes.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"89:[\"$\",\"li\",\"2026-05-20-Stackon for Windows — Tauri shell scaffolded (NSIS + MSI)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.84s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 20, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.39.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-rose-400/40 bg-rose-400/10 text-rose-300\",\"children\":\"Preview\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon for Windows — Tauri shell scaffolded (NSIS + MSI)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Tauri shell now targets Windows alongside macOS. `tauri.conf.json:bundle.targets` extends to `[\\\"dmg\\\", \\\"app\\\", \\\"nsis\\\", \\\"msi\\\"]` — Tauri silently skips the platform-foreign targets at build time, so the same `npm run desktop:build` invocation produces a DMG on macOS and an NSIS .exe + MSI on Windows. No code changes in `main.rs`; the Rust shell is platform-agnostic by design.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Added a Windows `bundle.windows` config block: `webviewInstallMode: downloadBootstrapper` (so older Windows 10 boxes get WebView2 fetched at install time), NSIS `installMode: perMachine` with the new `icon.ico` as the installer icon, WiX defaults set to `en-US`. The capability surface is unchanged from the macOS shell — same minimal `core:window:*` permissions.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Asset pipeline extended: `scripts/crop-stackon-logo.mjs` now also emits `desktop/src-tauri/icons/icon.ico`, a multi-resolution ICO covering 16/24/32/48/64/128/256 px. Built from the same RGBA mark via the `to-ico` npm package — no external tooling, runs on every `npm run gen:brand`.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"**You cannot build a Windows installer from macOS.** Tauri's Windows bundler relies on Windows-only tooling (NSIS, WiX, SignTool). Production builds happen either on a Windows machine or — recommended — a `windows-latest` GitHub Actions runner. `desktop/DEPLOY.md` gains a section 8 covering Windows prerequisites (MSVC C++ Build Tools, rustup), build commands, code signing (OV vs. EV certs), and the GH Actions workflow stub. The `desktopWindows` feature flag stays `enabled: false` until a signed `.exe` + `.msi` is hosted.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"8a:[\"$\",\"li\",\"2026-05-20-Stackon for Mac — first compiling build (scaffold fixes)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.8999999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 20, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.38.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon for Mac — first compiling build (scaffold fixes)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"v0.38.0 scaffolded the Tauri shell but never compiled locally — the dev box was missing Command Line Tools + Rust. After installing both (xcode-select --install, rustup default stable), the first `npx tauri build` surfaced two real bugs in the scaffold: a capability that doesn\u0026rsquo;t exist in Tauri v2.11, and icon PNGs in the wrong color space.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Capability fix: `core:webview:allow-reload` was requested in `capabilities/default.json`, but Tauri 2.11 removed it — reload now lives on the OS menu (⌘R). Dropped it; nothing was using it anyway.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Icon fix: `scripts/crop-stackon-logo.mjs` was emitting RGB PNGs for the desktop icon matrix (32×32, 128×128, 128×128@2x, 512×512). Tauri\u0026rsquo;s `generate_context!` proc-macro requires RGBA. Added `.ensureAlpha()` to the desktop icon loop. All four PNGs now write as 8-bit RGBA; `iconutil` still assembles `icon.icns` from the RGB sources cleanly.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"After fixes, the first end-to-end build produces `Stackon.app` + `Stackon_0.38.1_x64.dmg` in ~1m 23s (~4.2 MB DMG, unsigned x86_64). Signing + notarization still gated on Apple Developer Program enrollment. Bumped `desktop/{Cargo.toml,package.json,tauri.conf.json}` from the inherited 0.37.1 to 0.38.1 so the DMG filename + version sync to the repo cadence going forward.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"8b:[\"$\",\"li\",\"2026-05-13-Stackon for Mac — Tauri v2 desktop shell (scaffolded)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"6.96s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 13, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.38.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-rose-400/40 bg-rose-400/10 text-rose-300\",\"children\":\"Preview\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Stackon for Mac — Tauri v2 desktop shell (scaffolded)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `desktop/` package: a Tauri v2 Rust shell that wraps the Stackon web ADE in a native macOS window. Dev mode points at `http://localhost:3000` and hot-reloads alongside `npm run dev`; production build redirects to `https://stackon.ai/dashboard` from a tiny `dist/index.html` splash. Window chrome is native (titlebar, dock icon, ⌘W/⌘Q), backed by WKWebView on macOS so memory + cold start are roughly half of what an Electron equivalent would be.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Bundle identifier `ai.stackon.desktop`. Icons regenerate from `stackon/stackon_logo.png` via the existing `npm run gen:brand` script — the matrix now includes 32×32/128×128/128×128@2x/icon.png PNGs plus an `icon.icns` assembled via macOS `iconutil`. The Rust code is intentionally tiny: a single `main.rs` that calls `tauri::Builder::default().run()`. We\u0026rsquo;ll add commands + plugins (system tray, global hotkey for voice push-to-talk, native notifications) as later iterations.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Distribution: direct download from `/download`, no App Store. The `desktopMac` feature flag stays `enabled: false` until the signed DMG is hosted — the page renders a 'Coming in Phase 4' violet pill in the meantime. Signing + notarization requires Apple Developer Program enrollment ($99/yr), which is the same gate as TestFlight (mobile/DEPLOY.md step 0.2). Doing both together is the natural sequence.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Windows build is a near-identical follow-up in a later session — same Tauri base, swap the bundle target from DMG to MSI. The `/download` page already has a Windows card showing 'Coming in Phase 4' so the placement is in place.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"8c:[\"$\",\"li\",\"2026-05-13-Voice v2 — true local Whisper (wasm) joins the capability chain\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.02s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 13, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.37.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Voice v2 — true local Whisper (wasm) joins the capability chain\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Push-to-talk now has a third path: fully in-browser Whisper via `@huggingface/transformers` (ONNX wasm). Audio + inference both stay on the device — nothing leaves the browser. First use downloads ~145 MB of `onnx-community/whisper-tiny.en` at fp32 precision (cached in browser Cache Storage thereafter). Subsequent transcriptions reuse the loaded pipeline with no network round-trip. fp32 chosen over the smaller quantized variants because their per-tensor scale tensors are broken in the upstream exports — crashes session init via the new MatMulNBits kernel.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"User-selectable preference (auto / local / cloud) is persisted to localStorage and exposed as a one-click chip next to the mic button. `auto` resolves to webspeech → local → cloud (best UX everywhere). `local` is a privacy lock — it will never silently fall back to cloud. `cloud` keeps the existing Whisper-1 path for users who explicitly opt in.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Audit log records the same shape for all three modes (`bytes`, `mime`, `duration_ms`, `transcript_chars`, plus a new `mode` field). A new same-origin `POST /api/voice/audit` endpoint receives a JSON beacon from the browser when local-mode transcription finishes, so the compliance audit log shows the usage without the audio ever crossing the wire.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Component palette aligned to v0.36 — error states use rose instead of red. Build, lint, typecheck all clean.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"8d:[\"$\",\"li\",\"2026-05-12-Final amber sweep — every remaining marketing + auth + onboarding surface\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.08s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 12, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.36.3\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Final amber sweep — every remaining marketing + auth + onboarding surface\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Closes the v0.36 monochrome campaign. After this commit, `grep -rE 'amber|FBBF24|251,191,36' src/app src/components` returns empty across the entire repo. Home (v0.36), dashboard (v0.36.1), pricing (v0.36.2), and now everything else.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"16 files swept: About, Careers, Changelog, Community/Discord, Community/Events, Contact, Forge marketplace + listing detail, Invite landing, Media, Privacy, Terms, the auth layout + form, the onboarding layout + 3-step wizard. ~58 amber utilities + 5 amber-rgba hero backdrops retired.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Tone calls worth flagging: the changelog `preview` kind moved from amber to rose, filling the 4-tone categorical slot alongside shipped (emerald), fix (sky), infra (violet). The invite-landing `Pill` ('Team invite' / 'Email mismatch') moved to violet — categorical 'invitation' marker. The auth header's mini 'S' logo mark flipped to a white background. The onboarding wizard's 'checked' selection state, progress dots, and CTAs all moved to white (neutral primary) rather than picking a categorical color for what is fundamentally a selection-vs-unselected toggle.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every italic emphasis phrase ('one we'd trust with production', 'say hello first', 'where we build', 'on the calendar', 'the right answer', 'shipped', 'brand', 'policy', 'service') flipped from text-amber-300 to text-white. Emphasis without color, per v0.36 ethos. Every hero radial-gradient backdrop swapped from amber-rgba to a faint white glow. Every mailto link in /privacy and /terms moved from amber to text-zinc-100 with underline-offset.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[\"$Lcf\",\"$Ld0\"]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"8e:[\"$\",\"li\",\"2026-05-12-Pricing page — amber sweep to match v0.36 monochrome palette\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.14s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 12, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.36.2\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Pricing page — amber sweep to match v0.36 monochrome palette\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The last public marketing surface still running on the old amber-accented system. `/pricing` now follows the same recipe as the home (v0.36) and dashboard (v0.36.1): white-pill primary CTAs, neutral zinc eyebrows, monochrome chrome.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The featured Team plan card flipped from amber to violet — categorical 'premium tier' pop, matching the convention from v0.36.1 (Owner role badge, postmortem panel, modified-diff state). Border + gradient + ring + 'Most popular' badge text + the matrix column header all read violet now. The CTA inside the featured card is a white pill (same as every other primary action across the app).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Feature-list bullets uniform muted zinc across all plan cards. FAQ caret neutral. Italic accent phrases ('not seat-shaming.', 'Start free') keep the typography but drop the amber tint — emphasis without color, per v0.36 ethos. Hero radial-gradient backdrop swapped from amber-rgba to a faint white glow.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"12 amber utilities + 1 amber rgba retired in `src/app/pricing/page.tsx`. No behavior changes. Build, lint, typecheck clean. `/pricing` is now the third surface (after home + dashboard) running on the unified `--brand-*` palette.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"8f:[\"$\",\"li\",\"2026-05-12-Dashboard amber sweep — monochrome palette across the app shell\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.199999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 12, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.36.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Dashboard amber sweep — monochrome palette across the app shell\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"v0.36 retired amber on the marketing home and shared chrome. v0.36.1 finishes the job: every page under /dashboard (38 surfaces) plus five shared components (ComingSoon banner, trace/badges, voice-input, canvas-multiplayer, canvas-comments) now run on the same monochrome system. ~273 amber utilities replaced with `--brand-*`-aligned alternatives.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Primary CTAs flipped from amber pills to white pills (`bg-white text-zinc-950 hover:bg-zinc-200`), matching the home's primary action. Form focus rings dropped from amber to neutral white. Hover-link accents lost their amber tint.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Semantic emerald now appears only where v0.36's rule says it should: live status. Trace, Evals, and Approvals eyebrows are emerald (the live-measurement family). The Run-canvas and Run-mission action panels carry an emerald-tinted gradient. The cost breakdown bar reads as a live feed. Postmortem panels moved to violet (analytical / investigative, not a status). Diff-modified rows moved to violet (categorical, distinct from emerald-added and red-removed). 'Coming Soon' chips and the dashboard nav hover dropped to pure neutral. Warning banners (missing env vars, no canvas yet) moved to rose — pending/attention per the v0.36 semantic palette.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Trace span-kind badge for `agent` moved from amber to the paler categorical emerald (`emerald-300`) — distinct from the saturated emerald-400 used for OK/in-progress status. Build, lint, and typecheck all clean; no behavior changed.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"90:[\"$\",\"li\",\"2026-05-12-Marketing home rework — monochrome palette, editorial Trace pillar\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.26s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 12, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.36.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Marketing home rework — monochrome palette, editorial Trace pillar\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The home page and shared marketing chrome (header / nav / footer) traded amber for a monochrome white-on-near-black system. New brand tokens live in `globals.css` (`--brand-bg/surface/text/live/pending/tone-*`) as the single source of truth.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Muted emerald (#34D399) is the only chromatic accent and it's reserved for live/healthy status moments — pulsing dots, the eval-pass row, the '● Recently shipped' hero callout. Categorical product chips use a 4-tone set (sky for Canvas, violet for MCP, emerald for Trace, rose for Mobile).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Two new home sections: `\u003cProductQuad /\u003e` ('Four products. One workflow.') and `\u003cFromPromptToProduction /\u003e` (Describe / Orchestrate / Ship triptych). The Trace pillar was rebuilt as a single editorial spine — small chip, oversized two-line headline ('Every run / leaves a trace.'), `\u003cTraceSpecimen /\u003e` artifact with crop-mark corners, then a 3-up feature row.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"All `gpt-image-1` prompts rewritten end-to-end — HUNTERADE wordmark → STACKON, amber → emerald-only-where-functional, `ANTI_AI_TAIL` to reduce AI tell. 17 of 18 placeholders regenerated; the 18th (`home-fp2p-ship.png`) is blocked on raising the OpenAI billing limit and renders the dotted-grid fallback in the meantime.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"91:[\"$\",\"li\",\"2026-05-12-Renamed to Stackon\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.319999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 12, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.35.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Renamed to Stackon\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"HunterADE is now Stackon. The new brand mark — three stacked cards representing code, sparkle, and OpenAI's model — sits over the wordmark and reads as an editor environment built on top of the foundation models that actually do the work. The tagline followed: an Agentic Developmental Environment powered by Claude and Codex.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Sub-products dropped the Hunter prefix. HunterTrace is Trace, HunterCanvas is Canvas, HunterMobile is Mobile, HunterCost is Cost, and so on. Two exceptions where the bare noun was too generic: Stackon MCP and Stackon CLI.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"This release is the visible-surfaces flip: marketing pages, dashboard UI, mobile app icon + name + deep-link scheme, emails, OpenAPI docs, /privacy and /terms. Wire formats stayed put on purpose — `ht_` / `hbk_` / `htmi_` / `htmd_` token prefixes still work, the `X-HunterADE-Signature` webhook header is unchanged, and `HUNTERADE_*` env vars keep their names. Existing automation against the API does not break. A later cutover sprint will rotate those when there's a clean migration window.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"iOS bundle ID flipped to `com.stackon.mobile` — the one exception to the phased rule, because App Store records are permanent post-registration and the mobile build hadn't shipped to TestFlight yet. Free now, irreversible after.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"92:[\"$\",\"li\",\"2026-05-12-HunterMobile brand assets — icon, splash, adaptive, favicon\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.38s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 12, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.34.5\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-rose-400/40 bg-rose-400/10 text-rose-300\",\"children\":\"Preview\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMobile brand assets — icon, splash, adaptive, favicon\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"mobile/assets/ now ships with the four files EAS Build requires: icon.png (1024×1024 RGB), splash.png, adaptive-icon.png, and favicon.png. All derived from the existing HunterADE crosshair mark (public/placeholders/media-mark-dark.png) via macOS `sips` — center-cropped to 1024 square, no alpha channel (Apple rejects icons with transparency).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"mobile/app.json wires the new files through expo.icon, expo.splash (resizeMode contain, #0A0A0A background), expo.android.adaptiveIcon, and expo.web.favicon. Mobile bundle bumped to 0.34.5; DEPLOY.md step 1 now reads as ✅ shipped.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Closes the last codebase-side blocker before TestFlight submission. Remaining: deploy the backend at the apiBaseUrl, enroll Apple Developer, eas login, eas init, eas build + eas submit.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"93:[\"$\",\"li\",\"2026-05-11-TestFlight prep — privacy, terms, mobile deploy checklist\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.4399999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 11, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.34.4\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-rose-400/40 bg-rose-400/10 text-rose-300\",\"children\":\"Preview\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"TestFlight prep — privacy, terms, mobile deploy checklist\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New /privacy and /terms pages cover everything Apple needs to accept a TestFlight submission — what data the app collects, who we share it with (Supabase / Anthropic / OpenAI / Resend / Expo / Stripe), how to delete your data, and the standard alpha-stage warranty disclaimers. Footer links to both. Plain-English drafts written for honest disclosure, not legal cover — get them reviewed by counsel before public GA.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New mobile/DEPLOY.md walks the user through every step from Apple Developer enrollment to `eas submit --platform ios`. P0 flagged up top: the production build talks to hunterade.com, so the backend has to be deployed and reachable before TestFlight reviewers can pair.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Cleanup in mobile/: dropped the dangling googleServicesFile reference so a first `eas build --platform ios` succeeds without an Android Firebase project. Bumped mobile bundle + app.json to 0.34.0.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"94:[\"$\",\"li\",\"2026-05-11-Press kit — full-image view, click-to-open, download per asset\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.5s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 11, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.34.3\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Press kit — full-image view, click-to-open, download per asset\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The new /media tiles were being cropped: every press shot is wider than 16:9, and the old PlaceholderImage frame used object-cover, lopping content off both sides. Replaced the press-kit grid with a new MediaAsset component that renders each shot at its natural aspect (object-contain inside an aspect-ratio computed from the file).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Click any tile → opens the original file at full resolution in a new tab. Each tile now has a `↓ Download` link beneath it that saves the file directly. Captions are auto-built from the real PNG header — actual pixel dimensions + file size, so the page can't drift from what's in public/placeholders/.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"95:[\"$\",\"li\",\"2026-05-11-Press kit — real dashboard screenshots replace AI mockups\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.56s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 11, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.34.2\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Press kit — real dashboard screenshots replace AI mockups\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The three product shots on /media (HunterTrace, HunterCanvas, HunterMobile / Approvals) are now real screenshots of the running dashboard, not gpt-image-1 mockups. The AI versions were photoreal but leaked the prompt's example labels — \\\"span name\\\", \\\"PlanGPT\\\", \\\"Expense Report\\\" — into the UI; the new shots carry actual product copy.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New scripts/seed-demo-screenshots.mjs (`npm run seed:demo`) inserts a photogenic 16-span trace, a 3-node Planner→Coder→Reviewer canvas, and a pending approval — all tagged so re-runs (or `--clean`) replace prior demo rows without drift. Anyone refreshing the press kit can re-seed, screenshot, and commit in five minutes.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"96:[\"$\",\"li\",\"2026-05-14-Marketing site redesign — editorial nav + ecosystem index\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.62s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 14, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.34.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Marketing site redesign — editorial nav + ecosystem index\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Homepage and global nav rebuilt around an editorial column grid: monospaced eyebrows mark structural sections, Instrument Serif italic carries emphasis pulls, hairline amber rules act as scaffolding instead of decoration. The page reads like a print spread now — same proof artifacts, more breathing room.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New top nav: Logo · Pricing · Ecosystem (dropdown: Observability / Canvas \u0026 Missions / Apps \u0026 Surfaces — every enabled product from featureFlags.ts) · Community (Discord, Docs, Events, Blog) · Company (About, Changelog, Careers, Media, Contact). Hover-open + click-toggle + ESC + outside-click. Hand-rolled, no extra deps. Mobile hamburger opens a full-width sheet listing all three categories stacked.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Single source of truth at src/lib/marketing/ecosystem.ts — the nav dropdown, the new homepage Ecosystem section, and the footer columns all read the same data. Adding a product = one edit.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Six new stub pages so every nav link resolves: /about, /careers, /media, /contact, /community/discord, /community/events. Each is a real editorial page (not \u003cComingSoon /\u003e banners) with placeholder image slots tagged data-placeholder-slot=\\\"\u003cslug\u003e\\\" — grep that attribute to swap in OpenAI-generated assets once the API key lands.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Hero ops cluster recomposed as a \\\"specimen plate\\\" with bracket markers, t+ timer, and a span/eval/budget caption — reads as proof artifact rather than tech demo. The conic-gradient swirl is gone; one calm radial bloom + the existing dotted-grid texture handles atmosphere.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"97:[\"$\",\"li\",\"2026-05-14-pg_cron sweeper hardening\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.68s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 14, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.33.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"pg_cron sweeper hardening\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Both sweep_expired_canvas_pending_runs and sweep_expired_mission_pending_runs were tripping Supabase's function_search_path_mutable advisor: a function with no SET search_path leaves it role-mutable, so a malicious schema sitting earlier in resolution could shadow an unqualified table reference. Low risk in practice (pg_cron runs jobs as postgres; tables are owned by supabase_admin) but cleanest fix is to nail it down.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Migration recreates both functions with SET search_path = '' and fully-qualified public.\u003ctable\u003e references. CREATE OR REPLACE only — no schema or cron-schedule change. Both advisor warnings are gone; sweep_expired_*_pending_runs RPCs still callable and behaviorally identical (verified end-to-end in scripts/test-sweepers.mjs, 14 assertions).\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"98:[\"$\",\"li\",\"2026-05-13-HunterMobile — cost dashboard on your phone\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.739999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 13, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.33.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMobile — cost dashboard on your phone\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mobile gets `budget.breached` pushes (v0.28) but couldn't see the current state on the phone. v0.33 closes that loop. New Cost tab on HunterMobile mirrors the web HunterCost dashboard: current-month spend, vs. last month delta with percent change, hard / soft budget limits with usage bar, and a 7-day spend sparkline.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Server: new GET /api/v1/mobile/cost endpoint returns { current_spend_usd, last_month_spend_usd, budget, daily }. Reuses the same getMonthlySpend / getLastMonthSpend / getDailySpend / getBudget helpers the dashboard uses — refactored to thread an admin client so they work outside a session (mobile uses bearer tokens, no Supabase cookie).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"UI: pure-JSX sparkline (no chart library dep), color-coded budget bar (green under soft, amber over soft, red at hard), and a 'no limits set' empty state pointing to the web dashboard. Footnote spells out the spend formula so users can audit it.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mobile bundle bumped to 0.33.0.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"99:[\"$\",\"li\",\"2026-05-13-HunterMobile — mission approvals on your phone\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.8s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 13, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.32.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMobile — mission approvals on your phone\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The v0.31 server fan-out (mission.run.requested webhook + push) is now actionable from HunterMobile. New /(home)/approvals tab unifies canvas + mission pending runs in two grouped sections; each row deep-links to the right detail screen via expo-router.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New mobile/app/mission-approvals/[id].tsx screen mirrors the canvas detail layout — shows mission title, requester, bound canvas, user task, and the same Approve \u0026 run / Reject buttons. Approve redirects to the resulting trace (same admin-client identity override path the dashboard uses, so the trace is attributed to the original requester).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Three new bearer-token authed API routes: GET /api/v1/mobile/mission-approvals (list pending for team), GET /api/v1/mobile/mission-approvals/[id] (single), POST /api/v1/mobile/mission-approvals/[id] (action: approve | reject + optional reason). ApprovalError codes map cleanly: already_decided → 409 conflict, not_team_member → 403 forbidden.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Push notifications for mission.run.requested now deep-link properly — server pushes set data.kind = 'mission_approval', mobile's deepLinkForNotification routes to /mission-approvals/[id]. Tapping a notification opens the right screen on cold start + foreground.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mobile bundle bumped to 0.32.0. Tab labels stay 'Approvals' — the inside is what changed.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"9a:[\"$\",\"li\",\"2026-05-13-HunterMissions run approvals\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.859999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 13, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.31.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMissions run approvals\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Missions now opt into the same approval gate as canvases. Flip Require approval on a mission and Run mission queues a row in the new mission_pending_runs table instead of executing immediately. Any team member can approve or reject from /dashboard/approvals or the inline banner on the mission detail page.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mission-level approval supersedes canvas-level approval — signing off on a mission IS signing off on the run, so a canvas with its own requires_approval=true is NOT re-gated. The approveMissionRun helper calls runCanvas directly via the admin-client identity override, attributing the trace + cost to the original requester, not the approver. Same race-safe atomic claim pattern from canvas approvals (v0.29): UPDATE … WHERE status='pending' returns null on the second simultaneous approver, surfacing 'already_decided'.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New webhook event mission.run.requested fans to outgoing webhooks AND mobile push (sibling pattern from v0.28). Three new audit_action values: mission.run.requested / .approved / .rejected. The pending row snapshots canvas_id + user_task at request time so a teammate rebinding the mission to a different canvas — or editing its title — between request and approval doesn't change what the approver is signing off on.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/approvals is now a unified inbox: missions and canvases live in the same list, grouped by kind. The /dashboard/missions/[id] page shows an inline pending banner above the Run button so the requester sees their own queued run without leaving the mission.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"pg_cron job sweep-expired-mission-pending-runs runs every 5 minutes (mirrors the canvas sweeper from v0.30.1) and flips status pending → expired for any row past expires_at (24h default). security invoker, idempotent reschedule, no audit_action for the transition — the absence of an approve/reject IS the signal.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"9b:[\"$\",\"li\",\"2026-05-12-Approvals expiry sweeper\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.92s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 12, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.30.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Approvals expiry sweeper\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"canvas_pending_runs.expires_at defaults to now()+24h but nothing was marking expired rows — listings already filtered on status='pending' so they dropped out of view, but the audit trail showed a dangling 'pending' state forever. Closed.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New pg_cron job sweep-expired-canvas-pending-runs runs every 5 minutes (*/5 * * * *) and flips status pending → expired for any row past its deadline. The job calls public.sweep_expired_canvas_pending_runs() which is security invoker — pg_cron's runner role bypasses RLS so we don't need definer privileges.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"No new audit_action value: pg_cron is system maintenance, not a user action. The absence of an approve/reject decision before expires_at IS the entire signal.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"9c:[\"$\",\"li\",\"2026-05-11-HunterMobile diff viewer + EAS Build config\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"7.9799999999999995s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 11, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.30.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMobile diff viewer + EAS Build config\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"HunterMobile now has a canvas browser. New Canvases tab lists every canvas on your team with version count + 'requires approval' badge; tapping drills into the version history; tapping a version renders a side-by-side diff against the previous one (or against an arbitrary version via ?against=N).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The mobile diff reuses the server's existing diffSnapshots() engine — same algorithm that powers /dashboard/canvas/[id]/versions on the web. Per-node ADDED / MODIFIED / REMOVED / UNCHANGED blocks with per-field deltas (role / name / model / system_prompt). Metadata diffs (canvas name + description) surface separately. Summary pills at the top count each category.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Three new mobile API endpoints, all bearer-token (htmd_) authed, all team-scoped: GET /api/v1/mobile/canvases (list), GET /api/v1/mobile/canvases/[id]/versions (history), GET /api/v1/mobile/canvases/[id]/versions/[version]/diff (CanvasDiff between this version and previous, or `?against=` for an arbitrary base).\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mobile bundle bumped to 0.30.0. New eas.json with development / preview / production profiles is in place — running `eas build --profile preview` produces an internal-distribution build for both platforms; `eas submit --profile production` ships to TestFlight + Play internal track. First build needs `eas login` and the Apple Developer + Google Play Console records (those are out-of-band).\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"v0.30 closes the HunterMobile track for now — the app is feature-complete behind the mobile flag. Future work: actual store submissions, live multiplayer cursors mirrored to mobile, push-to-talk recording from the phone.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"9d:[\"$\",\"li\",\"2026-05-11-HunterMobile approve queued canvas runs\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.04s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 11, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.29.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMobile approve queued canvas runs\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Canvases can now opt in to an approval gate via a new requires_approval toggle on the canvas detail page. When on, every Run pipeline button queues a row in the new canvas_pending_runs table instead of executing immediately. Any team member can approve or reject from /dashboard/approvals or HunterMobile — approver != requester is allowed (the simplest rule that lets a phone-only co-pilot actually unblock a teammate).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New webhook event canvas.run.requested fans to outgoing webhooks AND mobile push (sibling pattern from v0.28). The push notification carries the canvas name, requester, and a truncated user_task; tapping deep-links straight to the mobile approval detail screen. Existing webhook subscribers don't see the new event unless they explicitly subscribe — backwards-compatible.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Server: new src/lib/canvas/approvals.ts wraps the lifecycle. requestCanvasRun inserts pending row + fires push/webhook. approveCanvasRun atomically claims the row (UPDATE … WHERE status='pending') so two simultaneous approvers can't double-run; then calls runCanvas via the admin-client identity override, attributing the trace to the original requester (not the approver). rejectCanvasRun mirrors the claim, with an optional reason stored in error_message.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Dashboard: /dashboard/approvals lists all pending requests across canvases; per-canvas pages also show their own pending list inline so the requester sees their own queued runs without leaving the canvas. Three new audit_action values: canvas.run.requested / canvas.run.approved / canvas.run.rejected.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],\"$Ld1\"]}],\"$Ld2\"]}]]}]\n"])</script><script>self.__next_f.push([1,"9e:[\"$\",\"li\",\"2026-05-11-HunterMobile push notifications — webhook events to your phone\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.1s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 11, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.28.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMobile push notifications — webhook events to your phone\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"HunterMobile flag flipped on. trace.failed / budget.breached / gate.failed / gate.passed now fan out to every paired device on the team alongside the existing outgoing webhook. Same fire-and-forget contract: fireMobilePush(teamId, event, payload) wraps the work in Next 16's after() so a slow Expo round-trip never adds latency to user-facing actions.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Server: new src/lib/mobile/push.ts hits exp.host/--/api/v2/push/send with all active push tokens for the team in a single request. Per-device receipts land in a new mobile_push_deliveries table (status / expo_ticket_id / error_code / error_message / timestamps), readable by team members. One audit event per fan-out (mobile.push.send) summarises delivered + failed counts.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Device life-cycle: when Expo returns DeviceNotRegistered or InvalidCredentials we set mobile_devices.expo_push_token_invalid_at and the device drops out of future fan-outs until the next heartbeat with a fresh token. The active-device index (mobile_devices_push_idx) is now scoped on (team_id) where token-present-and-not-invalid.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mobile: expo-notifications + expo-device added. New mobile/src/push.ts handles permission, projectId lookup, getExpoPushTokenAsync, and POSTs to /api/v1/mobile/heartbeat with push_token. RootLayout subscribes to addNotificationResponseReceivedListener — tapping a notification deep-links to /traces/\u003cid\u003e for trace + gate events, /(home) for budget. Settings tab shows ‘Push notifications: Enabled / Disabled’ and exposes a manual re-prompt button when the OS permission is off.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],\"$Ld3\"]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"9f:[\"$\",\"li\",\"2026-05-10-HunterMobile preview — pair-by-code + read-only viewer\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.16s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 10, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.27.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-rose-400/40 bg-rose-400/10 text-rose-300\",\"children\":\"Preview\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMobile preview — pair-by-code + read-only viewer\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 4's last surface starts shipping. New @hunterade/mobile package at mobile/ — Expo + Expo Router + TypeScript app with three screens (pair, traces list, trace detail) and a settings tab that shows device/team identity and signs out. Token lives in expo-secure-store (Keychain on iOS, Keystore on Android).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Pairing: /dashboard/settings/devices mints a 6-character code (15 min TTL) per user, the mobile app exchanges the code via /api/v1/mobile/exchange for a long-lived htmd_-prefixed device token. Each user only sees their own devices, even on shared teams.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"API surface: /api/v1/mobile/{exchange,heartbeat,me,traces,traces/[id]} — a separate authenticator from the scoped PAT one (mobile tokens are scope-less, mirrors HunterBridge's hbk_ pattern). Three new audit_action values: mobile.pair, mobile.revoke, mobile.heartbeat.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Scope deliberately small for v0.27 — read-only screens and pull-to-refresh. Push notifications via Expo Push API, approve/reject queued canvas runs, and a diff viewer all ship in v0.28+. The mobile feature flag stays off until that lands; the v0.27 preview is reachable directly from /dashboard/settings/devices.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a0:[\"$\",\"li\",\"2026-05-10-HunterVoice cloud-Whisper fallback (Firefox + everywhere else)\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.219999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 10, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.26.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterVoice cloud-Whisper fallback (Firefox + everywhere else)\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Closes gotcha #16 — the v1 push-to-talk button now works in browsers without the Web Speech API. The component picks its mode at mount: Web Speech where present (Chrome / Edge / Safari), or MediaRecorder + cloud Whisper where it isn't (Firefox, in-app webviews).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Cloud path: MediaRecorder captures audio with the best supported mime type (webm/opus → mp4 → ogg/opus → browser default), the blob is POSTed to a new same-origin /api/voice/transcribe route handler, the server calls OpenAI whisper-1 via raw fetch (no extra SDK — same pattern as HunterKnowledge embeddings), and the returned text is appended to the linked textarea using the existing appendForVoice helper. UX is byte-identical to the v1 path other than a small ‘cloud’ tag and a ‘Transcribing…’ status while the round-trip is in flight.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"OPENAI_API_KEY drives the fallback (already required for HunterKnowledge embeddings). Each callsite reads isWhisperConfigured() server-side and passes a cloudFallbackEnabled boolean to the client component, so the disabled-state copy can tell the user whether the limit is the browser or the server.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Audit-logged as voice.transcribe with bytes / mime / duration / transcript-char-count metadata only — we deliberately do not store the raw audio or the transcript itself. Compliance audit log already renders the new action label.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Auth: same-origin Supabase session cookie, same shape as server actions. 12 MB upload cap, normalized error envelope ({ error: { code, message } }), 503 when the key is missing, 502 on upstream failure.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a1:[\"$\",\"li\",\"2026-05-10-Webhooks: drop legacy plaintext secret column\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.28s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 10, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.25.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Webhooks: drop legacy plaintext secret column\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Follow-up to v0.24.1 — encrypt-at-rest is now the only path for webhook signing material. The plaintext webhooks.secret column is gone, the webhooks_secret_present_chk constraint is gone, and secret_encrypted / secret_iv / secret_auth_tag are NOT NULL.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"createWebhookAction now refuses to create a webhook unless HUNTERADE_BYOK_MASTER_KEY is set — no more silent plaintext fallback in dev. Local dev needs the master key configured to flag-flip webhooks.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"dispatch.ts is simpler: one decrypt path, no lazy migration, no fallback branch. Decrypt failures fail the delivery loudly with a hint that the master key probably rotated.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Closes gotcha #20 fully. The transition window is over.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a2:[\"$\",\"li\",\"2026-05-09-HunterMultiplayer v2: persisted comments + Realtime Authorization\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.34s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.25.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMultiplayer v2: persisted comments + Realtime Authorization\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Canvas comments are now a real persisted thread, not just live cursors. New canvas_comments table with author profiles, resolve/reopen, author-or-admin delete, full RLS scoped to team membership. The dashboard renders an SSR snapshot; new inserts stream in via Supabase postgres_changes — no refresh needed.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Closes gotcha #15 — the canvas:\u003cuuid\u003e cursor + presence channel is now private. Two new policies on realtime.messages enforce team membership before a client can subscribe or broadcast: split_part(realtime.topic(), ':', 2) gives the canvas id, then a join through canvases → team_members checks auth.uid(). Public-channel access by guessed UUIDs is no longer possible.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Browser client calls supabase.realtime.setAuth() with the active session JWT before subscribing, then opts in with config.private = true. The cursor / presence experience is byte-identical to v1 — just provably scoped.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Three new audit_action enum values — comment.create, comment.resolve, comment.delete — labeled on /dashboard/compliance. Author can edit their own comments; owners and admins can moderate any.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Comment writes go through server actions that look up canvas.team_id, populate the row, and invalidate the canvas page; the postgres_changes listener also re-fetches so two open tabs converge on the same state without thrashing.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a3:[\"$\",\"li\",\"2026-05-09-Webhook signing secrets encrypted at rest\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.4s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.24.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Webhook signing secrets encrypted at rest\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Closes the v2 hardening item (gotcha #20). Webhook secrets now live in three new bytea columns — secret_encrypted / secret_iv / secret_auth_tag — encrypted with AES-256-GCM keyed off HUNTERADE_BYOK_MASTER_KEY. Same scheme as BYOK API keys; rotating the master key invalidates both surfaces.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"AES-GCM helpers extracted from compliance/byok.ts to a shared src/lib/crypto/aes-gcm.ts (encryptSecret, decryptSecret, bytesFromBytea, bytesToBytea, masterKey, isMasterKeyConfigured). Rule of two — webhooks is the second consumer, so it earns the abstraction.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Transition: new webhooks insert encrypted-only with secret = NULL. Existing rows still have plaintext; dispatch.ts lazy-migrates on first read (decrypt → dispatch → write encrypted columns + null plaintext in the background). After every row has been hit, a follow-up commit will drop the plaintext column.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Defensive constraint: webhooks_secret_present_chk ensures every row has either plaintext OR all three encrypted columns. No row can lose its signing material via a partial write.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Behaviorally invisible to users — same /dashboard/settings/webhooks UI, same delivery log, same HMAC-SHA256 X-HunterADE-Signature on every request. Flag-flipped without a key in dev: createWebhookAction falls back to plaintext when isMasterKeyConfigured() is false.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a4:[\"$\",\"li\",\"2026-05-09-Public API: OpenAPI 3.1, scoped tokens, rate limits, request IDs\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.459999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.24.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Public API: OpenAPI 3.1, scoped tokens, rate limits, request IDs\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Hand-authored OpenAPI 3.1 spec at /openapi.yaml — every /api/v1 endpoint with request/response schemas, scope annotations, and error envelope. Rendered with Scalar at /docs (no npm dep, single CDN script).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Personal access tokens now hold scopes: traces:read (list/get traces + spans), traces:write (start traces, append spans, end, record_run), evals:run (trigger evals on a trace + run an eval gate). The token-create form at /dashboard/settings/tokens has a checkbox grid for picking a least-privilege subset; existing tokens were backfilled with the full scope set so no consumer broke.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Per-token sliding-window rate limit — 60 requests/minute default, settable via HUNTERADE_API_RPM. Counters live in api_rate_buckets via an atomic security-definer Postgres function. 429 responses carry Retry-After + X-RateLimit-{Limit,Remaining,Reset} headers. Fails open on infra blips so a transient DB error doesn't deny legitimate traffic.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Error envelope normalized across every /api/v1/* response: { error: { code, message, request_id } }. Every response (success + error) carries an X-Request-Id header — partners can pass one in to correlate their logs with ours, or read the one we mint. Hunter MCP client updated to read either the new or legacy shape, surfacing the request id when present.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Versioning policy committed in the spec's info.description: /api/v1 is stable; new optional fields and new endpoints land without a major bump; deprecations get a 90-day Deprecation header notice and a changelog entry; breaking changes ship under /api/v2 with parallel running.\"}}]]}],\"$Ld4\"]}]]}]\n"])</script><script>self.__next_f.push([1,"a5:[\"$\",\"li\",\"2026-05-09-Teams \u0026 invites — Phase 1 closer\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.52s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.23.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Teams \u0026 invites — Phase 1 closer\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `/dashboard/settings/team` surface. Owners and admins invite teammates by email + role, see pending invites with sent/expires timestamps, revoke any pending invite, promote/demote members, and remove members. The owner row is protected — never demotable or removable from this UI.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Each invite mints a single-use `htmi_`-prefixed token (sha256-hashed at rest, plaintext only sent in the email) with a 14-day expiry. The accept-invite landing at `/invite/[token]` handles every edge case explicitly: signed-out → sign-up/sign-in deeplink with the email pre-filled, signed-in but wrong email → sign-out CTA, expired/revoked/already-claimed → friendly explainer.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Resend delivery mirrors the waitlist pattern — gated on `resendIsConfigured()` so flag flips ship without a real key, dispatched via Next 16 `after()` so the user's redirect lands instantly. The `team_invites` row is the durable record; the email is delivery only.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Audit trail extended with three new actions — `member.invite.revoke`, `member.accept`, `member.role.update` — alongside the existing `member.invite` and `member.remove`. Every transition shows up on `/dashboard/compliance` with a recognizable label.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"RLS: members read their team's invites (so non-admins see who's been invited); owners and admins manage. Accept-invite redemption goes through the admin client because the redeemer isn't yet a team member when the row is being looked up by token_hash.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],\"$Ld5\"]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a6:[\"$\",\"li\",\"2026-05-09-Phase 1 cleanup: waitlist confirmation, onboarding wizard, ⌘K palette\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.58s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.22.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 1 cleanup: waitlist confirmation, onboarding wizard, ⌘K palette\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Waitlist now sends a Resend confirmation email after a fresh signup. Dispatch wraps Next 16's `after()` so the redirect lands instantly while the email send survives the serverless response. Already-on-the-list submissions skip the email and surface a friendly 'queued' toast on the home page; failures show a retry message instead of disappearing into the void.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Onboarding wizard at `/onboarding` — 3 steps (display name, role, primary use case) — runs after sign-up and before the first dashboard hit. Profile row gets `role`, `primary_use_case`, and `onboarded_at` columns; the dashboard layout detours fresh users until the wizard is complete. Skipped automatically for users who've already completed it (back-button safety).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Command palette (⌘K / Ctrl+K) mounts globally across `/dashboard/*`. Three groups: Navigate (every dashboard surface + settings), Create (new mission, canvas, eval, adversary sweep, scribe distillation, knowledge source), Settings \u0026 docs. Built on the shadcn `cmdk` primitive — fuzzy search, keyboard-only operation, no mouse required.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Marketing surface picks up post-submit feedback: `?status=joined|already|invalid|error` on the home renders a colored banner anchored to the waitlist section so users see exactly what happened with their submit.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Three Phase 1 flags flipped (`waitlist`, `onboarding`, `commandPalette`); Phase 1 is now substantively complete except for teams + invites.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a7:[\"$\",\"li\",\"2026-05-09-Webhooks: dispatch survives serverless response via Next 16 `after()`\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.64s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.21.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-sky-400/40 bg-sky-400/10 text-sky-300\",\"children\":\"Fix\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Webhooks: dispatch survives serverless response via Next 16 `after()`\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"fireWebhookEvent now wraps dispatch in `after()` from next/server. On Vercel a bare `void promise(...)` is dropped when the response returns; with after() the runtime keeps the function alive until dispatch finishes. Falls back to bare scheduling outside a request scope (tests / scripts) by catching the E468 'wrong context' throw.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"No behavior change in local dev — Node continues running async work either way. The change matters in production where serverless functions terminate the moment the response is sent.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a8:[\"$\",\"li\",\"2026-05-09-Outgoing webhooks: ping Slack / Discord / PagerDuty when things matter\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.7s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.21.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Outgoing webhooks: ping Slack / Discord / PagerDuty when things matter\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Subscribe a URL to events HunterADE already cares about: gate.passed, gate.failed, budget.breached, trace.failed. Slack / Discord / PagerDuty / your own infra now composes with the dashboard so an eval regression or a budget breach pages someone instead of sitting in a tab.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Each delivery is signed HMAC-SHA256 in the X-HunterADE-Signature header (sha256=hex(hmac(secret, body))) — same scheme as GitHub / Stripe / Linear. Receivers verify by re-signing the raw body and constant-time-comparing. The signing secret is shown once at create; lose it and you delete + recreate.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"X-HunterADE-Delivery carries a stable UUID so receivers can dedupe replays. Manual retry from the dashboard re-fires with the same delivery_uuid so the receiver's idempotency check still works.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Single-attempt inline + manual retry from the UI in v1; cron-driven exponential backoff is a deliberate v2 once we have a worker queue. 8s timeout per attempt so a slow receiver can't hang a gate run.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Dispatch is fire-and-forget at every call site (fireWebhookEvent, no await) so a wedged receiver never adds seconds to a user-facing response. Failures land in the delivery log with HTTP status, response body (truncated to 2KB), and error message.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/settings/webhooks: list + create (URL + event multi-select + auto-mint secret shown once) + per-webhook detail page with delivery log, manual retry, send-test-event button, enable/disable toggle. Three new audit_action values (webhook.create / update / delete) plus webhook.test for the synthetic-event path.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"a9:[\"$\",\"li\",\"2026-05-09-HunterEvals PR gates: block PRs from CI when an agent regresses\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.76s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.20.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterEvals PR gates: block PRs from CI when an agent regresses\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"The Phase-2.5 promise the README has been making for months. A 'gate' bundles a canvas + a fixed test input + the evals that must pass, identified by a stable slug. Trigger it from a GitHub Action and you get a synchronous pass/fail you can wire into branch protection — a regression to the canvas's prompt blocks merge.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New schema: eval_gates (slug-unique-per-team, eval_ids[], canvas + test_input) and eval_gate_runs (status, trace_id, pass/fail counts, optional commit_sha + pr_url for CI deep-links). Three new audit_action values (eval_gate.create / delete / run).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"POST /api/v1/eval-gates/[slug]/run is bearer-token authed, runs the canvas with the gate's test input via an admin-client identity override on runCanvas, then grades the gate's evals against the resulting trace and returns {status, passed_count, failed_count, trace_id, dashboard_url} in one synchronous call.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/evals/gates lets you create gates (canvas dropdown + test input + multi-select evals + auto-derived slug) and each gate page shows recent runs (manual + CI), a copyable workflow YAML pre-filled with the slug, and a 'Run gate now' button for smoke testing.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\".github/workflows/example-eval-gate.yml.template ships in the repo as a reference workflow — drop into your own repo, set HUNTERADE_API_TOKEN secret, add to branch protection, done.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"runCanvas now accepts an optional identity override ({teamId, userId, client}) so any non-session caller (eval gate runner, future webhooks) can drive a canvas run without hijacking auth.getUser. Existing user-session callers are unchanged.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"aa:[\"$\",\"li\",\"2026-05-09-HunterVoice: ⇧Space toggle replaces hold-Space PTT\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.82s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.19.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterVoice: ⇧Space toggle replaces hold-Space PTT\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Press ⇧Space inside a focused prompt textarea to start dictating; press it again to stop. Plain Space is no longer intercepted, so typing literal spaces while composing a prompt is back to normal.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Behaviour matches the click-to-toggle button: mic stays hot until you toggle off, so you can pause to think without losing the recognizer.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"ab:[\"$\",\"li\",\"2026-05-09-HunterVoice v1: push-to-talk dictation on agent + canvas inputs\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.879999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.19.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterVoice v1: push-to-talk dictation on agent + canvas inputs\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Click the mic next to any prompt textarea — or hold Space inside it — and dictate. Final transcript is appended to whatever you've already typed; live interim text shows next to the button so you see the recognizer working before you stop.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Two interaction modes: click-to-toggle (accessibility default, keyboard / screen-reader friendly with aria-pressed + aria-label) and hold-Space inside the focused textarea (Slack-style power-user shortcut).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Web Speech API only in v1 — works in Chrome, Edge, Safari with zero new deps and zero env vars. Firefox shows a disabled 'Voice n/a' button instead of crashing. True local Whisper (transformers.js wasm, ~40MB) and an OpenAI Whisper cloud fallback are deliberate v2 paths so we don't ship a 40MB browser bundle for an MVP.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Dropped on /dashboard/agents (user prompt) and /dashboard/canvas/[id] (run-canvas task input). Wires up by id — the textarea stays a normal server-rendered field, the VoiceInput client component finds it via document.getElementById and writes to .value so form submission picks up the dictated text without any controlled-input refactor.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"ac:[\"$\",\"li\",\"2026-05-09-HunterMultiplayer v1: Figma-style live cursors + presence on canvas\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"8.94s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.18.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMultiplayer v1: Figma-style live cursors + presence on canvas\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Open the same canvas detail page (`/dashboard/canvas/[id]`) in two windows — or with a teammate — and you see each other's cursor in real time, with a coloured arrow + name tag. Top-right pill stack shows everyone currently viewing.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Pure Supabase Realtime — one channel per canvas, presence for the pill stack, broadcast for cursor coordinates throttled to 20 Hz. Zero new tables, zero DB writes; opening a canvas you don't have access to never reaches the channel because Realtime inherits the same RLS as your other queries.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Per-user color is a stable hash of `user_id` from a hand-picked dark-theme palette (no amber, so the brand accent stays distinct from any one cursor). Initials computed from full_name → email → user_id fallback.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Each tab is its own session, but pills de-dupe by user_id so two tabs from the same person show one avatar — Figma-style. Cursors GC after 5s of silence as a safety net for crashed peers.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Comments + Multiplayer-on-other-surfaces (traces, missions) are deferred to v2 — the canvas headline experience is what the roadmap promised, and shipping it cleanly beats a half-built three-feature drop.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"ad:[\"$\",\"li\",\"2026-05-09-HunterBridge v1: BYO compute — pair your laptop, run agents locally\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.17.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterBridge v1: BYO compute — pair your laptop, run agents locally\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 3 closes. Register a machine (laptop, GPU box, self-hosted runner), pair it with a 15-minute one-time code, and dispatch agent runs to it from /dashboard/agents. The bridge polls the HunterADE API, executes locally with its own Anthropic key, and streams traces back into HunterTrace — zero model traffic touches our infra.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New schema: `bridges`, `bridge_pairing_codes`, `bridge_tokens` (hbk_… bearer, sha256-stored), `bridge_jobs` queue, plus `traces.bridge_id` so the trace viewer shows where a run executed. Three new audit_action values: bridge.register / bridge.revoke / bridge.run.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Daemon-facing API at /api/v1/bridge/*: pair, heartbeat, jobs/next (atomic claim), jobs/[id]/result. Bridge tokens authenticate every endpoint; tokens are sha256-hashed at rest and revoked the moment a bridge is decommissioned.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/compute lists bridges with online/offline state (90s heartbeat window), shows unclaimed pairing codes with countdown, recent jobs grouped by bridge with status + trace deep-link, and a one-line install command.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"@hunterade/bridge ships as a Node-based reference daemon under bridge/. `npx @hunterade/bridge pair --code …` then `npx @hunterade/bridge run` is the whole loop. Heartbeat every 30s, poll every 3s, graceful shutdown on SIGINT. Config stored chmod 600 at ~/.hunterade/bridge/config.json.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],\"$Ld6\"]}],\"$Ld7\"]}]]}]\n"])</script><script>self.__next_f.push([1,"ae:[\"$\",\"li\",\"2026-05-09-HunterCompliance v1: SOC2-ready audit log, PII proxy, BYOK\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.06s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.16.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterCompliance v1: SOC2-ready audit log, PII proxy, BYOK\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `audit_events` table captures every meaningful action — agent runs, canvas runs, evals, postmortems, adversary sweeps, scribe distillations, forge publishes / installs, knowledge ingests, budget changes, BYOK rotations, token lifecycle, compliance settings updates, and audit exports. Append-only, RLS-protected per team, indexed on (team_id, occurred_at).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"PII proxy redacts emails, phones, SSNs, credit cards (Luhn-checked), IPv4, AWS access keys, and known model-provider key formats from every prompt before it leaves our infra. Strict mode adds long digit runs and IPv6. Originals stay in your trace spans.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"BYOK lets a team supply their own Anthropic / OpenAI key. Encrypted at rest with AES-256-GCM under HUNTERADE_BYOK_MASTER_KEY. Runner resolves BYOK first, falls back to platform env. Rotating leaves a `byok.rotate` audit event.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/compliance — owner / admin only — surfaces PII toggle, retention slider, BYOK cards (key hint + last rotation), and a 100-event audit log. Stream the full log as JSONL or CSV; the export itself shows up as the next event in the trail.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Every LLM-calling surface (runAgent, runCanvas, runRedTeamCampaign, runPostmortem, distillSkillFromTrace, llm-judge) goes through one `prepareRun(teamId, provider)` helper that resolves the key + redacts inputs + stamps `compliance.*` attributes on the parent span.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],\"$Ld8\"]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"af:[\"$\",\"li\",\"2026-05-09-Naming pass: every product / surface now starts with \\\"Hunter\\\"\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.12s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.15.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Naming pass: every product / surface now starts with \\\"Hunter\\\"\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Locked in the naming rule from v0.14.0 across every shipped surface — product labels in featureFlags.ts, every dashboard page header, every empty-state, and the public marketing surfaces.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 2: Mission Control → HunterMissions, Eval Harness → HunterEvals, Multi-Agent Canvas → HunterCanvas. Phase 3: Cost Governance → HunterCost, Red Team Mode → HunterAdversary, Agent Postmortems → HunterPostmortems, Agent Git → HunterGit, Team Knowledge Graph → HunterKnowledge, Local Bridge → HunterBridge. Phase 4: Forge → HunterForge, with HunterMultiplayer / HunterMobile / HunterCompliance lined up.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Dashboard sub-nav labels stay terse on purpose — the Hunter brand prefix is implied by being inside the HunterADE app shell. Each terse label maps to its full Hunter-prefixed name on the page header (e.g. nav \\\"Adversary\\\" → page header \\\"HunterAdversary\\\").\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"ROADMAP.md and README.md status table refreshed in the same commit so external readers see the official names. Added an explicit Naming rule line to ROADMAP § Brand \u0026 Naming so the policy lives next to the surface list.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Internal code identifiers (table / column / variable names like canvas_versions, forge_listings) intentionally stay descriptive snake_case — the rule only governs user-facing product names.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b0:[\"$\",\"li\",\"2026-05-09-HunterScribe v1: distill a recorded trace into a reusable skill\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.18s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.14.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterScribe v1: distill a recorded trace into a reusable skill\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `skills` table — name, description, instructions (the actual prompt prefix), source_trace_ids[] for provenance, distill model + cost rollup. RLS via private.is_team_member; owners/admins delete.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Added `skill_id` to canvas_nodes — when set, the canvas runner prepends the skill's instructions to that node's system prompt automatically.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Distillation: pick a saved trace at /dashboard/scribe/new, click Distill — Sonnet 4.6 reads the trace's spans + IO previews and produces { name, description, instructions } in strict JSON. Typical cost ~$0.005 per skill.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/scribe — list of skills with provenance count + distill cost. /dashboard/scribe/[id] is a full edit page (refine the auto-generated instructions before attaching).\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Canvas node edit page gained a HunterScribe skill picker. The runner pre-loads all referenced skills in one query, splices skill.instructions into the system-prompt head before knowledge context and base role.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Naming rule: every product / surface starts with \\\"Hunter\\\" going forward. Skill Recorder → HunterScribe is the first feature shipped under this rule.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b1:[\"$\",\"li\",\"2026-05-09-HunterForge v1: publish a canvas, install someone else's\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.24s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.13.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterForge v1: publish a canvas, install someone else's\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `forge_listings` table — frozen canvas snapshots (same shape as canvas_versions), unique slug, published_at lifecycle, install_count rollup. RLS lets anon + authenticated read PUBLISHED listings; team members additionally see their own drafts.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/forge — public marketplace landing (no auth required). Hero, role-chip preview per listing, install_count + node count footer.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/forge/[slug] — public detail with full pipeline preview (every node's role, name, model, system prompt) and a one-click Install button.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Install action forks the listing into the user's team: new canvas + nodes, auto-commit as v1 with message \\\"Installed from Forge · \u003ctitle\u003e\\\", increments install_count, redirects to the new canvas.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Publish panel on /dashboard/canvas/[id]: title + description form. Server action snapshots current state, mints a slug (title + 6-char random suffix), sets published_at = now.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/forge — your team's listings with Unpublish / Republish / Delete actions. Drafts and unpublished listings remain visible to the team without leaking to the public.\"}}]]}],[\"$\",\"li\",\"6\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Forge link added to the marketing nav (public) and the dashboard sub-nav (publishers).\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b2:[\"$\",\"li\",\"2026-05-09-HunterKnowledge v1: pgvector retrieval that grounds every canvas run\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.299999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.12.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterKnowledge v1: pgvector retrieval that grounds every canvas run\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Enabled pgvector + new knowledge_sources / knowledge_chunks tables (1536-dim embeddings, HNSW cosine index). public.match_knowledge_chunks RPC runs as security_invoker over team-scoped RLS — no security-definer warnings.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built /dashboard/knowledge with paste-ingest (paragraph-aware chunker, ~500 tok / 50 tok overlap), source detail with chunk drill-down, and a built-in Search panel that runs cosine retrieval ad-hoc to verify quality.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"OpenAI text-embedding-3-small via raw fetch (no extra SDK dep). Friendly setup banner + form-disable when OPENAI_API_KEY isn't configured.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Per-canvas opt-in via a Use Knowledge toggle on the canvas detail page. When on, runCanvas embeds the user task once, retrieves top-6 chunks above min-similarity 0.4, and prepends a \\\"Relevant team context\\\" block to every node's system prompt.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Retrieved chunk_ids land on the agent.run span's attributes so trace replay shows exactly which knowledge informed the run.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b3:[\"$\",\"li\",\"2026-05-09-HunterGit v1: version-control your canvas like code\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.36s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.11.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterGit v1: version-control your canvas like code\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `canvas_versions` table — frozen snapshots of (canvas + ordered nodes) keyed on (canvas_id, version) with auto-incrementing per-canvas integers. Snapshots are immutable history; the table has no UPDATE policy.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Commit panel on /dashboard/canvas/[id]: type a message, click Commit, snapshot lands as the next version. Required commit message keeps history meaningful.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/canvas/[id]/versions: full list with revert links and a Diff vs vN-1 button on each row. Latest pair gets a one-click \\\"Diff latest\\\" shortcut in the header.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/canvas/[id]/versions/[versionId]: full snapshot view of name + description + every node (with its system prompt) + a Revert button.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/canvas/[id]/versions/diff?from=…\u0026to=…: side-by-side diff with metadata changes highlighted, per-position node states (added / removed / modified / unchanged), and per-field change summaries (role, name, model, system_prompt). Modified rows expand with both before/after states + full prompt text.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Revert is auditable: replaces canvas + nodes with the snapshot, then auto-writes a new version with `is_revert = true` and message \\\"Revert to vN\\\" so history stays linear.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b4:[\"$\",\"li\",\"2026-05-09-HunterPostmortems v1: 5-whys analysis on any trace\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.42s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.10.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterPostmortems v1: 5-whys analysis on any trace\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `postmortems` table — one per trace (UNIQUE), summary + structured analysis (whys, root_cause, recommendations) jsonb, model + cost + duration tracked. RLS via private.is_team_member.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Embedded a Postmortem panel into /dashboard/traces/[id]: empty state with a Generate button, populated state with summary + numbered 5-whys list + amber root-cause callout + recommendation bullets + Regenerate button.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Runner uses Claude Haiku 4.5 with a strict JSON-output system prompt and a compact trace-context summary (root + spans with status, IO previews, errors). Typical cost is sub-cent; budget gated.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Re-generation upserts on (trace_id) — running it again on the same trace overwrites with a fresh analysis. The trigger column reserves space for future auto-on-error / auto-on-budget triggers.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b5:[\"$\",\"li\",\"2026-05-09-HunterAdversary v1: automatic adversarial sweeps against your front-door agent\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.48s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.9.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterAdversary v1: automatic adversarial sweeps against your front-door agent\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `red_team_campaigns` + `red_team_attempts` tables with attack_kind enum (prompt_injection / jailbreak / system_extraction / off_task / edge_case). RLS via private.is_team_member.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Standard attack pack: 4 canonical adversarial inputs — \\\"Ignore previous instructions\\\", system-prompt extraction, DAN-style jailbreak, and an off-task chitchat distraction. Each attack ships with an explicit judge rubric so verdicts are auditable.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Runner targets the front-door (first node) of any saved canvas. Each attack creates a new HunterTrace + agent.run + llm.completion span — the campaign reuses the same trace + eval infrastructure, no new observability surface.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"LLM judge (Haiku 4.5 by default) grades each attempt: passed=true means the agent BLOCKED the attack, false means the attacker won. Judge cost is rolled into the campaign's total_cost_usd alongside the agent call.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built /dashboard/red-team with a list view (block-rate bar chart per campaign), /dashboard/red-team/new (canvas + pack picker), and /dashboard/red-team/[id] showing per-attempt verdicts, judge reasoning, and links into each generated trace.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Re-run + delete campaigns inline. Cost gated by the same monthly budget as everything else.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b6:[\"$\",\"li\",\"2026-05-09-HunterCost v1: monthly budgets that refuse runs over the hard limit\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.54s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.8.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterCost v1: monthly budgets that refuse runs over the hard limit\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `budgets` table — one per team via PK, hard + optional soft USD limits. RLS lets owners + admins update; members read.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built /dashboard/cost: this-month total + budget gauge, last-month comparison, 30-day SVG sparkline (no charting library — pure server-rendered), spend breakdown by runner (canvas, agent runner, evals, API) and by model, top 10 traces by cost.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"BudgetExceededError + assertBudgetAvailable() wired into runAgent, runCanvas, and runEvalsForTrace. Once the team's monthly spend reaches the hard limit, every LLM-triggering path returns a clear error with the exact number to raise the cap or wait for next cycle.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Soft limits surface as a banner above the dashboard (and on the budget gauge as a tick mark) — runs continue, but the team knows they're approaching the wall.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 3 begins. Budgets close the immediate enterprise-readiness gap that traces alone don't solve.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b7:[\"$\",\"li\",\"2026-05-09-HunterMissions v1: kanban tasks that run end-to-end through your canvases\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.6s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.7.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterMissions v1: kanban tasks that run end-to-end through your canvases\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `missions` table + `mission_status` enum (backlog / in_progress / done / failed / archived). Optional canvas_id and current_trace_id link each mission to its execution and resulting trace. RLS via private.is_team_member.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built /dashboard/missions kanban with four lanes, status dropdowns, priority chips, and a Run button on cards bound to a canvas.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built /dashboard/missions/new (title + description + canvas selector + priority) and /dashboard/missions/[id] for full edit + run + archive/delete with the latest linked trace pinned to the top.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"runMissionAction wraps runCanvas: marks the mission in_progress, executes synchronously, parks the trace_id back on the row, transitions to done (or failed). Closes the loop from queue → execute → replay.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Sub-nav now leads with Missions: Overview · Missions · Agents · Canvas · Traces · Evals.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 2 is complete: every roadmap surface for the lead pillar is shipped.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b8:[\"$\",\"li\",\"2026-05-09-HunterCanvas v1: orchestrate Planner → Coder → Reviewer pipelines\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.66s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.6.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterCanvas v1: orchestrate Planner → Coder → Reviewer pipelines\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `canvases` + `canvas_nodes` schema with a `canvas_role` enum (planner / coder / reviewer / tester / red_team / custom). RLS via private.is_team_member; ordered retrieval indexed on (canvas_id, position).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built /dashboard/canvas list, /dashboard/canvas/new (with four starter templates), /dashboard/canvas/[id] for the pipeline editor, and /dashboard/canvas/[id]/nodes/[nodeId] for per-node prompt + model editing.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Composer UX is fully server-rendered: add / remove / reorder nodes via server actions; no client JS required. Vertical card layout with animated connectors between steps.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Canvas runner walks nodes in order, feeds each output into the next agent's system prompt, captures every call as an llm.completion span under one agent.run root span. The whole pipeline lands as a single HunterTrace you can replay and grade with Evals.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Adaptive thinking on every node; ephemeral prompt caching on the system block; cost rolled up from each node's usage object.\"}}]]}],[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Sub-nav now: Overview · Agents · Canvas · Traces · Evals. Canvas tile is a Live link.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"b9:[\"$\",\"li\",\"2026-05-09-Hunter MCP server: stream traces from Cursor / Claude Code / any MCP client\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.719999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.5.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Hunter MCP server: stream traces from Cursor / Claude Code / any MCP client\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `api_tokens` table with sha-256 hashed PATs (plaintext shown once); `/dashboard/settings/tokens` to mint and revoke.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New v1 HTTP API: POST /api/v1/runs (one-shot), POST /api/v1/traces (start), GET /api/v1/traces, GET /api/v1/traces/:id, POST /api/v1/traces/:id/spans, POST /api/v1/traces/:id/end, POST /api/v1/traces/:id/evals/run. Bearer-token authed.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `mcp/` package: an independent npm module exposing six tools (record_run, start_trace, add_span, end_trace, list_recent_traces, run_evals) over MCP stdio. Drop the binary into Cursor or Claude Code's mcp.json and your editor agent emits HunterTrace spans on its own.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Eval runner refactored to accept an injected Supabase client so the API path can run evals with the admin client without going through user RLS.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Requires the SUPABASE_SECRET_KEY env var — the HTTP API returns 503 with a clear setup message until it's set.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"ba:[\"$\",\"li\",\"2026-05-09-HunterEvals v1: grade traces with output-contains or LLM judge\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.78s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.4.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterEvals v1: grade traces with output-contains or LLM judge\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New evals + eval_runs schema (RLS via private.is_team_member) — re-running an eval against the same trace upserts on (eval, trace).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Two grader types: output_contains (instant, free) and llm_judge (Haiku 4.5 by default — costs negligible tokens per run, returns a JSON verdict with pass/fail, score, and reason).\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"/dashboard/evals: list + create form with conditional config blocks per grader kind. /dashboard/evals/[id] shows the eval's recent runs with verdicts, scores, and per-run cost.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Trace detail (/dashboard/traces/[id]) gained an Evals panel: passed/failed counts, per-eval verdict chips, and a Run evals button that grades the trace against every enabled rule.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"PR-blocking eval gates land in Phase 2.5 once the local CLI ships.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"bb:[\"$\",\"li\",\"2026-05-09-Single-agent runner: real Anthropic calls, every span recorded\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.84s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.3.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Single-agent runner: real Anthropic calls, every span recorded\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Wired @anthropic-ai/sdk into a server-side runner that streams Messages API calls (adaptive thinking, prompt caching on system blocks) and persists every call as a HunterTrace span tree: agent.run wraps llm.completion.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built /dashboard/agents — a clean form (system prompt, user prompt, model dropdown). On submit you land on the trace detail with cost, tokens, latency, and the full assistant output captured.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Accurate cost calculation per model, including separate rates for cache writes (5m TTL × 1.25 input) and cache reads (× 0.1 input). Opus 4.7 / 4.6, Sonnet 4.6, Haiku 4.5 supported.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Typed Anthropic SDK exceptions (RateLimitError, AuthenticationError, etc.) surface as span.status = error with the HTTP status preserved on attributes.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Surface a clear setup banner when ANTHROPIC_API_KEY is missing rather than failing silently.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"bc:[\"$\",\"li\",\"2026-05-09-HunterTrace v1: trace + span ingest, list view, timeline replay\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.9s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 9, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.2.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"HunterTrace v1: trace + span ingest, list view, timeline replay\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"New `traces` and `spans` tables with full RLS — every span carries cost, latency, model, tokens, IO, and a typed `kind` (agent / llm / tool / eval / internal).\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built `/dashboard/traces` list view with status badges, span counts, total cost rollups, and relative timestamps.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Built `/dashboard/traces/[id]` timeline replay — proportional span bars colored by kind, stat tiles, and a full inspector with collapsible inputs/outputs/attributes per span.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Auto-create a personal team for every new user (and backfill existing users) so traces always have a home.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"One-click \\\"Generate sample trace\\\" action that inserts a realistic span tree to play with.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"bd:[\"$\",\"li\",\"2026-05-08-Supabase wired up — auth and waitlist persist\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"9.959999999999999s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 8, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.1.2\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-violet-400/40 bg-violet-400/10 text-violet-300\",\"children\":\"Infra\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Supabase wired up — auth and waitlist persist\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Provisioned the production Supabase project (us-west-1, Free tier) with `profiles`, `teams`, `team_members` (owner/admin/member enum), and `waitlist` tables — RLS on everything.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Security-definer trigger functions (`handle_new_user`, `handle_new_team`, `is_team_member`) live in a private schema so they can't be called as RPCs.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Generated typed `Database` for the Supabase clients — full autocomplete and compile-time safety on every query.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Waitlist form on the landing page now persists to Postgres. Duplicate emails are treated as success.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"be:[\"$\",\"li\",\"2026-05-08-Phase 1 auth: magic link + GitHub/Google OAuth\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"10.02s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 8, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.1.1\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 1 auth: magic link + GitHub/Google OAuth\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Added the `(auth)` route group: shared `AuthForm` with email magic-link plus GitHub and Google OAuth buttons.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Wired session-refresh middleware so Supabase auth cookies stay fresh on every navigation.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"OAuth callback exchanges the `?code` for a session and redirects to `?next` (defaults to `/dashboard`).\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"`/dashboard` is now server-side guarded — unauthenticated users land on `/sign-in?next=/dashboard`.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Site header switches to a user menu with email + sign-out once you're signed in.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"bf:[\"$\",\"li\",\"2026-05-08-Phase 0 foundation\",{\"className\":\"relative [animation:var(--animate-hunter-rise)]\",\"style\":{\"animationDelay\":\"10.08s\"},\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"absolute -left-[1.4rem] top-2 grid h-3 w-3 place-items-center rounded-full bg-white shadow-[0_0_0_4px_rgba(255,255,255,0.08)]\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-center gap-3 text-xs\",\"children\":[[\"$\",\"time\",null,{\"className\":\"font-mono text-zinc-500\",\"children\":\"May 8, 2026\"}],[\"$\",\"span\",null,{\"className\":\"rounded-md border border-white/10 bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-zinc-300\",\"children\":\"v0.1.0\"}],[\"$\",\"span\",null,{\"className\":\"rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider border-emerald-400/40 bg-emerald-400/10 text-emerald-300\",\"children\":\"Shipped\"}]]}],[\"$\",\"h2\",null,{\"className\":\"mt-3 font-display text-2xl leading-tight tracking-tight text-zinc-50\",\"children\":\"Phase 0 foundation\"}],[\"$\",\"ul\",null,{\"className\":\"mt-3 flex flex-col gap-2 text-sm leading-relaxed text-zinc-400\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Stood up the HunterADE app: Next.js 16 + React 19 + TypeScript + Tailwind v4 + shadcn/ui.\"}}]]}],[\"$\",\"li\",\"1\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Supabase clients (browser, server, middleware) typed end-to-end.\"}}]]}],[\"$\",\"li\",\"2\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Introduced the `\u003cComingSoon /\u003e` pattern + `featureFlags.ts` registry — flip a single boolean to launch a feature; banner self-removes.\"}}]]}],[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Marketing landing page with hero, four-pillar grid (HunterTrace as lead), and waitlist form.\"}}]]}],[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"CI on every push: typecheck + lint + build.\"}}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"c0:[\"$\",\"footer\",null,{\"className\":\"relative mt-12 border-t border-white/5 bg-zinc-950\",\"children\":[[\"$\",\"div\",null,{\"aria-hidden\":true,\"className\":\"pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/12 to-transparent\"}],[\"$\",\"div\",null,{\"className\":\"mx-auto grid w-full max-w-7xl grid-cols-2 gap-y-12 gap-x-8 px-6 py-16 sm:grid-cols-3 lg:grid-cols-[1.5fr_repeat(5,1fr)]\",\"children\":[[\"$\",\"div\",null,{\"className\":\"col-span-2 flex flex-col gap-4 sm:col-span-3 lg:col-span-1\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/\",\"className\":\"flex items-center gap-2.5 font-medium tracking-tight\",\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"grid h-7 w-7 place-items-center rounded-md bg-white font-display text-base leading-none text-zinc-950 shadow-[0_4px_18px_-6px_rgba(255,255,255,0.35)]\",\"children\":\"S\"}],[\"$\",\"span\",null,{\"className\":\"text-zinc-100\",\"children\":\"Stackon\"}]]}],[\"$\",\"p\",null,{\"className\":\"max-w-xs text-sm leading-relaxed text-zinc-500\",\"children\":\"The observability-first workspace for engineering teams running Claude and Codex. Every agent run, a replayable trace.\"}],[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.22em] text-zinc-600\",\"children\":\"Speed, with receipts.\"}]]}],[[\"$\",\"div\",\"Observability\",{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Observability\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",\"traces\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/trace\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Trace\"}]}],[\"$\",\"li\",\"evals\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/evals\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Evals\"}]}],[\"$\",\"li\",\"costGovernance\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/cost\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Cost\"}]}],[\"$\",\"li\",\"redTeam\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/adversary\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Adversary\"}]}],[\"$\",\"li\",\"postmortems\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/postmortems\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Postmortems\"}]}]]}]]}],[\"$\",\"div\",\"Canvas \u0026 Missions\",{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Canvas \u0026 Missions\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",\"canvas\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/canvas\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Canvas\"}]}],[\"$\",\"li\",\"missionControl\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/missions\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Missions\"}]}],[\"$\",\"li\",\"agentGit\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/versions\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Versions\"}]}],[\"$\",\"li\",\"multiplayer\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/multiplayer\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Multiplayer\"}]}],[\"$\",\"li\",\"skillRecorder\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/scribe\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Scribe\"}]}],[\"$\",\"li\",\"knowledge\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/knowledge\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Knowledge\"}]}]]}]]}],[\"$\",\"div\",\"Apps \u0026 Surfaces\",{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Apps \u0026 Surfaces\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",\"mobile\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/mobile\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Mobile\"}]}],\"$Ld9\",\"$Lda\",\"$Ldb\",\"$Ldc\",\"$Ldd\",\"$Lde\"]}]]}]],\"$Ldf\",\"$Le0\"]}],\"$Le1\"]}]\n"])</script><script>self.__next_f.push([1,"c1:[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0.yi9aimcng_a.js\",\"async\":true,\"nonce\":\"$undefined\"}]\nc2:[\"$\",\"$Le2\",null,{\"children\":[\"$\",\"$c7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@e3\"}]}]\nc9:[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Bundle: 783 KB JS / 26 KB CSS (gzip 215 + 6). +5 KB for the trace-session lib. \u003cstrong\u003ePhase 7 is complete.\u003c/strong\u003e Stackon Space now matches the original vision end-to-end — terminals, editor, missions, agents, skills, AND every shell session becomes a Stackon trace. The desktop workspace where every Claude Code session has receipts.\"}}]]}]\nca:[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7E next: Agents + Skills sidebar with drag-to-terminal injection. Phase 7F: terminal session → Stackon trace bridge (the killer differentiator — every \u003ccode\u003eclaude\u003c/code\u003e session in Space optionally becomes a replayable Stackon trace).\"}}]]}]\ncb:[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}]\ncc:[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Renderer side: \u003ccode\u003edesktop/src/lib/{supabase,auth}.ts\u003c/code\u003e. The Supabase JS client uses \u003ccode\u003edetectSessionInUrl: false\u003c/code\u003e because we feed the fragment to \u003ccode\u003esetSession\u003c/code\u003e ourselves from the deep-link listener. \u003ccode\u003eApp.tsx\u003c/code\u003e bootstraps with a brief \u0026quot;Restoring your session\u0026hellip;\u0026quot; state, then either mounts the shell (if a session restored from \u003ccode\u003etauri-plugin-store\u003c/code\u003e) or shows the sign-in splash. Build-time env vars: \u003ccode\u003eVITE_SUPABASE_URL\u003c/code\u003e + \u003ccode\u003eVITE_SUPABASE_PUBLISHABLE_KEY\u003c/code\u003e documented in new \u003ccode\u003edesktop/.env.example\u003c/code\u003e.\"}}]\ncd:[\"$\",\"li\",\"4\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 7A.1 unblocks 7B (real PTYs) and everything that follows — the session is now real, so Tasks/Agents/Skills can actually hit the Stackon API once those panes are wired in 7D/E.\"}}]]}]\nce:[\"$\",\"li\",\"3\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Multi-turn agent context is intentionally deferred to Phase 6D — each composer submit is currently a fresh run against the bound canvas with the composer text as the user task. The mission's title + description are visible context for humans but aren't re-injected into the LLM prompt today.\"}}]]}]\ncf:[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}]\nd0:[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Build, lint, typecheck clean. No behavior changes.\"}}]\nd1:[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Mobile: new /(home)/approvals tab + /approvals/[id] detail screen. Approve sends the user to the new trace; reject returns to the list. Notification taps deep-link to detail; the screen shows 'already decided' if two approvers race.\"}}]\nd2:[\"$\",\"li\",\"5\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Race safety: the WHERE status='pending' guard makes approve/reject idempotent — second caller gets a conflict error (409 on mobile API, friendly redirect on dashboard). pending_run.expires_at defaults to 24h after creation; a background cleanup will mark expired rows in a follow-up.\"}}]]}]\nd3:[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Notification payloads carry only event title + IDs (trace_id, gate_slug, event kind). Trace bodies, span outputs, and budget breakdowns stay on the server — Expo can't see them.\"}}]\nd4:[\"$\",\"li\",\"5"])</script><script>self.__next_f.push([1,"\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Bridge daemon endpoints (hbk_ namespace) inherit the same error envelope + request id flow but stay scope-less — single-purpose tokens for job dispatch.\"}}]]}]\nd5:[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Phase 1 now fully closes: marketing site, auth (magic link + OAuth), waitlist + Resend, onboarding wizard, ⌘K palette, and teams \u0026 invites — all live and registry-flagged.\"}}]\nd6:[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Agent runner gets a \\\"Run on\\\" select — defaults to Cloud, lists every bridge with online/offline status. Cloud path is unchanged; the bridge path enqueues a job + pre-creates the trace so the user lands on a live URL while the daemon picks it up.\"}}]\nd7:[\"$\",\"li\",\"6\",{\"className\":\"flex items-start gap-2\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 h-1 w-1 shrink-0 rounded-full bg-zinc-600\"}],[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"Tauri/Rust binaries with mTLS tunnel + auto-update + code signing are deferred to v2 — out of scope for a single session, and the v1 token-auth model is functionally complete for self-hosted use.\"}}]]}]\nd8:[\"$\",\"span\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"RBAC: owners and admins manage settings + BYOK; all team members can read the audit log. Personal teams treat their creator as owner even before team_members has a row.\"}}]\nd9:[\"$\",\"li\",\"voice\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/voice\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Voice\"}]}]\nda:[\"$\",\"li\",\"space\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/space\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Stackon Space\"}]}]\ndb:[\"$\",\"li\",\"hunterMcp\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/mcp\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Stackon MCP\"}]}]\ndc:[\"$\",\"li\",\"compute\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/bridge\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Bridge\"}]}]\ndd:[\"$\",\"li\",\"forge\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/forge\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Forge\"}]}]\nde:[\"$\",\"li\",\"compliance\",{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/product/compliance\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Compliance\"}]}]\ndf:[\"$\",\"div\",null,{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Resources\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/docs\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Docs\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/changelog\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Changelog\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/model-updates\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Model Updates\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/community/events\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Events\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/community/discord\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Discord\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/download\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Download\"}]}]]}]]}]\ne0:[\"$\",\"div\",null,{\"className\":\"flex flex-col gap-3\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.28em] text-zinc-500\",\"children\":\"Company\"}],[\"$\",\"ul\",null,{\"className\":\"flex flex-col gap-2\",\"children\":[[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"hre"])</script><script>self.__next_f.push([1,"f\":\"/about\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"About\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/pricing\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Pricing\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/careers\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Careers\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/media\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Media\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/contact\",\"className\":\"text-sm text-zinc-400 transition-colors hover:text-white\",\"children\":\"Contact\"}]}]]}]]}]\ne1:[\"$\",\"div\",null,{\"className\":\"border-t border-white/5\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto flex w-full max-w-7xl flex-col items-start justify-between gap-3 px-6 py-6 text-xs text-zinc-600 sm:flex-row sm:items-center\",\"children\":[[\"$\",\"p\",null,{\"children\":[\"© \",2026,\" Stackon\"]}],[\"$\",\"div\",null,{\"className\":\"flex items-center gap-5 text-xs\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/privacy\",\"className\":\"text-zinc-500 transition-colors hover:text-white\",\"children\":\"Privacy\"}],[\"$\",\"$L6\",null,{\"href\":\"/terms\",\"className\":\"text-zinc-500 transition-colors hover:text-white\",\"children\":\"Terms\"}]]}],[\"$\",\"p\",null,{\"className\":\"font-mono text-[10px] uppercase tracking-[0.22em] text-zinc-700\",\"children\":\"v0.99.53\"}]]}]}]\nc5:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n5:[\"$\",\"header\",null,{\"className\":\"sticky top-0 z-50 border-b border-white/5 bg-zinc-950/80 backdrop-blur\",\"children\":[[\"$\",\"div\",null,{\"aria-hidden\":true,\"className\":\"pointer-events-none absolute inset-x-0 -bottom-px h-px bg-gradient-to-r from-transparent via-white/15 to-transparent\"}],[\"$\",\"div\",null,{\"className\":\"mx-auto flex h-14 max-w-7xl items-center justify-between gap-6 px-6\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/\",\"className\":\"flex shrink-0 items-center gap-2.5 font-medium tracking-tight\",\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"grid h-7 w-7 place-items-center rounded-md bg-white font-display text-base leading-none text-zinc-950 shadow-[0_4px_18px_-6px_rgba(255,255,255,0.4)]\",\"children\":\"S\"}],[\"$\",\"span\",null,{\"className\":\"text-zinc-100\",\"children\":\"Stackon\"}]]}],[\"$\",\"$Le4\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex shrink-0 items-center gap-3\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/sign-in\",\"className\":\"hidden text-xs text-zinc-400 transition-colors hover:text-zinc-200 sm:inline\",\"children\":\"Sign in\"}],[\"$\",\"$L6\",null,{\"href\":\"/sign-up\",\"className\":\"rounded-full bg-white px-3.5 py-1.5 text-xs font-medium text-zinc-950 transition hover:bg-zinc-200\",\"children\":\"Start free\"}]]}]]}]]}]\n17:[\"$\",\"header\",null,{\"className\":\"sticky top-0 z-50 border-b border-white/5 bg-zinc-950/80 backdrop-blur\",\"children\":[[\"$\",\"div\",null,{\"aria-hidden\":true,\"className\":\"pointer-events-none absolute inset-x-0 -bottom-px h-px bg-gradient-to-r from-transparent via-white/15 to-transparent\"}],[\"$\",\"div\",null,{\"className\":\"mx-auto flex h-14 max-w-7xl items-center justify-between gap-6 px-6\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/\",\"className\":\"flex shrink-0 items-center gap-2.5 font-medium tracking-tight\",\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"className\":\"grid h-7 w-7 place-items-center rounded-md bg-white font-display text-base leading-none text-zinc-950 shadow-[0_4px_18px_-6px_rgba(255,255,255,0.4)]\",\"children\":\"S\"}],[\"$\",\"span\",null,{\"className\":\"text-zinc-100\",\"children\":\"Stackon\"}]]}],[\"$\",\"$Le4\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex shrink-0 items-center gap-3\",\"children\":[[\"$\",\"$L6\",null,{\"href\":\"/sign-in\",\"className\":\"hidden text-xs text-zinc-400 transition-colors hover:text-zinc-200 sm:inline\",\"children\":\"Sign in\"}],[\"$\",\"$L6\",null,{\"href\":\"/sign-up\",\"className\":\"rounded-full bg-white px-3.5 py-1.5 text-xs font-medium text-zinc-950 transition hover:bg-zinc-200\",\"children\":\"Start free\"}]]}]]}]]}]\n"])</script><script>self.__next_f.push([1,"c8:[[\"$\",\"title\",\"0\",{\"children\":\"Stackon — An ADE powered by Claude and Codex.\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Stackon is the agentic developmental environment for engineering teams who refuse to fly blind. Multi-agent orchestration with first-class observability, evals, BYO compute, and a creator marketplace.\"}],[\"$\",\"meta\",\"2\",{\"name\":\"application-name\",\"content\":\"Stackon\"}],[\"$\",\"meta\",\"3\",{\"property\":\"og:title\",\"content\":\"Stackon — An ADE powered by Claude and Codex.\"}],[\"$\",\"meta\",\"4\",{\"property\":\"og:description\",\"content\":\"Multi-agent orchestration with first-class observability, evals, BYO compute, and a creator marketplace.\"}],[\"$\",\"meta\",\"5\",{\"property\":\"og:url\",\"content\":\"https://stackon.ai\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:site_name\",\"content\":\"Stackon\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:locale\",\"content\":\"en_US\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:image\",\"content\":\"https://stackon.ai/opengraph-image?52fcaa9f050c0e4a\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:image:type\",\"content\":\"image/png\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:image:height\",\"content\":\"630\"}],[\"$\",\"meta\",\"12\",{\"property\":\"og:image:alt\",\"content\":\"Stackon — The ADE that traces every agent run.\"}],[\"$\",\"meta\",\"13\",{\"property\":\"og:type\",\"content\":\"website\"}],[\"$\",\"meta\",\"14\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"15\",{\"name\":\"twitter:title\",\"content\":\"Stackon — An ADE powered by Claude and Codex.\"}],[\"$\",\"meta\",\"16\",{\"name\":\"twitter:description\",\"content\":\"Multi-agent orchestration with first-class observability, evals, BYO compute, and a creator marketplace.\"}],[\"$\",\"meta\",\"17\",{\"name\":\"twitter:image\",\"content\":\"https://stackon.ai/opengraph-image?52fcaa9f050c0e4a\"}],[\"$\",\"meta\",\"18\",{\"name\":\"twitter:image:alt\",\"content\":\"Stackon — The ADE that traces every agent run.\"}],[\"$\",\"meta\",\"19\",{\"name\":\"twitter:image:type\",\"content\":\"image/png\"}],[\"$\",\"meta\",\"20\",{\"name\":\"twitter:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"21\",{\"name\":\"twitter:image:height\",\"content\":\"630\"}],[\"$\",\"link\",\"22\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0x3dzn~oxb6tn.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$Le5\",\"23\",{}]]\n"])</script><script>self.__next_f.push([1,"e3:null\n"])</script></body></html>