Skip to content

release: v1.0.5 → main (production) - #2435

Merged
kevinthelago merged 369 commits into
mainfrom
develop
Jul 6, 2026
Merged

release: v1.0.5 → main (production)#2435
kevinthelago merged 369 commits into
mainfrom
develop

Conversation

@kevinthelago

Copy link
Copy Markdown
Owner

Promotes the v1.0.5 release (tag v1.0.5, commit 0a9feef) to main. Snapshot includes the frontend consolidation wave (#2416#2421), Glance/Org designer work, the documentor role, and everything stamped under CHANGELOG [1.0.5] — 2026-07-06.

🤖 Generated with Claude Code

kevinthelago and others added 30 commits July 3, 2026 23:54
feat(components): kit-change propagation — fan-out decision spine (#2277)
…write-through slice (#2277)

The data the propagation fan-out reads: which projects use which kit. Mirrors the project-links store
(#2253) end-to-end.

Rust — `bsc component usage` (crates/bsc-component):
- `usage.rs`: a flat edge store at ~/.base-studio-code/kit-usage.json — load/add/remove over
  (projectKey, kitId) edges, idempotent by a deterministic `usage_id` ("<projectKey>><kitId>").
- `bsc component usage list [--json] | add <projectKey> <kitId> | remove <id>` (a custom command,
  not per-record CRUD), registered in the component help.

Frontend — the write-through cache:
- `kitUsageBridge`: load/push/drop via `bsc component usage …` (null → keeps the cache when unreachable).
- `kitUsageId` in propagation.ts — byte-identical to the Rust `usage_id` (one contract).
- store `ComponentsSlice`: `kitUsage: KitConsumer[]` + `addKitUsage`/`removeKitUsage` (write-through) +
  `hydrateKitUsage`; hydrated on boot, persisted as a fast-first-paint cache.

`kitUsage` is exactly the `KitConsumer[]` `planPropagation` (the #2291 spine) consumes — so the fan-out
now has real consumer data. clippy + typecheck + lint clean; tests: Rust add/idempotent/reject/remove +
help, frontend add/dedup/remove(by-id)/hydrate.

Part of #2277 — follow-ups: recording the edge at planning (blueprint→kit), `bsc component set` emitting
a classified change, and wiring the dispatch plan to the rails.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(components): kit-usage consumer index — bsc component usage + write-through slice (#2277)
…nge + fan-out plan (#2277)

Close the change→plan loop: editing a component now produces the propagation plan against the real
consumer index.

- `setComponent(component, changeOverride?)` — write-through the edit (upsert + `bsc component set`), and
  when it EDITS an existing component, emit a classified `KitChange` (the #2291 diff/classify), fan it
  out over `kitUsage` (the #2292 consumer index) via `planPropagation`, and queue the fresh dispatches.
  A brand-new component isn't a change; an author-declared class overrides the derived one.
- `kitDispatches: Dispatch[]` — the pending fan-out (notify-only by default; issue/assign only for
  breaking + opted-in), deduped by (projectKey, change.id); `dismissKitDispatch` drains one.

So: edit a component → additive is notify-only across consumers; a breaking edit queues an issue
(dormant) / assign (live) for each opted-in consuming app. typecheck + lint clean; tests cover
write-through, breaking→issue, additive→notify, new-component-no-change, dedup + dismiss.

Part of #2277 — remaining: auto-record the edge at planning (blueprint→kit), and DELIVER the queued
dispatches to the rails (issuer / bsc-issue+bsc-assign / a kit-update GitHub issue).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(components): change origin — setComponent emits a classified change + fan-out plan (#2277)
…-store

# Conflicts:
#	Cargo.toml
#	crates/bsc-agent/src/main.rs
#	crates/bsc-util/src/sidecars.rs
RUSTSEC-2026-0194/0195 fire on quick-xml 0.39.4, pulled in transitively
via tauri -> plist 1.9.0 -> quick-xml. plist 1.9.0 (latest) pins
`quick-xml = "^0.39.2"`; the fix lands in quick-xml >=0.41, an API-breaking
bump plist can't take, so neither `cargo update` nor a `[patch]` reaches it
without breaking the build. Both are DoS-only via untrusted XML, and plist
only parses the app's own bundle Info.plist at build time (not runtime
attacker input), so neither is reachable here.

Add a scoped `.cargo/audit.toml` ignoring EXACTLY these two IDs, matching the
workflow's existing non-blocking-transitive stance. Any other real advisory
still fails the audit. Revisit when tauri/plist ship a quick-xml 0.41 bump.

Closes #2173

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add SplitView to src/shared/ui/layouts/ — the standardized two-pane split
page skeleton (flexing primary + fixed-size, drag-resizable secondary +
optional toolbar), matching the MasterDetail/GraphCanvas template idiom.
Generalizes the hand-rolled Planner-session terminal/inspector split.

- Horizontal (default) or vertical orientation; the secondary is the resized
  pane (inverted drag), owning size/min/max + the splitter wiring by construction.
- Add a `.resize-y` splitter class for the vertical orientation.
- Colocated render smoke + layout-behavior tests.

Template only — no page migrations here (that is the separate #2213).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(errordb): fault store + `bsc errors` CLI — runtime fault spine (#2260)
fix(ci): scoped-ignore quick-xml DoS advisories in cargo audit (#2173)
feat(ui): SplitView layout template — the two-pane split page skeleton (#2197)
…nce + relationship graph

Slice 3 of the graph-core epic (#2214), tight sub-slice: extract the longest-path layer
ASSIGNMENT into `shared/lib/graph/layers.ts` (`layerDag`) and adopt it in the two consumers
that both compute layers over a precomputed back-edge-exclusion set — Glance's `buildGraph`
(was iterative relaxation) and the relationship graph's `buildRelationshipGraph` (was Kahn).
Both are the same unique DAG longest-path fixpoint, so the migration is byte-identical:
- Glance is a depends-on DAG (dependency sits LOWER), so it hands layerDag its edges reversed.
- Relationship passes its ordering edges + DFS back-edge set straight through.

Placement stays per-domain (Glance's grid, Relationship's swimlanes). Deliberately left for a
follow-up: Org's `layerNodes` (a runtime-cycle-guard memoized DFS feeding a d3-force layout —
different cycle semantics, higher layout-shift risk) and the Glance/Org barycenter ordering
(not shared by Relationship). Colocated `layers.test.ts` covers longest-path, order-independence,
back-edge exclusion, self-loop/unknown-node guards, and the reversed depends-on orientation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
refactor(graph): shared layerDag — consolidate Glance + Relationship layering (#2214)
Part of the runtime-fault epic (#2258). Adds a small synchronous HTTP receiver,
bound to 127.0.0.1 only, started with the app on a background thread. A locally
running generated app POSTs a fault/heartbeat envelope (an OTLP-log subset) to
`POST /ingest`; the collector validates the per-project ingest token, resolves
the project's error.db via `error_db_path`, opens the errordb `Store`, and
`record`s the fault (fingerprinting in the store). Heartbeats update an
in-memory per-project liveness timestamp (consumed later by #2263).

- New module `src-tauri/src/observability/collector.rs`: the `Envelope` wire
  type, the pure parse/validate/attribute/record `ingest` decision (returns an
  `Outcome` → HTTP status), a `tiny_http` accept loop on a named thread, the
  `CollectorState` managed state (port + per-project token/liveness/rate maps),
  and the `collector_info` Tauri command exposing `{ ingestPort, token }`.
- Auth/attribution: unknown project_key → 404, absent/bad token → 401; tokens
  minted on demand (32 hex chars, in-memory for this slice).
- Robustness: oversized bodies rejected (413) without buffering; malformed JSON
  and message-less faults → 400; per-project fixed-window rate limit
  (drop-with-count → 429); the accept loop never panics out.
- Wired into `app/run.rs`: `.manage(CollectorState::new())`, started in `setup`,
  `collector_info` registered.
- `src-tauri/Cargo.toml`: add `errordb` (path) + `tiny_http = "0.12"`.
- Tests (`#[cfg(test)]`): end-to-end record into a temp error.db, 401/404/400,
  oversized-body, heartbeat-liveness, default-type-is-fault, rate-limit
  drop-with-count, token stability, context stringify.

Verify: `cargo check -p base-studio-code` and
`cargo clippy -p base-studio-code --all-targets -- -D warnings` both clean.

Deferred: cloud transport seam (#2258), heartbeat/Glance status consumer
(#2263), and baking the shim into generation (#2262).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ights page (#2243)

Roll the reusable per-card empty/loading pattern (#2234) onto the planner's
GitHub board → Insights dashboard. The page kept a full-page "Loading insights…"
screen that hid every card while the ProjectV2 query ran, and used bare inline
text ("No status field found.", "No open issues.") for empty bodies.

Now the card layout ALWAYS renders; each body swaps loading skeleton | compact
EmptyState (size="sm") | content:
- Stat cards use StatCard `loading`.
- Status distribution / Assignee workload / Label frequency: SkeletonRows →
  CardEmpty → HBars/bars.
- Weekly activity: SkeletonChart → CardEmpty → Bars.
- `isLoading = loading && issues.length === 0`, so a background refetch keeps the
  rendered content instead of flashing back to skeletons.
- The Label frequency card is now always present (was hidden entirely when empty).

Adds Insights.test.tsx covering the three states (loading → skeletons + no
page-wide loader + no empty titles; empty → each card's compact EmptyState;
content → real charts, no empty states).

One slice of the #2243 rollout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(runtime): localhost fault-ingest collector (OTLP-log → errordb) (#2261)
feat(ui): per-card empty/loading on the Planner Insights dashboard (#2243)
…e apps (#2264)

Give an app bsc didn't generate (a brought-in repo, the migration case) best-
effort runtime-fault coverage by tapping the dev-server output the console
already streams — no injected shim required.

- observability/pty_faults.rs: a pure, tested signature extractor (extract_faults)
  scans a text block for Rust/Go panics, JS/Node stack traces, uncaught/unhandled
  rejections, and ERROR/FATAL log lines (ANSI-stripped, best-effort grouping of a
  head line with its frames). Detected faults are fingerprinted (stage runtime)
  and recorded to the pane's project error.db via the shared errordb::Store,
  tagged source_hint = "pty-tap" (lower confidence than a shim/OTLP fault).

- Side-tap in spawn_emitter (console/pty/pump.rs): a single additive `observe`
  call that only BORROWS the flushed batch before it's moved into app.emit, so the
  WebView emit + mobile-tunnel tee are byte-for-byte unchanged. A no-op (one
  relaxed atomic load) when no pane is tapped.

- Gated + rate-limited: off by default per pane. A pane must be explicitly marked
  an app-runner via the new pty_set_app_runner command; recordings are capped per
  pane per window. Attribution is the pane's owning project key → error_db_path.

- Cargo.toml: add errordb path dependency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…allback (#2264)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(runtime): best-effort PTY-tap fault fallback for uninstrumented in-pane apps (#2264)
Elevate the per-card content|empty|loading pattern into a property of each
component: a content-bearing primitive takes `loading` and renders a skeleton the
same shape as itself, via the shared Skeleton/SkeletonText (one shimmer app-wide).

Added to Card (skeleton body), Chip (shimmer pill), Text (inline shimmer line),
TextField (skeleton input, label kept), Code (shimmer lines in the frame), and
FillBar (indeterminate track). StatCard/StatTile already had it. Pure layout
(Box/Stack/Row) and interactive controls (Button/Toggle) don't "load" — skipped.

Registered the `loading` prop in each component's shared/ui/manifest.ts spec so
the design-system registry + the v1.0.5 visual builder know the state. Test covers
all six: loading → a shape-matched skeleton, real content hidden.

Closes #2302

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(ui): every content component ships a loading state (#2302)
…t-class destination

The Component Library UI (`ComponentLibraryPane`, #2269) was reachable ONLY as the
planner's optional `test_ui` stage (UI-Kit-blueprint-only), so it was effectively
invisible. Promote it to a top-level **Design Studio** Rail workspace that renders the
pane directly — it stands alone, reading the global `bsc component` store, so the
workspace is just the pane.

- registry.ts: add the `design` Workspace (key + "Design Studio" label + Blocks icon),
  placed after Skills in the library grouping.
- lazyWorkspaces.tsx: `DesignWorkspace` lazy export wrapping `ComponentLibraryPane`.
- App.tsx: render it in the Suspense screen-switch, in a flex-fill wrapper (the pane
  fills height:100%).
- rail.test.tsx / registry.test.ts: extend the locked rail order + the exhaustive
  Workspace-union map; add a Design Studio nav test.

The planner `test_ui` stage is unchanged. Part of the component-kit arc (#2238).

Closes #2303

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(app): Design Studio Rail workspace — Component Library as a first-class destination
…oadmap) (#2248)

Bring the two remaining board views up to the #2243 pattern (Insights was already
done): cards/columns always render; async bodies show a skeleton while loading and
a compact empty state when there's no data — no page-wide blank.

- ProjectBoard (Issues): replaced the full-section "Loading board…" overlay with
  skeleton columns while loading + a real "No board items yet" empty state (gated on
  items, since the "All items" column fallback means columns is never empty).
- Roadmap: stat values shimmer via StatCard `loading` (not "…"); the gantt shows a
  SkeletonChart while loading + a compact EmptyState when there are no milestones.

Tested (ProjectBoard loading/empty/content), mirroring Insights.test. Closes #2248.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(planner): per-card empty/loading on the GitHub board (Issues + Roadmap) (#2248)
The bsc-defer Stop-hook directive was the last inline PROMPT string in the
fleet/warden rc surface. Move its prose out of the BSC_DEFER_RC compile-time
const into config-dir-overridable data/fleet/defer-directive.md, loaded via
config::load_str at rc-assembly time and JSON-escaped into the block-reason
fragment. The ALL_BSC_RC const becomes all_bsc_rc() so the config-loaded
defer slot can sit in the ordered fragment list; bsc_rc_body() concats it.

Output is byte-identical to the old inline const (the escape is a no-op on the
current prose), so the #296 trailing-newline contract and the syntax guard
hold. Adds bsc_defer_rc_embeds_the_externalized_directive test.

Closes #2145

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
refactor(fleet): externalize bsc-defer directive prose to data/ (#2145)
#2303 added the Design Studio Rail workspace but pointed it at `ComponentLibraryPane`
— which is the *Kickoff* design that correctly lives in the planner's `test_ui` stage.
This builds the distinct, full-page Design Studio (from
`design/Component Library Design Studio/Design Studio.dc.html`) and repoints the
workspace at it. The planner Kickoff pane is untouched.

The page (`DesignStudio.tsx` + `designStudio.css`):
- Toolbar — ◆ logo · kit-switcher chips · ⌘K search · Library/Graph toggle · +Kit/+Component
- Resizable left rail — collapsible kits→components tree (role dots, ×used)
- Center — Library view (live preview + variant/theme/viewport switchers + Source/Props/
  Usage tabs + a generate-variants design bar with a candidate strip) ⇄ composition Graph view
- Resizable right inspector — title/meta · Props/API · Variants · Composes mini-graph · Guidance
- Empty (no kits), generating overlay, and preview-error states

Reuses the existing domain (`lib/model`, `renderSpecimen`, the global `bsc component`
store) and the shared graph toolkit — `useGraphViewport` (pan/zoom) + `layerDag`
(composition layering) + `useDragResize` (the splitters) — so it stays on-architecture.
The design-only demo-state switcher is dropped; its states are wired to real signals.

Closes #2308

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kevinthelago and others added 29 commits July 6, 2026 14:37
… + scoped globs)

The single-text-node fix exposed the real mismatch: the test asserted the
conceptual #219 table (planner code:none), but role-capabilities.json
encodes plan-only as code:write + writeGlobs scoped to plan-section files
(*.md, prompts/*, ...) — unlike the director, whose commons carve-out is
encoded code:none + globs (#851). The data drives real permission wiring,
so the test aligns with the model, with the encoding asymmetry documented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(ci): two born-broken #2420 tests (RoleTierChips text nodes + SectionLabel CSSOM serialization)
feat(console): single Terminal Host — one PTY terminal per agent, re-parented between surfaces (#2378)
feat(design-system): register the Layouts tier in the manifest + Design Studio gallery (#2197 slice 3)
fix(planner): deploy-config instructions were cloud-only + legacy schema (#2392)
fix(publish): don't 404 on a failed/missing GitHub issue — label streams at creation (#2397)
feat(components): kit-change propagation delivery — auto-record edges + drain to rails (#2277)
fix(hotkeys): restore F-key screen navigation off the console page (#2403)
…velop/npm-minor-78585cbe35

chore(deps): bump the npm-minor group with 7 updates
feat(recovery): durable per-project agent-session ledger in plan.db (#2405)
…develop/actions-minor-3d73cdc6eb

chore(deps): bump the actions-minor group with 5 updates
…point terminal mock

- glance.css: the drill transition moved to the shared .graph-drill-anim
  (shared/ui/layouts/graphCanvas.css, #2418) and GlanceWorkspace already
  uses it — dropped this file's now-dead .glance-drill-anim copy; kept
  the #2401 morph CSS.
- GlanceStreamMorph.test.tsx: the dock renders TerminalSlot since the
  single Terminal Host landed (#2378/#2399), so the old TerminalView
  mock intercepted nothing — mock the slot, mirroring the dock's test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(glance): morph a live agent node into its terminal for check-in (#2401)
…argo-minor-8dca6ac8b9

chore(deps): bump the cargo-minor group with 4 updates
fix(planner): resume the Claude conversation on reopen/restart instead of starting fresh (#2396)
…urrent)

- New "Milestones — the version system" subsection: milestone = the
  release an issue ships in; themes are epics/labels, never milestones;
  Current + next + Backlog are the only open milestones; on each release
  close the milestone and roll unfinished issues forward. (Matches the
  board migration done today: 32 stale milestones closed, in-flight
  issues paired to 1.0.5.)
- Roadmap: v1.0.4 + the 1.0.4n line marked Complete; v1.0.5 is Current
  (maintainer-confirmed — the app version is already 1.0.5).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs: milestone version-system policy + v1.0.5 Current roadmap flip
@kevinthelago
kevinthelago merged commit 651cb11 into main Jul 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant