Skip to content

Changelog

All notable changes to this project are documented in this file.

The format is loosely based on Keep a Changelog. Loupe carries no release tags yet, so all entries live under Unreleased.

Entries are listed newest first. Each one is anchored to the pull request that introduced it, and entries written before 2026-09-08 also carry the squash SHA. To recover the commit from a number, run git log --first-parent --grep='(#209)$', or gh pr view 209 --json mergeCommit. Keep the $: --grep reads the whole message, and commit bodies cite other pull requests in the same form. For an exhaustive diff between two points, run git log --oneline <older>..<newer> and cross-check, rather than trusting this file alone. Each entry carries one of the six tags Keep a Changelog defines: Added, Changed, Deprecated, Removed, Fixed or Security.

Granularity: one entry per merged pull request, one line each. A branch that shipped six features gets six entries, not one entry covering the branch — a reader looking for when tags arrived should find a line about tags, not a paragraph about the wave that contained them. Each entry is a single sentence stating what changed from the reader’s side; the reasoning behind a change belongs in the PR body and the commit message, which the PR number points at. The entry rides the pull request it describes. Write it in the same branch, in changelog.d/<pull request number>.md, and anchor it to that number. Two branches never write one fragment file, so two entries never conflict. This site folds every merged fragment into [Unreleased] on each deploy, newest pull request first, and just changelog folds them into the committed file at a release. changelog.d/README.md carries the format. A pull request whose whole content is this file and that directory earns no entry: recording that the changelog was written tells a reader nothing they cannot see by reading it.

Work that never surfaces in the product or the development workflow gets no entry.

[Unreleased]

  • (#1047) — Changed: A person can move a managed card of the Lifecycle workflow from the Backlog or Next straight to the terminal column.

  • (#1037) — Added: The design system has a page container, Ds:Workspace, with default, narrow and full widths, and the shell takes a full-width option that the board, the document review page and the artifact viewer use.

  • (#1036) — Added: The design system has a breadcrumbs component, and every page trail draws with it. The trail no longer starts with the project name.

  • (#1035) — Added: The design system has a drawer component, and the activity, worker run and card drawers render it, with one lazy frame for their loading and error states.

  • (#1034) — Fixed: A card whose last run stopped no longer shows Stuck while new work for it is queued or running.

  • (#1033) — Added: The design system has a settings layout component, and the account and project settings pages draw their heading, navigation and content column with it.

  • (#1032) — Added: The design system has a sidebar link component, and the 16 sidebar links draw themselves with it.

  • (#1031) — Added: The ⋯ menu of a document lists the artifacts of its linked cards.

  • (#1030) — Changed: The product design session now compares the answers with the prototype before the recap, and asks about each conflict.

  • (#1024) — Added: split view and list row components in the design system, which the inbox and the board now use, and their Claude Design export.

  • (#1023) — Added: The design system now documents the marketing shell, and the sign-in, marketing and home page footers share one set of legal links.

  • (#1020) — Changed: The sign-in, sign-up, password reset and install pages share one named page frame, and their forms use the same fields and buttons as the rest of the app.

  • (#1017) — Added: a page header component in the design system, which every page heading now uses, and its Claude Design export.

  • (#1016) — Changed: An inbox wait item has a short title, a one-line reason, the worker report rendered as Markdown under its own label, and Dismiss with its help in a tooltip. Opening a row keeps the scroll of the list.

  • (#1015) — Added: Public pages carry Open Graph and Twitter preview tags, with one preview image that the open_graph.image flag picks.

  • (#1015) — Added: The app serves /robots.txt and /sitemap.xml for its public pages.

  • (#1015) — Added: The analytics tag sends a click event for each waitlist button and one join event for each accepted waitlist submit. A reload or a direct visit of the confirmation sends no join event.

  • (#1015) — Changed: The analytics tag loads only on public pages, for signed-out visitors, and honours Do Not Track.

  • (#1015) — Changed: The Notify me form on the home page now redirects to /waitlist/notify?joined=1 after it saves an email.

  • (#1014) — Added: the app shell is a layout entry of the design system catalog, with a styleguide specimen and a Claude Design export wrapper, and its CSS lives in components/shell.css.

  • (#1012) — Changed: The nine emails now share one layout, so a change to the email frame reaches all of them.

  • (#1011) — Added: The design system has a brand mark component, and the sidebar, home page, legal pages, marketing footer and sign-in topbar draw the logo with it.

  • (#1009) — Added: A follow-up card moves from the Backlog to Next when every card it follows reaches a terminal column.

  • (#1008) — Added: The breakdown creates follow-up cards outside the epic for post-deploy entries, and the implementation stage builds them.

  • (#1005) — Added: the Tabs component has a segmented variant, a pill group for a view or a setting switch, in the design system catalog and its Claude Design export.

  • (#1004) — Added: a design system catalog entry can carry its own Claude Design export templates, and the export writes a layout group card.

  • (#1002) — Added: Cards can link as “has follow-up” and “follow-up of”, on the card page and through the MCP tools.

  • (#1001) — Added: The implementation, fix and review stages compare the built page with the prototype in screenshots, and discovery checks that Playwright works.

  • (#1000) — Fixed: The dev styleguide page now shows the site-review widget, so feedback can be filed on it.

  • (#999) — Changed: The implementation stage reads a linked prototype before it plans, maps each part to code, and the review stage fails a part the build leaves out with no recorded reason.

  • (#998) — Fixed: The artifact library refuses a raw Claude Design canvas, a .dc.html file, and tells you to push it with loupe artifact push from CLI 1.17.0 or later.

  • (#998) — Fixed: loupe artifact push leaves out the canvas.json of a Claude Design export, so it no longer reports false gaps for it.

  • (#997) — Changed: the board, the list, the card page and the MCP tools show the card markers that the workflow template defines. The engine stores them on each card after every evaluation, also for a held card and for a board with the automation off.

  • (#997) — Added: the markers waiting-on-checks, nothing-happened and session-open. A card with only the Unmanaged chip shows a neutral mark, and Waiting uses the hourglass icon. The state of the MCP tools names the new codes, and a chip is not in state.

  • (#997) — Added: the Workflow page lists the markers of the template.

  • (#997) — Removed: the list badges Checks failed, Conflict, Paused and Unmanaged. The list row shows the same state mark as the board tile.

  • (#996) — Added: the workflow engine checks card markers on every evaluation and stores them on the card, and both shipped templates declare their markers. Card checks now run on a workflow queue; the worker command reads it before async.

  • (#995) — Added: the workflow engine can read the facts and conditions that card markers need, such as paused, quiet, held and waiting for approval. No marker shows yet.

  • (#994) — Changed: each marker of a board tile and of a list row, such as the parent epic, the epic progress and the pull request count, explains itself in the tooltip of the design system instead of a browser title.

  • (#993) — Added: The inbox page follows changes while it is open. A new ask appears in the list, an ask that closes leaves the Open side, and an open ask that an agent withdraws locks with a line that says why. A response you were typing stays.

  • (#992) — Added: A workflow template can declare card markers, and the Workflow page lists them.

  • (#991) — Added: An agent review with findings now posts one summary comment in the pull request conversation, next to its check.

  • (#990) — Changed: The inbox ask pane now reads as one calm column with a Linked panel, a borderless decision block with a Clear choice link, and Decline in place of Close this item.

  • (#989) — Changed: After you answer, close or review an item in the inbox, the page opens the next ask in your list and shows a line that says what happened.

  • (#988) — Added: A Claude Design canvas with clicks, typed input or timers stays interactive after loupe artifact push compiles it.

  • (#987) — Added: loupe artifact push compiles several Claude Design artboards with --index, and links /_blob/ files from the folder.

  • (#986) — Changed: loupe.ac shows a new home page that sells Loupe as a software factory and joins the private beta waitlist, and the waitlist keeps the forge and agent picks of “Notify me”.

  • (#986) — Removed: the landing.enabled flag and the live demo of the old landing page. A self-hosted instance sends / to sign-in.

  • (#984) — Changed: The inbox page shows one view per address, so a reload or a shared link keeps the side, filter, search and selected ask, and search lists whole asks.

  • (#982) — Changed: The All inboxes page shows one calm row per project, and its Blocking mark now also counts a blocking item inside an open ask.

  • (#981) — Added: the artifact viewer has a file menu that lists the web pages of a version, and ?file=<path> keeps the pick in the address.

  • (#980) — Changed: The product design skill shows a recap with one line per decision when the questions end, and lets the owner correct any line before it writes the product document.

  • (#978) — Added: loupe artifact push compiles a Claude Design canvas to a plain page, and --out <folder> writes the pages with each gap marked.

  • (#977) — Fixed: an approved pull request that falls behind its base again after a sync is synced again, so it no longer waits for ever.

  • (#976) — Fixed: Stored artifact files now load on the content domain in production, whatever host the image was built with.

  • (#974) — Fixed: A card no longer shows the Stuck state “The last worker run did not finish its work” after a person moves it to another column.

  • (#973) — Fixed: A ready pull request stacked on another pull request now shows its card as Waiting and names the card it waits for, in place of a false Stuck.

  • (#972) — Changed: a failed agent review that an approval overrides now shows as a neutral loupe/agent-review check that names the approver, on the card page with a link to the check, and as two card history rows.

  • (#970) — Changed: an approval of a pull request after a failed agent review now lets the card go on, so the card moves to In review, a draft is marked ready, the pull request can merge, and no fix round starts for the findings.

  • (#969) — Changed: The product design skill checks each fact before a question or the product document uses it, and keeps only guesses that nothing can check in “Assumptions”.

  • (#969) — Changed: A tech design now opens with the problem and the recommended solution in plain words, with a diagram, then its strengths and weaknesses, the alternatives, and security and scalability when they apply. It proves claims about libraries and speed with the current docs or a proof of concept.

  • (#968) — Fixed: the bridge finds claude on the PATH of the account that launches it, so an env file that sets PATH no longer stops the bridge from starting or reloading.

  • (#967) — Fixed: Deleting a site-review note no longer deletes its card while a session or worker has an open run on it.

  • (#966) — Fixed: the hub keeps a bridge subscription open for up to one hour instead of about nine minutes, and the bridge logs stream_closed with the life and event count of each stream that ends cleanly.

  • (#965) — Fixed: The bridge now turns off a Codex account whose profile uses the OpenAI sign-in with no API key variable while codex login is logged out, instead of reading it as ready.

  • (#963) — Fixed: A workflow rule that asked for work while another rule’s work of the same kind ran now asks again when that work ends, so the card no longer turns Stuck.

  • (#962) — Fixed: An inbox wait line for a deleted document now says “A deleted document” in place of an empty title.

  • (#961) — Added: /admin/status now warns, and names each account, when a GitHub App installation lacks the Workflows permission, because Loupe cannot merge or sync a pull request that changes a workflow file without it.

  • (#960) — Fixed: A fix round that answers a failed agent review with evidence and pushes no commit now starts a new review of the same commit, so the card no longer turns Stuck.

  • (#959) — Changed: the product design session stores each validated prototype in the artifact library, and workers read it from there instead of from a prototype/<card number> branch.

  • (#958) — Added: A stored prototype now runs on its own sub-address of a content domain, set with ARTIFACT_CONTENT_HOST, and loads only from the sites in the new artifacts.allowed_origins setting.

  • (#957) — Fixed: a column that changes its terminal flag, or a column delete that finishes or reopens its cards, now updates their epics and the cards they block at once, and a column that turns terminal closes the inbox items it finishes.

  • (#956) — Fixed: The CLI bridge keeps the closing report of a worker run on disk when Loupe is not reachable, and sends it after the next connect, so the run shows how it ended instead of Lost.

  • (#955) — Fixed: an agent can now remove a card from its parent with card_update and clearParent: true, and clear the default model and effort of analytics_settings_update with clearDefaultModel and clearDefaultEffort, for clients that do not send an empty string.

  • (#954) — Fixed: A worker no longer fails to start when its before fetch loses a race with another git process. The fetch now retries up to three times.

  • (#953) — Fixed: The site-review card type picker and pull request verdict panel now draw their background, border and text colours in the light and dark themes.

  • (#952) — Added: The bridge logs its version in bridge_started, loupe mcp writes its version on stderr at start, and every CLI request sends User-Agent: loupe-cli/<version>, so a stale process is easy to find.

  • (#951) — Fixed: The bridge reports a hub answer that is not an event stream as stream_error, names what arrived, and backs off instead of reconnecting every second.

  • (#951) — Added: The bridge logs event_dropped for an event of an unknown type, once per type, and for a command meant for another bridge.

  • (#950) — Added: The Artifacts library lists the stored artifacts of a project, and a viewer shows each version with a limited preview, download, archive and a list of linked cards.

  • (#949) — Fixed: A decision pick or note that is still waiting to save now goes out when you press Back or Forward on the review page.

  • (#948) — Fixed: A bridge no longer runs again the lapsed work request of a card you made unmanaged. The lapse sweep leaves the claim of a held card alone until the hold ends.

  • (#947) — Added: Workers can list, read and archive stored design artifacts through the artifact_list, artifact_get, artifact_read, artifact_archive and artifact_unarchive MCP tools.

  • (#946) — Fixed: A card created straight into a column now starts the work of that column at once, instead of up to ten minutes later.

  • (#945) — Added: loupe artifact push stores a file or a folder as an artifact, or as a new version of one, and prints its links.

  • (#944) — Fixed: a held card no longer starts work after a bridge restart. The server refuses the claim, the heartbeat leaves out its requests, and a hold cancels its open requests.

  • (#943) — Fixed: The inbox opens a document wait only when a verdict on the document would make a workflow rule fire, so a card in Next with no parent no longer shows a false wait. A tag now counts as approved only when every document with that tag is approved.

  • (#942) — Fixed: The inbox no longer asks you to review the pull request of an epic child that targets its epic branch, because that pull request merges with no approval.

  • (#941) — Added: An artifact opens full screen in its own window, and each version can carry revision notes, which loupe artifact push --notes sets and the viewer lists.

  • (#941) — Added: A card page lists the artifacts that the card links, and the sidebar counts the artifacts of the project.

  • (#941) — Changed: The Artifacts library shows the source, the file count and the first linked card of each artifact, and the viewer bar keeps only the name, full screen, copy link and a menu that holds the other actions.

  • (#940) — Added: Loupe can store design artifacts and their versions for a project, behind the artifacts.enabled flag, which is off by default.

  • (#939) — Added: Account > Connected apps lists each live preview token with its own Revoke, and a card page shows the preview sign-in of its card.

  • (#938) — Changed: The agent review names the rule behind a finding and lists every place it applies. The fix round fixes the rule at each place, adds a test, and reviews its own fix before it pushes.

  • (#937) — Fixed: a card that a blocked or failed worker run paused no longer starts the same work again a second later. The pause now holds until a person, a resumed run or a real change of the card lifts it, and a retry waits for its delay.

  • (#937) — Added: the card history now shows each pause that the workflow ends by itself, with the reason, and card_get_history returns that reason as releaseReason.

  • (#936) — Added: loupe preview-token mint and revoke, and just worktree-up and just worktree-down now mint and revoke the preview token of a worktree.

  • (#935) — Added: The site-review widget signs in with a preview token that a preview page carries in data-preview-token, with no popup.

  • (#934) — Fixed: The workflow sweep no longer delays jobs that a person waits for, because it now runs on a separate async_low queue. A self-hosting operator with a custom worker command must also run php bin/console messenger:consume async_low, or the sweep never runs.

  • (#933) — Fixed: a review run that ends with no review now counts as a failed try, so the workflow asks for the review again instead of leaving the pull request a draft.

  • (#931) — Changed: A workflow evaluation of a card sends far fewer database statements, so the workflow sweep finishes sooner.

  • (#930) — Changed: A wait item in the inbox now says what blocked the card. Its title and body name the reason, the reason tag no longer shows in the text, and a paused card shows one line with the action “Fix the cause, then resume the card”. A blocked worker also quotes the failed command and names the kind of failure.

  • (#929) — Added: A card with an open pull request that nothing moves now shows Stuck on the board after the stuck delay, so a stalled card no longer looks fine.

  • (#928) — Changed: the development php-fpm container runs with Xdebug off, which makes each local page about 40% faster, and the database container now restarts with Docker.

  • (#927) — Added: The server can issue, list the use of and revoke a preview token, a 14-day widget sign-in for a preview site, through POST and DELETE /api/projects/{handle}/preview-tokens.

  • (#926) — Changed: The agent review no longer adds an inbox to-do for every spec finding. Only a spec finding that needs a decision reaches you, as one question from the fix worker.

  • (#925) — Fixed: A Codex worker with no permission mode now has network access, and its Loupe tools now know its run, so a Codex review can read the pull request and submit its result.

  • (#924) — Changed: SENTRY_TRACES_SAMPLE_RATE defaults to 0.25 instead of 1.0, and Sentry traces 1 in 20 card evaluations.

  • (#924) — Removed: Sentry no longer receives savepoint spans.

  • (#923) — Changed: a pull request whose change stays the same after a sync of its base keeps its agent review, and Loupe posts the check on the new head with no new review run.

  • (#922) — Fixed: The epic preview now refreshes when the head of the epic pull request moves, after a fix round or a sync, and no longer only after a child merge.

  • (#921) — Fixed: A bridge worker on a Codex account now starts its work, because the bridge sends Codex the strict output schema that the OpenAI API requires.

  • (#920) — Added: An implementation worker that has no code to build ends its run with the reason nothing-to-build or delivered-without-code, and the Lifecycle rule of the same name moves the card to the terminal column with no person in the loop.

  • (#919) — Added: The agent review also checks each pull request against the approved designs, and lists the gaps first on its check.

  • (#919) — Added: A review with a gap from the design creates a Loupe document and an inbox to-do for it.

  • (#918) — Changed: The Lifecycle workflow now starts the agent review of a pull request only after the implement, fix, sync or rebase work on its card ends.

  • (#917) — Changed: The Loupe plugin skills read pull request state in words that every forge shares, and a repository can name its forge in the lifecycle profile.

  • (#916) — Added: a product design session now keeps a temporary readable copy of an artifact prototype on an unmerged prototype/<card number> branch, which the card teardown deletes, a tech design links that copy and never an artifact alone, and the stage skills say which tool reads each prototype link.

  • (#915) — Fixed: loupe mcp waits and tries again when Loupe answers a rate limit or a short outage, so the agent keeps its Loupe tools.

  • (#914) — Removed: the stage skills no longer name a codex MCP unavailable refusal, because the gate runs no Codex review. The Loupe plugin is now 0.25.0.

  • (#913) — Removed: The Automation tab and the automation_settings_update tool keep only the switch that runs the workflow of the board. The rules of the workflow decide every write, and the merge strategy, fix strategy, loop limit and epic branch pattern settings are gone.

  • (#912) — Changed: A Lifecycle project now posts the fix-run comment and the stale-approval comment through two workflow rules, with no Automation switch, and the fix-run comment shows its round out of the limit of the fix rule.

  • (#911) — Changed: this repository drops the Codex review from its pre-push gate and opens each pull request as a draft for the agent review. The Lifecycle implement check now reads “A draft pull request that a separate agent reviews after the push”, and the landing page lists the agent review.

  • (#910) — Changed: The update-behind rule now updates each approved pull request that is behind its base at once, and Loupe no longer syncs one pull request of a project at a time.

  • (#910) — Removed: The card page no longer shows a sync status line under a linked pull request.

  • (#909) — Changed: The epic branch now comes from the epicBranch value of the workflow template, and the Automation tab and the automation_settings_update tool lose their epic branch pattern; each project keeps its own pattern through a migration.

  • (#908) — Changed: the Lifecycle workflow now asks an agent to review each pull request and waits for a passed review before a pull request leaves draft or merges, and a failed review asks for a fix with the reason agent-review, up to 10 times in a row. The agentReviewFailingSeverities value of the template names the severities that fail a review.

  • (#906) — Added: card_get returns the latest agent review of each pull request, and a loupe-stage-review skill lets a worker review a pull request and send its findings.

  • (#906) — Changed: The fix round reads the findings of the agent review of the head commit, whatever started the round.

  • (#905) — Changed: A merge, base change, branch sync, epic draft or close, epic pull request, widget verdict review and site-review check now follow their workflow rule alone, so a project that had the matching Automation switch off starts that write; a project with no GitHub App installation still gets bridge work.

  • (#904) — Changed: A review that a site-review verdict posts on GitHub now opens with a line that names the Loupe site review and links to the notes on the card.

  • (#902) — Added: a review agent can submit its findings with the agent_review_submit MCP tool, and Loupe posts them as a loupe/agent-review check with one note beside each line for each review that the workflow asks for.

  • (#900) — Changed: In the site-review widget, a Request changes or Comment verdict can go with no message when the card has an open note, because the notes become the review body.

  • (#899) — Added: The Metrics tab charts the time of each bucket, and the Time buckets tab shows the total, the median per run, the runs with data and the share of each bucket over a range you pick.

  • (#898) — Fixed: The “Loupe site review” check of a pull request now updates at once for every card on it when a card links or unlinks the pull request or is deleted. The check turns neutral when the last card leaves.

  • (#897) — Changed: just arkitect fails when a class of the workflow engine outside Workflow\Contract imports Board, Bridge, Forge, GitHub or Review.

  • (#896) — Changed: Workflow conditions take new names that put every card fact under card.: card.blocker.open, card.parent.exists, card.children.exist, card.children.finished, card.children.merged_into_epic_branch, card.document.linked, card.document.approved, card.document.changes_requested, card.parent.document.approved, card.parent.in_slot, card.pr.linked, card.pr.all_finished_one_merged, card.run.work_active, card.run.worker_active, card.run.last_refusal, card.parent.run.active and card.discovery.requested. A migration writes the shipped Simple and Lifecycle templates into every project, so an edited stored template loses its edits.

  • (#895) — Changed: Board now runs the request, forge-write, link-document, detach and move actions of a workflow rule. Rules behave as before.

  • (#894) — Changed: Workflow actions now declare themselves through a shared contract, so a module can add an action. Rules and screens behave as before.

  • (#893) — Changed: The workflow engine now reads its card, pull request and worker facts from Board and Bridge, and the new console command app:workflow:count-legacy-fingerprints counts the rule states that still hold the old fingerprint. Rules fire at the same moments as before.

  • (#891) — Added: card_get, card_list, card_search and the other card tools report the state of a card: what it needs now on the board, why, and since when.

  • (#888) — Changed: Each board tile shows one state mark, Stuck, Needs you, Working or Waiting, with a tooltip that gives the reason and a link to the card, in place of the Checks failed, Conflict and Paused chips and the run warning.

  • (#887) — Added: The board automation settings have a stuck delay, and a ready pull request that nothing merges turns its card Stuck on an open board when the delay ends.

  • (#886) — Changed: The landing page review mock shows the new review layout: Finish review in the top bar, the corner toolbar with the Decisions panel, and a comment thread open over its passage.

  • (#885) — Added: The card drawer shows a Status box at the top of the Overview tab. It names the state of the card and how long it has held, why, since when and what clears it, and lists the other states that apply.

  • (#881) — Changed: the Comments panel of the review page lists each thread as a short row, and a thread opens as a popover over its passage. The button for a comment on the whole document moves into the panel.

  • (#880) — Added: card_create and card_update take childDesign, so the agent that files a child of an epic says whether the epic tech design covers it, and the owner is asked only for a card made by hand.

  • (#879) — Changed: Stage workers fix a problem they find in their own branch, and stop opening follow-up cards under the epic for it.

  • (#878) — Changed: Inbox wait items now say in plain words why Loupe opened them, link to the page that closes them, show the whole worker summary, and explain what Dismiss does.

  • (#877) — Fixed: The “Loupe site review” check of a pull request that two cards link now counts the open notes of both cards, so it no longer passes while a note is open.

  • (#876) — Fixed: An older app version no longer refuses a stored workflow that names an action it does not know during a deploy. It keeps the rule, never fires it, and shows it as unknown.

  • (#875) — Fixed: A widget verdict on a pull request that Loupe stored before it knew the author no longer posts a review that GitHub refuses on the author’s own pull request.

  • (#874) — Fixed: A verdict sent again after a lost reply from the site-review widget no longer stores a second verdict or posts the review twice.

  • (#873) — Changed: the version diff is now a mode of the review page, with a compare bar, read-only decisions, change counts per section in the Outline, and panels beside the side by side columns.

  • (#871) — Added: Loupe records the time a linked pull request turns ready to merge.

  • (#870) — Added: The document review page has a “Highlight new text” switch that marks the passages the current version added since the previous one.

  • (#869) — Added: The e2e flake hunt workflow runs chosen e2e specs many times on CI and prints how often each test fails. A failed e2e leg now uploads the web server log with the time of each request.

  • (#868) — Fixed: The site review check on a pull request now refreshes when a reviewer swaps one note for another and the note count stays the same.

  • (#866) — Fixed: Four site-review widget e2e tests no longer fail when the CI runner is slow, because they wait for the widget to settle before they act.

  • (#864) — Added: The site-review widget shows Approve, Request changes and Comment buttons on a page that locks a card with an open GitHub pull request, with a confirm panel, a GitHub connect step and the result of the last verdict.

  • (#863) — Changed: The e2e job on CI compiles the assets, stubs the Mercure hub in specs that need no live update, and turns off profiler data with PROFILER_COLLECT=0.

  • (#862) — Changed: The landing try-it demo e2e spec now runs in the project that runs one test at a time, so its global flag no longer affects other specs.

  • (#861) — Added: The e2e flake hunt workflow runs chosen e2e specs many times on CI and prints how often each test fails, and a failed e2e leg now uploads the web server log with the time of each request.

  • (#860) — Changed: The document writing rules now ask that each open decision, and its recommendation, make sense without the rest of the document.

  • (#859) — Changed: A corner toolbar on the review page switches the Decisions, Comments and Outline panels on and off, and the page remembers the panels you left open.

  • (#859) — Changed: The Decisions panel shows each decision with its tag, its answer and its note, and the Details tab becomes a ”⋯” menu of linked cards, linked documents and version links.

  • (#858) — Changed: The bridge account check for Codex now fails when the loupe MCP server is missing, wrong or lacks tool approval, and the bridge checks every declared account, showing the ones no rule uses as unused.

  • (#857) — Changed: Every form field in the app now comes from shared form components, and just gamache blocks a hand-written one.

  • (#856) — Changed: The dialog, tabs, pagination and tooltip now come from shared components, and just gamache blocks a hand-written one.

  • (#855) — Fixed: A resume of a worker run, from a closed inbox ask, the runs page or worker_run_resume, now ends the workflow pause of its card and closes the pause item in the inbox.

  • (#854) — Added: bin/console app:design-system:export writes the design system in the layout of the Claude Design project, and the loupe-design-rebuild skill uploads it.

  • (#853) — Fixed: A child of an epic that links only the epic tech design now builds its card body against that design, instead of stopping for want of a design of its own.

  • (#852) — Changed: The flash message, empty state, badge, tag and status chip now come from shared components, and just gamache blocks a hand-written one.

  • (#851) — Added: Two workflow rules now turn a widget verdict into a GitHub review under the reviewer’s own account, and keep a “Loupe site review” check on each open pull request. Each write stays off until its board setting is on.

  • (#850) — Changed: The site-review widget, readiness proposals and note delete now follow the card types of the project template, and the widget shows a type selector when the template has two or more types that can have children.

  • (#849) — Changed: Every button in the app now comes from one shared component, and just gamache blocks a hand-written one.

  • (#848) — Changed: A bridge with appPrompts: true now runs an analysis with a prompt that ships with Loupe, and needs no work: analysis: entry.

  • (#847) — Added: The widget verdict panel shows whether the reviewer has connected GitHub, and marks pull requests the reviewer opened. A new GitHub connection also retries the verdicts that waited for it.

  • (#846) — Changed: The review page follows the validated design: a larger title, a quiet byline with Revise and the ”⋯” menu, icon buttons over tinted panels, lighter decision blocks and tables, a margin count beside each line that holds a thread, and a one-row compare bar that compares a new pair of versions as soon as you pick it.

  • (#846) — Removed: The Document and History tabs and the thread counts leave the top of the review page. The ”⋯” menu leads to the version history and the comparison, and the Comments panel holds the counts.

  • (#846) — Changed: The review page aligns the document to the left beside wider side panels. The verdict detail opens from the verdict in the top bar, the diff views sit behind a settings button, and a card that waits on the review shows as an icon in the byline.

  • (#845) — Added: A table between <!-- options --> and <!-- /options --> shows as option blocks on the review page.

  • (#845) — Changed: A recommended option shows one to three stars, and “Clear choice” sits beside “Pick one”.

  • (#844) — Changed: emails now use the current app colours, and a test keeps the email stylesheet equal to the design tokens.

  • (#843) — Changed: The site-review widget uses the design-system token names and the app accent colour.

  • (#842) — Changed: The document review page is now one centred text column. Finish review and the verdict, with Change verdict and Undo, sit in the top bar, and a line under the title names the cards that wait on the review.

  • (#841) — Removed: Section approvals, including the approval button beside each heading, the approval counts, and the sections list in document_get_review.

  • (#840) — Changed: loupe bridge reload now applies the server flags, such as host sampling and the heartbeat interval, so a flag change no longer waits for a restart or a reconnect.

  • (#839) — Added: a stage worker on a Codex account follows its own Codex harness adapter, and the skills and MCP tools name the session id of every harness.

  • (#836) — Added: just gamache reports each template that writes the markup of a design system component by hand, as a warning until that component is enforced.

  • (#835) — Changed: A new child of an epic now waits in Next instead of the Backlog, the Backlog parks a child, and a child starts only while its epic is in Implementation.

  • (#834) — Added: a design tokens stylesheet with radius, spacing and motion groups, and a dev-only /styleguide page that draws every token.

  • (#833) — Added: A Codex run reports its tool calls, its shell signatures, its tool, idle and sub-agent time, its peak context and the tokens of its sub-agents, read from the Codex session files.

  • (#833) — Added: The Metrics page groups the runs by harness and by account.

  • (#833) — Changed: Each tool call of a run carries a kind (shell, subagent or tool), and the sub-agent time reads the kind in place of the tool names Agent and Task.

  • (#832) — Added: Loupe can post a review as the GitHub account a user connected, and report a check run as the App. The GitHub App needs Checks write for the check run.

  • (#831) — Added: a reviewer can send a widget verdict that Board stores on the card, with two opt-ins on the automation settings that stay off.

  • (#830) — Fixed: The implementation and tech design stage workers now read the saved decision answers of a design, so an answer counts even when the design text still calls the decision open.

  • (#829) — Added: Connected apps now lets you connect a GitHub account, and disconnect it again.

  • (#828) — Added: The bridge prices Codex runs on OpenRouter models when rules.yaml holds openRouterPrices: true.

  • (#827) — Added: an interactive work entry can run on a Codex account, and opens Codex in a terminal.

  • (#824) — Changed: The fix round now reads the pending site-review notes of a card, fixes them, and marks them addressed.

  • (#823) — Added: A bridge account with harness: codex runs workers with codex exec, with codexHome and profile keys, and prices OpenAI models.

  • (#822) — Added: The bridge checks each account of rules.yaml at start and on reload, turns off only the entries of a failing account, and the Agents page shows each account with its state and reason.

  • (#822) — Added: loupe status checks each account of the rule file, and fails when one is not ready.

  • (#821) — Added: rules.yaml names accounts, and each rule, experiment variant and the defaults pick one, with its own Claude Code config folder, model, permissions and environment file.

  • (#821) — Added: The permission levels read-only, workspace and full set what a worker may do, and the bridge migrates an old rules.yaml to an account on start.

  • (#821) — Changed: A person’s resume of a worker run uses the account the run started on, and the bridge refuses it when that account is gone.

  • (#820) — Added: A Lifecycle child of an epic that links no approved tech design now asks the owner in the inbox whether to link the epic design, send the child to Tech design, or remove it from the epic.

  • (#819) — Fixed: the GitHub App setup docs list the Workflows permission, which Loupe needs to merge a pull request that changes a workflow file.

  • (#817) — Changed: The breakdown now links the tech design of the epic to each matched child and writes the entry into its body. It no longer moves children to Implementation.

  • (#816) — Added: A card records its source, and a card from the site review widget shows a site review badge and keeps the default card type.

  • (#813) — Changed: In the Lifecycle workflow, a child of an epic starts only when it links an approved tech design, and the requested work of an epic counts as work of the epic.

  • (#812) — Changed: Card types now come from the workflow template on the board. The board, the card forms and the MCP tools read the declared types and their capabilities. An undeclared type is refused with the list of declared ones, and board_columns returns the types.

  • (#810) — Added: The workflow template declares the card types of a board, with a label, a colour and two capabilities, and the Workflow page lists them.

  • (#808) — Fixed: An interactive run that starts and ends in one second now reports the usage of its replies, and a longer run keeps the replies of its first second.

  • (#806) — Changed: CI runs the e2e suite on eight legs instead of three, and splits the chromium tests per test over six of them.

  • (#805) — Changed: CI pulls a pre-built php-fpm image from the GitHub registry instead of building it in every Docker job.

  • (#804) — Added: An owner can group the tool time of worker runs into buckets with rules on the new Time buckets tab, start a Time analysis, and read a bucket with metric_query as bucket-time:<name>.

  • (#803) — Added: a bridge rule declares the metrics its experiment compares, and an agent reads an experiment and recommends a variant or more runs.

  • (#802) — Added: a bridge can sample its host (CPU, memory, swap, battery and power source) behind the flag bridge.host_sampling_enabled, each worker run gets its mean CPU, peak memory and swap, concurrent runs and battery state, the MCP tool bridge_host_samples reads the samples, and the Reports tab offers a Host analysis.

  • (#801) — Fixed: A board card no longer shows an old run warning, such as Failed, once a newer run of the card starts, and an open board updates at once.

  • (#800) — Changed: A fix round now recovers a worker branch that diverged from its pull request branch, instead of pausing the card.

  • (#799) — Fixed: The Lifecycle workflow no longer merges a child pull request into its epic branch while a worker run of the epic is open. The merge goes ahead when the run ends.

  • (#797) — Fixed: A pull request’s fix limit now starts again while the pull request is healthy, so routine conflict fixes no longer pause the card.

  • (#795) — Added: The workflow_get MCP tool and the loupe-discovery plugin skill. Each request of a workflow template now names what its work needs from the project, and discovery checks the repository against that list.

  • (#794) — Added: The new Reports tab under Analytics starts a cost analysis that a bridge worker runs with the loupe-analysis skill. The report is a Loupe document, and each proposal in it becomes a Backlog card when the owner clicks Create.

  • (#794) — Added: A work request can name the model and the effort of its run, and the bridge uses them over its work entry. The MCP tools analysis_get, analysis_report, analytics_settings_get and analytics_settings_update read and finish an analysis and change the analysis defaults of a project.

  • (#792) — Added: the readiness_report_submit MCP tool stores the report of a discovery run as a document. When you approve it, each proposal you ticked becomes a card in Next.

  • (#791) — Added: each worker run records its harness, account, model and harness session id, and the Runs page and worker_run_list filter on harness, account and model.

  • (#789) — Added: When the retries of a workflow rule run out, the Lifecycle workflow starts one repair worker that fixes the cause, gives the rule one last try, and pauses the card only when that fails.

  • (#788) — Changed: Lifecycle retries a failed worker run only when it failed or timed out, three times, after 2, 3 and 5 minutes, and the workflow settings page shows these delays.

  • (#787) — Added: the readiness guide and the discovery_start MCP tool start a read-only discovery run on a bridge, and the Repository row shows whether it runs or failed. readiness_get reads the guide rows through the MCP. A bridge needs a CLI with app prompts and appPrompts: true in its rules.yaml.

  • (#785) — Added: The workflow retries a work request that a bridge refuses, such as a failed worker run, then pauses the card when the retries run out, and the board marks a card whose latest run failed.

  • (#784) — Added: An agent can change the project name, description, domain and search language, the allowed widget origins, the Inbox wait switches and the readiness guide, through the MCP tools project_update, project_origins_set, inbox_settings_update and readiness_guide_set.

  • (#783) — Added: the automation_settings_update MCP tool sets “Open the epic pull request” and the epic branch pattern, and refuses a pattern that the Automation page refuses.

  • (#782) — Added: Each worker run now records its peak context, the largest context the main session held, in tokens. worker_run_list, worker_run_get and the data exports show it as peakContextTokens.

  • (#781) — Changed: In the Lifecycle workflow, a person can now move a card from Implementation back to Tech design, in new and existing projects.

  • (#780) — Fixed: In the Lifecycle workflow, a child of an epic now waits in the Backlog while any worker run of its epic is open, not only a breakdown, and a merged epic waits for its open runs before it moves to done.

  • (#780) — Added: A manual move of a workflow template can name by: parent-run, so only an open worker run of the card’s parent epic may make it. The Workflow settings page shows who may make each move.

  • (#780) — Fixed: A confirmation message no longer disappears when you act in the card drawer while the drawer loads a card in the background.

  • (#779) — Added: a guided page sets up a separate GitHub account for agents, loupe agent-account set gives its token to bridge workers, and the readiness guide shows the account as done when a running bridge pushes as it.

  • (#778) — Fixed: When a held card is released, each workflow rule that matches it now fires, with a fresh work budget and a new timeout for its open work requests, so a hold and a release restart a stuck card.

  • (#777) — Fixed: Loupe now asks for the usage of an interactive session when a person closes its run, or when its card moves or is deleted, not only when the session closes the run itself.

  • (#774) — Added: The bridge records the tool calls of each worker run, and each run gets tool time, model time, idle gaps and subagent time, which the new MCP tool worker_run_tool_calls and the run metrics show.

  • (#774) — Changed: The bridge starts each worker with --verbose --output-format stream-json, and still reads the output of a run that an older bridge started.

  • (#773) — Fixed: The first child of an epic now merges into the epic branch before the epic pull request exists, because a board setting names the epic branch pattern.

  • (#773) — Added: The board setting “Open the epic pull request” lets Loupe open the epic pull request as a draft after the first child merge, and link it to the epic.

  • (#773) — Added: An epic-preview work request refreshes the epic preview after each child merge, also when Loupe merges the child itself.

  • (#772) — Added: the Workshop shows the project owner a “Ready for agents” checklist, and project settings have an Agent readiness tab that shows a hidden checklist again.

  • (#771) — Fixed: A workflow rule now acts on each open pull request of a card, from the bottom of a stack up, so an older red pull request also gets its fix.

  • (#770) — Fixed: a child of an epic now waits in the Backlog while the breakdown of its epic runs, and moves to Implementation when the breakdown ends and it has no open blocker.

  • (#769) — Added: An agent can add, rename, reorder and delete board columns, and change the Automation settings, through the MCP tools column_create, column_update, column_reorder, column_delete and automation_settings_update.

  • (#768) — Added: A bridge with appPrompts: true in rules.yaml runs a prompt that Loupe ships with a work request, for a kind that its work: map does not hold. Update the CLI to use it.

  • (#767) — Added: An agent can create a document as a draft with document_create, and send it to review with the new document_publish tool. A Publish button sends a draft to review from its review page.

  • (#767) — Changed: A revise keeps a draft a draft, and the stage workers publish their documents only at the end of their run.

  • (#766) — Added: an Analytics section in the project sidebar holds a Metrics page and the Experiments pages.

  • (#766) — Added: the Metrics page charts any metric per run or per finished card, with a statistic, a grouping, a range and a bucket, and lists the rows behind the chart.

  • (#766) — Added: the worker run drawer shows the cost, tokens, model and duration of the run.

  • (#766) — Removed: the Cost and Experiments tabs of Activity. Their old addresses redirect to the Analytics pages.

  • (#765) — Removed: the card page no longer shows the line about what the board automation did last, and the MCP card payload no longer carries the automation key. The History tab still records each sync of a pull request branch.

  • (#764) — Changed: CI no longer runs the fan-in e2e job, and the three shard checks e2e-chromium, e2e-chromium-2 and e2e-rest are the required e2e checks.

  • (#763) — Added: an interactive Claude Code session that calls card_run_close adds the estimated usage of its run to the card cost, read from the transcript by an updated bridge.

  • (#762) — Changed: product designs and tech designs now explain each decision in product terms first, mark only estimates, and keep the code of each option in a “How each option works” list of the tech design.

  • (#762) — Security: source-map-js moves from 1.2.1 to 1.2.2, and postcss-selector-parser under @tailwindcss/typography moves from 6.0.10 to 7.1.6, in the development tooling. This fixes two denial-of-service advisories: GHSA-68fv-2mgg-jv7q and GHSA-rj75-hqrm-r3gf.

  • (#761) — Added: each worker run keeps a metrics row with its cost, tokens, model, duration and outcome after the retention purge deletes the run.

  • (#761) — Added: the MCP tools metric_list and metric_query read one metric over time, by run or by finished card, grouped by stage, model, variant, card type or bridge.

  • (#761) — Added: worker_run_list and worker_run_get show the usage, model, experiment, variant and metrics of each run.

  • (#760) — Removed: the card_id column of work requests, worker runs and run usage. The subject is now their only reference.

  • (#759) — Changed: Work requests, worker runs and the bridge protocol name a subject type and id instead of a card id. Update every bridge right after the server deploy, because an outdated bridge cannot claim work.

  • (#757) — Added: a person can end a workflow pause after its retries, work limit or work timeout ran out with “Retry now” on the card page or the card_pause_release MCP tool, and the paused rule runs again with a fresh budget.

  • (#756) — Removed: The board.enabled flag is gone, so the board is always on. An instance that had the board off has it on after the upgrade, and the bridge CLI no longer has a board-off error.

  • (#755) — Fixed: An epic that already has children gets its breakdown when it enters Implementation, and waits there until the breakdown ends.

  • (#755) — Changed: The breakdown matches an existing child to its entry by judgement rather than by exact title, and asks the owner before it writes when a match is unsure.

  • (#754) — Added: each open decision in a product design or a tech design now shows a worked example of one real case for each option, between its pros and cons table and its decision fence.

  • (#753) — Fixed: A card that went through Product design no longer stalls in Tech design. The stage documents now carry the tags product-design and tech-design, and an upgrade retags the existing documents.

  • (#752) — Fixed: Lifecycle no longer asks for a second design while a design document of the card is in review, after a revision or an undo.

  • (#752) — Added: a Change verdict button on the review page gives another verdict in one step.

  • (#752) — Added: the workflow condition card.document tests for a document with a tag, and optionally a status.

  • (#751) — Changed: A reviewer can request changes on a document with no review note when the version has an open comment.

  • (#750) — Added: a design document gives a short meaning and the source at the first mention of an outside ID, such as a rule ID of a skill, so a reviewer can read it without the source open.

  • (#749) — Changed: /loupe:product-design recommends one Claude Design session at the first visual choice, follows the Claude Design MCP guide to run it, and links a recap of the picks in the product document.

  • (#748) — Added: A work request carries the number, link and head commit of the card’s pull request, the reason for a fix and the document a revision works on, and a work map entry fills them through {pullRequestNumber}, {pullRequestUrl}, {headSha}, {reason} and {documentId}.

  • (#748) — Added: A workflow request rule takes a document: { tag: …, status: … } parameter that names the one linked document with that tag and status, and the Lifecycle revision rules use it.

  • (#747) — Added: the tech design stage writes a deploy notes document when a feature changes how production deploys, and project-deploy reads the notes of every card in a release through bin/agents/release-cards.

  • (#746) — Added: the Workflow panel says why a rule waits when it cannot read its facts, and the Workflow page groups the conditions of each rule by module and marks a condition that no longer exists.

  • (#745) — Added: ADR 0003 says that a refactor for a new requirement replaces the old shape of any system, data, API, bridge protocol or code path, and deletes its legacy fields and compatibility layers in the same work.

  • (#744) — Added: a module can give the workflow engine its own facts, and a rule that cannot read them waits while the other rules of the card still run.

  • (#743) — Changed: The interactive product design session asks every open decision in the chat, and tech designs gain an Architecture section, fuller Decided entries, diagram types by subject and code sketches.

  • (#741) — Changed: A module can now import the workflow condition and fact classes from App\Module\Workflow\Contract, which also declares FactProvider and the CardEvaluations port.

  • (#740) — Changed: just phpunit runs the tests through ParaTest on 4 processes, each with its own test database. Set PHPUNIT_PROCESSES to change the count.

  • (#739) — Changed: Every board now follows a workflow template, Lifecycle or Simple, and the bridge only runs the work that the workflow asks for. A bridge config with rules: is refused, so update the CLI and move each rule to the work: map.

  • (#738) — Fixed: The agent gate hooks no longer refuse a command whose here-document or quoted text only mentions just ci, just phpunit or just e2e, and they still refuse a shell wrapper such as bash -c "just ci".

  • (#737) — Removed: a card whose pull requests all close with none merged no longer goes back to the Backlog. It stays in its column.

  • (#735) — Fixed: A card in a terminal column stays there when each of its pull requests closes without a merge, in the Lifecycle and the Simple workflow templates.

  • (#734) — Fixed: A changes-requested review now counts in the workflow only while it covers the head commit, so each new change request after a fix push opens a new fix round.

  • (#732) — Added: A new project picks the Lifecycle or the Simple workflow template at setup, and a read-only Workflow page shows the template a project runs.

  • (#731) — Changed: “Pause agents” on a card is now “Make unmanaged”, and the board tile marks an unmanaged or paused card.

  • (#731) — Added: A Workflow panel on the card page shows a workflow pause and its release condition, and, once the workflow engine runs, the slot, what the card waits for, the next action and the last refusal.

  • (#730) — Changed: a coding agent can no longer run the full local gate, just ci, or the whole PHPUnit suite. A hook refuses both, and CI’s required checks are the full gate. The local gate is now just cs, the static checks, and PHPUnit on the tests for what changed.

  • (#729) — Changed: the board page loads the list view only when you pick List, and each terminal column now shows 3 days of finished cards by default, set on the columns settings page.

  • (#728) — Added: the Sentry browser SDK traces each Turbo form submit, Turbo visit and live board, card or decision update, with the tab age and the heap size on each span.

  • (#726) — Added: A bridge shows a name in place of its id. The name comes from name: in rules.yaml, and the default is the host name.

  • (#725) — Added: an opt-in Sentry browser SDK. Set SENTRY_BROWSER_DSN to send page loads, Web Vitals and scrubbed JavaScript errors, with page loads linked to their PHP trace.

  • (#724) — Added: Loupe now has a workflow engine that moves cards, asks bridges for work, retries a refused step a bounded number of times and pauses the card after the last one. It stays switched off until every project moves to it.

  • (#724) — Added: The inbox settings have a “Workflow paused the card” switch, for the wait that opens when the workflow pauses a card.

  • (#723) — Added: the bridge teardown removes the epic preview when the epic card reaches Done.

  • (#723) — Fixed: the merge stage refreshes an epic preview under a lock, skips the preview of a finished epic, and marks a carried preview link it cannot mint as “not minted”.

  • (#722) — Added: The bridge reads a work: map in its rule file, and claims, runs and settles the work requests that the app offers.

  • (#721) — Fixed: a pull request into an epic branch waits for the required checks of main, so it no longer reads green before CI ends.

  • (#721) — Changed: the epic pull request syncs by a merge of main, and a fix round on it pushes to epic/<n> directly.

  • (#720) — Added: the Lifecycle and Simple workflow templates, and the tables that store a project’s workflow. No project uses them yet.

  • (#719) — Added: the card_hold and card_release MCP tools pause the agents on a card and let them run again, by card id or number.

  • (#717) — Added: the board automation settings have two new opt-ins, off by default, that let the workflow merge a pull request and change its base branch.

  • (#716) — Added: the bridge API has work requests: a bridge claims one with a lease and a token, renews the lease in its heartbeat, and posts the result.

  • (#715) — Changed: The app publishes outbox events to Mercure on the project owner topic only, and no longer on the per-project topic that no client could subscribe to.

  • (#713) — Added: Each worker run reports a reason code, such as stacked or approval-stale, and the worker run drawer shows it.

  • (#712) — Changed: a stop ends one run and no longer pauses the card, and a resume of a run on a paused card is refused.

  • (#712) — Added: Pause agents and Let agents run on the card page, which hold every worker off a card and end that hold.

  • (#712) — Changed: the deploy ends every hold that a stop wrote, so a card that a stop paused starts its queued runs.

  • (#711) — Added: after each child merge into an epic branch, the merge stage refreshes the epic preview and copies the child’s preview links, each with its check result, into the epic pull request.

  • (#710) — Added: under a profile with an Epics section, the stage skills push an epic/<n> branch at the breakdown, build each child on it, merge a child into it with no approval, and open the draft epic pull request after the first child merge.

  • (#709) — Changed: a stop in the bridge ends one run and no longer holds the card, once the server reports the cards it holds.

  • (#708) — Changed: The Loupe plugin stage skills work in the folder the worker starts in, and no longer create or bind a worktree. Add a before command to the implementation and pull request fix rules, and a teardown command rule on Done, before the bridge loads plugin 0.10.0.

  • (#707) — Added: A stage worker that refuses a pull request with not ready or blocked: now comments the reason and the next step there, once per head and reason.

  • (#707) — Added: A board automation setting, off by default, makes Loupe comment once per head when new commits follow a pull request’s approval.

  • (#706) — Added: the setup prompt asks whether each bridge worker gets its own folder, and adds a before command and a teardown rule to your worker rules when it does.

  • (#705) — Fixed: the working-with-prs skill reads the main ruleset by name, so a second ruleset no longer makes it report the wrong required checks, and it describes the Epics ruleset on epic/* branches.

  • (#702) — Added: A bridge rule with action: command runs a command with no agent, such as a teardown when a card reaches Done. It waits for the runs of its card and takes no worker slot.

  • (#702) — Added: The runs page, the card and the workshop show a Command tag on a command run, with no session and no cost.

  • (#702) — Added: A failed command run has a Run again button, which asks the bridge to run the command again as a new run.

  • (#701) — Changed: Loupe sends pull_request.ready_to_merge only when an approval, if there is one, covers the head, and the card shows Approval outdated while it does not.

  • (#700) — Added: An epic that links an open pull request waits in In review after its last child finishes, and goes back to Implementation when it gains an open child.

  • (#700) — Added: The app marks an epic pull request ready when the epic enters In review, converts it to draft when the epic goes back to Implementation, and closes it when a person moves the epic to the Backlog.

  • (#700) — Fixed: Green checks no longer move a card with an open child to In review.

  • (#699) — Added: when Loupe syncs behind pull requests, the Rules page, the board banner and an inbox notice flag each bridge rule on pull_request.behind that races the sync.

  • (#698) — Added: The Activity page has an Experiments tab that compares the variants of a bridge experiment on merge rate, fix rounds, cost, tokens and time to merge, each with a likely range, and lists the cards of each variant.

  • (#697) — Added: The card page and the card drawer update live when the card moves, a pull request changes, the automation acts or a worker run changes, and they keep the open tab and any unsaved input.

  • (#696) — Added: an approved pull request that gets new commits after the approval waits in the inbox again, while a merge from the base keeps the approval.

  • (#696) — Changed: the merge stage of the Loupe plugin counts a conflict resolution from the base as covered by the approval.

  • (#695) — Added: A project can let Loupe sync the next approved pull request that is behind its base, one at a time, and the card shows why a pull request waits.

  • (#694) — Added: a bridge worker rule can set before, a command that runs ahead of the worker and prints the folder the worker starts in. The run shows the new state preparing while the command runs, and a resumed conversation starts in the folder where it began.

  • (#693) — Added: Admins can make single-use beta invite links at /admin/beta-invites; a link skips the sign-up cap and grants a comp that never expires, and the list can copy an unused link again.

  • (#693) — Fixed: A GitHub or Google sign-up at the registration cap now honours a waitlist invite whose address matches the provider email.

  • (#692) — Added: the card page and drawer have a History tab that lists who created and moved the card and why, each automation action and each finished agent run.

  • (#692) — Changed: the card Overview shows only the agent runs in progress and the usage total. Finished runs move to History, and an ended run resumes from Run history.

  • (#691) — Added: The bridge keeps a cursor file and, after each connect, runs the events it missed while it was stopped or reconnecting, except a card move whose card has since left the column.

  • (#690) — Added: six MCP tools let an agent list worker runs and bridges, read the whole series of a run, and stop, resume or cancel runs, with a resume of up to 50 runs in one call.

  • (#690) — Added: the loupe-workers plugin skill tells an agent how to recover workers after a usage limit or a network outage stopped them.

  • (#689) — Added: A card whose pull requests all close with none merged moves back to the Backlog about ten minutes after the last close.

  • (#688) — Added: ADR 0002 says that a stage skill works in the directory it starts in, and that bridge rules set up and remove that directory.

  • (#687) — Added: A card move that an agent makes through the MCP now names its worker run in the card history, because loupe mcp sends the claude session in the X-Loupe-Session header.

  • (#686) — Added: Loupe records the approval, the default branch and the head parents of each GitHub pull request.

  • (#685) — Fixed: The inbox shows a pull request that is behind its base branch as waiting for review, when its checks passed and it has no approval.

  • (#684) — Added: Every instance serves a CLI install script at /install.sh, so curl -fsSL <instance>/install.sh | sh installs the loupe CLI on macOS and Linux, and brew install ubermuda/tap/loupe installs it with Homebrew.

  • (#684) — Changed: Automatic CLI updates are off by default for a new install. Turn them on with loupe update auto on. A bridge that updates itself into this release writes autoUpdate: true once and keeps updating.

  • (#684) — Added: The agents page shows “Update available” when a bridge has automatic updates off and a newer CLI release fits the server. A click on it shows the upgrade command.

  • (#684) — Added: The Connect page shows the install step before loupe login.

  • (#683) — Added: The card_get_history MCP tool reads the history of one card, newest first, one page at a time.

  • (#682) — Changed: An approved card with an open blocking card stays in its stage column, and it moves on when its last blocker finishes. The card page and card_get (heldBy) name the open blockers.

  • (#681) — Changed: the Backlog page sorts by a click on its Type, Epic and Added column headers, and it shows the newest cards first by default.

  • (#681) — Removed: the Sort menu and drag ranking on the Backlog page.

  • (#680) — Added: the Connect page and the first-run wizard give a short prompt that makes a coding agent set up Loupe from the steps at /setup.md.

  • (#680) — Added: loupe status calls project_current through the MCP server and says whether the setup works.

  • (#679) — Fixed: the implementation worker builds a child card with no Breakdown entry from its own approved tech design, instead of blocking with “no breakdown item”.

  • (#678) — Added: The board now records the history of each card: its creation, each move to another column with its cause, and each automation action.

  • (#677) — Changed: Getting started in the docs now takes a person with an account from the CLI install to a first reviewed document. The install pages move to Operating, under operating/install/, and “What runs in production” moves to architecture/. The old addresses of the moved pages do not redirect.

  • (#676) — Added: GET /api/events/replay returns the outbox events that a bridge missed after its cursor, and GET /api/events returns the current head sequence.

  • (#675) — Added: the project owner can resume, stop and cancel bridge worker runs from the card page and the run drawer, and a stop holds the card until a person resumes a run or moves the card.

  • (#675) — Added: the agents page has a menu on each bridge to pause and resume new work, and its health chip shows Paused, Pausing or Resuming new work.

  • (#674) — Security: league/commonmark moves from 2.10.0 to 2.10.3. This fixes a denial of service in the GitHub Flavored Markdown extension (GHSA-3q6v-r5mr-hxv8), and a bypass of the raw HTML filter (GHSA-97jj-33gv-5xf9).

  • (#673) — Added: The bridge sends the weight of each experiment variant with each pin request, and the server keeps the latest weights of each experiment.

  • (#673) — Added: Loupe records when each GitHub pull request opened and merged.

  • (#673) — Security: league/commonmark moves from 2.10.0 to 2.10.3. This fixes two advisories: GHSA-97jj-33gv-5xf9, a bypass of the raw HTML filter, and GHSA-3q6v-r5mr-hxv8, a denial of service in the table extension.

  • (#672) — Fixed: a CI job that hangs, such as the e2e browser install on a stalled apt mirror, now fails within minutes instead of holding the required checks for six hours.

  • (#671) — Added: docs/adr/ holds the architecture decision records. The first one says that the app does a lifecycle step that needs no judgment, and a bridge worker does only the work that needs an agent.

  • (#670) — Added: The command-line bridge takes a person’s stop, resume and pause from the server, and stops a worker with SIGINT, SIGTERM and SIGKILL on timings that two new flags set.

  • (#669) — Security: brace-expansion moves from 5.0.9 to 5.0.12 in the development tooling. This fixes three denial-of-service advisories: GHSA-q2hr-2g5m-vwhr, GHSA-qhr7-859c-m2p7 and GHSA-6j4f-fj2g-mc7p.

  • (#668) — Fixed: The loupe-stage-merge skill now updates a branch that is behind its base only when the review decision is approved and the approval covers the head, so an unapproved pull request no longer costs a CI run on each pull_request.behind event.

  • (#667) — Added: a project can turn on a GitHub comment on the pull request each time a bridge queues a fix run, with the reason, the failed checks, the round and a link to the card.

  • (#667) — Changed: the GitHub App asks for Pull requests: read and write, so an existing installation must accept the new permission before the comment can post.

  • (#666) — Fixed: e2e pages that cannot reach the Mercure hub no longer retry it, so the stale withdrawal review test stops timing out on a busy runner.

  • (#664) — Fixed: The loupe-stage-merge skill now merges only when every current approval covers each commit: a sync merge from the base passes, and a conflict resolution or any other commit pushed after the approval stops the run as not ready.

  • (#663) — Fixed: CI pulls its Docker Hub images through mirror.gcr.io, so a slow Docker Hub token request no longer fails a job before its tests start.

  • (#662) — Fixed: The trial sweep test for a failing send no longer fails at random in CI when Postgres returns the two expired trials in a different order.

  • (#661) — Changed: A card move, a Backlog drag and a bulk move now renumber a column in one database statement, so a move off the top of a long column is faster.

  • (#660) — Fixed: CI restores the Tailwind binary from a cache, so a transient GitHub download error no longer fails a job before it starts.

  • (#659) — Added: The server accepts the worker run states stopping and stopped, and it tells a bridge through card.held and the card endpoint when a person stopped the work on a card.

  • (#658) — Added: the server stores stop and resume commands for a bridge, sends them in a bridge.command event and the heartbeat reply, and takes the answer at PUT /api/bridges/{bridgeId}/commands/{commandId}.

  • (#658) — Added: the bridge heartbeat takes paused and capabilities, and its reply says whether the server asks the bridge to pause.

  • (#658) — Added: the bridge.command_ttl_minutes feature flag sets how long a command waits before it expires, 15 minutes by default.

  • (#657) — Fixed: The Up next deck of an epic lane stays at the right edge of the board when the lanes scroll sideways, and a long epic title wraps to two lines clear of it.

  • (#656) — Changed: the gate’s Codex review runs on gpt-6-sol, which works with Codex CLI 0.155.1.

  • (#655) — Fixed: The site-review launcher no longer loses a click on Review while a signed-out widget collapses its quick actions.

  • (#654) — Added: A bridge rule can join an experiment with experiment:, and each card then runs the model of the variant the server pins to it.

  • (#654) — Security: league/flysystem is now 3.36.0, which fixes CVE-2026-102601.

  • (#653) — Changed: The implementation stage and the pull request fix round end at the push and report waiting, because Loupe now reads the checks and sends the next event itself.

  • (#653) — Added: A new loupe-stage-merge skill merges a card’s pull request on pull_request.ready_to_merge after it checks the head, the approval and the required checks again, and updates a branch on pull_request.behind.

  • (#652) — Added: A linked GitHub pull request adds a wait to the card’s Waiting item in the inbox when it is ready for review or when its fix loop stopped, and two inbox switches turn these waits off.

  • (#651) — Security: league/flysystem moves from 3.35.2 to 3.35.3. This fixes CVE-2026-102601, where malformed UTF-8 in a path bypassed the control-character check.

  • (#650) — Changed: /loupe:product-design shows the options of a look-and-feel choice side by side on one Claude Design canvas, built from the project’s real templates and stylesheet.

  • (#650) — Changed: /loupe:product-design writes the product document when the questions end, and the owner reviews the requirements and the scenarios in the document instead of in the terminal.

  • (#649) — Added: The bridge tells Loupe which event queued a run, and Loupe records it on the run, so a queued fix run is linked to its pull request.

  • (#648) — Added: A decision answer saved in one tab now shows in every other open tab of the document, with the name of who changed it.

  • (#647) — Added: The server keeps the experiment variant of each card for the bridge, and the run drawer shows the experiment, the variant and the model a run used.

  • (#646) — Fixed: A card waits in the inbox only for its product design or tech design while it sits in that stage column, so a linked plan no longer opens a blocking item.

  • (#645) — Changed: hiding or showing an epic lane from the board now updates only the board structure through the live update, and a refused lane change shows its message without a page reload.

  • (#644) — Changed: /loupe:product-design takes its intake from the card body, and offers a Claude Design session on a look-and-feel choice when the Claude Design MCP is connected.

  • (#643) — Changed: A card on the board shows only its title, with no preview of its body.

  • (#642) — Fixed: CI installs a pinned just without a GitHub release listing, so a transient API answer no longer fails a job before it starts.

  • (#641) — Added: for a repository connected through the GitHub App, Loupe moves a card from implementation to in-review when the required checks pass, and to a terminal column when its pull requests merge.

  • (#640) — Added: the project owner can choose which card waits open an automatic inbox item, at Project settings > Inbox, and Loupe checks the waits of every project every 15 minutes.

  • (#639) — Added: MCP inbox rows now say whether an agent or Loupe opened each item, and inbox_get returns the card and the waits of an automatic item.

  • (#639) — Changed: the Workshop “Needs you” block now lists the oldest open inbox items first, and shows an automatic item with the Loupe icon.

  • (#638) — Changed: A decision block saves a pick at once and a note when you stop typing, with no Save button, and the last answer wins.

  • (#638) — Added: A decision block takes an optional note, a Clear button removes the pick and keeps the note, and document_get_review returns the note with updated_at.

  • (#638) — Added: A trailing (recommended: high), moderate or low on one option of a decision fence shows a Recommended badge.

  • (#637) — Added: a card whose newest worker run is blocked, gave up or waits for a person now gets one inbox item from Loupe, which closes when a newer run starts or the card moves.

  • (#636) — Added: The Runs tab shows the worker pool of each run, and the Agents page shows how many slots each pool of a bridge uses and how many events wait, once the bridge reports them.

  • (#635) — Added: the bridge splits its worker budget into worker pools, so a rule with workerPool in rules.yaml no longer waits behind a full pool of other rules.

  • (#635) — Deprecated: loupe bridge run --max-workers does nothing now. Set maxWorkers in rules.yaml instead.

  • (#634) — Added: a fenced mermaid block renders as a diagram on the review page, once an administrator turns on the review.mermaid.enabled flag.

  • (#633) — Changed: Backlog is a fixed bucket on every board, not a column. The board shows a Backlog button with the card count, and nobody can rename, reorder or delete Backlog. On upgrade, the default column of each board becomes Backlog and loses a custom name.

  • (#633) — Added: a Backlog page lists the Backlog cards 25 at a time, with search, type, epic and sort filters, drag to rank, a Move to menu on each row and a bulk move.

  • (#633) — Added: each epic lane shows its progress and an Up next deck of its Backlog cards, which fans out on hover and takes cards dragged in and out. A collapsed epic lane is a slim bar.

  • (#633) — Added: board_columns and the REST columns list mark the Backlog row with backlog: true.

  • (#632) — Added: the review page marks each stable ID that a document or a referenced document defines, such as R3, and shows its definition on hover, focus or tap.

  • (#631) — Added: Sentry traces now show the start of each request as app.boot, db.connect, session.connect and session.read spans, which ran before the transaction and had no span before.

  • (#630) — Added: the card page shows the checks, the conflicts and the review of each linked pull request, and the board tile shows a badge for failed checks, a conflict or a blocked automation. card_get returns the same state.

  • (#629) — Changed: The Loupe plugin 0.6.0 skills write product and tech designs that open with “At a glance”, give each open decision a pros and cons table with a confidence, and add Priorities and “How others do it” sections to a full design.

  • (#628) — Fixed: In the site-review widget, a pill you point at or tab to now stays emphasised and keeps its focus when the widget refreshes.

  • (#627) — Added: a card with a linked document in review now gets one inbox item from Loupe. The item closes when the review ends or the card finishes, and the owner can dismiss it.

  • (#626) — Changed: The board no longer reloads as a whole on a live change. When it cannot catch up after a few tries, the toolbar says “Live updates stopped. Reload the page to catch up.”

  • (#625) — Added: A card pull request connected through the GitHub App now sends pull_request.conflicted, pull_request.behind, pull_request.closed, pull_request.fix_requested and pull_request.ready_to_merge events, and its check, review and merge events carry the card, the pull request and the result.

  • (#625) — Added: A new Automation tab in the project settings turns the automation on or off, and sets the merge strategy, the fix strategy and the loop limit that stops repeated fix rounds on a card.

  • (#625) — Fixed: An outbox event that the messenger worker writes reaches a bridge when the message ends, not up to five minutes later.

  • (#623) — Changed: A change to the board’s columns, epic lanes or rules banner updates only that part of an open board, and no longer reloads the whole board.

  • (#622) — Changed: The Events tab of the Activity page shows its events in the shared table, in pages of 20, with search and the family filter on the server. A card move shows the columns it moved between.

  • (#622) — Changed: The Events tab refreshes its first page live when an event is recorded or delivered. The ten-second refresh and the Pause feed button are gone.

  • (#620) — Fixed: A page that renews its live-update subscription no longer makes your next click wait, even when the live-update hub is down.

  • (#619) — Changed: the Workshop “In motion” section lists the cards that a bridge queued or that a worker or a session works on now, with the run state, the rule and a live elapsed time.

  • (#619) — Added: an “Open runs” filter on the worker runs page, which the Workshop “+N more” link opens.

  • (#618) — Fixed: A decision question that contains inline code now reads as one paragraph on the review page, not as narrow columns.

  • (#616) — Changed: Run history and Activity are now one Activity page with the tabs Runs, Events and Cost, and the sidebar shows one Activity item.

  • (#616) — Changed: The Runs tab shows one line per run with the card title, and a click on the row opens the run details. A failure reason shows in a tooltip on the outcome.

  • (#616) — Added: The Events filter offers the Pull requests and Project families, and pull request events show a readable label.

  • (#615) — Changed: When the live connection comes back, the board updates only the cards that changed while it was down, and no longer loads the whole board again.

  • (#614) — Changed: The board now fills the whole width of a wide window, rather than stopping at 1530 px.

  • (#613) — Changed: A card move, a new card and a live board update now place one card without reading the whole board, so they answer faster on a large board.

  • (#611) — Fixed: A card change that fails to show on the board now retries that card and then marks it as out of date, and a change on a board with epic lanes shows in place, with no reload of the whole board.

  • (#610) — Fixed: A worker run that changes a card’s warning now updates that one card on an open board, and the board no longer reloads whole on each run change.

  • (#609) — Fixed: A live reload of the board, the inbox pill or the worker runs no longer delays your next click, and a board reload no longer hides a flash message.

  • (#608) — Changed: The board page renders faster, because it builds the hidden move form once per project instead of once per card.

  • (#607) — Fixed: The board page loads faster on a large board, because it counts the documents of every card in one query.

  • (#606) — Added: Loupe keeps the state of each GitHub pull request that a card links, read through the App after each delivery and every ten minutes: open or closed, the required checks, the mergeability and the review.

  • (#605) — Fixed: Sentry no longer receives an access denial from a visitor who is not signed in, because Loupe answers it with a sign-in prompt.

  • (#604) — Added: Two optional variables, GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY, let Loupe read repositories as the GitHub App, and a GitHub App access row on /admin/status reports a refused key or a missing permission.

  • (#604) — Added: The webhook block on the Connections tab says that a webhook connection gets no pull request automation.

  • (#603) — Added: A bridge rule on a pull_request.* event can read the card and pull request placeholders, filter with a when map, and resume a fix request’s session with resume: true.

  • (#603) — Added: A worker can end with the status waiting when its work waits on the forge, and the worker runs page shows that run as “Waiting on the forge”.

  • (#602) — Fixed: An epic’s progress badge, and the lanes of the board, update on every open board when a card changes, with no reload.

  • (#601) — Fixed: An MCP tool call that names no project, or the wrong one, now tells you to run loupe init rather than to set a header, and loupe mcp --project refuses a value that is not a project id.

  • (#600) — Fixed: A collapsed epic lane on the board stays collapsed when a live update redraws the board, and its first click acts on what the lane shows.

  • (#599) — Fixed: Sentry no longer traces the health check or the bridge heartbeat, and still receives their errors.

  • (#598) — Fixed: the server image reports its version from web/vX.Y.Z tags only, without the web/ prefix, and just deploy forces App Platform to pull the pushed image.

  • (#597) — Changed: Each board column and each epic lane cell now scrolls its own cards, and an epic lane has a height cap, so the page header stays in place.

  • (#597) — Changed: The board header is one row with the title, search, card count, view switch, a Board settings button and Add card.

  • (#597) — Removed: The board no longer has column grips or a column menu. Change columns in Board settings.

  • (#596) — Added: an operator can set SENTRY_DSN to send errors, traces with Doctrine query spans, and profiles from the web, console and worker to Sentry, with personal data removed. See docs/operating/sentry.md.

  • (#595) — Changed: the Amphetamine bridge hook ends any session at idle during quiet_hours or after away_minutes with no input, and otherwise makes it a timed session that ends when quiet hours start. The takeover setting is gone.

  • (#595) — Fixed: a hook package that a bridge reload adds while the bridge is busy now gets the idle that follows.

  • (#594) — Added: just cli-install-release downloads a published loupe CLI release, checks it against checksums.txt and puts it on your PATH, with the newest stable release as the default.

  • (#593) — Added: The worker runs page has a Cost tab that charts the average cost per finished card by day, week or month, split by rule or by model, with a median line.

  • (#590) — Changed: The CLI has its own version numbers. A CLI release now has a cli/vX.Y.Z tag, such as cli/v1.0.0, and the bridge updates only to such a release.

  • (#589) — Added: loupe usage backfill sends the usage of past worker runs to Loupe from the bridge log and the local transcripts, with a --dry-run mode.

  • (#588) — Changed: A pull request that changes a page now needs a seeded preview per link, proved with curl, or the implementation stage stops as blocked.

  • (#587) — Added: The Worker runs panel of a card shows the total cost and tokens of every run of the card, with marks for runs that have no usage and for estimated usage.

  • (#586) — Added: The CLI bridge reports the token usage and cost of each worker run, and estimates it from the local transcript when a run is killed.

  • (#585) — Added: Loupe stores the token usage and cost of each worker run per model, from the run’s outcome report or from a new session usage endpoint.

  • (#584) — Added: a loupe bridge rule with action: interactive opens an interactive Claude Code session in a terminal when a card enters its column, through a launch.command set in rules.yaml, and the Worker runs page shows the launch.

  • (#582) — Changed: /loupe:product-design now starts from any column that comes before Product design on the board, such as Next, and moves the card to Product design.

  • (#581) — Changed: a stacked pull request now targets the branch of the pull request it stacks on, never main, in the contributor guide and the agent guidance.

  • (#578) — Fixed: An implementation worker waits for CI in the foreground, so a bridge run no longer ends its turn while it waits for a notice that never comes.

  • (#577) — Fixed: a site-review comment on a card preview worktree now links to its card, because the stage skills pass card:<cardId> to just worktree-up.

  • (#576) — Changed: each site-review widget note is now feedback on a board card. The widget asks once per project for a mode: one card per note, one card per review, or an epic with one card per note.

  • (#576) — Added: a “Site review” card type, and a card that moves to a terminal column resolves its open feedback.

  • (#576) — Added: the MCP tools feedback_list and feedback_mark_addressed, and card_get returns each feedback item in full.

  • (#576) — Removed: the site-review inbox page, its attach-to-card flow, site_reviews.json in the data export, and the MCP tools site_review_get and site_review_mark_comment_addressed.

  • (#576) — Changed: the board now ships on. The upgrade turns board.enabled on for an existing instance.

  • (#576) — Removed: the upgrade deletes every existing site-review comment, including comments already on a card. This cannot be undone, so back up the database first if you need them.

  • (#575) — Changed: a card move now changes only that card and the two columns involved. A refused move goes back in place with a message, and the board does not reload.

  • (#575) — Added: the board shows card changes by other people and agents live, with a short highlight. A “Live updates paused” sign shows while the connection is down.

  • (#575) — Added: the card drawer shows Saving… and Saved, and a create closes the drawer. It warns you when someone else changed the card you edit, and it asks you to confirm the overwrite.

  • (#574) — Added: The Loupe CLI updates itself to the newest verified release that the instance supports, and a running bridge keeps its workers through the update.

  • (#574) — Added: loupe update updates the CLI by hand, and autoUpdate: false in the rule file turns automatic updates off.

  • (#574) — Added: The agents list shows the update state of each bridge, and warns when a bridge runs a CLI version that the instance does not support.

  • (#574) — Changed: The bridge heartbeat answers 200 with the supported CLI range, in place of 204.

  • (#574) — Removed: The CLI no longer supports Windows.

  • (#573) — Added: loupe bridge runs hook packages on its start, stop, busy and idle events, installed from GitHub at a pinned commit with loupe bridge hooks install.

  • (#573) — Added: the Rules page shows the last run of each bridge hook, with its outcome and its last error.

  • (#573) — Added: the Amphetamine hook package keeps a Mac awake, lid closed included, while the bridge has work.

  • (#572) — Added: a card can be an epic, and a card can have one epic as its parent. The epic page lists its children with a progress count such as “3/7 done”.

  • (#572) — Added: the board shows each epic as a swimlane across the columns. Each lane has a collapse control for each browser and a lane toggle that the epic stores. A drag into another lane changes the parent of the card.

  • (#572) — Added: the app closes an epic when all its children are done, and reopens it when a child reopens. It moves a blocked child to Implementation when its last blocker is done.

  • (#572) — Added: the MCP card tools read and write the parent and the lane toggle, and card_list filters by parentCardId.

  • (#572) — Added: the tech design stage can propose a Breakdown section, and the implementation stage then creates the child cards instead of code.

  • (#571) — Fixed: The bridge resumes a worker that ends its turn before its work is done, up to maxResumes times per rule, and marks the run Gave up at the cap.

  • (#571) — Added: Worker runs record a structured result, show the states Unfinished, Blocked and Gave up, and a board card warns when its latest run gave up or is blocked.

  • (#570) — Added: An interactive session can register on a card with the card_run_open and card_run_close MCP tools, and the card drawer shows the open run with a close control.

  • (#570) — Added: A bridge rule takes card: { interactiveRun: false } to skip a card that a person works in an interactive session.

  • (#569) — Fixed: the production image boots again. Opcache preload had outgrown the 128M memory limit, so php-fpm crashed at startup.

  • (#568) — Added: the /loupe:product-design skill runs an interactive product design session with the owner, from a card or a one-line idea, and writes the product document with Scenarios, Risks, Assumptions, a Decisions log and notes for the tech design.

  • (#568) — Changed: no worker writes the product document now, and loupe-stage-product-design answers review rounds only. Delete any product-design rule from rules.yaml, then run loupe bridge reload.

  • (#567) — Added: A board card links to another card of its project as “related to”, “blocks” or “blocked by”. The card page, the card form and the relatedCards field of the MCP board tools show and write these links.

  • (#567) — Fixed: just worktree-up no longer deletes the committed files under assets/vendor in a worktree.

  • (#566) — Added: The Worker runs page and the card page show each state of a bridge worker run, from queued to its outcome, with the history of states in the drawer, and they update live.

  • (#566) — Added: A run whose bridge goes quiet reads Timed out, and a run that a restarted bridge no longer holds reads Lost.

  • (#566) — Changed: The bridge run report limit is 240 requests a minute for each token, up from 60.

  • (#565) — Changed: A card can go from Backlog straight to Tech design. The tech design worker then uses the card body as its requirement source.

  • (#563) — Added: loupe bridge reload applies a changed rules.yaml to a running bridge with no restart, and a failed reload keeps the old rules.

  • (#563) — Added: rules.yaml takes a defaults: block that sets permissionMode and model for every rule that sets none.

  • (#563) — Changed: loupe mcp reads .loupe.yaml again when the file changes, so the next request names the new project.

  • (#563) — Changed: A second loupe bridge run on the same rule file refuses to start.

  • (#562) — Fixed: The bridge no longer lets claude -p end a worker after 600 seconds while a background subagent still runs.

  • (#562) — Fixed: A worker that ends with no STAGE RESULT: line now logs worker_no_result and shows No result on the Worker runs page, where it read as a success before.

  • (#561) — Removed: GITHUB_WEBHOOK_SECRET no longer verifies any delivery, so every existing GitHub webhook stops reaching cards after the upgrade, and each project owner must connect the project’s repositories again.

  • (#561) — Added: a project owner connects GitHub repositories on the Connections tab, with a per-project webhook or the GitHub App, and sees the state of each repository.

  • (#561) — Security: a GitHub delivery reaches only the cards of the project that received it, and only an App installation can make a repository belong to one project.

  • (#560) — Added: A document.review_submitted event now names the stage card and its column, and a bridge rule can match it on verdict, so a request for changes on a stage document starts a fix-round worker with no card move.

  • (#560) — Changed: A bridge rule on document.review_submitted now skips a verdict that names no stage card, where it matched every verdict of the project before.

  • (#559) — Added: the card_get and card_update MCP tools take a card number in place of the cardId, so an agent reads “card 42” in one call.

  • (#557) — Fixed: a self-hosted instance on DigitalOcean App Platform reaches its Mercure hub. The ingress stripped the matched path prefix, so the hub received / and answered its welcome page, and loupe bridge run reconnected in a loop without reporting an error.

  • (#556) — Fixed: an instance with no Mercure hub answers 404 on GET /api/events instead of 500. The endpoint is meant to report that push is switched off, and it could not be reached at all: the Mercure token factory reads MERCURE_JWT_SECRET while it is built, so the controller could not be constructed. loupe bridge run reported an opaque server error against such an instance.

  • (#553) — Added: The admin user detail page lists the apps an account has connected, with the scopes and the project each one reaches.

  • (#550) — Fixed: a board card title that holds a long identifier now wraps, so a narrow column no longer scrolls sideways and clips its cards.

  • (#549) — Added: a GitHub adapter for the forge webhook. A merge, a review verdict and a concluded check on a linked pull request now reach the board. It serves a GitHub App and a hook added in repository settings alike, because both sign the body the same way.

  • (#548) — Added: Loupe receives forge webhooks at /webhooks/forge/{forge}. A merge, a review verdict and a concluded check reach the board on their own, so a card no longer waits for a person to read the forge and drag it.

  • (#547) — Added: approving a document moves its card to the next lifecycle column by itself. A product design approval moves the card to Tech design, and a tech design approval moves it to Implementation, so an agent watching that column starts without anyone dragging the card.

  • (#544) — Fixed: loupe bridge accepts the system actor. Loupe writes it on the card move that follows an approved document, and the router dropped that event as malformed, so an approval moved a card no worker saw.

  • (#543) — Changed: an outbox event now reaches a bridge in the length of the request that wrote it, instead of waiting for the five-minute drain. A card that crosses six lifecycle columns no longer pays that wait at every hop.

  • (#542) — Removed: Static API tokens. Every credential now comes from an OAuth grant. /account/api-tokens and the project token pages are gone, and loupe login --token and LOUPE_TOKEN go with them.

  • (#542) — Removed: SITE_REVIEW_WIDGET_TOKEN, with its Terraform variable and its compose slot. Use SITE_REVIEW_WIDGET_PROJECT.

  • (#542) — Changed: The site-review widget reads data-project only. A page that still carries data-token serves no widget, so re-embed it with the project id from the project’s Connect page.

  • (#542) — Changed: The audit trail names the credential that acted through a new oauth_credentials row, which survives a token refresh.

  • (#542) — Changed: The Connect page and the first-run wizard hand out no credential. They show the OAuth connect commands instead.

  • (#542) — Changed: The privacy policy describes connected apps instead of API tokens, because no page mints a token any more.

  • (#541) — Removed: the Claude Code plugin no longer declares an MCP server, so installing it asks for no project API token. loupe login and loupe init set the server up instead, which binds per project through .loupe.yaml rather than holding one token for every project at once.

  • (#541) — Added: the plugin now ships all eight loupe-* skills, including the board, the inbox and the four card stages. It previously shipped two.

  • (#540) — Added: SITE_REVIEW_WIDGET_PROJECT embeds the site-review widget by project id, so the reviewer signs in through the OAuth popup and the page source carries no widget token. It takes precedence over SITE_REVIEW_WIDGET_TOKEN.

  • (#539) — Added: loupe init now checks how Claude Code starts the loupe MCP server, and offers to declare loupe mcp for every project when nothing does. One declaration serves every repository, because the working directory chooses the project through .loupe.yaml.

  • (#539) — Added: loupe init reports a declaration that starts something else, and offers to remove it. Removing always asks, so a script never drops one you made by hand.

  • (#539) — Added: loupe init --mcp-json writes .mcp.json instead, to commit the server to the repository. Every other server in that file is kept, and init says when a higher-scoped declaration hides it.

  • (#538) — Fixed: loupe login now signs in to https://loupe.ac by default. It previously defaulted to a local development host, so a release binary could not sign in without --url.

  • (#538) — Added: LOUPE_URL sets the instance loupe login uses, so a self-hosted or development instance needs the flag only once.

  • (#537) — Added: just cli-install builds the loupe CLI for your machine and puts it on your PATH, reading the platform from uname and warning when the shell would pick a different copy.

  • (#536) — Fixed: the production image builds again. Warming the cache had outgrown PHP’s default memory limit, and the image now has a build stage whose limit does not follow it into production.

  • (#536) — Changed: the Tailwind binary is fetched by Docker with a pinned checksum rather than downloaded during the build, so a transient GitHub failure no longer fails the whole image build.

  • (#529) — Added: one Loupe login now reaches both the bridge endpoints and the MCP endpoint, so loupe mcp works from the same sign-in as loupe bridge.

  • (#529) — Added: the consent screen says when an app is asking for every project you own, including ones you create later.

  • (#529) — Changed: the connected-apps entry in your data export now lists scopes rather than one scope, with an allProjects flag beside it.

  • (#527) — Fixed: The site-review widget keeps its offer to quote a selection when you hold the add-another modifier and then let go.

  • (#526) — Added: an OAuth grant can cover every project you own, so a new project needs no new login.

  • (#526) — Added: a request names the project it acts on in an X-Loupe-Project header. A header naming a project your login does not cover is refused rather than ignored.

  • (#526) — Fixed: a login survives a refresh whose response was lost. A rotated refresh token stays redeemable once for OAUTH_REFRESH_GRACE_SECONDS, which defaults to 60 and accepts 0 to switch it off.

  • (#525) — Added: a new MCP tool, project_current, reports which Loupe project the connection acts on, so an agent can state the project it is about to write to.

  • (#524) — Fixed: A flash message in the card drawer no longer takes the focus meant for the card’s own content.

  • (#523) — Added: loupe mcp serves Loupe’s MCP tools to a local agent over stdio, signed with your own loupe login, so no tool and no configuration file holds a token.

  • (#523) — Added: loupe init writes .loupe.yaml, the committed file that names the Loupe project a repository belongs to.

  • (#523) — Fixed: an agent connected through loupe mcp keeps its Loupe tools when the server ends its MCP session. The command opens a new session and replays the handshake.

  • (#520) — Changed: The device verification page now uses the consent card design, so both pages of the sign-in flow look the same.

  • (#519) — Fixed: The card drawer no longer takes the focus back from the page behind it when a card is saved.

  • (#518) — Added: the site-review widget can name a project instead of carrying a token, and the project owner then signs in through a Loupe pop-up on the sites the project allows.

  • (#517) — Added: Claude Code and Claude connect to the MCP endpoint by its URL and a sign-in, with no token to copy, through OAuth with Client ID Metadata Documents.

  • (#517) — Added: The consent page shows the icon of the host that published the app’s metadata document, for a client the operator vouches for, fetched by Loupe and served from Loupe.

  • (#517) — Added: OAUTH_TRUSTED_CLIENT_IDS names the client ids the consent page vouches for. Every other client shows its whole client_id, with the host emphasised and no icon.

  • (#517) — Changed: The consent page asks the decision as a question and answers it in three rows: who published the app, what it can do, and where the browser returns.

  • (#516) — Added: loupe login with no token signs the CLI in through a browser with a short code, and the CLI refreshes its access token by itself.

  • (#515) — Added: Loupe is an OAuth 2.1 authorization server: an app can ask a user for access on a consent page, and the user sees and revokes connected apps in the account settings.

  • (#514) — Changed: The account data export lists agent forwarding as forwardsToAgent in projects.json instead of api_tokens.json.

  • (#513) — Added: Each board column has a colour you pick from twelve in board settings, and a new column starts with one no other column uses.

  • (#513) — Changed: Cards open, and are added and edited, in a drawer that slides in beside the board, and the notifications drawer slides in the same way.

  • (#513) — Changed: The topbar search sits behind the search.topbar.enabled flag, which is off by default.

  • (#513) — Changed: An inbox ask shows its first item’s title as its heading, and a presence dot on the agent shows whether its bridge is live, with the session in a tooltip.

  • (#513) — Changed: The card overview lays its fields out as a grid and lists the agent runs on the card.

  • (#513) — Changed: Site review, Rules, All inboxes and About follow the new visual design, and a site review comment lists its linked work in a table.

  • (#513) — Fixed: A dragged board card stays under the pointer, and a faded copy holds its original slot during the drag.

  • (#513) — Removed: A reply to site-review feedback. The feedback keeps its capture, its status and its card link, and site_review_get no longer returns a replies field.

  • (#513) — Changed: The project inbox and the site review page hold their header still, and the list and the detail each scroll on their own.

  • (#513) — Changed: “Create card and attach” on the site review page opens the card form in the drawer, and the feedback list refreshes when the card is created.

  • (#513) — Changed: The inbox calls the action that ends an item without an answer “Close”, where it said “Decline”.

  • (#513) — Changed: A card’s Conversation tab holds the inbox requests, and its Feedback tab holds the site review captures.

  • (#513) — Changed: Hovering anywhere on a board card prefetches it, so the drawer opens from the prefetch rather than a fresh request.

  • (#513) — Changed: The card drawer’s loading state carries no Close button. Escape and the backdrop close it, and the error state keeps both buttons.

  • (#513) — Changed: A board column never grows the page. The strip fits the viewport, each column scrolls its own cards, and a drag near a column’s edge scrolls it.

  • (#513) — Changed: The card drawer leaves the board usable: no backdrop, the page behind stays clickable and scrollable, and a second card loads into the same drawer. Escape still closes it, and a narrow screen keeps the modal drawer.

  • (#513) — Changed: Every scrolling pane carries the same quiet scrollbar: thin, no track, and a muted thumb. A pane that does not scroll shows no bar and no gap.

  • (#512) — Changed: The document review page now matches the approved redesign: a compact header with a status byline, icon margin tabs, restyled comment cards and decisions, a linked board card in Details, a one-row diff toolbar, and a History table with per-version discussion counts.

  • (#512) — Changed: The comment margin opens on its Open filter, so resolving a thread takes its card out of the column, and Details lists only the rows the document has.

  • (#512) — Removed: The Deleted threads page, the permanent purge and Copy review summary. Deleting a thread keeps its confirmation and its immediate Undo.

  • (#512) — Removed: The diff view’s compare chip, metadata tabs and contents rail; the diff now carries the same margin as the document view.

  • (#511) — Changed: Redesigned project navigation, boards, cards, inbox, documents, site review, agents, activity, and settings.

  • (#511) — Fixed: Authentication controls, wizard steps, and update notices use readable text colors on chartreuse and light backgrounds.

  • (#511) — Fixed: Application and admin fields use darker keyboard focus rings, and board filters retain outlines in forced-colors mode.

  • (#511) — Added: A keyboard skip link bypasses navigation in the application, authentication, legal, and landing layouts.

  • (#511) — Added: Project settings include a Board columns section with existing column controls and stale rename, reorder, and default protection.

  • (#511) — Fixed: Column settings adapt to available space at enlarged text sizes without clipping long names or compressing action icons.

  • (#511) — Fixed: Bridge connection health is accessible to screen readers, and connection cards adapt to enlarged text.

  • (#511) — Fixed: Connection setup controls wrap inside their panels, and keyboard focus reveals Rules search controls at enlarged text sizes.

  • (#511) — Fixed: Run history wraps long rule names, keeps outcome badges compact, and contains the Bridge filter at enlarged text sizes.

  • (#511) — Added: Completed runs have a read-only attempt drawer with identifiers, reported timestamps, failure details, and Copy output.

  • (#511) — Added: Run history search accepts a complete run ID while preserving project, outcome, and bridge filters.

  • (#511) — Added: Rules can be searched by name, with a separate no-match state and a clear-search action.

  • (#511) — Fixed: Board controls remain usable with enlarged text, scrolling filters preserve visible focus rings, and hidden priority headings no longer widen the page.

  • (#511) — Fixed: All projects, Documents, Inbox, and Site review header actions stay reachable on narrow screens and with enlarged text.

  • (#511) — Added: Review margin views, explicit decision saving, revision history controls, and review-summary copying.

  • (#511) — Added: The selection toolbar has a Dismiss control that clears the selection and returns focus to the document.

  • (#511) — Fixed: The floating review menu no longer covers annotation form controls on narrow screens.

  • (#511) — Added: Annotations on retained current-version text in side-by-side document comparisons.

  • (#511) — Fixed: Stale document forms and historical thread actions cannot write into a newer review version.

  • (#511) — Added: Deleted review threads remain recoverable until explicitly purged, with immediate Undo and a Deleted threads page.

  • (#511) — Changed: Account token revocation requires confirmation and returns to the API tokens section.

  • (#511) — Fixed: Linked inbox responses keep the card drawer open and show confirmation messages without leaving the board.

  • (#511) — Fixed: Signed-in pages no longer expose cached preview forms whose replacement can discard a new draft.

  • (#511) — Fixed: Thread deletion logs one recoverable action with its reply count; permanent purge logs each removed comment.

  • (#511) — Fixed: Project and review disclosure buttons report whether their panels are expanded to assistive technology.

  • (#511) — Fixed: The project inbox filter row retains its transparent background and compact spacing after CSS layering changes.

  • (#511) — Fixed: Rapid disclosure toggles reverse the current transition. Disclosures, dialogs, and flash messages respect reduced motion.

  • (#511) — Fixed: Form fields, version selectors, and diff-view buttons use consistent desktop sizing and larger touch targets.

  • (#511) — Fixed: Legacy decision submissions cannot overwrite an answer saved through the new review form without checking its previous state.

  • (#511) — Fixed: Search and status filters stay together on narrow document and run pages, with scrollable controls and visible keyboard focus at enlarged text sizes.

  • (#511) — Added: Inbox linked items include pull requests from linked cards, with deduplicated URLs and explicit unavailable states.

  • (#511) — Fixed: The inbox search keeps its compact width, with Clear and the result count accessible on narrow screens.

  • (#511) — Fixed: Inbox card links open the matching request in Conversation, including older closed requests outside the usual ten-item list.

  • (#511) — Fixed: An old Undo form cannot withdraw a newer document verdict, including one on the same version.

  • (#511) — Added: Explicit document and PR Review requests share results across inbox and card views, with required change notes and retained answers after withdrawal.

  • (#511) — Fixed: Stale review forms preserve draft notes and cannot replace a newer verdict on the same document version.

  • (#511) — Added: Inbox and card conversations share replies, including on completed requests, without changing answers or resuming agents again.

  • (#511) — Added: Site review and linked card tabs share feedback replies, with author history, safe retries, account exports, and agent reads.

  • (#511) — Fixed: The Agents summary distinguishes missing, healthy, stale, and mixed bridge connections from their heartbeat reports.

  • (#511) — Fixed: Widget saves retain a submission ID across retries, preventing duplicate feedback when a saved comment’s response is lost.

  • (#511) — Added: Activity refreshes durable history, links related cards, pauses presentation without stopping work, and reconciles missed events with failure and gap notices.

  • (#511) — Added: The topbar bell opens recent project activity without leaving the current page.

  • (#511) — Added: Project search combines available pages, cards, and documents with paginated, project-scoped results.

  • (#511) — Changed: Workshop shows individual open requests, card drawers, and recent recorded events for the current project.

  • (#511) — Fixed: Card drawers show Retry and Close controls when loading fails.

  • (#511) — Added: Projects have optional descriptions in creation, settings, project tiles, and account exports.

  • (#511) — Changed: Workshop counts completed cards and distinguishes disabled features from empty work.

  • (#511) — Added: Workshop crew rows show project bridge connections and heartbeat health, with links to matching connection details.

  • (#511) — Changed: Creating a project opens its Workshop with the new project selected.

  • (#511) — Fixed: The project picker marks the current project and restores keyboard focus when closed.

  • (#511) — Fixed: Resizing an open mobile sidebar releases the page at the desktop breakpoint and keeps keyboard focus visible.

  • (#511) — Fixed: Unsent inbox and feedback replies survive drawer closure and in-app navigation in the same browser tab.

  • (#511) — Fixed: Reopening a dialog cancels its pending close without clearing its fields.

  • (#511) — Fixed: Reply confirmation preserves new text entered while the submission is pending.

  • (#511) — Fixed: Secondary text and active sidebar counts have readable contrast on their light and dark surfaces.

  • (#511) — Fixed: Unsent question answers survive drawer replacement and remain available to copy or discard after the request closes.

  • (#511) — Fixed: Decline notes survive drawer replacement and remain available after the request closes.

  • (#511) — Fixed: Inbox review drafts survive drawer replacement without silently adopting a newer document version, verdict, or pull-request address.

  • (#511) — Fixed: Closed or unavailable review requests keep unsent review drafts separate from the saved result, with an explicit discard action.

  • (#511) — Added: Document creation, revision, and review dialogs retain unsent drafts across in-app navigation within the same tab.

  • (#511) — Added: Search on Account and All projects finds results across all projects owned by the signed-in account.

  • (#511) — Fixed: Document comment filters stay within narrow screens and remain separate from the margin tablist.

  • (#511) — Fixed: Enlarged document margin tabs stay reachable without shifting the page horizontally.

  • (#511) — Fixed: Account and project settings keep enlarged action labels within their panels. Account no longer claims an export email was sent before a request.

  • (#511) — Changed: Headings and the wordmark use Manrope, which the design system specifies, and page titles render at one size across every page.

  • (#511) — Fixed: Icon buttons are square, the document margin keeps its designed width at every window size, and Site review and Inbox stack on narrow screens.

  • (#511) — Fixed: Flash messages announce to a screen reader, admin toggles report themselves as switches, and linked-work rows label their Open button.

  • (#511) — Removed: Cards no longer have a high, medium or low priority, on the board, in the card forms, in the API, or in the MCP card tools.

  • (#511) — Changed: Each board column is one ordered list of cards, and existing cards keep the order they had.

  • (#511) — Changed: Account settings open at /account/profile, /account/api-tokens and /account/data, and old /account?tab= links redirect there.

  • (#511) — Changed: The sidebar keeps the last project you opened on pages that belong to no project, such as account settings.

  • (#511) — Changed: Connect now lives in Project settings as Connections, with the setup guide in a Configure connection dialog.

  • (#511) — Changed: Board settings configure a column’s name, default and finishing-point flags in one dialog, and move columns up and down.

  • (#511) — Removed: The board no longer shows Default and Terminal chips or an inline add-column form; board settings handle both.

  • (#511) — Changed: Every workspace page shares one page frame, form fields share one layout, and type follows the handoff’s scale.

  • (#511) — Changed: The recent-activity drawer is a compact feed, and activity rows show readable event names instead of raw event types.

  • (#511) — Changed: The project inbox shows one queue at a time, Open or Completed, as a request list beside the selected request.

  • (#510) — Changed: Agent instructions, skills and worktree tooling now use harness-neutral paths while keeping Claude Code compatibility.

  • (#509) — Changed: the development lifecycle gains an In review column after Implementation, and pull request fix rounds run there.

  • (#508) — Changed: the working-with-prs skill asks every pull request body for a preview link and, when a card exists, the card URL.

  • (#507) — Changed: the holding-a-merge-queue skill tells the queue holder to start a monitor that reports each change to an open pull request.

  • (#505) — Added: stage skills, a senior-dev agent and a contributing page that let bridge workers run the development lifecycle on this repository.

  • (#504) — Added: a bridge rule on inbox.ask_closed with resume: true resumes the Claude Code session that asked, on the card of that session, and skips the resume when the session already read every item of its ask.

  • (#504) — Changed: a bridge rule on inbox.ask_closed without resume: true now stops the bridge at start.

  • (#504) — Changed: while the inbox is on, a bridge worker’s prompt tells the agent to pass its session id as readerSessionId when it reads its answers.

  • (#503) — Added: The inbox count in the project sidebar updates without a page reload when an item opens or closes, on an instance with a Mercure hub and live_updates.enabled on.

  • (#502) — Added: inbox_list and inbox_get take an optional readerSessionId, which records that a session read the items of its own closed asks.

  • (#502) — Added: GET /api/projects/{handle}/inbox/asks/{askId} tells an agent-scoped token whether an inbox ask closed and whether its session read every item.

  • (#502) — Changed: an inbox_list call with readerSessionId returns each item’s options, selected options, written answer and close note.

  • (#502) — Changed: inbox_ask refuses an option longer than 500 characters.

  • (#501) — Fixed: the site-review widget now keeps its offer to quote your selected text when you leave draw mode or finish picking an element, where before the offer came back for a moment and then disappeared.

  • (#500) — Added: an inbox ask closes when its last blocking item closes, and an ask from a bridge-started session writes an inbox.ask_closed event that names the ask, the session, the bridge and the card.

  • (#500) — Added: the project inbox page has a search field that finds items by the words in their title or body, closed items included.

  • (#499) — Added: the card page and the document page list the inbox items linked to them, and the owner answers them there without leaving the page.

  • (#498) — Added: an open inbox ask from a bridge-started agent shows when its bridge was last heard from, and warns that no resume will come when the bridge sent no heartbeat in three intervals.

  • (#497) — Added: an “All inboxes” page, behind inbox.enabled, that lists the open asks and open items of every project you own and links each one to its project inbox.

  • (#495) — Added: a project inbox page, behind inbox.enabled, where the owner answers the questions and to-dos agents hand over, and a sidebar count of open items.

  • (#494) — Added: six inbox MCP tools, behind inbox.enabled, let an agent hand questions and to-dos to the project owner, search them, join an open item, list and read items, and withdraw an item it no longer needs.

  • (#494) — Added: an open inbox item closes as obsolete when every card it links to is moved into a terminal column.

  • (#493) — Added: the bridge sends a heartbeat to PUT /api/bridges/{bridgeId}/heartbeat at start and then at an interval, so Loupe records which bridges run. The bridge.heartbeat_interval_seconds flag sets the interval, 60 seconds by default.

  • (#492) — Changed: The bridge starts each worker under a new Claude Code session id, and the worker run report now requires sessionId. The server refuses a report from a bridge built before this change, so rebuild the bridge.

  • (#492) — Added: GET /api/events returns a flags map with inbox.enabled, and a bridge on an instance with the inbox on names the session id and the bridge id in the worker prompt.

  • (#490) — Changed: the holding-a-merge-queue skill keeps the queue holder to merging, so a peer session takes its own questions to the owner.

  • (#487) — Changed: the gate’s Codex review runs on gpt-6-astra, which needs Codex CLI 0.154.0 or later.

  • (#486) — Changed: the holding-a-merge-queue, project-worktrees and working-with-prs skills record the merge queue lessons of 2026-09-14, including how to read an approval by time and why a worktree must never run npm ci.

  • (#484) — Fixed: the site-review widget no longer loses a pending quote selection when you leave draw mode or finish picking an element, so the offer to quote the text comes back as it promises.

  • (#482) — Fixed: The loupe bridge replaces a hand-edited bridge id that the server refuses, such as an upper-case uuid, instead of sending it and getting a bare 404.

  • (#481) — Fixed: just worker consumes the scheduler_default transport, so scheduled work runs in development and in a worktree.

  • (#480) — Changed: the heading de-duplication timing test compares 5,000 with 20,000 headings against a ratio of 8.0, so a loaded machine does not fail it.

  • (#479) — Changed: the working-with-prs skill asks for a brief pull request body, about 100 words on a small change and under 250 on a large one, and puts the full reasoning in the commit messages.

  • (#478) — Changed: the CI end-to-end check runs on two runners, and just ci-report e2e-timing prints one timing summary per runner.

  • (#477) — Added: The loupe bridge reports every worker run to Loupe, the ones that crash or never start included, and retries a failed report for about four minutes.

  • (#476) — Added: a project now has a Worker runs page that lists what a CLI bridge reported about the Claude Code workers it ran. A row shows the card, the rule, when the run started, how long it took and how it ended, and every run carries its full output collapsed under it. The list pages at 20, searches the card number, the rule name and the output text, and filters by outcome and by bridge. The page states that a missing record means unknown and never means that the worker did not run.

  • (#475) — Added: the server records a CLI bridge worker run at POST /api/projects/{handle}/worker-runs, keeps it for 180 days, and sweeps the rest every hour. A run holds the card as plain values, so a deleted card leaves its history intact, and a spawn failure stays distinct from a process that ran and failed. The bridge.run_retention_days feature flag sets the window. The CLI bridge does not send reports yet, and there is no page for them yet.

  • (#474) — Added: every CI run keeps a PHPUnit timing report, and just ci-report phpunit-timing prints the mean seconds per test with the slowest classes and tests.

  • (#473) — Added: The loupe CLI gives each machine’s bridge a persistent id, stored in config.json and generated on first use after you log in.

  • (#473) — Changed: The loupe CLI writes config.json through a temporary file and a rename, so a failed write no longer leaves the login half written.

  • (#472) — Added: the CLI bridge stops a rule until restart when a column rename, a column delete or a project rename takes away a slug the rule names.

  • (#472) — Added: the CLI bridge reports the health of its rules to the server at start and whenever a rule dies, without prompt text.

  • (#472) — Changed: the CLI bridge refuses at start a rule file whose health report the server would reject, such as a rule name longer than 100 characters.

  • (#469) — Fixed: The project sidebar links to the outbox page, which no page had pointed to since #436.

  • (#469) — Fixed: The show and hide icons on the document review screen’s resolved-comments toggle render in production again.

  • (#467) — Changed: GET /api/events returns the hub URL, your user topic, one subscriber JWT for that topic, and the projects you own.

  • (#467) — Changed: Loupe publishes each project event on the project owner’s user topic as well as on the project topic.

  • (#467) — Removed: GET /api/projects/{handle}/stream is gone, so every loupe CLI built before this change, including one built after #459, gets 404 and must be rebuilt.

  • (#467) — Changed: one CLI bridge follows every project in its rule file on one connection, and ignores the events of a project the file does not map.

  • (#467) — Changed: a project created while the CLI bridge runs reaches it with no restart, and the bridge logs it once and ignores it until you map it.

  • (#467) — Added: the CLI bridge logs project_gone once when a mapped project is deleted or stops being yours, with the rules that stop working.

  • (#467) — Added: GET /api/projects carries each project’s slug, and the CLI bridge lists your slugs when a rule file names a project you do not own.

  • (#466) — Changed: Live browser updates, such as the board refresh, now switch on the new live_updates.enabled flag, so they no longer depend on agent.push.enabled.

  • (#465) — Fixed: the CLI bridge runs a rule prompt that starts with -, because it passes the prompt to claude after --.

  • (#465) — Changed: the CLI bridge refuses to start when a permissionMode or a model holds whitespace, in the rule file or in --permission-mode and --model, and it logs a warning at start for a mode it does not know.

  • (#464) — Added: the server accepts bridge rule health reports at PUT /api/projects/{handle}/bridges/{bridgeId}/rules, the board shows the owner a banner for each dead rule, and the column rename and delete dialogs warn when a live rule watches the column.

  • (#463) — Changed: the board documentation, the loupe-board skill and the landing page describe the columns each board sets, and the skill tells an agent to read board_columns before it names a column.

  • (#462) — Changed: the holding-a-merge-queue skill asks the queue holder to report every flaky or unrelated CI failure it sees to the owner, with a count of earlier sightings, and never to re-run a check just to get green.

  • (#461) — Added: just ci-report fetches the mutation, coverage and e2e timing reports from CI, and every e2e run keeps a timing report per Playwright project.

  • (#460) — Changed: the e2e suite runs spec files on 4 workers, and a spec that changes a global flag or shares an account runs in a one-worker project.

  • (#459) — Changed: GET /api/projects/{handle}/stream takes a project id or slug only, so a project name no longer resolves there and the CLI’s --site needs a slug or an id.

  • (#458) — Changed: the loupe CLI reads GET /api/projects and GET /api/projects/{handle}/stream, which replace GET /api/agent/sites and GET /api/agent/stream?site=<handle>.

  • (#458) — Removed: GET /api/agent/sites and GET /api/agent/stream are gone, so a loupe CLI built before this change gets 404 and must be upgraded.

  • (#453) — Added: An open board reloads its columns when someone adds, renames, reorders, flags or deletes a column, through the Mercure hub, and an instance with no hub shows the change on the next page load.

  • (#452) — Changed: a CLI bridge event for a card whose worker still runs waits and runs after that worker exits, once per rule however many events arrived, and logs worker_coalesced for each event it replaced.

  • (#452) — Added: each bridge rule’s maxChain, three by default, caps the runs in a row that agents’ events start for one card, until a person moves the card.

  • (#451) — Added: GET /api/projects/{handle}/board/columns gives an agent-scoped token the columns of one of its owner’s boards, so the CLI bridge can check its rules against the board.

  • (#450) — Changed: loupe bridge run reads a rule file, rules.yaml beside the CLI’s config.json, that says which event, project and column start an agent, with which prompt, in which directory.

  • (#450) — Removed: loupe bridge run no longer takes --site or --dir, and it refuses to start without a rule file. To upgrade, write rules.yaml with one project and a rule on to: next, as cli/README.md shows.

  • (#449) — Added: A column rename that changes the slug writes a board.column_renamed outbox event, and every column delete writes one board.column_deleted event that names the target column and the moved cards.

  • (#447) — Added: Any project save that changes the slug writes a project.renamed outbox event, even one that keeps the name and repairs a stale or -2 slug.

  • (#445) — Added: the board_columns MCP tool lists the columns of the board, with each slug, label and terminal and default flag.

  • (#445) — Changed: card_list returns the columns of the board beside its cards, and the board tools no longer describe a fixed set of four columns.

  • (#444) — Added: a project owner adds, renames, reorders and deletes board columns on the board, and chooses the terminal and default columns.

  • (#444) — Added: the rename dialog shows the new slug before it saves, and a deleted column moves its cards to a column the owner picks.

  • (#443) — Changed: a card now sits in a column row of its own board, and the board draws the columns its project holds.

  • (#443) — Changed: the history page of a finished column has a URL that names the column, and the old URL redirects there.

  • (#443) — Added: the card export carries the column label beside its slug.

  • (#442) — Added: every project has a slug that follows its name, unique per owner, shown read-only on the project settings page.

  • (#442) — Changed: a project name that gives an empty slug, or the slug of another of your projects, is refused.

  • (#442) — Changed: GET /api/agent/stream and the MCP site parameter accept a project slug beside the id and the name.

  • (#442) — Changed: a site handle that is the slug of one of your projects and the name of another is now refused; pass the project id or its unique slug instead.

  • (#442) — Fixed: the development PHP image builds xdebug without contacting pecl.php.net, so an outage there no longer fails the build.

  • (#441) — Added: API tokens gain an agent scope, and the account settings page now mints it instead of site-review.

  • (#441) — Changed: the loupe CLI reads GET /api/agent/sites and GET /api/agent/stream, which replace GET /api/site-review/sites and GET /api/site-review/stream.

  • (#441) — Changed: the firewall grants ^/api/agent to the agent scope alone, so a project’s widget token is now refused before the controller runs rather than by the controller.

  • (#441) — Changed: an audit record written through an agent token reports the agent channel rather than widget.

  • (#441) — Removed: an account-level API token minted before this release stops working on the CLI endpoints, and has to be minted again from /account.

  • (#441) — Changed: no widget token is affected by the scope split, and no widget deployment changes.

  • (#439) — Added: The CLI bridge runs at most --max-workers workers at once, three by default, and queues the rest in arrival order.

  • (#439) — Changed: The CLI bridge writes one JSON object per line, to stdout and to a log file named by --log-file, and appends to that file across runs.

  • (#438) — Added: Each board.card_moved outbox event now names its actor: human for a move in the web UI, or agent for a move through the MCP.

  • (#437) — Changed: loupe bridge run now runs a non-interactive claude -p worker for each board card moved to next, and reports its exit code and its output.

  • (#437) — Changed: loupe bridge run requires --dir, and refuses a path that is not a directory.

  • (#437) — Removed: loupe bridge run drops tmux, --session, --attach and the bridge log, and no longer acts on a submitted site review.

  • (#437) — Fixed: a card whose worker has finished starts a new worker the next time it moves to next.

  • (#436) — Removed: The site-review page no longer shows a notice counting reviews that have not reached your agent.

  • (#435) — Changed: every controller that injects a collaborator now delegates through a Command/Handler pair, and a PHPStan rule holds the line, so a new controller that keeps its work in the request fails the build.

  • (#434) — Added: loupe version reports the commit the binary was built from, and marks it when the working tree had uncommitted changes.

  • (#433) — Added: account settings lists your API tokens and mints a new one, which is how you get the token the loupe CLI needs. The raw value is shown once.

  • (#432) — Changed: every MCP tool now reads and writes through a Command/Handler pair, and two PHPStan rules hold the line, so a new tool that injects no handler or queries a repository fails the build.

  • (#431) — Changed: the working-with-prs skill carries the rule that a check is a fault until you have seen it fail, with the comm instrument for proving that a conflict resolution lost or invented nothing.

  • (#431) — Changed: the loupe-board skill says what earns a card. A lesson belongs in the skill that covers it rather than in a card nobody can finish.

  • (#430) — Changed: a changelog entry now rides its own file under changelog.d/, named after its pull request, and the documentation deploy folds the pending entries into the published changelog.

  • (#427) — Fixed: a fresh clone now boots before Tailwind has ever been built, because var/tailwind/ ships in the repository as an empty directory.

  • (#424) — Added: loupe bridge run starts a Claude Code worker session for a board card moved to next, one session per card, and --permission-mode passes that flag through to each worker it spawns.

  • (#428) — Added: moving a board card now writes a durable outbox row, so a connected agent can react to the move. board.card_updated is recorded only when a field actually changed.

  • (#423) — Changed: the site-review outbox is now a general agent outbox. Its table, drain, scheduler and listing pages moved to the root namespace, every row records which producer wrote it, the per-project page moved to /projects/{id}/outbox, and the site_review.push.enabled flag became agent.push.enabled.

  • (#426) — Added: a card_search MCP tool, which searches the title and the body of every card on a project board, done cards included, and answers best match first.

  • (#425) — Added: the card_list MCP tool takes a reporter filter, which reads human, agent and reviewer alike, so the cards the site-review widget raised are listable.

  • (#425) — Changed: the board card field origin is now called reporter on the card page and in every card_create, card_list and card_get row. The three values human, agent and reviewer are unchanged.

  • (#425) — Deprecated: the origin parameter on card_create. It still works, and reporter replaces it. A call that sends both uses reporter. A later release removes origin.

  • (#422) — Changed: the card_list MCP tool answers one page of summary rows, with page, perPage and full to steer it, rather than the whole board with every card’s full body.

  • (#421) — Added: the document_list MCP tool takes search, status, tag and series, and each row now carries the description of the document’s current version.

  • (#420) — Changed: the development php-fpm now caches every checkout’s code rather than the first ~32,000 files it happened to see, so worktrees no longer recompile on every request, and /fpm-status reports the shared pool.

  • (#418) — Fixed: a comment thread in the review rail keeps its author row in place when you open it, and carries its age and its status on that row rather than on a second row that appeared on expand.

  • (#418) — Fixed: the site-review widget finds an element again when the page has dropped a class the stored anchor recorded, such as one the page adds while an element is hovered or open.

  • (#418) — Fixed: a document linked to a board card shows its status as words rather than as a translation key.

  • (#417) — Added: you can resolve a site-review comment from the widget, either in its list or on the card that opens from a pin. The comment leaves the widget and moves to Resolved on the project’s site-review page.

  • (#417) — Added: the contents rail stands beside a version diff, and starts level with the document rather than with the title above it.

  • (#417) — Added: the version diff page carries a contents panel, listing the headings of the view you are reading, including the ones the revision removed.

  • (#417) — Added: the site-review widget shows a Local label in its launcher when it saves to a local build, so you can see which instance your comments reach.

  • (#417) — Changed: the general comment composer opens under the button that asks for it, rather than over the middle of the document.

  • (#417) — Changed: a metadata panel opens directly under the bar that names it, the diff view switch reads Document, Markdown, Side by side, and the resolved-threads toggle is a button with an icon.

  • (#417) — Fixed: j and k on a diff now light the arrow button they stand for.

  • (#417) — Changed: the document review page no longer stacks notices above the title: the since-your-last-visit note is a chip in the metadata bar, and a comment thread whose passage is gone leads the comment column instead of announcing itself across the page.

  • (#417) — Changed: the document review page stands its contents and its decisions in a left rail on a wide window, marks the section you are reading, moves tags into a dropdown, and starts its content at the same left edge as every other screen.

  • (#417) — Fixed: a heading in the contents panel or the rail now scrolls to its section instead of jumping to it.

  • (#417) — Changed: a document in the list keeps its title on a line of its own, so a long title wraps instead of truncating to one letter.

  • (#417) — Changed: the section approval circle shows the tick a click would leave, and turns green once the approval is saved.

  • (#417) — Removed: the + and − gutter signs on a whole block a revision added or removed in the version diff.

  • (#417) — Fixed: the site-review picker no longer flashes on and off when a modifier chord such as Cmd+Enter is typed into the comment composer.

  • (#417) — Fixed: the diff view’s j and k shortcuts no longer swallow those letters typed into the site-review comment composer.

  • (#417) — Fixed: a resolved comment thread whose passage is gone now says Resolved instead of Open.

  • (#417) — Changed: the mark that names the heading you jumped to is slower, has room around it, and no longer fades a decision block to white.

  • (#417) — Fixed: jumping to a heading near the end of a document now marks that heading rather than the last one.

  • (#417) — Changed: approving a section now updates the page in place instead of reloading it, so an open panel stays open and the reading position is kept.

  • (#417) — Fixed: the site-review widget no longer offers “Comment on this text” over a Loupe document, which has commenting of its own.

  • (#417) — Changed: the version chip now leads the metadata bar of a document review page.

  • (#417) — Fixed: clicking one of the last headings in the contents rail now marks that row, which the end of a document could never reach before.

  • (#417) — Added: arriving at a heading from the contents rail tints its section head for a moment, so the scroll says which heading it answered.

  • (#417) — Changed: the group of comment threads whose passage is gone now starts collapsed, behind a heading that says how many there are.

  • (#417) — Changed: the action row below a document now has room above it.

  • (#417) — Removed: the compare hint on the version history page, which said what the two pickers beside it already show.

  • (#417) — Fixed: the timeline on the version history page now runs from the first node to the last, instead of overshooting above and stopping short.

  • (#411) — Changed: open work now lives on the Loupe project board instead of docs/NEXT_STEPS.md, which is deleted along with the project-next-steps skill.

  • (#415) — Added: a comparison of two versions now offers a Side by side view, which puts the two versions in two columns with each block opposite the block it became.

  • (#415) — Changed: comparing two versions now names the pair with a chip in the metadata bar and holds the view switch, the change count and the jump controls on one row, so the document starts 214 pixels higher.

  • (#415) — Changed: the comment margin beside a document is now a rail of one-line markers, and one thread at a time opens in place beside its passage.

  • (#415) — Added: a document has a version history page listing every version with its date and note, and a picker there compares any two versions; the review page’s Versions tab now carries the current version alone plus a link to that page.

  • (#415) — Changed: the Contents tab in the document review page shows its count as 2/6, the shape the Decisions tab beside it already used.

  • (#409) — Changed: a changelog entry now rides the pull request it describes, anchored to the pull request number, so a change and its entry land together instead of needing a second pull request.

  • 891ca70 (#408) — Added: working-with-prs says to match a changelog SHA with git rev-parse --short=7, because %h returns a wider one and makes a recorded commit look missing.

  • 891ca70 (#408) — Added: working-with-prs says the changelog exemption keys on a pull request’s content rather than its subject, so a skill change about the changelog earns a line.

  • 34b2732 (#406) — Added: working-with-prs says to re-derive a changelog branch’s entry list immediately before merging it, because merges that land while it waits leave no visible sign.

  • 0096491 (#403) — Added: the site-review widget’s composer says which board card a comment will attach to, and lets a reviewer search the board, pick a different card, create one, or detach.

  • 0096491 (#403) — Added: a card links to the documents its work is written up in, through documentIds on card_create and card_update, and the card page lists them.

  • 0096491 (#403) — Added: a card raised through the review widget records its origin as reviewer, which says the app could not name who raised it.

  • 0096491 (#403) — Changed: a widget token may now list and create board cards, through /api/board/cards. It is a public token, so this publishes card titles to anyone who can read an instrumented page’s source. Off unless board.enabled is on.

  • 0096491 (#403) — Fixed: every worktree’s compiled stylesheet stays current, so a preview no longer serves the CSS it was provisioned with while its templates are newer.

  • a254574 (#399) — Fixed: the development profiler collects every request again, not only the ones that threw.

  • 306c57b (#395) — Added: a site-review comment made on a preview that names a card attaches to it, and the card page and board show the feedback waiting on it.

  • f8d778b (#394) — Fixed: the contributor guide named a console command that does not exist for seeding a feature flag, and said main requires eight CI checks when the ruleset requires ten.

  • f8d778b (#394) — Added: working-with-prs says where a changelog entry sits, to strip a preview link before merging, and that a formatter can reorder arguments against a signature its branch cannot see; project-frontend gains a reference for the board’s drag controller.

  • a778fcd (#393) — Fixed: two cards finished in the same second read newest first in the board’s Done column, and the Done history now agrees with it.

  • fe3c518 (#391) — Changed: the environment reference says to write each variable’s full name, because a shorthand row that folds two names together hides the second.

  • 564618c (#389) — Changed: the mobile review end-to-end spec drops three stale comments. Two said the app shell still overflowed a 375px window, which 23764c51 fixed in the same wave, and one described a return value the helper does not have.

  • b3adc03 (#388) — Added: DeploymentConfigParityCheck reads docs/reference/environment.md, so an environment variable that no page documents fails just gamache.

  • f2a7e2e (#383) — Added: a holding-a-merge-queue skill records how one session holds the merge queue while other sessions push branches to it.

  • 0a1fcac (#385) — Changed: the project-backend skill says what an environment variable can carry, and that normalising a payload field belongs on the request DTO rather than in the controller.

  • ed9f573 (#382) — Added: the site-review widget embed takes an optional data-context, set by SITE_REVIEW_WIDGET_CONTEXT, and every comment made through it stores that marker and reports it in site_review_get.

  • c84fdf8 (#371) — Added: a project board, behind the board.enabled flag which ships off, shows four columns with cards grouped by priority. A drag re-ranks a card, re-grades it or moves it to another column, and each card has its own page.

  • c84fdf8 (#371) — Added: the board’s Done column shows the last 7 days, and a history page carries every card that finished before that.

  • c84fdf8 (#371) — Added: four MCP tools, card_create, card_list, card_get and card_update, let an agent read and write the board.

  • c84fdf8 (#371) — Added: every card carries a number that counts from 1 inside its project, so a person and an agent have a short handle for it.

  • c84fdf8 (#371) — Added: a card holds pull request links. Loupe reads the forge, the repository and the number out of a URL it recognises, and it calls no forge.

  • c84fdf8 (#371) — Added: a user’s data export includes their cards.

  • c84fdf8 (#371) — Added: the projects list shows how many open cards each project has.

  • c84fdf8 (#371) — Added: the loupe-board skill tells an agent how to work a board, and CLAUDE.md says what a skill’s name prefix means.

  • c84fdf8 (#371) — Changed: one voter, App\Security\McpBoundProjectVoter, scopes every MCP subject to the token’s own project, and it replaces the two per-module voters.

  • c84fdf8 (#371) — Added: a phparkitect rule fences App\Module\Board as a leaf, so no code outside the module may depend on it.

  • c84fdf8 (#371) — Added: the creation, the update, the move and the deletion of a card each write an audit record, which /admin/audit-log shows.

  • 23764c5 (#381) — Added: the authenticated app and the review screen work on a phone. Below the lg breakpoint the sidebar becomes a drawer behind a hamburger, comment cards sit inline under the paragraph they anchor to, the review top bar keeps its controls behind one round button, a touch selection raises the comment toolbar, and a wide table scrolls inside itself.

  • 5a64e74 (#374) — Changed: the symfony-authorization skill says to keep an explicit attribute-to-class pairing in a voter’s supports(), and to test the denials.

  • e06c292 (#370) — Fixed: the e2e job in the weekly coverage workflow has 180 minutes, so its own timeout no longer kills a slow run.

  • b90416b (#367) — Fixed: the build no longer fetches JavaScript from a CDN. assets/vendor/ is committed, so importmap:install has nothing to download and a failed fetch can no longer turn an unrelated branch red.

  • c71cec3 (#359) — Added: mutation testing over all of src and code coverage, both on their own weekly schedules and neither gating a merge. just mutation, just mutation-diff, just phpunit-coverage and just e2e-coverage run them, and the project-mutation-and-coverage skill says how to fetch a weekly report.

  • aabed3a (#368) — Added: a JavaScript test harness. just js-test runs vitest over tests/js, covering comment-anchor matching and the site-review widget’s fatal state, and a js-test CI job runs it on every pull request.

  • 2eb21ad (#355) — Changed: public/site-review/ is in prettier’s scope, so the widget is formatted like the rest of the JavaScript.

  • fd66350 (#362) — Added: a reviewer can draw freehand over the page and attach the strokes to a comment, from the composer or from the collapsed launcher. It is behind the site_review.drawing.enabled flag, on by default.

  • 9123005 (#335) — Added: a reviewer can approve a document one section at a time, with a control beside each heading. The Contents and Sections panels become one, and a document with a single heading now shows it, so a one-section document keeps an aggregate view of what has been approved.

  • 01684ad (#352) — Changed: CommentBudgetCheck no longer policies .env, so a dotenv comment can explain a variable at whatever length it needs.

  • f1bca43 (#361) — Added: a site-review comment can quote a range of text rather than only pointing at an element, so a comment about a sentence anchors to the sentence. The quote and its surrounding context are stored, so the anchor survives the page changing around it.

  • 2c2c37c (#349) — Changed: the e2e run stops at the first failure. waitlist, trial-end-lifecycle and install-reset depend on chromium, and Playwright skips a dependent project when its dependency fails, so a red test used to withhold three suites behind a “did not run” line that read as a deliberate skip.

  • 7e1060c (#358) — Changed: the test suite writes deprecations to their own always-on log with rotation, and writes far less to test.log, which now holds exactly one run.

  • e887a13 (#356) — Added: docs/contributing/architectural-priorities.md ranks correctness, simplicity, performance and shipping speed, and says which one yields in each of six collisions and when to escalate instead.

  • 3fdfd63 (#360) — Added: the site-review launcher can be moved to any corner of the page, so it no longer sits over the review console’s pinned controls. The choice is remembered per browser.

  • 001a00a (#354) — Changed: the project-backend skill names the rule that picks between the two CSRF shapes for a fieldless POST action, with the detail in references/csrf.md.

  • cd8b30c (#353) — Changed: User::$disabledAt now documents what it is for: a cache the Billing module writes, which the paywall no longer reads.

  • 59defea (#357) — Fixed: two site-review widget tests asserted a resting state the interaction never promises. Releasing the modifier key makes every anchor box hit-testable again, and Chromium dispatches a mouseover for the stationary pointer with no matching mouseout, so the emphasis arrives and stays. Both tests now park the pointer before asserting. The widget was correct; the assertions were not.

  • f335764 (#341) — Added: a site-review comment can point at several elements, so it can describe a relationship between them rather than being tied to one. Hold Cmd, or Ctrl away from a Mac, and keep clicking to add elements to the comment you are writing. Each appears as a pill in the composer; hovering a pill lights up its anchor on the page, and hovering an anchor lights up the others in the same comment. Remove an anchor by its pill or by a control on the element.

  • f335764 (#341) — Changed: site_review_comments keeps writing its selector and text columns, which nothing reads any more. The contraction that drops them must re-run the backfill and remove the entity mapping in the same release, or a rollback breaks.

  • 7af7f10 (#351) — Changed: CLAUDE.md tells an agent to read git diff --cached before committing. Staging by name protects against another branch’s files, not against another session’s hunks in a file two sessions are both editing.

  • d937c04 (#332) — Changed: the documents list shows one signal per row, “N threads waiting for you”, and only where something waits, in place of three per-row counts. The full breakdown moves to the document page. It also fixes the count: an orphaned thread was counted alongside its status rather than as part of it, so a thread that was both orphaned and addressed appeared in two totals and three such threads read as six.

  • f3822e2 (#350) — Changed: the working-with-prs skill says to open a pull request ready rather than draft, because a draft waits for a review that never starts.

  • db025af (#338) — Changed: site_review_mark_comment_addressed states in its tool description, its docblock, the loupe-site-review skill and docs/using/mcp.md that a skip reason is best-effort. The write is authoritative; only the reported reason can name a status that moved under it.

  • 26d6bf5 (#348) — Added: a development-only preview-login link. bin/console app:dev:preview-login-link --path=/projects prints a URL that signs the reader in and lands them on that page, so a pull request body needs no credentials. The signature covers the whole URL including the host, so a link works against one worktree only.

  • 2091a0c (#346) — Changed: the working-with-prs skill now says what a Codex pass is worth and when to stop asking for one.

  • f03f345 (#333) — Added: a document is stemmed for search in its own language, set per document or inherited from the project, so a French document matches a French query rather than an English stemmer’s guess.

  • e275bb2 (#336) — Added: a decision block can take more than one answer, and the status line names the option a reviewer cleared as well as one they chose.

  • c795eff (#340) — Changed: an MCP tool reports every rejected argument at once, rather than the first one it reached.

  • f8a26b6 (#337) — Added: a reviewer can leave a comment while looking at a diff, anchored to the passage the diff shows.

  • 8ceae0f (#334) — Added: documents can say they belong to an ordered series, filtered and read in their own order rather than newest first, with document_set_series and series_rename to place and rename them.

  • 60ec749 (#331) — Changed: the decision status line names the option and the version an answer was recorded against, taken from what was stored rather than what was submitted.

  • 7000cb0 (#330) — Changed: the front-matter table and the rendered annotations carry names, so a screen reader announces what they are.

  • aaec685 (#347) — Fixed: the development image installs xdebug from its tarball rather than by package name, so a build no longer queries the PECL index that was intermittently answering “No releases available” and failing four CI jobs at once.

  • 3aa3bcd (#329) — Changed: the document documentation warns that an annotation wrapped in an HTML element is dropped without a warning.

  • 46fe5e6 (#344) — Changed: the working-with-prs skill puts the preview links at the top of a pull request body.

  • 6cef3f9 (#345) — Fixed: the development image pins the xdebug version it installs, so two builds a month apart no longer install different ones.

  • 1183917 (#325) — Changed: the audit trail now comes from the ubermuda/audit-bundle package. The /admin/audit-log screen and the audit:purge command work as before; the retention window moves from app.audit.retention_days in config/services.yaml to retention_days in config/packages/ubermuda_audit.yaml, which also carries the sweep’s cron expression.

  • 0406b9c (#209) — Fixed: the admin area loads the application stylesheet again; it extends the bundle’s layout rather than layout_base.html.twig, so it lost its only source of CSS when assets/app.js stopped importing the sheet.

  • 167f3c9 (#208) — Added: /healthz reports the running build to a caller presenting HEALTH_PROBE_TOKEN as an X-Probe-Token header, so a post-deploy check can prove which image is live; unset, it reports nothing.

  • 77bc23c (#207) — Changed: the production and demo images no longer ship the marketing site or the Tailwind CLI, taking them from 1.13 GB to 105 MB and from 1.16 GB to 505 MB.

  • 47c67f5 (#206) — Fixed: marking a comment addressed no longer overwrites a human’s Resolve, the documents list counts matching documents rather than rows on the current page, and the project-backend skill stops documenting a getLogger() helper that does not exist.

  • 2f30fd2 (#205) — Changed: the landing page moves into its own module, and each module seeds its own feature flags.

  • fdefb96 (#204) — Changed: each module owns its own counts, tokens and gates rather than sharing one surface.

  • 87fc6bb (#203) — Changed: the list pages batch their queries, and an account export stops buffering every payload at once.

  • 7d788fa (#202) — Changed: the content security policy blocks rather than merely reporting, and responses carry HSTS; assets/app.js no longer imports the stylesheet, which becomes a plain <link>.

  • d077eff (#201) — Added: the gate audits the npm dependency trees, and the site-review widget ships minified.

  • 2de6a00 (#200) — Fixed: the spacing of the type scale, and the landing page’s document head.

  • 4b8a339 (#199) — Fixed: five small correctness gaps found by the audit.

  • b8c0563 (#198) — Fixed: the site-review bridge CLI no longer stalls silently or acts on stray events.

  • 80ccd47 (#197) — Changed: the system status page moves into its own Diagnostics module.

  • d749322 (#196) — Fixed: an incomplete subscription no longer disables an account that is still trialling.

  • 9377355 (#195) — Fixed: review writes require a write permission.

  • 11612ae (#194) — Fixed: a 500 on the display name “0”, widget robustness, a CSRF gap and colour contrast.

  • 4a656f8 (#193) — Fixed: the bridge’s SSE resume point survives a connection dropped mid-event.

  • 53797e9 (#192) — Changed: messages dispatched under Playwright are handled inline, so the e2e suite needs no consumer.

  • 9021216 (#190) — Fixed: the authentication pages render outside the signed-in application shell.

  • aa76637 (#189) — Changed: the Terraform configuration pins the shared module at v2.1.0.

  • f35b3fd (#188) — Added: predeploy migrations can be switched on and off with a Terraform variable.

  • 18070c3 (#187) — Added: Terraform configuration for a first DigitalOcean deploy.

  • 8f5b08e (#185) — Added: two site-review skills, and a correction to the site-review user documentation.

  • ab352e0 (#184) — Changed: the site-review widget saves comments as they are written, so there is no send step.

  • 8de0aaf (#178) — Fixed: the landing page scrolls to a section instead of jumping to it.

  • db02e7d (#177) — Added: the site-review widget loads on public pages as well as authenticated ones.

  • ee0bad6 (#176) — Added: a marketing landing page at /.

  • f3f6a85 (#175) — Changed: document_highlight sits behind the review.highlights.enabled flag, seeded off.

  • 97a1ecd (#174) — Added: a Starlight site that renders docs/ in place.

  • b8981fc (#173) — Changed: the documentation is restructured, and non- development configuration moves out of the repository root.

  • 90a73ce (#169) — Added: composer audit runs as part of the CI gate.

  • 31f9280 (#172) — Added: a single-container demo image, published to GHCR.

  • 57be275 (#170) — Added: an About page, branded error pages and a real build version, alongside install-wizard polish.

  • 0b44e2a (#167) — Fixed: league/commonmark moves to 2.9.0, closing six published advisories.

  • bd03266 (#166) — Changed: the comment budget fails the build instead of advising.

  • dae4ba1 (#165) — Fixed: a third party’s first install works, from the self-hosting audit.

  • a752adc (#161) — Changed: the over-budget comment blocks reported by the comment budget are cut.

  • 6d2f003 (#164) — Fixed: the minor items the review loop left open.

  • 4387161 (#163) — Changed: the signed-in application is redesigned.

  • 6624b79 (#162) — Changed: gamache is repointed at its Flex-marker fix.

  • e384254 (#159) — Added: comment length is measured, and handlers are read through everywhere.

  • 99c6f21 (#154) — Changed: sessions, the application cache and rate- limit counters move to Postgres.

  • d50f3ed (#158) — Changed: the site-review Mercure push sits behind a flag with an environment prerequisite.

  • 24c9d8d (#160) — Changed: the Mercure hub is opt-in.

  • b7c9f2a (#156) — Added: an opt-in MinIO container, with the export storage exercised against it.

  • 0e45ade (#155) — Changed: the inline importmap scripts carry a nonce, ahead of enforcing the policy.

  • 5a2b8b2 (#153) — Added: backup guidance, the torn-down-worktree write hazard, and the MCP findings.

  • 0b2acd6 (#152) — Fixed: nine easy tracker items.

  • dc62be7 (#151) — Fixed: guzzlehttp/guzzle moves to 7.15.2.

  • 1fa8b42 (#150) — Changed: the changelog is rewritten at one entry per pull request.

  • 455648b (#138) — Fixed: six small tracker items — phpstan’s memory limit, MCP array parameter schemas, a DisplayLabel rename, the tsconfig, and the widget’s send guard.

  • c80aa85 (#141) — Added: document_get reports a document’s tags and the documents that reference it.

  • 599339e (#145) — Added: browser coverage for the decision controls, asserting the anchors that were actually stored.

  • 04bc2a6 (#149) — Changed: just e2e refuses to run without an explicit target rather than defaulting to one.

  • 647c21d (#144) — Added: the agent account is created during install and shown on the system status page.

  • cc0aff1 (#140) — Fixed: pending verification links are revoked when an account is linked socially, waitlist idioms are deduplicated, and the Mercure publish is bounded.

  • f025820 (#139) — Fixed: the data export fetch-joins its projects instead of issuing a query per row, and the regenerate-token handlers take a lock.

  • 3bb26d8 (#146) — Removed: the site-era widget-token names, and the deprecations this codebase owns.

  • 31c2fc9 (#148) — Changed: a display name is mandatory, suggested from the email address.

  • 758cde0 (#143) — Added: a user can edit their display name.

  • f6ed975 (#142) — Changed: just e2e refuses to run without a consumer, and keeps the worker alive for the duration of the suite.

  • 421c484 (#137) — Added: archiving a document takes a reason, required through MCP and optional in the app; a blank reason is rejected and the archive guard runs under a row lock.

  • 435f128 (#136) — Added: document_set_references replaces a document’s references without minting a version.

  • bf34403 (#134) — Added: a manual test plan for the review wave.

  • 83a3e5e (#133) — Added: reviewer-selectable decision controls — an author fences a list in <!-- decision: id --> and the reviewer clicks an option instead of describing it in a comment.

  • f7e32df (#129) — Added: YAML front matter renders as a table and standalone HTML comments render as visible annotations instead of vanishing.

  • 39aa6a3 (#126) — Added: a word-level diff between two document versions.

  • aa47989 (#132) — Fixed: the documents-search e2e spec waits for the search visit to land instead of sleeping past the debounce.

  • 0d8e47e (#131) — Fixed: site_review_get answers a missing site and an inaccessible one identically, so it no longer reveals which sites exist.

  • 6b3f55f (#124) — Added: full-text search and a filter bar on the documents list.

  • c68224e (#123) — Added: project-scoped tags on documents, with document_set_tags and tag_list.

  • f7773ef (#130) — Fixed: the dev php-fpm pool raised, so worktree and Playwright traffic stops starving requests of a worker.

  • 36e3806 (#128) — Added: an agent can highlight passages of a document.

  • c9ccac4 (#122) — Added: one document can reference another, shown on both sides.

  • c06226c (#127) — Added: strike and suggest as first-class review actions, distinct from leaving a comment.

  • c5adc21 (#125) — Changed: the Markdown sanitizer rewritten to an explicit per-element allowlist. Added: a table-of-contents panel driven by heading ids.

  • 7ceb9ed (#118) — Added: documents can be renamed and archived, and each version records what changed in it.

  • 7ad8c57 (#120) — Added: an agent can reply to and address comments in a document review.

  • 333d02f (#119) — Added: a comment thread carries a status, held by its root comment.

  • 0602470 (#117) — Fixed: comment anchoring uses character-unit windows, word-edge quotes, and untrimmed captured context.

  • dce09f9 (#116) — Changed: every MCP tool renamed with a feature prefix (create_document → document_create and so on, with no aliases — a breaking MCP change), tool access scoped to the token’s bound project, and unrecognised failures reported with a real message instead of a bare -32603.

  • 7ac6fc9 (#114) — Changed: dev logs buffered behind fingers_crossed.

  • cbcc9b0 (#112) — Changed: the DeleteAccountHandler docblock corrected on its coupling to Billing.

  • a3c6b2a (#111) — Removed: stale DaisyUI references from CLAUDE.md and the project-e2e skill.

  • d399c97 (#109) — Fixed: Turbo no longer prefetches the system status page on hover.

  • d50d850 (#108) — Changed: documentation-only branches skip e2e and the Codex review in the pre-PR gate.

  • 83d0985 (#107) — Changed: DEPLOY.md is the single home for deployment documentation.

  • 659576d (#106) — Added: a reference production stack, with deploy tooling unbound from the author’s own accounts.

  • 7c9c1f8 (#101) — Added: the AGPL source is offered from the UI, as the licence requires.

  • 546102c (#103) — Added: the site-review outbox drains on a schedule and surfaces what is stuck.

  • efee5eb (#100) — Added: recovery console commands and registration gating for a self-hosted instance.

  • 3174b05 (#105) — Added: a health endpoint and a system status page.

  • dcd660c (#102) — Changed: data-export archives moved to object storage.

  • 9fbdaca (#104) — Changed: the configuration surface reworked to be the operator’s rather than the author’s.

  • 2a14104 (#99) — Fixed: a batch of one-line self-hosting corrections.

  • 6ca2a63 (#97) — Added: e2e runs against its own disposable target instead of borrowing a worktree.

  • eb0f7d7 (#96) — Changed: just worktree-up takes a NAME, so nothing has to cd into a worktree to provision one.

  • 59c1834 (#95) — Changed: icon SVGs are committed and no longer fetched from Iconify at runtime in production.

  • ca06a80 (#94) — Changed: Loupe documents must use stable IDs for cross-references.

  • eaa0d1c (#92) — Changed: the worktree cwd rule reconciled, and the dnsmasq certificate failure recorded.

  • 1b31251 (#91) — Added: ⌘⏎ submits a document review comment.

  • 78c284e (#89) — Changed: the main session must never move into a worktree.

  • cc6eac6 (#88) — Changed: the site-review feedback on the app shell, the widget and the pages addressed.

  • ac016f5 (#87) — Changed: /api is deny-by-default, widget agent forwarding is opt-in, and review rendering is per-version.

  • 0bff96c (#86) — Changed: docs/NEXT_STEPS.md is committed instead of gitignored.

  • 34f10c0 (#85) — Added: the messenger worker enabled in infrastructure, with the app’s environment wired to it.

  • 0af639e (#84) — Removed: the site-review Review entity; comments carry their own draft state.

  • 04d9896 (#82) — Added: the wave-2 conventions in CLAUDE.md and the skills.

  • e8e0cf5 (#81) — Changed: every value in app.css put on the Tailwind scale.

  • 865f5e3 (#80) — Changed: controllers renamed to the action verbs the convention requires.

  • 3214b66 (#79) — Added: pagination on the projects and documents lists.

  • db995b0 (#78) — Changed: the Review templates namespaced and the Twig components relocated.

  • c139963 (#76) — Changed: arbitrary CSS values converted, and the site-review class names spelled out.

  • a20f5e6 (#73) — Changed: current-user narrowing enforced explicitly, since assert() drops it in production.

  • 4208782 (#75) — Fixed: emailed link hosts pinned, the install wizard gated, and the revision race closed.

  • cbec5e5 (#77) — Added: site-review events persisted in a transactional outbox.

  • 0cab887 (#74) — Changed: symfony/mcp-bundle upgraded to 0.12 and the custom endpoint controller retired.

  • ec1d88f (#72) — Added: the audit-remediation wave’s conventions.

  • d95854e (#71) — Changed: the waitlist full-loop e2e spec split into named behaviours.

  • 17363e6 (#69) — Changed: domain input bound through forms, and the command and messenger handlers thinned out.

  • 2a846fd (#66) — Changed: token revocation routed through a handler, with the CSRF and redirect drift fixed.

  • 06bc59c (#68) — Changed: per-module data purgers, and Stripe cancellation made retryable.

  • c5879eb (#65) — Fixed: hot read paths no longer scale with history size and row count.

  • 1242f50 (#67) — Fixed: a cancelled subscription keeps access through the paid-through date, and the sweep is indexed.

  • 3e152b7 (#62) — Fixed: resolved threads no longer resurrect their replies.

  • 6c3a8bf (#64) — Fixed: the bridge CLI no longer injects reviewer-controlled text into the agent prompt.

  • 32bbf62 (#70) — Fixed: the cs gate reports honestly inside worktrees, and phpstan is warmed.

  • 72762b3 (#63) — Changed: Symfony upgraded to 8.1, clearing the dependency advisories.

  • 0c9c210 (#61) — Removed: stale Codex model names from the pre-PR gate.

  • 6f9f243 (#60) — Added: the loupe-documents skill, covering the formatting rules for the review UI.

  • c766259 (#59) — Added: the post-trial lifecycle — ended trials are disabled, their cap spots freed, and survey emails sent.

  • f16f45e (#49) — Fixed: list_documents wraps its result in a documents object key.

  • 5e7d9aa (#58) — Changed: tracker entries may not carry ephemeral identifiers.

  • 5813dc1 (#57) — Added: a Status field on tracker entries.

  • 7c07e60 (#56) — Added: a priority ordering rule for the tracker.

  • c4253bd (#55) — Added: the project-next-steps skill, defining the tracker entry format.

  • dd134ba (#54) — Added: opt-in ngrok tunnel ingress for the dev app.

  • 1c172ef (#53) — Added: a first-install wizard.

  • 708e35a (#52) — Fixed: the worktree tooling gaps found in the nine-feature-wave retro.

  • d3e9bd7 (#51) — Added: the nine-feature-wave retro learnings, spread across the skills.

  • 3451da3 (#50) — Fixed: transactional email sends from hello@loupe.ac.

  • 2136340 (#47) — Added: self-service account deletion, confirmed by email.

  • 7641503 (#45) — Added: a registration cap with a waitlist behind it.

  • 1528356 (#46) — Added: a project can be deleted.

  • 50db7d2 (#44) — Added: the paid plan — a Stripe trial, then a paywall.

  • 64dd9d8 (#43) — Added: a first-run wizard.

  • 395df8e (#41) — Added: GitHub and Google social login, behind feature flags.

  • d6bf02d (#42) — Changed: admin-bundle re-pinned to main, with #[\Override] style fixes.

  • 3d8bb00 (#40) — Added: an asynchronous “download my data” export.

  • 25a03e8 (#39) — Fixed: dev tooling for multi-worktree development — opcache and lint scope.

  • 18b2ea3 (#38) — Added: an admin area and feature flags.

  • 1e87f0a (#37) — Fixed: rendered documents no longer truncate at the sanitizer’s 20 KB default.

  • c183b8b (#36) — Fixed: truncated just descriptions, and the e2e node_modules symlink ignored.

  • de09ec4 (#35) — Added: the project-worktrees skill.

  • f8a980a (#34) — Added: every worktree gets its own URL and database.

  • 36afb56 (#32) — Added: a project’s name and domain can be edited.

  • bc9fa70 (#33) — Fixed: login throttling relaxed in dev and test, to stop the e2e auth flakes.

  • 7c9363d (#31) — Fixed: the widget surfaces token errors instead of a generic “try again”.

  • b7f8562 (#30) — Added: a just secrets-scan recipe.

  • 7921f67 (#29) — Added: a just composer recipe, used in the README.

  • 6c59e61 (#28) — Changed: dependencies updated, clearing eight security advisories.

  • 38187be (#26) — Changed: open-source readiness — licence, hardening and repository hygiene.

  • ecf3074 (#27) — Changed: updated from the skeleton at 9d91f89.

  • 483a571 (#25) — Added: the symfony/mercure-bundle recipe artifacts committed.

  • 9f54ddc (#24) — Changed: Better Plans renamed to Loupe in the project-templates skill.

  • ab13ded (#23) — Changed: the application renamed from Better Plans to Loupe.

  • bad9e9e (#22) — Added: the API and page-title conventions from AUTOMATIONS.md enforced.

  • 9752117 (#21) — Fixed: the Connect page’s claude mcp add syntax, with an embedded token, a regenerate action and a parameterised name.

  • 01d8012 (#20) — Added: the Connect agent page. Removed: the API-tokens page it replaces.

  • a14495b (#19) — Added: the document review and site review screens.

  • 2562927 (#18) — Added: the app shell and the Projects and Documents screens.

  • 24ac3bf (#17) — Changed: Site renamed to Project, the MCP bound to a project, and the URL space moved to /projects.

  • 9b1693e (#16) — Changed: site review rebuilt from ephemeral batches to a persistent per-site model — a Site entity, site-bound widget tokens, a server-backed widget, per-site Mercure topics, and get_site_review / address_site_review_comments replacing the batch fetch (a breaking MCP change).

  • 4e7b5b0 (#15) — Added: the site-review bridge, piping a submitted review into a local Claude Code session.

  • a5581af (#14) — Changed: the site-review widget redesigned, visually and in its interaction.

  • 968a9e0 (#13) — Changed: site-review widget icons, pins, shortcuts and feedback improved.

  • b72adc8 (#12) — Changed: gamache bumped to the hardened deny-access rule.

  • 7f6c1a8 (#11) — Fixed: a batch of site-review feedback across review, site review and account.

  • 85366f9 (#10) — Changed: the SaaS visual redesign — a collapsible sidebar and a coherent set of primitives.

  • f9d417a (#9) — Added: review comments can be replied to and resolved through forms and Turbo Streams, with the anchor quote shown.

  • 47e72b3 (#8) — Fixed: Turbo prefetch disabled on the logout link.

  • 225f5b4 (#7) — Added: the annotation widget embedded on the app itself, for dogfooding.

  • c3bd63e (#6) — Added: human-facing site-review batch list and detail pages.

  • 5ad6f74 (#5) — Added: an embeddable annotation widget and scoped API tokens.

  • 23bcb25 (#4) — Fixed: anchor context kept UTF-8-safe, which was crashing revisions.

  • b06b44d (#3) — Changed: the skeleton sync point recorded for the gamache bump.

  • d1ffc2e (#2) — Changed: ubermuda/gamache bumped for the third-party-arguments exemption.

  • a0d60dc (#1) — Added: the agent document review MCP service — the first feature of the app.

  • 2cc07e0 — Added: the application bootstrapped from symfony-skeleton, with the MCP and Markdown dependencies. Every entry below this line belongs to the skeleton’s own history, not this app’s, and predates the one-entry-per-PR rule above.

  • 7618557 — Removed: generic slash commands (port-to-skeleton, pr-feedback, retro) promoted out of the template to user-level ~/.claude/commands, shared across all skeleton-derived projects rather than duplicated per-repo.

  • 496d168 — Changed: consume the extracted ubermuda/doctrine-extra and ubermuda/symfony-extra packages instead of in-tree helpers.

  • 90443f5 — Changed: whole-tree test discovery in phpunit.dist.xml, so new test directories are picked up without config edits.

  • fc342f6, 24ee28c — Changed: prettier no longer formats assets/controllers.json; the file was normalised to 2-space indentation.

  • 328ff99 — Added: optional infrastructure presets — a worktree-aware CI harness, an in-memory test messenger transport, and an encrypted Doctrine column type (all opt-in).

  • a2810d3 — Added: command-handler, authorization, and entity-route-mapping skills under .claude/skills/, plus the dotted resource.action authorization naming convention.

  • 8d3d2d2 — Added: declarative #[CsrfToken] attribute for hand-rolled forms, plus Monolog stack traces in the logging stack.

  • f24bcd9, 8edeb0d, b6d3e6f — Changed: custom static analysis moved to the ubermuda/gamache package (PHPStan/Rector/TwigCsFixer rules and Check classes), consumed as a dev-main dependency instead of living inline.

  • cbd83ad — Added: Mercure SSE documentation section and the Symfony UX Icons import conventions.

  • 7064a94, fdc3c2a, b4f5d42 — Removed: legacy bin/check-* and bin/gamache scripts, superseded by gamache’s Check classes and the package-provided vendor/bin/gamache.

  • 5fd43be — Added: Dockerised dev environment wired so just ci and just e2e run inside the container.

  • c57e7c8 — Added: PHPArkitect architecture tests and the initial set of custom CI checks.

  • c33efd8 — Added: initial skeleton — base Symfony application, tooling, and .claude/ conventions.