moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
# Fast-follow: multi-step plan execution for the NL Command Bar
**Opened:** 2026-06-27 · **Status:** open · **Owner:** TBD
## Context
The Tier 1 NL intent resolver (`POST /api/command/interpret`) ships in v1 with
**single-action + approval** only (per the brief's §2 "v1 = single-action").
The `plan` kind is **typed but not executed**:
- `command-intent.ts` carries `InterpretResult.steps?: ResolvedAction[]`.
- `command-interpret.ts` collapses a 1-step plan to a single action and
**downgrades a multi-step plan to `clarify`** ("This needs multiple steps: …
Want me to start with the first?"), offering only the first step.
## Scope of this ticket
Execute a validated multi-step plan end-to-end:
1. Sequential execution of `steps[]` with a per-step preview (reuse the approval
surface for each side-effect step; reads/navs run inline).
2. Stop-on-failure + partial-progress reporting.
3. A plan review surface in the palette (list the steps, let the user drop/reorder
before running) — or hand off to the chat/agent loop for true orchestration.
4. Decide ownership: a multi-step plan may belong to the **agent loop**
(`agent-loop.ts`) rather than the command bar, since it already has
step/confirmation/loop-guard machinery. Evaluate routing `plan` → a scoped
agent run instead of bespoke palette orchestration.
## Guardrails (unchanged)
- Closed registry only — every step is a registry action id, server-validated.
- Destructive steps always approve (D4 / `confirmation.ts`), every autonomy level.
- Tier gate applies per step.

View File

@@ -0,0 +1,45 @@
# NL Universal Command Bar (Ctrl+K Intent Layer) — Step 0 verification + design
> Brief: `docs/Waggle OS — Claude Code Brief add on.txt`. Implementation arc 2026-06-27.
## Step 0 — source verification (brief assumptions vs live source)
| Brief assumption | Verified at source | Delta |
|---|---|---|
| `overlays/CommandCenter.tsx` is cmdk-based, 6 verb groups, structured matcher, no LLM | ✅ `cmdk`; `CATEGORY_ORDER = search/launch/create/run/navigate/extend`; server `commandSearch` + offline `fuzzyMatch`; NL fallback row posts raw to `/api/command/execute` | none |
| `/api/command/*` = search/recent/suggestions/execute; no interpret | ✅ all four in `routes/command.ts` (`commandRoutes: FastifyPluginAsync`, registered `index.ts:2117`); **no interpret endpoint** | none |
| Bar navigates via routes (`handleSearchNavigate` successor) | ✅ `onNavigate(type,id)` → AppShell `handleSearchNavigate``routeForSearchResult()` (`lib/routes.ts`). `command:<appId>``routeFor(appId)`; `workspace:<id>``/workspaces/<id>` | none |
| Capability surface enumerable | ✅ `filterToolsForContext`, `PERSONAS`, `/api/workspaces`, `/api/mcps/install` (PRO), `/api/skills`, `/api/connectors`, `/api/automations`, `APP_ROUTES`/`routeFor` | none |
| Approval surface | ✅ `ui/approval-modal.tsx` (`ApprovalRequest{action,scope[],riskLevel,…}`) + CommandCenter inline `PermissionPrompt` | reuse inline `PermissionPrompt` |
| Tier gate | ✅ `requireTier()`/`readTierFromRequest` 403 `TIER_INSUFFICIENT`; `adapter.fetch` auto-dispatches `waggle:tier-insufficient{required,actual,message}`; `UpgradeModal` listens | none |
| Sidecar LLM | ✅ in-process `/v1/chat/completions` proxy, model `claude-haiku-4-5`, needs `vault.get('anthropic')` | not a LiteLLM client lib — use the proxy (per `profile.ts`) |
**Verdict:** brief holds. No material delta — proceed.
## Architecture
**Two-tier.** Tier 0 = existing cmdk fuzzy (untouched). Tier 1 = `POST /api/command/interpret` (LLM), fired only on sentence-like / no-match input, never blocking the cmdk list.
**Closed-registry safety (core property).** The LLM returns only an action **`id` + `params`**. The **server** maps `id`→route/endpoint via `ACTION_REGISTRY`, validates params, and derives `sideEffect`/`riskLevel`/`requiredTier`. The LLM can never emit an endpoint, route, or free code — only pick a registry id. Unknown id → `none`.
**Reuse, no new execution layer.** Resolved actions execute through existing paths: navigation via `onNavigate` (→ `routeForSearchResult`), side-effects via the existing `PermissionPrompt` then a POST to the **server-derived** endpoint, tier-gated via the existing `waggle:tier-insufficient` event.
**v1 registry (closed set):** `open_app` (nav), `open_workspace` (nav), `create_workspace` (side-effect, low), `install_mcp` (side-effect, medium, PRO). Plus resolver kinds `clarify` / `tier_gated` / `none` / `plan` (typed, **not executed** in v1 → downgraded to clarify/single-action).
**Memory context (differentiator).** Reuse `buildWorkspaceNowBlock` + `formatWorkspaceNowPrompt` (already imported in `command.ts`) for the active-workspace "now" block, plus `workspaceManager.list()` (id+name) so "continue what I was working on" / "open the X workspace" resolve against real ids. No new memory queries.
**Side-effect taxonomy.** `create_workspace`/`install_mcp` are `sideEffect:true` (preview-and-approve), consistent with `confirmation.ts` (writes/installs gate); nav/reads execute directly. Tier check reuses `assertTierCapability`.
**Graceful degradation.** No vault key / LLM error / JSON parse fail → `{ kind:'none', fallback:true }` (HTTP 200) → FE shows Tier 0 matches + "couldn't interpret".
## Files
- `packages/shared/src/command-intent.ts``InterpretResult` / `ResolvedAction` contract (+ barrel).
- `packages/server/src/local/command-registry.ts``ACTION_REGISTRY` + pure validate/build/tier (unit-tested).
- `packages/server/src/local/command-interpret.ts` — prompt build + memory context + LLM call + JSON parse → `InterpretResult`.
- `packages/server/src/local/routes/command.ts` — add `POST /api/command/interpret` (thin).
- `apps/web/src/lib/adapter.ts``commandInterpret` + `commandDispatchAction`.
- `apps/web/src/components/os/overlays/CommandCenter.tsx` — Tier 1 wiring (additive; Tier 0 untouched).
## Fast-follow (out of v1 scope)
- Multi-step `plan` execution (typed now, returns clarify). Ticket: `docs/nl-command-bar/FASTFOLLOW-multistep-plan.md`.
- `switch_persona`, `connect_connector` headless, `install_skill` headless (v1 routes these intents to their screens via `open_app`).