Files
waggle-os/docs/ux-refactor/deltas/open-questions.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

702 lines
54 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Open Questions — UX Refactor (Founder Ratification)
> Source: PRD §23 (`docs/Waggle_OS_UX_Refactor_Master_Handoff_Package/Waggle_OS_UX_Refactor_PRD.md:1414-1424`)
> + the §9 "Open questions" sections of all 22 gap cards (`docs/ux-refactor/gap-cards/S00..S21`).
> Every recommendation is kept consistent with the **locked direction**: in-place incremental refactor
> of `apps/web` + targeted backend extensions, **full-stack** (net-new/extended APIs where PRD §16 has no
> route yet), **local-first** default. Mockups are directional (PRD §24); PRD acceptance criteria win.
>
> **How to use:** each question has (a) why it matters, (b) options + tradeoffs, (c) a RECOMMENDED answer
> for founder ratification, (d) the phase it blocks if unresolved. Questions are grouped: **§A** = the 8
> PRD §23 questions; **§B** = cross-cutting decisions surfaced by the gap cards that block ≥2 screens;
> **§C** = screen-local questions that block a single screen. Critical (Phase 12 blocking) items are
> flagged **[BLOCKS P1]** / **[BLOCKS P2]**.
---
## ✅ Founder Ratifications — 2026-06-09
The **spine (Phase 0/1) blockers are RATIFIED as recommended** (founder, 2026-06-09). Phase 0 is
unblocked; these are now locked decisions alongside the execution-model + full-stack scope locks:
- **B1** Shell topology → in-place dock reframe; keep windowed `AppId` nav; group the dock into
Work / Intelligence / Extend / Team zones. **No react-router.**
- **A1** Workspace Desktop → fixed widget layout v1.
- **A2** Home Cockpit → personal-only v1 (team strip later, behind RBAC).
- **B4** `/api/*` → alias PRD vocabulary onto existing routes (command / automations / connector-revoke); do not rename.
- **B8** Identity → onboarding writes profile **and** seeds the `identity` table.
## ✅ Founder Ratifications — Phase 2 gate (2026-06-09 S2)
The **Phase-2 blockers are RATIFIED as recommended** (founder, 2026-06-09), except **C33** which is
**held for discussion** (see note below). Locked Phase-2 decisions:
- **A6** Artifact storage → per-workspace `artifacts.json` index over the existing StorageProvider;
artifact = explicit produced output (not every ingested input). No `.mind` migration.
- **A8** Memory retention → soft-status in `metadata` (Archive = reversible; Deprecate = existing
`importance`); **Delete = hard delete behind a scope-and-consequence confirmation** (PRD J20).
≤1 additive migration.
- **B2** Confidence → cheap heuristic at preview (source-trust × adapter-type × dedup), persisted in
`metadata` only if it becomes a queryable filter; LLM scoring reserved for the standing J08 queue.
- **B6** `MemoryKind` → PRD §15.2 canonical in `@waggle/shared`; pure harvest + display-category mapping
helpers. Drop FE `event`/`insight` drift.
- **A3** Memory graph tab → **ship in v1** (substrate already renders).
- **C33** Import↔Review commit split → **RESOLVED to the middle path** (founder, 2026-06-09 S2, after
discussion). **Commit-as-unreviewed, non-blocking review:** onboarding Import commits immediately (memory
feels alive on first run), but frames land with `status:'unreviewed'` + the B2 confidence score; Review is
a **non-blocking** curation surface (Memory Center "needs review" filter + the standing J08 queue), NOT a
blocking onboarding step. Reads PRD "nothing imports without review/approval" (646/1207) as *nothing is
trusted/surfaced until reviewed*, not *nothing is written*. Rationale: importing one's own memories is
additive + reversible (A8 archive/delete), so a blocking first-run gate would be friction in the wrong
place (founder principle: friction reserved for irreversible/destructive actions). Reuses A8 soft-status
+ B2 confidence — no extra migration. Supersedes the original §C C33 "blocking split" recommendation.
## ✅ Founder Ratifications — Phase 3 gate (2026-06-10)
The **Phase-3 (Intelligence) items are RATIFIED as recommended** (founder, 2026-06-10). Locked:
- **B3** Agent entity → real Agent object in `{dataDir}/agents.json` referencing `personaId`; persona =
behavioral template field. `successRate`/`lastRun` derived at read from `execution_traces`. No `.mind`
migration (M3 not shipped).
- **C24** Automation triggers → schedule-only v1 (cron cadence); Event trigger deferred (no event→automation
dispatch substrate).
- **C26** Builder test-run → NET-NEW no-persist dry-run route (`POST /api/automations/test`); do NOT reuse
`cron/:id/trigger` (executes + auto-enables).
- **C13** Skill Builder publishes create-to-local (`POST /api/skills/create`); marketplace publish lives in S06/S21.
- **C14** Skill inputs/outputs → body markdown v1; no `SkillFrontmatter` extension.
- **C22** Agent Center tabs = All/Personal/Workspace/Team/Autonomous/Archive; Templates = side affordance.
- **C23** Agent `/run` → one-shot fleet-spawn into a chosen workspace (picker if multiple `workspaceIds`);
persistent always-running agents deferred.
- **C25** Automation condition step → advisory `jobConfig.condition` string, no evaluation engine v1.
- **C27** Analytics tiles → keep success-rate (from `cron_execution_history`); drop "hours saved" or label
it an explicit heuristic estimate.
- **C36** Skill scope vocabulary → PRD `organization` (align §15.2 `Scope` union).
- **C37** Skill test-run fidelity → preview-only (injected-prompt + parsed metadata) v1; live LLM dry-run deferred.
## ✅ Founder Ratifications — Phase 4 gate (2026-06-10)
The **Phase-4 (Extend) items are RATIFIED as recommended** (founder, 2026-06-10). Locked:
- **A4** Real-where-substrate-exists, catalog-for-the-rest: connectors connect + health-probe +
`lastSyncAt` stamp (background data re-pull deferred); MCPs install/start/stop/test via the existing
marketplace installer + stdio runtime; static catalog renders honest "available / not installed"
states — never fake entries (PRD §22.2).
- **A5** Marketplace → federate-at-read over the six local domains; no `marketplace.db` migration;
remote registry / public marketplace deferred (PRD §4.4 + §22).
- **B5** Tier vocabulary → document the mapping; all new gates route through `@waggle/shared tiers.ts`
(`TierCapabilities`); MCP Hub + Marketplace install gated **PRO+**.
- **B7** `ExtensionType``skill | agent | connector | mcp | model | template` (drop `external_tool`;
external tools surface via connectors/MCPs). Defined once in `@waggle/shared`.
- **C15 / M2** install-audit `critical` CHECK → ship the additive migration (live sighting:
`marketplace.ts:228` writes `critical`, silently rejected by the DDL CHECK today).
- **C16** Connector "sync now" v1 = re-probe health + stamp `lastSyncAt`.
- **C17** `revoke` purges OAuth tokens + writes the stronger audit entry (PRD §17.3); `disconnect`
stays the lighter alias.
- **C18** One shared `GET /api/extend/audit?type=` serving connectors + MCPs + marketplace.
- **C19** MCP scope = single-`workspaceId` config v1 (matches stdio runtime); N:N deferred.
- **C20** "Remote Registry" tab deferred (runtime is stdio-only); v1 points at the static catalog.
- **C21** MCP `test` = live spawn-and-`isHealthy()`/`tools/list` round-trip where cheap; static
manifest validation fallback.
- Foundational task (coverage-check C4): populate `mcpRuntime` at boot from persisted config
(`local/index.ts` registers none today) — explicit Phase-4 work item gating all MCP routes.
---
Remaining pending: **A7** (RBAC — ratify before S10/Phase 5) + Phase-5/6 screen-local items.
## §A — PRD §23 Open Questions (the canonical 8)
### A1. Widget customization in Workspace Desktop — fixed layout or true customization in v1?
*(PRD §23 Q1, line 1416; gap card S02 §9 Q1.)*
- **(a) Why it matters:** Determines whether S02 reuses the maximized `AppWindow` + fixed widget layout
(cheap, in-place) or builds a draggable/resizable grid (parallel layout system, large blast radius).
PRD §12.2 already says "configurable widgets in *later* phase; fixed default layout in initial release".
- **(b) Options:**
1. *Fixed layout v1* — one default widget arrangement; reuse window manager. Lowest cost, ships Phase 1.
2. *Customizable grid v1* — drag/resize/persisted layout. New layout engine, persistence, much larger.
3. *Fixed + per-tab presets* — fixed canvas but a couple of named presets. Middle cost.
- **(c) RECOMMENDED:** **(a) Fixed layout v1.** PRD §12.2 self-answers this; customization is explicitly
a later phase. Rationale: keeps Workspace Desktop a maximized window in the existing OS, zero parallel
layout system.
- **(d) Blocks:** **Phase 1** (Workspace Desktop, S02). **[BLOCKS P1]** — but the PRD text already
resolves it, so this is a confirm-not-debate.
### A2. Home Cockpit scope — personal-only, or team/global views too?
*(PRD §23 Q2, line 1417; gap card S01 §9 Q3, Q5.)*
- **(a) Why it matters:** Decides whether the briefing reads cross-workspace personal state only, or also
team/shared rows. S01 §9 Q3 flags that reading the user's *own* workspaces server-side is now safe
(same-user), while team/shared rows must still gate through `approvalGrantStore`/RBAC.
- **(b) Options:**
1. *Personal-only v1* — briefing aggregates the user's own workspaces; team rows deferred to Phase 5.
2. *Personal + team summary v1* — adds a shared-activity strip (needs RBAC + Team substrate live).
3. *Toggle (personal/team) v1* — most flexible, most work; team substrate not ready until S10.
- **(c) RECOMMENDED:** **(a) Personal-only v1**, with the briefing builder written so a team summary can
be appended later behind the existing RBAC gate. Rationale: Team Workspace (S10) is a Phase-5 screen;
Home must ship in Phase 1 without it. Local-first + own-data read is the safe boundary.
- **(d) Blocks:** **Phase 1** (Home Cockpit, S01). **[BLOCKS P1]**.
### A3. Memory Center graph view — v1 or later?
*(PRD §23 Q3, line 1418; gap card S04 §9 / line 232.)*
- **(a) Why it matters:** Whether the "Graph" tab ships in the first Memory Center cut.
- **(b) Options:**
1. *Ship graph in v1* — the `knowledge_entities`/`knowledge_relations` substrate + a graph render
already work (S04 line 232: "Graph already works, so keep").
2. *Defer graph* — tab hidden until a later polish pass.
- **(c) RECOMMENDED:** **(a) Ship in v1.** Rationale: the substrate exists and S04 already confirms it
renders; deferring would be removing working capability for no gain.
- **(d) Blocks:** **Phase 2** (Memory Center, S04). **[BLOCKS P2]** (scoping-only; default = keep).
### A4. Which connectors/MCPs are real in v1 vs seeded/mock catalog?
*(PRD §23 Q4, line 1419; gap cards S06 §9 Q3, S07 §9 Q1, S08 §9 Q4Q5, S14 §9 Q1, S15 §9 Q3, S21 §9 Q2.)*
- **(a) Why it matters:** Touches six screens. Determines the empty/syncing states of the Marketplace,
Connector Hub, MCP Hub, Tool Discovery and Memory-Import surfaces, and whether onboarding can pull data
in-flow. The connector registry has ~31 real entries; the MCP catalog (`@waggle/shared mcp-catalog.ts`)
is static; MCP runtime is **stdio-only** (`mcp-runtime.ts:108-115`) and currently never populated
(`local/index.ts:911`).
- **(b) Options:**
1. *Real-where-the-substrate-exists, catalog-for-the-rest* — OAuth connectors that already have SDK
entries connect for real (health-probe + timestamp, no background data-sync — S07 §9 Q1); MCPs
install via the existing marketplace installer (`installer.ts:580` writes `.mcp.json`); everything
else renders from the static catalog with honest "available / not installed" states.
2. *All-mock catalog v1* — nothing actually connects; fastest UI, but violates PRD §22.2 ("no major
screen depends only on mocked data when backend support exists").
3. *All-real v1* — build connector background-sync + remote MCP transport now; out of scope per PRD §4.4.
- **(c) RECOMMENDED:** **(1) Real-where-it-exists, catalog-for-the-rest.** Connectors: connect + health
probe + `lastSyncAt` stamp (defer true data re-pull). MCPs: install/start/stop/test against the static
catalog via the existing installer + stdio runtime; defer "Remote Registry" transport. Marketplace/Tool
Discovery: render the live registry, never invent fake entries. Rationale: honors PRD §22.2 and the
local-first default while staying in-place.
- **(d) Blocks:** **Phase 4** (S07/S08/S21) and the onboarding **Phase 2** import flow (S14/S15). Not P1.
### A5. Marketplace — local catalog vs remote registry initially?
*(PRD §23 Q5, line 1420; gap card S21 §9 Q2, S08 §9 Q4.)*
- **(a) Why it matters:** Whether S21 federates the existing local domains (marketplace.db + connectors +
templates + personas + models) client-side, or invests in widening `marketplace.db`/`InstallationType`
to natively catalog all six extension kinds.
- **(b) Options:**
1. *Federate-at-read (local-first)* — S21 composes the six categories from existing domains; no DB
change; "Remote Registry" is a later tab. (S21 §9 Q2 recommendation.)
2. *Native unified catalog table* — widen `marketplace.db` for publish/install/version parity across
all six kinds. Enables update-tracking but is a real schema investment; conflicts with PRD §22
"postpone public marketplace".
- **(c) RECOMMENDED:** **(1) Federate-at-read, local catalog first.** Remote registry / public
marketplace billing stays out per PRD §4.4 + §22. Rationale: matches local-first + in-place; no
`marketplace.db` migration.
- **(d) Blocks:** **Phase 4** (Marketplace, S21). Not P1/P2.
### A6. Artifact storage — workspace filesystem, virtual store, or external references first?
*(PRD §23 Q6, line 1421; gap card S05 §9 Q1, Q2.)*
- **(a) Why it matters:** Artifacts have **no backing entity today** (the single largest entity gap,
S10 line 226). PATCH/relations/status/tags require a stable id + an index. The file registry mixes
ingested inputs with produced outputs, so a `kind`/`status` classification rule is also needed.
- **(b) Options:**
1. *Per-workspace `artifacts.json` index over the existing workspace FS/virtual store* — mirrors
`documents.json`; assigns stable ids, holds status/tags/relations; reuses the StorageProvider
(virtual | local | team) already in the repo. (S05 §9 Q1.)
2. *Composite synthetic id (`workspaceId:store:name`), no index* — cheapest, but can't persist
status/tags/relations (PATCH becomes impossible).
3. *External references only* — point at files elsewhere; defers the entity but breaks "artifacts are
first-class outcomes" (PRD §6.4).
- **(c) RECOMMENDED:** **(1) `artifacts.json` index over the existing workspace storage**, with a
classification rule: an artifact is an **explicit produced output** (generated doc/deck/sheet/etc. or
user-promoted file), not every ingested input. Rationale: gives PATCH/relations a home with no `.mind`
migration, reuses the StorageProvider, keeps local-first.
- **(d) Blocks:** **Phase 2** (Artifact Center, S05); also gates artifact-sharing in S10. **[BLOCKS P2]**.
### A7. Minimum viable RBAC for team mode?
*(PRD §23 Q7, line 1422; gap card S10 §9 Q1 (blocking), Q2.)*
- **(a) Why it matters:** Three role models disagree: PRD §17.2 (`Owner/Admin/Contributor/Viewer`),
blueprint (`+Member +Guest`), and the **live `teams.db` CHECK** (`owner/admin/member/viewer`,
`team.ts:21`). Picking wrong forces a DB CHECK migration + RBAC-logic rewrite. There is also a **real
bug**: `PUT …/members/:userId` is owner-only (`team.ts:624`) while `PATCH` on the same path is
owner/admin (`team.ts:649`).
- **(b) Options:**
1. *Keep the live 4-role union (`owner/admin/member/viewer`)* — map PRD "Contributor" → "Member",
defer "Guest". No DB migration, no RBAC rewrite. (S10 §9 Q1 recommendation.)
2. *Adopt PRD §17.2 four roles literally* — rename `member``contributor` in the DB CHECK + all
enforcement (migration + grep-everywhere).
3. *Adopt blueprint six roles (+Guest)* — new deny-by-default capability rules; largest scope.
- **(c) RECOMMENDED:** **(1) Keep the live union; Contributor==Member; defer Guest.** Also **align the
PUT/PATCH gate to owner+admin** (PRD uses PATCH; pick the broader gate consistently). Rationale:
in-place, zero migration, fixes a real inconsistency.
- **(d) Blocks:** **Phase 5** (Team Workspace, S10) — the `TeamRole` type + all member-management UI.
Not P1/P2, but **must be ratified before S10 coding starts** (S10 §6: "decision needed before coding").
### A8. Memory retention / delete / tombstone behavior?
*(PRD §23 Q8, line 1423; gap cards S04 §9 Q3, S16 §9 Q2.)*
- **(a) Why it matters:** PRD §14.4 distinguishes Deprecated / Archived / Deleted-tombstoned, but
`memory_frames` has only `importance:'deprecated'` today and no `status`/tombstone column; delete is a
hard `FrameStore.delete`. Determines whether an additive `.mind` migration is required and what
"archive" vs "delete" mean to the user.
- **(b) Options:**
1. *Soft-status via `metadata` JSON, hard-delete on Delete* — store `{status: active|archived|
deprecated}` in the existing `metadata TEXT` (idempotent `ADD COLUMN` pattern at `db.ts:122` if a
queryable column is needed); Delete = hard `FrameStore.delete`. Archive = reversible status.
2. *Full tombstone model* — Delete writes a tombstone row (retained, hidden, syncable) for audit/undo.
Heavier; needed only if team-sync conflict-resolution requires it.
3. *No status, delete-only* — simplest, but loses the Archived/Deprecated states PRD §14.4 requires.
- **(c) RECOMMENDED:** **(1) Soft-status in `metadata` (Archive = reversible status, Deprecate = existing
`importance`), Delete = hard delete with a scope-and-consequence confirmation** (PRD J20). Promote
`status` to a real column only if it becomes a primary filter axis. Defer full tombstones to the
team-sync phase. Rationale: local-first, one additive migration at most, satisfies §14.4 states.
- **(d) Blocks:** **Phase 2** (Memory Center, S04) — and shares the confidence/metadata migration
decision with the onboarding Memory Review (S16, see B2). **[BLOCKS P2]**.
---
## §B — Cross-cutting decisions (block ≥2 screens; not in PRD §23 but surfaced by gap cards)
### B1. Shell topology — keep the bottom-dock OS, or migrate to a left-rail / route-based shell?
*(Gap cards S00 §9 Q1Q2, Q5; S01 §9 Q4; S11 §9 Q5/Q7; S20 §9 Q7.)*
- **(a) Why it matters:** This is the **Phase-0 IA freeze**. The live shell is a single-route windowed
OS with a bottom `Dock.tsx`; blueprint/mocks show a **left navigation** + `/home,/workspaces,…` route
groups. Every later screen's navigation/AppId/dock placement depends on this. Deep-linking + browser
back-button are the only things real routes buy.
- **(b) Options:**
1. *In-place dock reframe, keep `AppId`-keyed window navigation* — cheapest, preserves the OS feel and
multi-window runtime; no react-router. (S00 §9 Q1Q2 recommendation.)
2. *Left rail + react-router routes* — closer to the mock, gains deep-linking, but a parallel layout +
conflicts with multi-window; large blast radius.
- **(c) RECOMMENDED:** **(1) In-place dock reframe; keep windowed `AppId` navigation.** Group dock
entries into Work / Intelligence / Extend / Team zones to satisfy the IA without a router. Rationale:
PRD §24 (mocks directional) + locked in-place direction. Revisit deep-linking only if it becomes a hard
requirement.
- **(d) Blocks:** **Phase 0 → Phase 1** (AppShell/IA, S00) — and the dock/AppId placement of S11/S20
("automations" zone) and S01 (`home` vs `cockpit`). **[BLOCKS P1]** — the IA freeze gates everything.
### B2. Memory confidence — heuristic-at-preview vs LLM-classify, and persisted vs preview-only?
*(Gap cards S04 §9 Q1, S16 §9 Q1Q2; S15 §9.)*
- **(a) Why it matters:** `memory_frames` has no confidence today (only `knowledge_relations.confidence`,
edges-only, `schema.ts:93`). PRD §12.4 wants "filter by confidence" + "low-confidence surfaced for
review", and onboarding Memory Review (S16) + the standing J08 review queue both depend on it. Wiring
the existing `HarvestPipeline` classify/synthesize means paid Haiku/Sonnet calls per import (slow,
gated on a real embedder); a cheap heuristic avoids that.
- **(b) Options:**
1. *Cheap heuristic at preview (source-trust × adapter-type × dedup signal), persisted in `metadata`
when a queryable filter is needed* — fast, no per-import LLM cost; reserve LLM scoring for an opt-in
deep pass / the J08 standing queue. (S16 §9 Q1 recommendation.)
2. *LLM classify/synthesize at preview* — real confidence, but onboarding-latency + cost hit.
3. *No confidence v1* — drops a core PRD trust requirement (§12.4).
- **(c) RECOMMENDED:** **(1) Heuristic for onboarding v1; LLM classify reserved for the standing J08
queue.** Persist `{kind, confidence, sourceId, status}` in the existing `memory_frames.metadata TEXT`
via the idempotent `ADD COLUMN` pattern (`db.ts:122`) **only if** confidence/status become queryable
filters; preview-only needs no migration. Make this one decision once and reuse it across S04 + S16.
Rationale: honors PRD trust criteria within the onboarding latency budget, local-first, one additive
migration at most.
- **(d) Blocks:** **Phase 2** — onboarding Memory Review (S16, a day-0 J01 flow) and Memory Center
filters (S04). **[BLOCKS P2]**. Shares the migration with A8.
### B3. Agent vs Persona boundary, and where the Agent entity is stored.
*(Gap cards S09 §9 Q1, Q3; S18 §9 Q1, Q2.)*
- **(a) Why it matters:** Decides whether Phase 3 introduces a real persisted Agent object (distinct from
the 13/17 personas in `persona-data.ts`) or just re-skins the persona catalog. PRD §15.5 lists explicit
agent fields (model, autonomy, memoryScopes, skillIds, connectorIds, mcpIds, permissions, …) that a
persona does not carry.
- **(b) Options:**
1. *Real Agent entity in a JSON store (`{dataDir}/agents.json`), referencing `personaId`* — no `.mind`
migration, mirrors the `agent-groups.json` precedent; persona = behavioral template field of the
agent. (S09 §9 Q1/Q3 + S18 §9 Q1/Q2 recommendation.)
2. *`agents` table in `mind/schema.ts` (SCHEMA_VERSION bump)* — heavier; PRD §4.4 non-goal favors
minimal backend.
3. *No Agent entity; persona re-skin only* — can't satisfy PRD §12.9 explicit-scope requirements.
- **(c) RECOMMENDED:** **(1) Real Agent entity, JSON store, references `personaId`.** Derive
`successRate`/`lastRun` at read from `execution_traces` (avoid a third tally vocabulary). Rationale:
satisfies PRD §12.9/§15.5 with zero migration, in-place over the existing fleet/traces substrate.
- **(d) Blocks:** **Phase 3** (Agent Center S09 + Agent Builder S18). Not P1/P2.
### B4. `/api/*` vocabulary aliasing — singular command, automations, mcps, connectors revoke.
*(Gap cards S03 §9 Q1, S11 §9 Q4, S20 §9 Q4, S07 §9 Q3; backend-api-delta.)*
- **(a) Why it matters:** PRD §16 uses vocabulary (`/api/command/*`, `/api/automations/*`,
`/api/connectors/:id/revoke`) that differs from the live routes (`/api/commands/execute`, `/api/cron/*`,
`/api/connectors/:id/disconnect`). Renaming breaks existing callers (`adapter.executeCommand`,
`commands.ts`, `cron.ts`); aliasing keeps both contracts.
- **(b) Options:**
1. *Add PRD-vocabulary aliases alongside the live routes* — new `command.ts`/`automations.ts` alias
plugins that delegate to the existing registry/cron; existing callers unbroken. (S03/S11/S20
recommendations converge on this.)
2. *Hard-rename to PRD vocabulary* — clean surface, but breaking; needs exhaustive grep (CLAUDE.md §3.5).
- **(c) RECOMMENDED:** **(1) Alias, don't rename.** New singular/plural aliases that delegate to the
existing handlers; UI/adapter point at the PRD vocabulary. Rationale: in-place, non-breaking, matches
the backend-api-delta dispositions.
- **(d) Blocks:** **Phase 1** (Command Center S03) for `/api/command/*`; **Phase 3** (S11/S20) for
`/api/automations/*`; **Phase 4** (S07) for connector revoke. The command alias is **[BLOCKS P1]**.
### B5. Tier-vocabulary unification (`UserTier` / `BillingTier` / `PlanTier` + RBAC roles).
*(Gap cards S00 §9 Q3, S08 §9 Q6.)*
- **(a) Why it matters:** Three independent tier vocabularies gate the dock, billing, and feature access;
PRD §17 RBAC roles add a 4th axis. MCP Hub (S08) and the dock (S00) both need a single answer for
"is this gated PRO+ or power-user-density".
- **(b) Options:**
1. *Document the mapping, defer unification* — keep the three vocabularies, ship a single mapping table
and a `useFeatureGate` that reads the canonical `tiers.ts`; no cross-cutting rewrite now.
2. *Unify into one tier model now* — clean, but cross-cutting (billing + dock + features + RBAC) during
a high-velocity refactor.
- **(c) RECOMMENDED:** **(1) Document the mapping + route all new gates through `@waggle/shared tiers.ts`
(`TierCapabilities`); defer the unification refactor.** Gate MCP Hub + Marketplace install at **PRO+**
(matches the existing marketplace install gate). Rationale: avoids a cross-cutting rewrite mid-refactor;
reuses the canonical tier system; no parallel gate (S10 §6).
- **(d) Blocks:** **Phase 4** (S08 tier gate) primarily; informs the dock gate in Phase 0/1. Not P1
blocking if the mapping is documented.
### B6. `MemoryKind` / `ImportItemType` / FE `MemoryFrame.type` reconciliation.
*(Gap cards S04 §9 Q6, S16 §9 Q3.)*
- **(a) Why it matters:** Three vocabularies disagree: FE `MemoryFrame.type` (`event`/`insight`/…),
PRD §15.2 `MemoryKind` (`fact|decision|task|preference|strategy|learning|goal|entity`), and the harvest
adapter's 8 `ImportItemType` values. Memory Review categories (Memories/Decisions/Tasks/Artifacts/
Projects) need a 1:1 map. Wrong choice re-renders existing frames and changes the type-filter chips.
- **(b) Options:**
1. *Adopt PRD §15.2 `MemoryKind` as canonical; add a pure `lib/harvest-kind-map.ts` mapping
`ImportItemType → MemoryKind` and a display-category map* — drop FE `event`/`insight`, add
`preference/strategy/learning/goal`. (S04 §9 Q6 + S16 §9 Q3 direction.)
2. *Keep FE types, map PRD onto them* — less churn now, perpetuates drift (precedent: the FrameSource
TS-vs-DB drift the shared-types-delta warns against).
- **(c) RECOMMENDED:** **(1) PRD §15.2 `MemoryKind` canonical, in `@waggle/shared`; pure mapping helpers
for harvest + display categories.** Rationale: one source of truth (shared-types-delta §0 rule), avoids
perpetuating drift, keeps the import/review/center contract consistent.
- **(d) Blocks:** **Phase 2** (S04 + S16). **[BLOCKS P2]**.
### B7. `ExtensionType` union — add `agent`, keep `external_tool`, or both?
*(Gap card S21 §9 Q1; PRD §12.13 vs §15.2.)*
- **(a) Why it matters:** PRD §12.13 marketplace categories include **Agents** but `ExtensionType`
(§15.2) omits `agent` and adds `external_tool`. The two PRD sections contradict; S21's faceted catalog
needs a canonical union.
- **(b) Options:**
1. *`skill | agent | connector | mcp | model | template`* — matches the §12.13 visible categories;
drop `external_tool` (external tools surface via connectors/MCPs anyway).
2. *Keep §15.2 literally (`…| external_tool`, no agent)* — but then Agents have no marketplace category.
3. *Superset of 7 (`…| external_tool | agent`)* — covers both, at the cost of an unused-for-now member.
- **(c) RECOMMENDED:** **(1) `skill | agent | connector | mcp | model | template`.** Rationale: PRD §12.13
is the user-visible contract; external tools are already represented by connectors/MCPs, so `agent`
earns the slot. Define once in `@waggle/shared`.
- **(d) Blocks:** **Phase 4** (Marketplace, S21). Not P1/P2.
### B8. Identity store of record for onboarding profile.
*(Gap card S13 §9 Q1; S01 §9 (greeting name).)*
- **(a) Why it matters:** Two identity stores exist — `/api/profile` (current onboarding write path) and
`/api/identity` (the `identity` table that backs the Home greeting name / `adapter.getIdentity()`).
Writing only one leaves the other stale (e.g. Home greets with an empty name).
- **(b) Options:**
1. *Onboarding writes profile AND seeds identity* — single round-trip extension; Home greeting works
immediately. (S13 §9 Q1 direction.)
2. *Profile-only, derive identity lazily* — fewer writes, but Home greeting drift until first identity write.
- **(c) RECOMMENDED:** **(1) Write profile + seed identity in the same onboarding commit.** Rationale:
prevents the two-store drift the gap card flags; cheap; makes the Phase-1 Home greeting correct.
- **(d) Blocks:** **Phase 2** (onboarding S13) and the **Phase 1** Home greeting depends on identity
being populated. Practically **[BLOCKS P1]** for a correct greeting; functionally a small fix.
---
## §C — Screen-local questions (single-screen scope; ratify with the owning card)
> These do not block other screens. Each carries a default recommendation consistent with the locked
> direction; founder can rubber-stamp or override per screen. Cited to the gap card for full context.
- **C1. S01 Q1 — LoginBriefing fate.** Retire the modal; absorb catch-up into Home Cockpit's first paint
(~80% overlap). **Rec: retire + absorb.** *(Phase 1.)*
- **C2. S01 Q2 — "Overnight" time-window semantics** (since last close vs midnight vs 12h). **Rec: since
last app close, fallback midnight-local.** *(Phase 1.)*
- **C3. S01 Q6 — Quick-capture `file` destination** (default/personal store vs prompt for workspace).
**Rec: default personal store + optional workspace picker.** *(Phase 1/2.)*
- **C4. S02 Q1 — Workspace Desktop window vs full-bleed route.** **Rec: maximized `AppWindow`** (no
parallel layout system). *(Phase 1.)*
- **C5. S02 Q2 — Overview chat: live mini-composer vs read-only preview.** **Rec: read-only preview that
deep-links to the Chat tab** (avoids dual ChatApp render modes in v1). *(Phase 1.)*
- **C6. S02 Q3 / S17 Q1 — `WorkspaceType` enum values.** **Rec: `project | client | research | personal`
(+`team`/`organization` reserved); `type` coexists with the free-string `group`.** *(Phase 1/2.)*
- **C7. S02 Q6 — Tasks store of record** (`/api/workspaces/:id/tasks` vs `WorkspaceState`
`pending`/`blocked`). **Rec: seed Tasks from `WorkspaceState` for v1; reconcile to a first-class task
store only if editing is needed.** *(Phase 1.)*
- **C8. S03 Q4 — Natural-language commands** (heuristic vs LLM). **Rec: deterministic heuristic
intent-parse v1; LLM resolver later.** *(Phase 1.)*
- **C9. S03 Q5 — Palette permission prompt mechanism.** **Rec: reuse the chat approvals pipeline
(`approval.ts` + `pendingApproval`).** *(Phase 1.)*
- **C10. S04 Q2 — Conflict state: live recall-time vs persisted.** **Rec: live recall-time signal v1**
(`CombinedRetrieval.detectConflict`); persist only if a standing conflict queue is needed. *(Phase 2.)*
- **C11. S04 Q4 — Merge semantics.** **Rec: re-cognify/concatenate v1, archive originals (not hard
delete); LLM-synthesis later.** *(Phase 2.)*
- **C12. S05 Q5 — Artifact previews.** **Rec: icon + on-click `FilePreview` v1; no server thumbnails.** *(Phase 2.)*
- **C13. S06 Q2 / S19 Q1 — Skill Builder publish target** (local dir vs marketplace). **Rec: Builder =
create-to-local (`POST /api/skills/create`); install-by-id + marketplace publish live in S06/S21.** *(Phase 3.)*
- **C14. S06 Q4 / S19 Q2 — Inputs/Outputs persistence** (frontmatter vs body markdown). **Rec: body
markdown v1; extend `SkillFrontmatter` only if inputs/outputs must be queryable.** *(Phase 3.)*
- **C15. S06 Q6 / install-audit `critical` CHECK bug.** Real bug: `AuditRiskLevel` TS includes `critical`
but the DDL CHECK allows only `low/medium/high` (`install-audit.ts:65` vs `:16`) — a `record()` with
`critical` throws; skill/MCP/connector installs route through this path. **Rec: ship the one-line CHECK
migration to add `critical`** (additive, idempotent-migration pattern at `db.ts:122`), OR make the
marketplace `CRITICAL → 'high' + approvalClass:'blocked'` mapping the permanent contract. **Pick the
migration** for correctness. *(Phase 4; cross-cuts any install-audit write.)*
- **C16. S07 Q1 — Connector "sync now" semantics.** **Rec: v1 = re-probe health + stamp `lastSyncAt`**;
background data re-pull deferred. *(Phase 4.)*
- **C17. S07 Q3 — revoke vs disconnect.** **Rec: `revoke` purges OAuth tokens + writes a stronger audit
entry (PRD §17.3); `disconnect` is the lighter alias.** *(Phase 4.)*
- **C18. S07 Q4 / S08 — Audit route shape.** **Rec: one shared `GET /api/extend/audit?type=` serving
connectors + MCPs + marketplace**, bound to `personal.mind`. *(Phase 4.)*
- **C19. S08 Q2 — MCP scope model** (single `workspaceId` vs `mcpIds[]` N:N). **Rec: single-`workspaceId`
config v1 (matches the stdio runtime); N:N membership deferred.** *(Phase 4.)*
- **C20. S08 Q4 — "Remote Registry" tab.** **Rec: defer remote-transport MCPs (runtime is stdio-only);
v1 tab points at the static catalog / Composio gateway reference, no new transport.** *(Phase 4.)*
- **C21. S08 Q5 / S21 Q5 — MCP "test" semantics.** **Rec: live spawn-and-`isHealthy()`/`tools/list`
round-trip** where cheap; fall back to static manifest validation. *(Phase 4.)*
- **C22. S09 Q6 — Agent categories taxonomy.** **Rec: Templates is a side affordance, not a tab; tabs =
All/Personal/Workspace/Team/Autonomous/Archive.** *(Phase 3.)*
- **C23. S09 Q7 / S18 Q3 — `/run` target + lifecycle.** **Rec: fleet-spawn a one-shot into a chosen
workspace (picker if multiple `workspaceIds`); persistent always-running agents deferred.** *(Phase 3.)*
- **C24. S11 Q1 / S20 Q1 — Automation triggers: schedule-only vs event-driven.** **Rec: schedule-only v1
(cron cadence); gate/defer the "Event" trigger (no event→automation dispatch substrate today).** *(Phase 3.)*
- **C25. S11 Q2 / S20 Q2 — Condition step.** **Rec: store an advisory `jobConfig.condition` string (no
evaluation engine) v1.** *(Phase 3.)*
- **C26. S11 Q3 / S20 Q3 — Builder "test run".** **Rec: add a no-persist dry-run route (`POST
/api/automations/test`); do NOT reuse the real `cron/:id/trigger` which executes + auto-enables.** *(Phase 3.)*
- **C27. S11 Q6 — Analytics tiles.** **Rec: keep success-rate (derivable from `cron_execution_history`);
drop "hours saved" (no source) or label it an explicit heuristic estimate.** *(Phase 3.)*
- **C28. S12 Q1 — Onboarding language selector.** **Rec: static disabled `English (US)` chip (no i18n
exists; PRD §4.4 puts i18n out of first-phase scope).** *(Phase 2.)*
- **C29. S12 Q2 — First-launch 3s auto-advance on the privacy screen.** **Rec: drop the auto-advance**
(it fights the read-the-privacy-note intent). *(Phase 2.)*
- **C30. S13 Q3 — Work-type vs Industry vs Template axis.** **Rec: keep Work type as a distinct
personalization signal; don't re-ask what the template already implies (PRD §12.12).** *(Phase 2.)*
- **C31. S14 Q2 — Tool Discovery id-space.** **Rec: unify under a namespaced scheme
(`connector:gmail` / `tool:cursor`) so the recommender + S15 disambiguate.** *(Phase 2.)*
- **C32. S14 Q3 — Pre-check detected AI tools.** **Rec: pre-select from `GET /api/tools/detect` with a
visible "detected" badge** (J01 implies a trusted populated start). *(Phase 2.)*
- **C33. S15 Q2 / S16 Q5 — Import↔Review commit split.** **Rec: S15 stages previews, S16 commits the
approved selection** (PRD:646/1207 "nothing imports without review/approval"; current code commits at
S15 — fix). Splits onboarding into the Import + Review steps. *(Phase 2; correctness-relevant.)*
- **C34. S15 Q1 — Hermes/Codex/Cursor tiles.** **Rec: render as `upload`/"Other" file pickers or
"coming soon" v1** (they are AI-OS launcher/hook surfaces, not harvest adapters). *(Phase 2.)*
- **C35. S17 Q5 — Workspace Creation: install-on-create vs stage selections.** **Rec: record connector/
MCP ids as workspace *intent* on the config; do NOT run install/OAuth at create time.** *(Phase 2.)*
- **C36. S19 Q4 — Skill scope vocabulary** (`enterprise` vs PRD `organization`). **Rec: adopt PRD
`organization`** for the publish-scope picker (align to the §15.2 `Scope` union). *(Phase 3.)*
- **C37. S19 Q5 — Skill test-run fidelity.** **Rec: preview-only (injected-prompt + parsed metadata) v1**;
live LLM dry-run deferred. *(Phase 3.)*
---
## Phase-blocking summary (founder fast-path)
**Before Phase 0/1 coding** (the spine): ✅ **RATIFIED 2026-06-09** — **B1** (shell topology / IA freeze),
**A1** (fixed layout), **A2** (Home personal-only), **B4** (command alias), **B8** (identity seed for
greeting). **Phase 0 is unblocked.**
**Must ratify before Phase 2** (work + onboarding): **A6** (artifact storage entity), **A8** (memory
retention/delete), **B2** (confidence: heuristic + optional migration), **B6** (MemoryKind canonical),
**A3** (graph keep — default yes), plus the onboarding correctness item **C33** (Import stages / Review
commits).
**Phase 3+ (intelligence/extend/team), not blocking P1P2:** **A4, A5, A7, B3, B5, B7** + all remaining
§C items. Note **A7** (RBAC) must be ratified before S10 coding specifically, and **C15** (install-audit
`critical` CHECK bug) should be fixed before any install-audit write path ships in Phase 4.
---
# UX Refactor v2.1 — Ratification of Decision Register D1D15 (2026-06-10)
**Ratifies:** `docs/UX_REFACTOR_STATE_AUDIT.md` §8.3 · **Ratified by:** Marko Marković (founder)
**Authority chain (declared by this register, D10):** this ratification > Brief v2.1 > `docs/UX_REFACTOR_STATE_AUDIT.md` > blueprint handoff package > prior-plan docs (`docs/ux-refactor/`).
This document + Brief v2.1 + the audit **supersede all prior conflicting ratifications, explicitly including B1 (2026-06-09)**. This file is the **single decision log** going forward — no parallel ratification tracks.
## Structural (D1D5)
### D1 — Shell topology: RATIFIED option (b) — AppShell via in-place conversion. **B1 is explicitly superseded.**
Convert to AppShell + left nav + single canvas + URL routes, reusing every shipped screen component as a route surface. Conditions:
1. **Zero screen-component rewrites during conversion**; screens mount under routes as-is. Divergences are phase work, not conversion work.
2. Brief route groups become **canonical addresses**; Ctrl+K command index and `handleSearchNavigate` retarget to routes; `waggle:open-app` CustomEvent deep links convert to URL navigation (the event bus may remain as an internal shim during transition, but **URLs are the contract**).
3. **No window z-order code ships** (`useWindowManager` z-order/focus/minimize/cascade retired). `waggle-window-state-v1` localStorage migrates or clears cleanly.
4. **Chat multi-instance:** chat becomes the widget inside Workspace Desktop (one per workspace, per blueprint "chat is one widget"). If conversion design surfaces a hard requirement for detached chat, propose it as a scoped exception ("D1-c lite") — do not silently keep windowing.
5. **B4 ("alias, don't rename" for `/api/*`) survives** — orthogonal to the shell and correct.
### D2 — Memory Center: RATIFIED — rework AND promote to standalone.
Standalone `MemoryCenterApp` (same shape as `ArtifactCenterApp`; audit §7.9 inconsistency resolved in favor of the standalone pattern). Top-level structure = **two-mind split**: "About you" (Personal Mind) / "About this work" (Workspace Mind, per workspace). Reuse `MemoryCenterTab` internals as the per-mind list. Confidence/metadata (B2, M1) carry over. Legacy MemoryApp tabs (Graph/Timeline/etc.) remain accessible from within the new surface or as secondary tabs — **do not delete capability, restructure the entry**.
### D3 — Auth gate: RATIFIED — full structural scope. All four audit conflicts in scope:
1. **Adapter-level pre-token deferral** (structural gate, not per-component convention).
2. **Throw-on-`!ok` mandated adapter-wide** — convert all silent-empty getters (`getMarketplace`, `getMcps`, `getPersonas`, `getModels`, `getWorkspaceTemplates`, `getTier`).
3. **401 → silent token refresh → single retry** (sidecar-restart recovery) — in scope.
4. **Boot-path surfaces in scope:** `Desktop.refreshTier` and `LoginBriefing` must never render silent-FREE / silent-empty on auth failure. **Tier resolution failing open to a rendered FREE state is classified as a monetization defect, severity-critical.**
Plus: error states never cache as valid-empty; focus/visibility revalidation on errored surfaces.
### D4 — Skill-write governance: RATIFIED — autonomy-aware gating, four bindings:
- **(i) Policy:** `create_skill` — normal autonomy = ask (in-chat approval card), trusted/yolo = auto-execute. `delete_skill` — **always ask, every autonomy level** (add to `isCriticalNeverAutopass`); destructive actions do not inherit autonomy. `read_skill` ungated. **Always-audit all three** outcomes with `initiator:'agent'`.
- **(ii) Surface:** the **in-chat SSE approval card is canonical** for agent skill writes. Brief §2.3's "same modal" is hereby interpreted as **same policy and risk taxonomy, not same component**. Align the card's risk display with the `ui/approval-modal.tsx` taxonomy (D15 work).
- **(iii) One write path — AMENDED ruling: do NOT route the agent tool through HTTP.** Extract a **shared skill-write service module** (create/update/delete + redaction + audit write inside the service) consumed by both `routes/skills.ts` and `skill-tools.ts`. One module, one audit trail, two callers.
- **(iv) Endpoint consolidation (absorbs D14):** raw `POST /api/skills` delegates to the audited service (or is deprecated in favor of `/api/skills/create`); `PUT` and `DELETE /api/skills/:name` enter the audit trail. **Provenance:** skill frontmatter `initiator`/`source` + `GET /api/skills` returns it + Skills Hub badge ("created by agent — review"), replacing the name-heuristic "Custom" classification for agent-created skills.
- **Persona exception RATIFIED:** read-only personas (planner/verifier) keep losing `create_skill`/`delete_skill` while retaining `read_skill`.
- **PM residual ruled (PRO-gate on skill creation):** skill creation — human and agent — **stays available at FREE for launch**. The self-evolving loop is the differentiator and must demo at the free tier. Marketplace installs remain PRO-gated. Reversible post-launch with data.
- **Two-seam WorkspaceDesktopApp edit RATIFIED (founder "go", 2026-06-10):** the derived edit from plan §5.2 — (a) controlled activeTab/onTabChange for URL-driven tabs, (b) chat widget embedded in the chat tab body — is signed off, scoped to exactly those two seams, test-pinned. P1a unblocked.
### D5 — Team zone: RATIFIED — keep tier-hidden. No stripping, no new work. Approvals-inbox PRO visibility: post-launch consideration, not launch scope.
## Scope clarifications (D6D10) — defaults ratified, with notes
- **D6 — RATIFIED.** S14-in-Launcher and S16-as-needs-review-filter satisfy the launch cut. Consent is given at import initiation; review is quality control, not consent. **Verification item:** Home Cockpit must surface a "N memories need review" alert (journey J08); if absent, add as a small Phase-2 item.
- **D7 — RATIFIED.** `UpgradeModal` satisfies §2.2; no rename, no rebuild — tests pin it. Brief language amended to "Upgrade surface."
- **D8 — RATIFIED.** Relabel dock `cockpit` entry ("Mission Control"); **"Command Center" is reserved for the Ctrl+K palette.**
- **D9 — RATIFIED.** Sweep: code (the `HomeCockpit.tsx:145` user-visible "Win+K" pill is the must-fix; comments included) + `docs/ux-refactor/` prose. Handoff-package PDFs/docx get a one-page annotation (naming erratum), not regeneration.
- **D10 — RATIFIED, extended.** Commit the package's text files; gitignore (or LFS) the binaries. Authority chain declared (header above). Prune merged worktrees (`waggle-os-ux-refactor`, `waggle-os-ga`) and the 5 merged branches. Brief path corrections from audit §7 accepted (workspace-manager in hive-mind-core; state/context in server/local).
## Launch integrity (D11D15) — all confirmed
- **D11 — RATIFIED.** Honor `WAGGLE_DATA_DIR` in `service.ts` with the same default; **one startup log line: resolved dataDir + tier**. Fix the stale "default to SOLO" comment while in there. Closes the split-brain with installer/launcher.
- **D12 — RATIFIED, launch-blocking for the desktop binary.** Refresh `app/src-tauri/resources/service.js` now; prefer build-time generation + untracking; CI staleness/hash gate is the minimum acceptable. **A binary shipping an April server is a release-stopping defect class.**
- **D13 — RATIFIED, both halves.** Document `build:packages` in the boot recipe AND alias `@waggle/shared`→src on the dev path so the class dies.
- **D14 — Folded into D4(iv). Closed.**
- **D15 — RATIFIED.** Launch-blocking from prior-plan P6: **per-screen state grid** (brief rule 10) + **approval/audit taxonomy consolidation** (brief rule 7, includes D4-ii alignment). Post-launch: connector `/sync` real implementation (stub stands), MCP logs.
## Additional items (no decision letter — just do)
- **Backlog flag:** investigate the teams-server boot error from the live probe (`Build failed: Fastify instance is already listening` when `CLERK_SECRET_KEY` is set) — classify noise vs defect. Post-launch unless it affects the solo boot path.
- **memory-mcp duplication (audit §7):** out of launch scope. Mark `packages/memory-mcp` dormant; canonical-package decision (vs `hive-mind-mcp-server`) deferred post-launch.
- **`WorkspaceBriefing.tsx`:** keep as ChatApp empty state; no merge into Home. Brief's keep-list note corrected.
- **Audit process rule going forward:** audits report, they don't mutate (no fast-forwards, no pid overwrites mid-audit; disclose if unavoidable).
## Phase sequence (unblocked)
**Phase 0** = D1 conversion plan + route map, naming sweep (D8/D9), doc authority (D10). Then **P1**=D3, **P2**=verify + J08 alert, **P3**=D2, **P4**=D11/D12 + FREE→Upgrade e2e re-run, **P5**=D4 ✅ (2026-06-12, 7 commits 73f2ed5→48292ef), **P7**=D15 scope ✅ (2026-06-12: Track B B1-B5 + Track A A1-A7; D15 closure bar MET). **Nothing from prior Phases 04 is rebuilt.**
---
## D3 implementation notes (P1b, 2026-06-11)
Recorded per the single-decision-log rule; full design + verification record in
`docs/ux-refactor/p1b-auth-gate-plan.md` + `p1b-plan-review-record.md`.
1. **fetchRaw exception class — ratified-flow-preserving deviation from the literal
"throw mandated adapter-wide" (D3-2).** Two caller classes keep non-throwing
semantics because their *error-path payload is load-bearing*: raw-Response
consumers (`installMarketplacePackage` — documented 403/SecurityGate status
handling) and body-envelope getters (`installMcp` + 6 MCP siblings +
`revokeConnector` — their 403/422 bodies carry `TIER_INSUFFICIENT` and the
`requiresApproval/blocked/severity` envelope that drives the D4 ApprovalModal
security flow). All six ruling-named getters throw as mandated. Adapter-level
envelope pins added (component tests mock the adapter and cannot see this layer).
2. **Plus-clause revalidation scope.** Wired: tier (ShellContext), useBilling,
useWorkspaces, LoginBriefing, MCPHubApp resolvableMcpNames, ComplianceDashboard
templates. Deferred to P7 with ledger: ChatWindowInstance FALLBACK_MODELS,
TemplatesView/AgentBuilder catalogs (their boot-race instance dies with the gate;
the 401-retry leg cures their restart instance; residual is genuine-5xx staleness).
3. **D3-4 extensions (same monetization-defect class):** useBilling (Settings→Billing
rendered FREE-as-fact + upgrade CTAs on failure) and the Settings→General
"{tier} plan" badge (separate getSettings-fed copy, now single-sourced from
resolved billing state).
4. **DISCOVERED, OUT OF P1b SCOPE — needs a founder ruling:** all five EventSource
SSE channels (notifications / events / subagent status / waggle signals / harvest
progress) are **401-dead in every default run since D1** — the server bearer-gates
all /api/* GETs, EventSource cannot send headers, no SSE route accepts ?token=
(only /ws does), and onerror handlers permanently close. Working only under
WAGGLE_TRUST_LOCALHOST=1. Fix = server auth model (per-route ?token= like /ws, or
exempt-with-validation) + client reconnect design — one coherent follow-up
("SSE auth + reconnect"). **Ask: ratify as P1b follow-up stage or P2 line item.**
---
## P2 implementation notes (verify + J08, 2026-06-11)
Recorded per the single-decision-log rule; full record in
`docs/ux-refactor/p2-verification-record.md`.
1. **P2 verification CLOSED.** Home (§12.1) + Desktop (§12.2) verified against Brief
v2.1 via a 4-lane adversarial workflow: 25/37 met or ratified-divergence, 12
confirmed gaps, 2 claims refuted. The HIGH (dead Artifacts feed — envelope
unwrap) + all tiny/small verified defects fixed; feature-shaped residuals
ledgered in the record (S02 tab embeds → P3/P7; status-bar chips, upNext
tasks, activeModels → P7).
2. **D6 J08 alert SHIPPED.** `needsReviewCount` rides `GET /api/home/briefing`
(personal-mind only, 200-frame bound matching the Memory Center's own window);
Home banner deep-links via `waggle:open-app {appId:'memory', filter:'unreviewed'}`
with a `?filter=` URL carrier + MemoryRoute cold-load re-stash (typed URLs and
the §2.3 shim share one mechanism, AutomationsRoute pattern).
3. **D3-4 extension:** WorkspaceDesktop revalidation arms only for the transient
offline state — deterministic 404/403 states do not auto-refetch on focus.
4. **Note (P1b-SSE follow-up):** the SSE ask above was ratified and SHIPPED as a
P1b follow-up (PR #15, main @ 4e3d65d) — closed before P2 started.
---
## P3 implementation notes (D2 two-mind Memory Center, 2026-06-11)
Recorded per the single-decision-log rule; full design + live-run findings in
`docs/ux-refactor/p3-memory-center-plan.md`.
1. **D2 SHIPPED in full.** Standalone `MemoryCenterApp` (ArtifactCenterApp shape, fully
controlled — URL is the only navigation authority): mind pills "About you" / "About this
work · {ws}" on the Memories view; all six legacy MemoryApp views survive as secondary
tabs (Timeline extracted verbatim to `memory/TimelineTab.tsx`; `MemoryApp.tsx` retired —
capability preserved, entry restructured). `/memory/:mindScope` + `?tab=` implemented
(conversion plan §5.3 #1-2 closed); `?filter=` J08 stash unchanged. S02-FR2 Memory part
closed: WorkspaceDesktop memory tab embeds the per-mind list (`consumeDeepLinks=false` so
the J08 stash stays with the /memory route).
2. **Server contract (additive):** `GET /api/memory?mind=personal|workspace` selects one
store; invalid mind or workspace-less `mind=workspace` is a 400 (a typo must not silently
become the merge view); omitted mind keeps the legacy merge (pinned). Workspace-mind
mutations now carry `workspace` from the FE — without it, PATCH/archive/delete/merge
missed the workspace store entirely (404 class, fixed + pinned).
3. **Cross-mind id-collision class:** per-mind SQLite autoincrements collide; the split makes
every view single-mind (mutation ambiguity structurally gone from the new UI); selection +
list clear on mind switch (cross-mind merge / stale-rows-under-wrong-pill pins). Full id
namespacing remains post-launch.
4. **Live-run defects fixed (pre-existing, surfaced by the mandatory smoke):**
KnowledgeGraphViewer crashed the surface on untyped entities (54/214 real rows; fixed via
single-entry node normalization, 'unknown' legend chip); Timeline duplicated React keys on
cross-mind id 36 (fixed via mind-qualified keys).
---
## P4 implementation notes (D11 + D12 + clean-install onboarding, 2026-06-11)
Recorded per the single-decision-log rule; full record in
`docs/ux-refactor/p4-launch-integrity-record.md`.
1. **D11 SHIPPED.** `resolveDataDir()` = option > `WAGGLE_DATA_DIR` > `~/.waggle` (split-brain with
installer/marketplace/memory-mcp closed); the ratified one-line startup log
`Data dir: <resolved> · tier: <effective>` via `readTierFromDataDir` (extracted; same
config.json + getEffectiveTier contract as `GET /api/tier`); both stale SOLO comments fixed.
Live-verified: env-pointed boot logged the tmp dir + tier FREE.
2. **D12 SHIPPED — preferred shape (generation + untracking).** `service.js`/`.map` untracked +
gitignored; `tauri.conf.json` `beforeBuildCommand` owns the full prep chain so a raw
`npx tauri build` ships a CURRENT server (previously: the April copy). Dev mode unaffected
(service.rs debug branch spawns service.ts via tsx). Pinned in tauri-config.test.ts.
3. **S4 founder flag RESOLVED — the clean-install skip was REAL.** `ensureDefault()` at boot +
the `getWorkspaces().length > 0` auto-complete evidence meant brand-new production users never
saw the wizard. Fix: server-authoritative `GET /api/onboarding/status` (completion flag
`<dataDir>/first-launch.flag` — same file as the Tauri IPC stamp — OR legacy evidence: any
personal-mind frame / >1 workspaces; the seeded stub is NOT evidence) +
`POST /api/onboarding/complete` stamped from `useOnboarding.update()` on completion. Fail
direction: toward showing the wizard. Live-verified clean dataDir → `completed:false`.
Accepted edge: a pre-flag returning user with zero frames + only the default workspace re-sees
the wizard once (no durable signal can distinguish them; class dies as flags stamp).
4. **FREE→Upgrade e2e re-ran:** Act 4 Tier Wall 6/6 on a fresh FREE install under
`WAGGLE_TRUST_LOCALHOST=1`; the unauthenticated first run's 3 failures are the documented
dock-era-spec-vs-P1b-bearer-gate class — spec-side token wiring stays ledgered with the P7 e2e
band.
5. **Two-round adversarial review (19 confirmed total / 34 refuted) — all confirmed findings
fixed,** headlined by: a HIGH in P4's own first cut (the D12 hook re-ran arch-parameterized
bundle scripts arch-blind — cross-arch macOS release legs would ship a non-launching Intel DMG;
hook trimmed to the arch-independent sidecar bundle + a fail-loud resources preflight); a
verified MED chain where the wizard's own step-1 profile write counted as returning-user
evidence (server-durable PENDING latch added — only explicit completion flips status once a
dataDir is identified as un-onboarded); the Tauri fs-flag now honors `WAGGLE_DATA_DIR` (Rust)
so the IPC fast-path and the server stamp share one file on every install shape; and the
sidecar bundle now compiles `@waggle/shared`/`@waggle/hive-mind-core` from SOURCE (esbuild
alias — the regenerated bundle used to embed stale gitignored dist silently). Full dispositions:
`docs/ux-refactor/p4-launch-integrity-record.md`.