From d8b15086d8bb0c43031c19d1282ef27828688ab1 Mon Sep 17 00:00:00 2001
From: Aaron Phifer <191053702+aaronphifer@users.noreply.github.com>
Date: Mon, 12 Oct 2026 13:19:23 -0400
Subject: [PATCH 1/3] feat: prepare Agent Board 0.7.0-rc.1
---
CHANGELOG.md | 27 ++++-
PLUGIN_OVERVIEW.md | 12 +-
README.md | 11 ++
RELEASE_NOTES.md | 41 +++++++
components/board/activity-freshness.tsx | 11 ++
components/board/board-card-view.tsx | 8 +-
components/board/completion-summary.tsx | 14 +++
components/board/single-agent-focus.tsx | 2 +
components/global/global-dashboard.tsx | 52 +++++++--
components/global/release-announcement.tsx | 36 ++++++
contract/rpc.ts | 22 ++++
docs/architecture.md | 2 +-
docs/marketplace-0.7.0-proposal.md | 30 +++++
docs/release-convention.md | 25 +++++
docs/upgrade-0.7.0.md | 69 ++++++++++++
docs/validation-0.7.0.md | 48 ++++++++
docs/vnext-design.md | 40 +++++++
docs/vnext-testing.md | 125 +++++++++++++++++++++
hooks/useGlobalDashboard.ts | 20 ++--
lib/bb-source.ts | 17 +++
lib/board-model.ts | 4 +-
lib/collect.ts | 61 +++++++++-
lib/dashboard-view.ts | 75 +++++++++++++
lib/global-model.ts | 4 +
lib/releases.ts | 36 ++++++
lib/watch.ts | 50 ++++++---
package-lock.json | 4 +-
package.json | 20 +++-
scripts/build-dev.ps1 | 24 ++++
scripts/dev-host.sh | 43 +++++++
scripts/linux-validation-host.sh | 38 +++++++
scripts/validation-host.ps1 | 41 +++++++
server.ts | 10 +-
tests/bb-source.test.ts | 21 ++++
tests/board-model.test.ts | 6 +
tests/dashboard-view.test.ts | 78 +++++++++++++
tests/global-app.test.tsx | 30 ++---
tests/global-collect.test.ts | 21 +++-
tests/public-sdk.test.ts | 8 +-
tests/releases.test.ts | 50 +++++++++
tests/vnext-app.test.tsx | 97 ++++++++++++++++
tests/vnext-fixtures.ts | 13 +++
tests/vnext-server.test.ts | 20 ++++
tests/watch.test.ts | 19 ++++
tsconfig.json | 1 +
vitest.config.ts | 6 +-
46 files changed, 1321 insertions(+), 71 deletions(-)
create mode 100644 components/board/activity-freshness.tsx
create mode 100644 components/board/completion-summary.tsx
create mode 100644 components/global/release-announcement.tsx
create mode 100644 docs/marketplace-0.7.0-proposal.md
create mode 100644 docs/release-convention.md
create mode 100644 docs/upgrade-0.7.0.md
create mode 100644 docs/validation-0.7.0.md
create mode 100644 docs/vnext-design.md
create mode 100644 docs/vnext-testing.md
create mode 100644 lib/dashboard-view.ts
create mode 100644 lib/releases.ts
create mode 100644 scripts/build-dev.ps1
create mode 100644 scripts/dev-host.sh
create mode 100644 scripts/linux-validation-host.sh
create mode 100644 scripts/validation-host.ps1
create mode 100644 tests/dashboard-view.test.ts
create mode 100644 tests/releases.test.ts
create mode 100644 tests/vnext-app.test.tsx
create mode 100644 tests/vnext-fixtures.ts
create mode 100644 tests/vnext-server.test.ts
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2bdc1fa..ef06174 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,30 @@
# Changelog
+## Unreleased — 0.7.0 (candidate 0.7.0-rc.1)
+
+- Show the latest observed public activity and distinguish recent from quiet
+ reporting, without changing task status or the indeterminate activity strips.
+- Add structured completion outcome/result/failure sections, explicitly labeled
+ agent-reported verification and access to the original bounded output preview.
+- Filter and group the bounded dashboard by project, repository, provider and
+ status. Project metadata lookup is optional, bounded and credential-safe.
+- Separate transport connection, refresh/change timestamps and watcher health.
+ Contain watcher callback/publication errors and surface degraded monitoring.
+- Reduce empty Needs attention to a compact line; actionable items remain visible.
+- Add bundled What's New highlights with per-version local dismissal and a
+ persistent Release notes control. No telemetry or remote release fetching.
+- Retain explicit result/check labels before truncating the original output preview.
+- Qualify cached watcher health when disconnected, a refresh fails or becomes overdue.
+- Keep terminal duration unknown when the source supplies no completion timing.
+- Bound package contents to runtime source, assets and user documentation;
+ exclude tests, validation helpers, reports and temporary evidence from npm packs.
+- Make public-SDK test paths portable to Windows and use a serial Vitest thread
+ pool for reliable startup on the development laptop.
+
+No storage migration or settings reset is required. BB >=0.40 and SDK >=0.4.21
+remain declared; BB 0.46.0 is recommended. See [upgrade notes](docs/upgrade-0.7.0.md)
+and [release convention](docs/release-convention.md). This candidate is not published.
+
## 0.6.1 — first public beta
- Fix managed Git installation when BB omits development dependencies: keep the
@@ -7,7 +32,7 @@
- 0.6.0 remained an unpublished release candidate.
Dates are omitted because these milestones were local development commits.
-0.6.0 is the first planned public beta.
+0.6.1 is the first public beta; 0.6.0 remained unpublished.
## 0.6.0
- Optional Ollama Fleet public observability integration.
diff --git a/PLUGIN_OVERVIEW.md b/PLUGIN_OVERVIEW.md
index eab8927..3a0c5e7 100644
--- a/PLUGIN_OVERVIEW.md
+++ b/PLUGIN_OVERVIEW.md
@@ -5,9 +5,19 @@ completion. Open a thread's Agent Board action for automatic single-agent focus
or a multi-agent Kanban view. Inspect the bounded execution timeline to see
public operational updates, actual models, and tools as sources report them.
+See how recently an agent reported public activity. Quiet reporting keeps the
+source's task status intact. Review completion outcomes, results, failures and
+explicitly agent-reported checks, then open the original thread or timeline for
+details. Filter and group visible work by project, repository, provider or status.
+Needs Attention stays visible across filters. Connection, refresh and watcher
+health help you distinguish an observation problem from quiet execution.
+
+What's New shows bundled version highlights. Dismiss an announcement once and
+reopen its notes from the dashboard whenever needed.
+
## Requirements
-Requires BB. Ollama Fleet 0.6.0 or newer and Redteam's public observability RPC
+Requires BB 0.40 or newer; BB 0.46.0 is recommended. Ollama Fleet 0.6.0 or newer and Redteam's public observability RPC
are optional integrations. Missing integrations leave native BB observation
available. Mobile layouts and reduced-motion preferences are supported.
Hidden reasoning is excluded. System/push notifications are unavailable in
diff --git a/README.md b/README.md
index 353cf01..025de95 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,11 @@ focus and the global dashboard offer other views of the same bounded state.
- **Multi-Agent Kanban:** live state for concurrent agents and workers.
- **Needs Attention:** structured waiting/failure states and persistent dismissal.
- **Execution Timeline:** bounded operational events, loaded when opened.
+- **Activity freshness:** recent or quiet public reporting without inferring a stall.
+- **Completion summaries:** outcomes, results, failures and agent-reported checks.
+- **Filters and grouping:** project, repository, provider and status over visible work.
+- **Monitoring health:** connection, successful refresh and watcher status.
+- **What's New:** version highlights with persistent dismissal and later viewing.
- Native BB threads, workflows, delegations, models and tools.
- Optional Ollama Fleet and Redteam observation.
- Mobile layouts, keyboard controls, and reduced-motion support.
@@ -64,6 +69,7 @@ bb plugin install .
Neither Fleet nor Redteam is required. Declared compatibility is BB >=0.40 and
SDK >=0.4.21; the development SDK is pinned to 0.4.34. See the honest
[compatibility matrix](RELEASE_AUDIT.md), including historical runtime evidence.
+For the unreleased 0.7.0 candidate, see [compatibility and upgrade notes](docs/upgrade-0.7.0.md).
## Usage
@@ -144,6 +150,11 @@ This is a bounded latest view, not a persistent history database.
## Development
+The unreleased Phase 1 preview is documented in [vnext launch/testing](docs/vnext-testing.md),
+[design](docs/vnext-design.md) and [release convention](docs/release-convention.md).
+Use a separate BB data directory and ports for development; keep your stable
+installation untouched. `0.7.0-rc.1` is not a published release.
+
```sh
npm ci
npm test
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index d003375..2e3b877 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,3 +1,44 @@
+# Agent Board v0.7.0 — draft release notes
+
+Candidate: **0.7.0-rc.1**, unpublished and awaiting review. These notes are a
+draft for the eventual 0.7.0 release.
+
+Agent Board gives you a clearer view of live agent work and completed outcomes.
+
+- **Activity freshness:** see the age of the latest public activity and whether
+ reporting is recent or quiet. Long tasks keep their authoritative status and
+ the existing animated activity bars.
+- **Completion outcomes:** review results, failures and explicitly agent-reported
+ checks in separate sections. Open the original thread or bounded timeline for details.
+- **Filters and grouping:** organize visible work by project, repository, provider
+ or status. Needs Attention and operational counts remain visible across filters.
+- **Monitoring health:** distinguish transport connection, snapshot refresh and
+ source-watcher health. Cached watcher status is qualified when it cannot be confirmed.
+- **What's New:** read bundled version highlights, persist dismissal for that
+ version, and reopen its notes from the dashboard. Empty Needs Attention is compact.
+
+Reliability fixes preserve explicit result/check metadata before output truncation,
+qualify cached health during disconnects and failed/overdue refreshes, and avoid
+inventing elapsed duration for terminal tasks without completion timing.
+
+Existing settings and attention dismissals are preserved. No manual data migration
+or configuration change is required. BB >=0.40 and public SDK >=0.4.21 remain
+declared; BB **0.46.0 is recommended**. Optional Fleet >=0.6.0 and a Redteam
+runtime exposing the public observability contract remain optional.
+
+BB installs tracking `^0.6.1` do not include 0.7.0. After publication, users must
+select the new marketplace release or change their Git selector to `^0.7.0`.
+Pinned tags/commits remain pinned. See [compatibility and upgrade notes](docs/upgrade-0.7.0.md).
+
+Filters cover the bounded visible snapshot. Quiet reporting does not prove a
+stall, and reported checks are not independent test evidence. Release notes in
+the UI are bundled highlights; GitHub hosts the full release notes. There are
+no new push notifications, automatic-install promises or Phase 2 features.
+
+Candidate checks, coverage provenance and remaining limits are recorded in
+[the validation summary](docs/validation-0.7.0.md). Detailed machine-specific
+reports and live screenshots remain local development evidence.
+
# Agent Board v0.6.1
First public beta: live execution observability for BB.
diff --git a/components/board/activity-freshness.tsx b/components/board/activity-freshness.tsx
new file mode 100644
index 0000000..abf45e2
--- /dev/null
+++ b/components/board/activity-freshness.tsx
@@ -0,0 +1,11 @@
+import type { BoardCard } from "@/contract/rpc";
+import { activityFreshness } from "@/lib/dashboard-view";
+import { formatElapsed } from "@/lib/board-model";
+
+export function ActivityFreshness({ card, now }: { card: BoardCard; now: number }) {
+ const freshness = activityFreshness(card, now);
+ return
;
+}
diff --git a/contract/rpc.ts b/contract/rpc.ts
index 13a3119..030830f 100644
--- a/contract/rpc.ts
+++ b/contract/rpc.ts
@@ -123,8 +123,13 @@ export const boardCardSchema = z.object({
/** Task preview where the source exposes one (workflow promptPreview). */
promptPreview: z.string().nullable(),
activity: boardActivitySchema.nullable(),
+ /** Most recent public activity; never the snapshot fetch time. */
+ lastActivityAt: z.number().nullable().optional(),
/** Compact final-output preview (truncated server-side). */
outputPreview: z.string().nullable(),
+ /** Explicit agent-reported labels, retained before output preview truncation. */
+ completionResult: z.string().max(240).nullable().optional(),
+ reportedVerification: z.array(z.string().max(240)).max(4).optional(),
/**
* Latest user-visible assistant-authored text (bounded excerpt). Strictly
* conversational: never reasoning, tool/command output, or user/system
@@ -219,6 +224,8 @@ export const globalExecutionSchema = z.object({
card: boardCardSchema,
projectId: z.string().nullable(),
delegatedWorkers: z.array(boardCardSchema).max(4).optional(),
+ projectName: z.string().nullable().optional(),
+ repository: z.string().nullable().optional(),
delegatedWorkerCount: z.number().int().nonnegative().optional(),
activeDelegatedWorkerCount: z.number().int().nonnegative().optional(),
childCount: z.number().int().nonnegative(),
@@ -353,6 +360,13 @@ export const globalDashboardCountsSchema = z.object({
export type GlobalDashboardCounts = z.infer;
const globalDashboardSnapshotSchema = z.object({
+ monitoring: z.object({
+ status: z.enum(["watching", "degraded", "unavailable", "disposed"]),
+ startedAt: z.number(),
+ lastEventAt: z.number().nullable(),
+ lastPublishedAt: z.number().nullable(),
+ lastErrorAt: z.number().nullable(),
+ }).optional(),
active: z.array(globalExecutionSchema),
attention: z.array(attentionItemSchema),
recent: z.array(globalExecutionSchema),
@@ -382,6 +396,14 @@ export const boardChangedPayloadSchema = z.object({
});
export const rpcContract = {
+ release_announcement: {
+ input: z.object({}),
+ output: z.object({ version: z.string(), title: z.string(), highlights: z.array(z.string()), dismissed: z.boolean() }),
+ },
+ dismiss_release_announcement: {
+ input: z.object({ version: z.string().min(1).max(80) }),
+ output: z.object({ dismissed: z.boolean() }),
+ },
/**
* Normalized board for one root thread and its publicly visible
* descendants/workflows. `fresh: true` bypasses the short-lived
diff --git a/docs/architecture.md b/docs/architecture.md
index 122fb38..bca105b 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -14,7 +14,7 @@ Agent Board is a generic BB execution-observability plugin with two complementar
The mode is derived from the normalized snapshot by a pure view model (`lib/focus-model.ts`); no source-specific logic lives in the UI. The board is derived from authoritative sources on demand. It stores no duplicate board state and never renders reasoning/thinking events, fabricated progress percentages, or raw tool output.
-The global page uses the stable public `app.slots.navPanel` surface and `useBbNavigate().toThread(...)`. `lib/global-model.ts` collapses normalized source cards into independent logical executions, derives attention only from explicit structured metadata, and removes resolved conditions automatically. It does not inspect assistant prose. Stale/no-activity warnings are intentionally omitted because current timestamps cannot prove a stall reliably.
+The global page uses the stable public `app.slots.navPanel` surface and `useBbNavigate().toThread(...)`. `lib/global-model.ts` collapses normalized source cards into independent logical executions, derives attention only from explicit structured metadata, and removes resolved conditions automatically. It does not inspect assistant prose to infer attention. Phase 1 adds public-activity age and recent/quiet reporting labels; these never prove a stall or change execution status. Completion verification is explicitly agent-reported. See [the vnext design](vnext-design.md).
## Sources
diff --git a/docs/marketplace-0.7.0-proposal.md b/docs/marketplace-0.7.0-proposal.md
new file mode 100644
index 0000000..26011d1
--- /dev/null
+++ b/docs/marketplace-0.7.0-proposal.md
@@ -0,0 +1,30 @@
+# Marketplace update proposal — not submitted
+
+Current reviewed entry: `get-bb/marketplace/entries/agent-board.json`, source
+range `^0.6.1`. Preserve its id, source URL, category, author, icon and existing
+reviewed synthetic screenshot. After 0.7.0 publication, propose:
+
+```json
+{
+ "description": "Follow live BB agent activity, freshness, completion outcomes and monitoring health. Filter and group visible work by project, repository, provider or status. Optional Ollama Fleet and Redteam add worker visibility. Requires BB 0.40+; BB 0.46.0 recommended.",
+ "source": {
+ "git": {
+ "url": "https://github.com/aaronphifer/bb-plugin-agent-board.git",
+ "range": "^0.7.0"
+ }
+ }
+}
+```
+
+This is a fragment describing edits to the existing entry, not a standalone
+marketplace manifest. Copy the updated `PLUGIN_OVERVIEW.md` into
+`overview/agent-board.md`. Compatibility remains in package engines; do not add
+unsupported compatibility/version fields to the marketplace entry. Do not use
+live validation screenshots containing private task details as listing media.
+
+Existing installs retain their stored source range. Tell `^0.6.1` users to
+select/reinstall the new marketplace release or use the `^0.7.0` Git command in
+the upgrade notes. Do not ask them to uninstall, which would delete preferences.
+Publishing only a `v0.7.0` tag will not move their existing 0.6.x selector.
+
+No marketplace repository edits, PRs, submissions or announcements were made.
diff --git a/docs/release-convention.md b/docs/release-convention.md
new file mode 100644
index 0000000..37e76f9
--- /dev/null
+++ b/docs/release-convention.md
@@ -0,0 +1,25 @@
+# Release notes convention
+
+This work is unreleased. `0.7.0-rc.1` identifies the development release candidate;
+it is not a stable tag, release, marketplace or production update.
+
+For each approved release:
+
+1. Finalize the `Unreleased` section of CHANGELOG.md, with user-facing changes,
+ relevant fixes, compatibility and known limitations. Move it to a versioned
+ section with the actual release date; keep earlier sections intact.
+2. Set package.json and the lockfile root to the same version. `lib/releases.ts`
+ imports that package version and provides the bundled announcement title and
+ highlights. Do not include unverified test claims in those highlights.
+3. Put the complete human-facing notes in RELEASE_NOTES.md, led by the new
+ version. Keep previous notes below it. Link compatibility/testing evidence.
+4. Use GitHub release title `Agent Board vX.Y.Z`, tag `vX.Y.Z`, and copy the
+ finalized release notes into its body. Keep pre-release builds marked as
+ pre-releases. A repository tag/release or marketplace change requires the
+ maintainer's explicit approval; this convention grants none.
+
+The UI reads only bundled notes, never GitHub or the marketplace. Dismissal is
+stored in plugin KV for the exact version (latest 20 dismissed versions), so
+reloads retain dismissal, upgrades show new notes, and a recent downgrade
+retains its old dismissal. Release notes can be opened later from the dashboard.
+Storage failures are shown, not silently treated as saved.
diff --git a/docs/upgrade-0.7.0.md b/docs/upgrade-0.7.0.md
new file mode 100644
index 0000000..6a503b5
--- /dev/null
+++ b/docs/upgrade-0.7.0.md
@@ -0,0 +1,69 @@
+# Agent Board 0.7.0 compatibility and upgrade notes
+
+The current source is **0.7.0-rc.1**, an unpublished candidate. Do not install
+it over a stable installation as part of release review.
+
+## Compatibility
+
+The package declares BB `>=0.40` and public Plugin SDK `>=0.4.21`.
+BB **0.46.0** is the recommended runtime, also the latest published `bb-app`
+version checked during this review on 12 October 2026. The development/test SDK
+remains pinned to **0.4.34**. The BB 0.40.0 builder stamps SDK 0.4.21; the
+BB 0.46.0 builder stamps SDK 0.6.37. These are different roles: the development
+pin supplies types/test harnesses, while BB builds and supplies runtime shims.
+No dependency upgrade or compatibility-range narrowing was made.
+
+Phase 1 adds one BB SDK read, `projects.get`, using `name` and `gitRemoteUrl`.
+Both fields and that method exist in SDK 0.4.21. Project lookup is optional,
+bounded, cached and failure-tolerant. New announcement RPCs use existing plugin
+RPC and KV storage APIs. Existing realtime, navigation and lifecycle APIs are
+reused. No new permission/capability declaration, migration, provider access
+or external service is required.
+
+A disposable BB 0.40.0 runtime built, installed and served the preview.
+Candidate checks are detailed in the [validation summary](validation-0.7.0.md). A source-only
+typecheck against SDK 0.4.21 reports eight references to the newer optional queue
+`waitingOn` field; the unchanged 0.6.1 source reports the same eight errors.
+Those accesses already tolerate an absent field at runtime. New Phase 1 API
+uses pass that static comparison. This is not a claim that the full development
+suite runs on the oldest SDK harness.
+
+BB 0.40.0 could not refresh today's community catalog because it accepts at
+most 256 entries. Direct local plugin installation and RPC smoke work; use
+BB 0.46.0 for current marketplace discovery. Fresh Linux graphical-browser and
+physical-device checks remain limited. The RC subsequently passed Windows
+automated/build and browser/live-provider validation; prior Linux live-provider
+coverage applies to the same reviewed runtime source. See the validation summary
+for the distinction between fresh and historical checks.
+
+Fleet >=0.6.0 is optional. Redteam is optional and must actually expose
+`observability_snapshot` schema version 1; a version number alone is not enough.
+The installed local Redteam 0.7.2 does not expose it and correctly remains unavailable.
+
+## Existing users
+
+Agent Board keeps the same plugin identity (`agent-board`). Existing settings
+and attention-dismissal storage are retained; no manual migration or reset is
+needed. The new release-dismissal preference is separate and version-specific.
+The current announcement appears when upgrading from 0.6.1 or skipping earlier
+releases. Missing/malformed dismissal storage shows the announcement again;
+storage read/write failures are surfaced. Only the latest 20 dismissed versions
+are retained. Bundled notes can be reopened after dismissal.
+
+After final approval and publication only:
+
+```sh
+bb plugin install git:https://github.com/aaronphifer/bb-plugin-agent-board.git@^0.7.0
+```
+
+Reinstalling the same identity through BB replaces its source while retaining
+plugin preferences; do not remove/uninstall first, because removal deletes
+plugin storage. Exact tag/commit installations stay pinned. `^0.6.1` permits
+0.6.x but excludes 0.7.0. Changing the marketplace entry to `^0.7.0` affects new
+selections, not the selector already stored by an existing installation.
+
+BB checks managed Git/npm installations for compatible updates and presents
+them for an explicit update action. Path/builtin sources are pinned. Stable
+semver ranges exclude prereleases unless the range explicitly names one.
+Agent Board's What's New appears after installing a new version; it does not
+discover remote releases, send push notifications or install updates itself.
diff --git a/docs/validation-0.7.0.md b/docs/validation-0.7.0.md
new file mode 100644
index 0000000..461a70b
--- /dev/null
+++ b/docs/validation-0.7.0.md
@@ -0,0 +1,48 @@
+# Agent Board 0.7.0-rc.1 validation summary
+
+The candidate is unpublished. These checks support development review, not
+stable-release, marketplace or automatic-install approval. Detailed host-specific
+reports, logs, synchronization manifests and live screenshots are retained
+locally and excluded from the public commit.
+
+## Reviewed source and checks (12 October 2026)
+
+Before public-documentation cleanup, 134 source inventory hashes matched between
+Windows and Pop!_OS. Public cleanup only changes documentation and one launcher's
+missing-tools help message; plugin implementation, tests, animation, dependencies,
+version and compatibility declarations remain the reviewed candidate.
+
+| Coverage | Result and provenance |
+| --- | --- |
+| Windows full suite | 468 tests / 24 files passed. The first cold-import timeout was followed by an unchanged passing full rerun. |
+| Windows adapter regression | 109 Fleet/Redteam tests / 6 files passed; a subset of the full suite. |
+| Windows focused checks | 37 announcement, dashboard, JSON and public-SDK tests / 4 files passed; a subset of the full suite. |
+| Windows typecheck / official build | Passed, BB 0.46.0 builder. Fresh frontend/backend metadata both identify the candidate. |
+| Pop!_OS RC review | Independently passed 468 tests / 24 files, 109 adapter tests, typecheck and official build. |
+| Minimum/current Linux runtime | BB 0.40.0 and 0.46.0 built, directly installed and served the RC in disposable hosts; RPC/app-asset/announcement smoke passed. |
+| Production-only Linux install | Clean runtime dependency/source build and installation passed without the development SDK. |
+| Actual Windows providers | Codex created and ran three Python unittests; Grok completed harmless delay/review tasks and explicitly reported tests not run. A controlled invalid-model failure appeared correctly. |
+| Actual Linux providers | Earlier Linux validation ran Codex/Grok tasks and host recovery on the preview; the reviewed implementation is unchanged by RC documentation/version preparation. New inference tasks were not rerun in the independent Linux RC review. |
+| Windows UI/storage | Monitoring health, saved attention preservation, version dismissal/reload/reopening, filtering/grouping, completion provenance, active animation, Open/Timeline and desktop/narrow rendering passed. |
+| Package inspection | Fresh 68-file Windows package: correct plugin/version metadata, required runtime assets, unchanged dependencies and no test/runtime/credential data. |
+
+Windows native BB worked in the inspected environment. This is empirical evidence,
+not a claim of general native Windows host support. Codex's Windows sandbox
+startup failures required scoped one-time approvals for the disposable fixture;
+no authentication, persistent permissions or networking settings were changed.
+
+The SDK 0.4.34 development pin differs from the builder SDK. A source-only
+typecheck against the declared 0.4.21 floor finds eight existing optional queue
+`waitingOn` typing errors, also present in unchanged 0.6.1. New Phase 1 SDK use
+is present at that floor and optional at runtime. This does not claim the full
+development harness runs against the oldest SDK package.
+
+Nonempty live Fleet/Redteam coverage remains limited. Optional Redteam needs the
+public schema-version-1 observability RPC; a version number alone is insufficient.
+BB 0.40.0's community-catalog entry cap limits current marketplace discovery,
+while direct installation works. Physical-device and fresh Linux graphical
+browser coverage remain separate. Existing bounded-history and agent-reported
+verification limits still apply.
+
+See [testing instructions](vnext-testing.md), [compatibility/upgrade notes](upgrade-0.7.0.md),
+[release notes](../RELEASE_NOTES.md) and [release procedure](release-convention.md).
diff --git a/docs/vnext-design.md b/docs/vnext-design.md
new file mode 100644
index 0000000..3f38f85
--- /dev/null
+++ b/docs/vnext-design.md
@@ -0,0 +1,40 @@
+# Phase 1 design (unreleased)
+
+Base: main, 92efdcdf89b838713dac7ebc9fc2eaef9e4b8860, plugin 0.6.1.
+Development branch: feature/agent-board-vnext. This is an unpublished
+release candidate. Stable installation and publication require separate approval.
+
+Reuse the public SDK collectors, normalized cards, bounded caches, lifecycle
+watcher, optional Fleet/Redteam adapters and React hooks. Codex/Grok observation
+is mediated by BB threads/providers; there are no provider session-file watchers.
+Preserve LiveStrip, its CSS, reduced motion, source privacy and collection caps.
+
+Add pure dashboard derivation for freshness, filters/grouping and completion
+sections. Freshness uses source activity timestamps rather than fetch times or
+thread updatedAt (which can include cosmetic changes). Old observations mean
+quiet reporting, never failed/stalled work. Verification extracted from labeled
+output remains agent-reported, not independently verified. Full output remains
+accessible in BB through Open; the plugin keeps its bounded sanitized preview.
+
+Enrich global executions with project names/git remotes using bounded public
+projects.get calls for observed project IDs. Missing metadata is explicit and
+must not prevent native observation. Filter only the already bounded snapshot;
+the page states that matching sessions outside that window are not searched.
+Attention stays visible independently of execution filters.
+
+Separate transport connection, successful snapshot refresh and server watcher
+health. Record timestamps and generic error categories only. Quiet connections
+are not errors. Catch asynchronous watcher errors and failed publication instead
+of leaking rejected promises; expose degradation in the snapshot.
+
+Add a small version-keyed release dismissal store using plugin KV and bundled
+release highlights. Use the package version as the single version source. A
+release-notes control remains available after dismissal; storage failures stay
+visible. No network, account, telemetry or external release fetching.
+
+Automated validation uses the official SDK fake server/app hosts, synthetic
+data, separate dependencies and isolated storage. Real provider checks use a
+verified separate BB data directory and loopback ports; never install a preview
+into the production host. See [testing](vnext-testing.md) and
+[candidate validation](validation-0.7.0.md).
+No Lattice runtime integration or future orchestration/analytics is added.
diff --git a/docs/vnext-testing.md b/docs/vnext-testing.md
new file mode 100644
index 0000000..19e6acb
--- /dev/null
+++ b/docs/vnext-testing.md
@@ -0,0 +1,125 @@
+# Development launch and verification
+
+Use Node.js 24 and an isolated BB host. The candidate is `0.7.0-rc.1`;
+it is unpublished. See [candidate validation](validation-0.7.0.md) for
+cross-platform results and their limits. Never install a review build over the
+stable plugin, share its data directory, or copy its credentials into a test host.
+
+## Automated checks
+
+From the candidate checkout:
+
+```sh
+npm ci --ignore-scripts --no-audit --no-fund
+npm test
+npm run typecheck
+```
+
+The suite uses the public SDK fake hosts, synthetic fixtures and isolated
+storage. Vitest uses a serial thread pool for reliable Windows startup. A cold
+import timeout has been observed: record the failed run, investigate it and
+rerun unchanged checks; do not count a timeout as a pass. The development SDK
+pin is 0.4.34. The official BB 0.46.0 builder stamps SDK 0.6.37; these serve
+different roles and a build notice does not authorize upgrading the pin.
+
+## Guarded Windows helpers
+
+The helpers intentionally require this disposable workspace layout:
+
+```text
+/outputs/agent-board-vnext/ candidate checkout
+/work/bb-build-tools/ isolated official BB tools
+/work/bb-validation-windows-data/ test data; preserve across restarts
+```
+
+Prepare tools outside the checkout, from ``:
+
+```powershell
+npm install --prefix work\bb-build-tools --ignore-scripts --no-audit --no-fund bb-app@0.46.0
+```
+
+Use an environment with working native SQLite dependencies. The native Windows
+host was exercised successfully during this review; that is empirical coverage,
+not a general platform-support promise. Prefer the supported Linux/WSL host
+where available; do not change system networking or authentication to make a
+validation environment work.
+
+From the candidate checkout, build and start in one terminal:
+
+```powershell
+$env:BB_CLI=''
+.\scripts\build-dev.ps1
+.\scripts\validation-host.ps1 start
+```
+
+After the test host is healthy, in a second terminal in the same checkout:
+
+```powershell
+$env:BB_CLI=''
+.\scripts\validation-host.ps1 install
+.\scripts\validation-host.ps1 status
+```
+
+Open and choose Agent Board. Server/daemon ports are
+49986/49987; telemetry and in-app updates are disabled for this host. Install
+and stop verify the launcher marker, executable path, URL and process identity.
+The build helper uses separate build data and restores the caller's environment.
+
+After all disposable tasks finish:
+
+```powershell
+$env:BB_CLI=''
+.\scripts\validation-host.ps1 stop
+```
+
+Keep the test data. Do not uninstall to test an upgrade: replacing the same
+plugin identity preserves preferences, while uninstalling deletes them.
+
+## Guarded Linux helper
+
+`scripts/linux-validation-host.sh` uses only
+`$HOME/.local/share/agent-board-vnext-validation/`, loopback ports 50886/50887,
+and the source checkout containing the script. It refuses occupied start ports
+and verifies the launcher identity before install/stop. Prepare its dedicated
+`node24/` directory with an official Node 24 distribution verified against the
+vendor checksums; keep it separate from system and production runtimes.
+
+```bash
+runtime="$HOME/.local/share/agent-board-vnext-validation"
+npm install --prefix "$runtime/bb-tools" --ignore-scripts --no-audit --no-fund bb-app@0.46.0
+(cd "$runtime/bb-tools" && npm rebuild better-sqlite3)
+bash scripts/linux-validation-host.sh build
+bash scripts/linux-validation-host.sh start
+```
+
+In another terminal, from the candidate checkout:
+
+```bash
+bash scripts/linux-validation-host.sh install
+bash scripts/linux-validation-host.sh status
+```
+
+Open . Stop only that test host after tasks finish:
+
+```bash
+bash scripts/linux-validation-host.sh stop
+```
+
+The older `scripts/dev-host.sh` is a workspace-layout-specific WSL helper using
+`/work/bb-linux-tools`, `/work/bb-wsl-data` and ports
+49886/49887. It does not share selectors with the native Windows or Linux
+validation hosts. Inspect selectors and prerequisites before using any helper.
+
+## Acceptance checks
+
+Use a disposable project for real provider work. Verify connected transport,
+refresh/watch health, project/repository/provider/status filters and grouping,
+attention preservation, completed results with explicit verification provenance,
+controlled failure states, Open/Timeline navigation, active animation and
+version-scoped announcement dismissal/reload/reopening. Test a narrow viewport
+as well as desktop and reset temporary viewport overrides afterward.
+
+Agent-reported checks are not independent test evidence. Quiet reporting does
+not prove a stall. Optional Fleet/Redteam fixtures do not replace nonempty live
+adapter coverage. Save detailed local logs/screenshots in ignored `evidence/`;
+do not publish private task text, paths, databases or credentials.
diff --git a/hooks/useGlobalDashboard.ts b/hooks/useGlobalDashboard.ts
index 20bb78b..e9defb7 100644
--- a/hooks/useGlobalDashboard.ts
+++ b/hooks/useGlobalDashboard.ts
@@ -1,6 +1,6 @@
// Global dashboard data hook. Core thread events drive immediate refreshes;
// one slow bounded discovery check catches unrelated optional-plugin work.
-import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { useCallback, useEffect, useRef, useState } from "react";
import { useRealtime, useRealtimeConnectionState, useRpc } from "@get-bb/plugin-sdk/app";
import {
BOARD_CHANGED_CHANNEL,
@@ -25,6 +25,8 @@ export function useGlobalDashboard() {
const [refreshing, setRefreshing] = useState(false);
const [error, setError] = useState(null);
const [tick, setTick] = useState(0);
+ const [lastSignalAt, setLastSignalAt] = useState(null);
+ const [lastRefreshAt, setLastRefreshAt] = useState(null);
const snapshotRef = useRef(null);
const inflight = useRef(false);
/**
@@ -52,6 +54,7 @@ export function useGlobalDashboard() {
if (id !== requestId.current) return;
snapshotRef.current = result;
setSnapshot(result);
+ setLastRefreshAt(Date.now());
setError(null);
},
(cause: unknown) => {
@@ -79,7 +82,7 @@ export function useGlobalDashboard() {
}, [refetch]);
useRealtime(BOARD_CHANGED_CHANNEL, (payload) => {
- if (isForGlobalDashboard(payload)) refetch();
+ if (isForGlobalDashboard(payload)) { setLastSignalAt(Date.now()); refetch(); }
});
const connectionState = useRealtimeConnectionState();
@@ -129,19 +132,10 @@ export function useGlobalDashboard() {
return () => clearInterval(timer);
}, [refetch]);
- const hasLive = useMemo(
- () => snapshot?.active.some((execution) =>
- execution.card.status === "running" ||
- execution.card.status === "starting" ||
- execution.card.status === "waiting",
- ) ?? false,
- [snapshot],
- );
useEffect(() => {
- if (!hasLive) return;
const timer = setInterval(() => setTick((value) => value + 1), 1_000);
return () => clearInterval(timer);
- }, [hasLive]);
+ }, []);
return {
snapshot,
@@ -153,5 +147,7 @@ export function useGlobalDashboard() {
dismissAttention,
clearDismissedAttentions,
connectionState,
+ lastSignalAt,
+ lastRefreshAt,
};
}
diff --git a/lib/bb-source.ts b/lib/bb-source.ts
index 019a951..c7e812a 100644
--- a/lib/bb-source.ts
+++ b/lib/bb-source.ts
@@ -15,6 +15,7 @@
// presentation labels, outputs.
// - Statuses are mapped losslessly enough to drive column placement.
import type { BbPluginApi } from "@get-bb/plugin-sdk";
+import { reportedCompletion } from "./dashboard-view";
import type {
BoardActivity,
BoardActivityFeed,
@@ -206,6 +207,20 @@ export function latestPublicUpdate(rows: readonly TimelineRow[]): string | null
return publicUpdatePreview(last.text);
}
+/** Work and public assistant timestamps; excludes reasoning/user/cosmetic events. */
+export function latestPublicActivityAt(rows: readonly TimelineRow[]): number | null {
+ const times: number[] = [];
+ for (const row of flattenRows(rows)) {
+ if (row.kind === "work" && !("presentation" in row && row.presentation?.suppress === true)) {
+ times.push(("completedAt" in row ? row.completedAt : null) ?? row.startedAt);
+ } else if (row.kind === "conversation" && "role" in row && row.role === "assistant") {
+ times.push(row.createdAt);
+ }
+ }
+ const valid = times.filter(at => Number.isFinite(at) && at >= 0);
+ return valid.length ? Math.max(...valid) : null;
+}
+
/** Compact human label for a work kind (recent-activity rows). */
export function workKindLabel(workKind: string): string {
switch (workKind) {
@@ -499,6 +514,8 @@ export function normalizeThread(
phaseTitle: null,
promptPreview: null,
activity: latestActivity(facts.timeline.rows),
+ lastActivityAt: latestPublicActivityAt(facts.timeline.rows),
+ ...reportedCompletion(facts.output ?? delegation?.output),
outputPreview:
previewText(facts.output ?? delegation?.output ?? null, BOARD_LIMITS.outputPreviewChars) ??
null,
diff --git a/lib/board-model.ts b/lib/board-model.ts
index a43005c..51b29cc 100644
--- a/lib/board-model.ts
+++ b/lib/board-model.ts
@@ -203,7 +203,8 @@ export function formatElapsed(ms: number): string {
/**
* Live elapsed for a card between authoritative snapshots: use durationMs
- * when the work finished, otherwise clock from startedAt against `now`.
+ * when the work finished, otherwise clock live work from startedAt against `now`.
+ * Terminal work without an authoritative end time has unknown duration.
*/
export function cardElapsedMs(card: BoardCard, now: number): number | null {
if (card.durationMs !== null && card.durationMs !== undefined) return card.durationMs;
@@ -211,5 +212,6 @@ export function cardElapsedMs(card: BoardCard, now: number): number | null {
if (card.completedAt !== null && card.completedAt !== undefined) {
return Math.max(0, card.completedAt - card.startedAt);
}
+ if (["completed", "failed", "interrupted", "skipped"].includes(card.status)) return null;
return Math.max(0, now - card.startedAt);
}
diff --git a/lib/collect.ts b/lib/collect.ts
index bbcc8f4..124b1d2 100644
--- a/lib/collect.ts
+++ b/lib/collect.ts
@@ -10,7 +10,7 @@
// say so instead of lying by omission.
import type { BbPluginApi } from "@get-bb/plugin-sdk";
import type { BoardCard, ExecutionTimeline, ExecutionTimelineInput, GlobalDashboardSnapshot } from "../contract/rpc";
-import { BOARD_LIMITS, columnForStatus, countCards, previewText } from "./board-model";
+import { BOARD_LIMITS, columnForStatus, countCards, previewText, redactOperationalText } from "./board-model";
import {
activityFromEvents,
normalizeThread,
@@ -37,6 +37,19 @@ import {
import { FleetSource, scopedFleetCards, addFleetGroups, fleetTimelineEvents, fleetActive } from "./fleet-source";
import { normalizeBbTimeline } from "./timeline-model";
+/** Remote label only, stripped of credentials/query/fragment; never a link. */
+export function safeRepositoryLabel(remote: string | null | undefined): string | null {
+ if (!remote) return null;
+ try {
+ const url = new URL(remote);
+ if (!["https:", "http:", "ssh:", "git:"].includes(url.protocol)) return null;
+ return previewText(redactOperationalText(`${url.host}${url.pathname.replace(/\.git$/, "")}`), 240);
+ } catch {
+ const scp = /^(?:[^@\s]+@)?([\w.-]+):([\w./-]+?)(?:\.git)?$/.exec(remote);
+ return scp ? previewText(redactOperationalText(`${scp[1]}/${scp[2]}`), 240) : null;
+ }
+}
+
/** Output of board_snapshot (shape matches contract/rpc.ts). */
export interface BoardSnapshot {
root: ReturnType;
@@ -64,6 +77,8 @@ interface CacheEntry {
at: number;
value: V;
}
+type ProjectMetadata = { name: string | null; repository: string | null };
+export const PROJECT_METADATA_TIMEOUT_MS = 750;
export class BoardCollector {
private readonly sdk: Sdk;
@@ -74,6 +89,8 @@ export class BoardCollector {
private readonly outputCache = new Map>();
private readonly modelCache = new Map>();
private providersCache: CacheEntry