diff --git a/.agents/skills/flect-quality/SKILL.md b/.agents/skills/flect-quality/SKILL.md new file mode 100644 index 0000000..a635973 --- /dev/null +++ b/.agents/skills/flect-quality/SKILL.md @@ -0,0 +1,158 @@ +--- +name: flect-quality +description: Evaluate, improve, review, or release Flect against its canonical user-quality contract. Use for product-quality baselines, release readiness, user-outcome audits, evidence verification, gap prioritization, claim validation, dogfooding, or implementation work intended to move an FQ criterion to proven. +--- + +# Flect quality + +Use Flect's public behavior to prove user outcomes. Do not reconstruct the +quality contract inside this skill. + +## Load the contract + +1. Read the repository `AGENTS.md`, `VISION.md`, `PRODUCT.md`, + `ARCHITECTURE.md`, `CONTRIBUTING.md`, and every nearer instruction file. +2. Read `docs/product-quality.md` completely. It owns criteria, constituencies, + release gates, and proof classes. +3. Read the current release claims in `README.md` and the relevant owning + documentation. +4. Read existing reports under `docs/verification/` that claim evidence for + the criteria in scope. +5. Inspect the worktree and record uncommitted-state caveats. Never discard or + overwrite unrelated work. + +## Select the operation + +- **Evaluate:** classify every criterion required by the requested release or + scope and write a dated baseline. +- **Improve:** start from a frozen baseline, select the smallest independently + reviewable gap, and follow the repository's design, plan, TDD, and + verification workflow. +- **Review:** compare a proposed change and its evidence with the affected + criteria; report missing behavior, weakened boundaries, and unsupported + claims before style concerns. +- **Release:** prove every current release claim and every criterion required + by that release class. Any regression, unsupported claim, missing mandatory + evidence, or non-waivable gate failure blocks the release. + +Evaluation and improvement are separate phases. Freeze the observations before +changing the behavior they describe. + +## Build an evidence map + +For every criterion in scope, record: + +- criterion identifier; +- `unimplemented`, `partial`, `implemented`, `proven`, or `regressed`; +- exact evidence path, command, workflow, host, date, and revision; +- missing proof or observed failure; +- release impact; and +- existing GitHub issue, if any. + +Use only the proof classes required by the contract. Prefer the smallest public +surface that establishes the whole outcome: + +- exported Effect contracts and Layers for deterministic behavior; +- production Chromium for visible browser behavior; +- the packaged application and public `flect` executable for native behavior; +- adversarial tests for capabilities, credentials, sandboxes, extensions, and + recovery; +- keyboard, assistive-technology, visual, and dogfooding evidence for outcomes + automation cannot judge alone; +- clean artifacts and clean-machine workflows for release claims; and +- public integration contracts for adopter outcomes. + +Source inspection may identify where to test. Prose, source strings, successful +compilation, test names, screenshots without behavior, generated plans, and an +agent's assertion cannot establish `proven`. + +## Exercise Flect publicly + +Use visible UI, public HTTP/SSE or MCP contracts, and the public `flect` AXI. +Do not drive React internals, mutate browser storage, call private sidecar +modes, or treat direct database or journal inspection as user evidence. + +Start agent-first discovery with `flect`, then request only the bounded state +needed. Keep outside control disabled unless the user explicitly enables it in +the protected shell. Revoke it when live inspection is finished. + +For a complete supported-slice baseline, normally run: + +```bash +bun install --frozen-lockfile +bun run check:quality +bun run check:all +``` + +Run `bun run test:pi-smoke` only when approved provider authentication is +available and a live turn is required. Never capture credentials, private +control capabilities, unbounded logs, or sensitive product output. + +## Record the baseline + +Write `docs/verification/YYYY-MM-DD--verification.md`. Include: + +1. scope, release class, date, revision, branch, dirty-state caveat, and hosts; +2. commands and public workflows actually run; +3. one classification for every criterion in scope; +4. exact evidence and limitations; +5. current claims contradicted by behavior; and +6. unproven release gates and their issue links. + +Keep a baseline immutable after it is frozen except to correct factual or +redaction errors. A later run creates a later report and may supersede it. + +## Reconcile delivery work + +Use `gh-axi` for GitHub inspection and mutation. Search open and closed issues +before creating anything. Do not create one issue per criterion mechanically. + +Create the smallest independently reviewable issue that closes a real behavior +gap. Each issue names: + +- affected `FQ-*` identifiers; +- observable acceptance criteria; +- exact proof classes and public workflows; +- dependencies and explicit non-goals; +- owning documentation; and +- security, recovery, portability, or accessibility constraints that must + remain true. + +Place delivery issues in the dedicated Flect organization project. The project +owns live priority, dependency order, release slice, assignee, and status. Do +not copy that status into `docs/product-quality.md`. + +## Improve one vertical slice + +Before behavior changes, use the repository's required brainstorming and plan +workflow. Split independent subsystems into separate reviewed designs and +plans. Start observable behavior with a failing test and use Effect throughout +the application architecture as required by `AGENTS.md`. + +Require: + +- real Chromium for UI, shaping, import, accessibility, or browser sandbox + behavior; +- packaged-host and public AXI dogfooding for native or external-control + behavior; +- adversarial negative tests for new authority or extension boundaries; +- deterministic recovery tests for changes affecting candidates, persistence, + extensions, or accepted state; and +- updates to the canonical documentation owner without parallel capability + lists or implementation claims. + +Implementation does not make its own criterion `proven`. Re-run the required +public evidence after the change and record a new verification report. + +## Fail closed + +Immediately report and treat as release-blocking when applicable: + +- shipped behavior contradicts a current claim; +- credentials or private capabilities appear in output or artifacts; +- shaped or extension code can bypass typed capabilities or recovery; +- acceptance, rollback, safe mode, or outside-control revocation is not + deterministic; +- evidence is missing, stale, scoped to the wrong host, or derived only from + implementation details; or +- a regression is obscured by changing prose or lowering the criterion. diff --git a/.agents/skills/flect-quality/agents/openai.yaml b/.agents/skills/flect-quality/agents/openai.yaml new file mode 100644 index 0000000..b10f832 --- /dev/null +++ b/.agents/skills/flect-quality/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Flect Quality" + short_description: "Prove and improve Flect user outcomes" + default_prompt: "Use $flect-quality to evaluate Flect against its canonical user-quality contract and produce evidence-backed gaps." diff --git a/.agents/skills/flect/SKILL.md b/.agents/skills/flect/SKILL.md new file mode 100644 index 0000000..4e3d282 --- /dev/null +++ b/.agents/skills/flect/SKILL.md @@ -0,0 +1,66 @@ +--- +name: flect +description: Operate and inspect a running Flect interface through its bounded agent-first command surface. Use when an agent needs to inspect Flect state, read operation evidence, invoke visible actions, shape an interface, manage revisions or models, debug a Flect workspace, or configure explicit native Flect integrations. +--- + +# Flect + +Use the public `flect` command. Treat it as the authoritative command surface for the running interface; do not drive React, storage, broker internals, or private runtime binaries directly. + +## Start with discovery + +1. Run `flect` with no arguments for content-first discovery and relevant next actions. +2. Run `flect inspect` only when more workspace detail is needed. +3. Run `flect action list` before invoking a product action. +4. Prefer default bounded TOON output. Add `--json` only for a consumer that requires JSON and `--full` only when complete authorized text is necessary. + +## Respect authority + +- App Agent uses the accepted product and its projected actions. It does not shape or accept revisions. +- Shaper changes interface candidates inside its disposable sandbox. Run `flect interface validate ` before `flect interface propose `; proposal acceptance remains a user decision. +- Outside agents require the user's explicit local-control grant before live workspace operations become available. +- Help visibility is not authorization. Treat structured `unauthorized`, `conflict`, `rejected`, and `unavailable` results as definitive. + +## Command map + +| Command | Purpose | Intended caller | +| --- | --- | --- | +| `flect` | Show content-first live discovery and relevant next commands. | outside agent, App Agent, Shaper | +| `flect inspect [--fields ]` | Inspect validated live workspace state. | outside agent, App Agent, Shaper | +| `flect logs [--limit ] [--role ]` | Read bounded, correlated operation evidence. | outside agent, App Agent, Shaper | +| `flect watch [--after ]` | Wait for the next reactive workspace event. | outside agent, App Agent, Shaper | +| `flect target ` | Select the visible Use or Shape conversation explicitly. | outside agent, App Agent | +| `flect mode set ` | Compatibility alias for selecting Shape or Use. | outside agent, App Agent | +| `flect prompt \|--stdin` | Ask App Agent to use the accepted product. | outside agent, App Agent | +| `flect shape \|--stdin` | Ask Shaper to prepare a validated interface proposal. | outside agent, Shaper | +| `flect cancel ` | Stop the selected running agent turn. | outside agent | +| `flect action list\|inspect\|invoke` | Discover and invoke actions projected by the visible interface. | outside agent, App Agent | +| `flect product invoke [--input ]` | Invoke a registered product operation without raw HTTP access. | outside agent, App Agent | +| `flect permissions list\|revoke ` | Inspect product permission lifecycle or revoke a visible decision; grants remain protected UI decisions. | outside agent, App Agent, Shaper | +| `flect interface inspect\|schema\|validate\|propose` | Inspect or propose interface documents inside Shaper's sandbox. | Shaper | +| `flect proposal accept\|reject` | Resolve the current validated preview as a protected user decision. | outside agent, App Agent | +| `flect revision list\|rollback` | Inspect revision state or request deterministic rollback. | outside agent, App Agent | +| `flect repository status` | Inspect canonical Git refs, isolation, and conflict state. | outside agent, App Agent, Shaper | +| `flect share list\|inspect` | Inspect bounded inactive shared candidates and retained installations. | outside agent, App Agent, Shaper | +| `flect share open-url\|open-git\|reject\|export` | Route bounded shared-source actions through protected user review. | outside agent | +| `flect share checkpoint --at --write --message ` | Checkpoint bounded Shaper sandbox files onto an exact retained share fork. | Shaper | +| `flect share resolve --base --upstream --fork --write --message ` | Submit an exact bounded Shaper resolution for every reviewed shared conflict path. | Shaper | +| `flect model list\|select\|favorite` | Inspect and select Pi-backed models without exposing credentials. | outside agent, App Agent, Shaper | +| `flect extensions list\|describe\|call` | Discover and call enabled portable extensions for the current role and binding. | outside agent, App Agent, Shaper | +| `flect trusted-extensions enable\|disable ` | Set opt-in loading for the selected Pi role's outside extensions. | outside agent, App Agent | +| `flect safe enter\|restore` | Enter compiled recovery or restore the last-known-good interface. | outside agent, App Agent | +| `flect rail collapse\|expand\|width ` | Set the protected agent rail presentation. | outside agent, App Agent | +| `flect control status\|disable` | Inspect or revoke explicitly granted outside control. | outside agent | +| `flect context --host ` | Emit bounded static guidance plus available live Flect context. | outside agent | +| `flect setup status` | Inspect the fixed shell link and opt-in agent integrations. | outside agent | +| `flect setup shell install\|remove` | Manage only ~/.local/bin/flect for the installed desktop app. | outside agent | +| `flect setup agent install\|remove ` | Manage one ownership-marked ambient context integration. | outside agent | +| `flect setup uninstall inspect\|prepare` | Inspect or remove only Flect-owned integrations before moving the app to Trash. | outside agent | +| `flect mcp` | Serve the compact MCP adapter over stdio. | outside agent | + +## Keep the boundary safe + +- Never request or print model credentials, the local-control capability, private runtime flags, or unbounded logs. +- Use explicit set-shaped commands instead of inventing toggles or raw payload escape hatches. +- Read the returned receipt and resulting workspace state before deciding whether another command is needed. +- Use `flect logs --limit 20` for bounded failure evidence and safe mode for deterministic recovery. diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..35df499 --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,74 @@ +name: Flect quality + +on: + pull_request: + branches: + - main + push: + branches: + - main + workflow_dispatch: + inputs: + failure_probe: + description: Prove that the public quality check fails closed + required: false + type: boolean + default: false + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + quality: + name: Flect quality gate + runs-on: macos-15 + timeout-minutes: 45 + env: + CI: true + steps: + - name: Check out the exact revision + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 + with: + persist-credentials: false + + - name: Install the pinned Bun runtime + uses: oven-sh/setup-bun@b7a1c7ccf290d58743029c4f6903da283811b979 + with: + bun-version: "1.3.14" + no-cache: true + + - name: Install the pinned Rust toolchain + uses: dtolnay/rust-toolchain@2c7215f132e9ebf062739d9130488b56d53c060c + with: + toolchain: "1.93.0" + components: rustfmt + + - name: Install locked dependencies + run: bun install --frozen-lockfile + + - name: Install the pinned Chromium runtime + run: bunx playwright install chromium + + - name: Run the canonical quality gate + run: bun run check:all + + - name: Deliberate failure probe + if: github.event_name == 'workflow_dispatch' && inputs.failure_probe + run: bun -e 'throw new Error("Deliberate Flect CI failure probe.")' + + - name: Upload bounded browser failure evidence + if: failure() && !cancelled() + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 + with: + name: flect-browser-failure-${{ github.run_id }} + path: | + test-results/** + !test-results/control-state/** + if-no-files-found: ignore + retention-days: 7 + compression-level: 9 + include-hidden-files: false diff --git a/.gitignore b/.gitignore index bad842d..44896d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ .DS_Store .worktrees/ -.repos/effect +.repos/ node_modules/ +.astro/ dist/ +dist-spa/ +dist-product-sdk/ dist-release/ coverage/ playwright-report/ @@ -13,3 +16,4 @@ src-tauri/binaries/ .env .env.* !.env.example +.tauri-signing-key* diff --git a/AGENTS.md b/AGENTS.md index 77d5c20..fc81296 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,6 +15,10 @@ Before changing Flect: - Keep changes inside the smallest component that owns the behavior. - Use the approved design and implementation plan under `docs/superpowers/` for the initial MVP. +- Read `docs/product-quality.md` before designing, implementing, reviewing, or + releasing user-visible behavior. It owns Flect's stable user outcomes and + proof requirements. Do not claim an outcome is supported or proven without + current linked evidence through the required public interfaces. Repository-wide constraints: @@ -27,9 +31,15 @@ Repository-wide constraints: `Ref`/`SubscriptionRef` for shared or observable state. Use Effect configuration, scheduling, retry, timeout, logging, and observability facilities instead of parallel ad hoc mechanisms. +- Use `Effect.all` or `Effect.forEach` for concurrent fan-out. Do not use native + promise fan-out in owned TypeScript; `bun run check:effect-concurrency` + enforces this across application, tooling, release, and test code. - Name non-trivial workflows with `Effect.fn`, keep defects distinct from expected typed failures, and provide dependencies through Layers in tests. Use Effect test services such as `TestClock` when behavior depends on time. +- Match expected Effect failures structurally by their stable `_tag`, using + `Effect.catchTag` or `Effect.catchTags` when recovering. Do not use + `instanceof` to route errors in an Effect error channel. - Compose Layers once at the runtime edge. React components may own rendering state, but data access and business workflows must enter through an Effect runtime rather than Promise-shaped application services. @@ -73,6 +83,18 @@ Repository-wide constraints: prompts. App Agent cannot shape revisions or modify recovery. The Shaper may receive explicitly approved UI-shaping capabilities, but it cannot modify the Guardian, safe mode, recovery code, or revision journal. +- Keep accepted App Agent, candidate Preview App Agent, and Shaper conversation, + Pi-session, cancellation, and browser-shell workspace state separate. Preview + App may inherit App authority policy, but it receives only bounded candidate + context and must not read accepted history or accepted workspace files. +- Present one continuous agent conversation. Keep App Agent, Shaper, Preview + App, and Guardian as internal trust domains, never as modes or identities the + user must select. Route intent through typed controller decisions informed by + the active canvas, selected semantic target, requested operation, and + available capabilities. A valid local UI-only change activates and + checkpoints automatically; capability expansion, destructive outside + effects, installation, sharing, and protected recovery remain explicit + decisions. - A shared Pi `ModelRuntime` may resolve models and provider authentication, but Guardian, App Agent, and Shaper sessions use separate `SessionManager`, `SettingsManager`, and `ResourceLoader` instances. An @@ -105,6 +127,25 @@ Repository-wide constraints: Tauri, DOM, storage, module, or arbitrary host-function authority. - Keep runtime automation in TypeScript. Prefer native browser, Bun, Pi, and provider interfaces over repository-owned wrappers or shadow state. +- Route every semantic user, CLI, HTTP, MCP, and platform action through the + same schema-defined `FlectWorkspaceController`. Outside adapters may not + drive DOM selectors, edit client storage, or create parallel revision, + conversation, preference, control, or operation state. +- Keep outside control disabled by default, user-enabled only from the + protected shell, bound to an ephemeral loopback address, authenticated by a + rotating private capability, attributable, and immediately revocable. Never + expose its bearer through output, logs, prompts, argv, tests, screenshots, or + public workspace state. +- Keep operation evidence bounded, in-memory, correlated, and redacted. It may + explain controller, transport, turn, tool, validation, and revision behavior; + it must not become a credential-bearing transcript, durable audit database, + or second source of application truth. +- Keep every agent-facing command surface AXI-compliant: route commands through + the shared Effect parser and `FlectWorkspaceController`, default to bounded + TOON, and preserve stable exit codes and output channels. When command + metadata changes, regenerate `.agents/skills/flect/SKILL.md`. The canonical + reference is `docs/local-control.md`; design rationale lives in + `docs/superpowers/specs/2026-07-31-flect-embedded-axi-design.md`. - Keep platform behavior behind Effect services and Layers. The browser, Tauri host, and macOS Swift code are adapters to shared application capabilities, not alternate homes for product workflows or interface state. @@ -126,12 +167,19 @@ Keep each kind of information in one canonical place and link to it elsewhere: and intentional non-capabilities. - `PRODUCT.md` owns users, positioning, personality, and product principles. - `DESIGN.md` owns the visible design system and interface tokens. +- `docs/product-quality.md` owns stable user outcomes, release gates, and proof + requirements. Dated maturity and evidence belong under `docs/verification/`; + GitHub issues own executable gaps, and the dedicated organization project + owns live priority and status. - `ARCHITECTURE.md` describes only verified behavior and boundaries that exist in the current implementation. Planned behavior must not be written there as though it were shipped. - `docs/trust-model.md` explains the public capability, isolation, permission, and recovery model. Permanent contributor safety constraints remain in the closest `AGENTS.md`. +- `docs/local-control.md` owns the user-facing CLI, MCP, JSON/SSE, descriptor, + lifecycle, and invocation reference for the implemented local control + plane. - reviewed future designs belong in `docs/superpowers/specs/`; durable technical decisions and their tradeoffs belong in `docs/decisions/`. - GitHub issues own executable work and acceptance criteria. The dedicated diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 536fa3b..5db18d3 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,7 +1,10 @@ # Flect architecture Flect is an agent-native interface shell with one shared TypeScript application -kernel and two current hosts: a normal browser and a Tauri desktop app. +kernel and two current hosts: a normal browser and a Tauri desktop app. Astro +owns the static browser document above Vite. Focus and pointer intent arm a +small coordinator; prompt submission, the keyboard shortcut, or an agent action +hydrates the protected Effect workspace through a custom `client:flect` island. This document describes the implementation that exists now. Future platform and remote-runtime work belongs in the design documents under `docs/superpowers/`. @@ -9,17 +12,30 @@ remote-runtime work belongs in the design documents under `docs/superpowers/`. ## Runtime topology ```text - validated InterfaceDocument - revision and shaping state - | - v -Browser or Tauri WebView -> Effect application kernel -> React renderer +Astro static document -- focus/pointer --> armed coordinator + | | + | prompt/Cmd-K/agent action v + | -- client:flect --> Preact-compatible workspace entry + | | + | view-only: no Flect runtime v + | Effect application kernel + | | + | +-> validated live canvas + | +-> one protected conversation + | +-> bounded Git-backed history + | +Browser or Tauri WebView ----------------------+ | | + | +-> FlectWorkspaceController + | -> typed commands and events + | -> bounded OperationJournal + | | +-> disposable QuickJS-NG/WASM Worker | -> typed inert intents only | - | +-> role-owned just-bash workspace + | +-> lazy role-owned just-bash workspace | -> reserved Bun-compatible command + | -> reserved role-bound `flect` | -> Rifty Workers and preview broker | +-- browser development @@ -33,14 +49,25 @@ Browser or Tauri WebView -> Effect application kernel -> React renderer -> private NDJSON stdio -> compiled Bun sidecar | + optional authenticated + loopback control broker + / | \ + public `flect` JSON/SSE `flect mcp` + | v shared Pi ModelRuntime - / | \ - Guardian session App session Shaper session + / \ + primary session set candidate session set + Guardian/App/Shaper Preview App (+ isolated managers) ``` -The browser never imports Pi. React never writes interface storage or revision -state directly. The native host never interprets prompts or model responses. +The browser never imports Pi. React-compatible components never write interface +storage or revision state directly. The native host never interprets prompts or +model responses. The static view-only route fetches neither the Preact renderer +nor Effect. Compiler, package, shell, Worker, and Wasm implementations are +separate dynamic boundaries after workspace activation. Astro production uses +Preact compatibility for the protected components; the direct Vite SPA remains +a React fallback. ## Effect application kernel @@ -57,9 +84,56 @@ Effect is the application architecture, not a utility wrapper: - `Scope`, `acquireRelease`, finalizers, fibers, queues, refs, and subscription refs own cancellation, worker lifetime, transport lifetime, and serialized state. +- `Effect.all` and `Effect.forEach` own concurrent fan-out. A checked-in source + gate rejects native promise fan-out everywhere and ad hoc Promise + constructors or native Promise serialization tails outside tests. Callback + hosts enter through `Effect.callback` with interruption cleanup; + Promise-returning platform APIs enter through `Effect.tryPromise`; + `runPromise` or `runCallback` appears only where a host framework requires + Effect to leave its runtime. - React owns rendering and ephemeral form state only. Event handlers are thin adapters into the managed Effect runtimes. +The custom Astro directive is one such host edge: it accepts Astro's +Promise-returning island loader but contains no orchestration or resource +ownership. The deferred activation module enters `Effect` before it coordinates +island readiness, stylesheet readiness, cancellation, success, or failure. This +keeps Effect and workspace CSS out of the static document without recreating +Astro's hydration lifecycle by hand. + +`FlectWorkspaceController` is the single semantic command and observable state +authority. Visible controls and authorized outside clients submit the same +strict `FlectCommandEnvelope` union. Its `SubscriptionRef` snapshot contains +validated interface, revision, workbench target and binding, model, +shell-preference, activity, control-client, and bounded diagnostic state. Its +event stream attributes +command, turn, tool, revision, safe-mode, and control transitions. Command IDs +are retained in a bounded idempotency window, and optional expected sequences +fail with a typed conflict instead of applying to newer state. + +`FlectAxiProgram` is the single command-language boundary. One strict parser, +typed gateway, bounded projection, TOON/JSON formatter, and stable `0`/`1`/`2` +exit contract serve native terminal calls and browser-agent calls. The +`AgentCommandBus` is a bounded, scoped queue whose deferred response carries +the captured agent source into `FlectWorkspaceController`; its bridge owns +inspection, log reads, interface proposals, and authorized commands. Queue +capacity, cancellation, shutdown, and timeout fail closed without introducing +another state owner. + +An interactive agent turn may call an authorized controller command from its +reserved Bash while the parent prompt command is waiting. The controller marks +only that exact parent operation as re-entrant, keeps unrelated user/control +commands behind the global permit, and removes the marker with an Effect +finalizer. This lets Shaper checkpoint a retained share fork or submit an exact +reviewed conflict resolution without deadlock or granting App Agent, Capsule, +or unrelated agent turns concurrent mutation. + +`OperationJournal` retains at most 128 records and 512 KiB in memory; the public +workspace snapshot projects only the latest 12. Records +correlate workspace, command, operation, role, session, tool call, revision, +and outside client identifiers. Secret-shaped text is redacted before storage. +It is diagnostic evidence, not revision authority or a durable audit store. + All Effect packages are pinned to one exact version. `.repos/effect` is an ignored checkout of that matching upstream release and is the primary local API reference. @@ -87,17 +161,32 @@ runtime. Trusted browser and native clients schema-encode validated documents before JSON transport. An `InterfaceDocument` contains no generated HTML, CSS, JSX, or executable code path. -The `ShapingKernel` owns the active, proposed, previewed, accepted, +Shaper must terminate a proposal turn through its role-bound browser shell: +it writes `/workspace/interface.json`, runs `flect interface validate`, then +runs `flect interface propose` as its final action. The reserved command reads +only that disposable workspace, decodes unknown JSON through the closed +`InterfaceDocument` Effect Schema, and sends the validated value over the +bounded `AgentCommandBus`; the controller never receives a sandbox path. +Missing fields, invented node types or actions, excess properties, duplicate +identifiers, and tree bounds become safe path-specific output. Shaper receives +one bounded corrective retry in the same Pi session. A second missing or +invalid proposal ends without creating a revision and leaves field-level tool +evidence in the activity UI and journal. + +The `ShapingKernel` owns the active, proposed, previewed, superseded, accepted, last-known-good, rejected, and recovered revision transitions. A Shaper result -is decoded as an unknown value and fully validated before it becomes a preview. +is decoded as an unknown value and fully validated. A valid local conversation +edit becomes one accepted Git transition without a visible proposal. External +code, shared artifacts, and authority changes remain isolated candidates until +explicit activation. Ordinary transitions write one versioned journal snapshot before making the new state visible; the startup-only reconciliation of a persisted `proposed` revision is the exception. Reconciliation first creates the in-memory `previewed` state, then makes its repair write best-effort so a storage failure does not remove the visible preview or the safe-mode escape. Each journal snapshot contains the active and last-known-good revisions, any proposal, -disabled extensions, safe-mode state, and the latest sequenced event. Rejecting -leaves the active document unchanged. Rollback and safe mode are deterministic +disabled extensions, safe-mode state, and the latest sequenced event. Discarding +an external candidate leaves the active document unchanged. Undo and safe mode are deterministic and do not require Pi. The previous document-only storage key is read only as a one-time migration source when no journal exists. @@ -105,39 +194,51 @@ The built-in recovery shell is compiled with the app. `?safe=1` bypasses customized storage without reading or writing it. Invalid persisted state fails closed to that shell in a protected recovery state. The shell renders one compiled composer outside the customizable document, so shaping cannot remove -the user's route back to an agent. A blank workspace routes it to Edit/Shaper; -an accepted product routes it to Run/App Agent. The same mounted composer moves -from the centered blank state into the protected right rail when a document or -conversation appears. +the user's route back to the agent. Internal bindings route each request, but +the person sees no Use/Shape or agent-role selector. The same mounted composer +moves from the centered blank state into the protected right rail when a +document or conversation appears. ## Pi trust domains -Flect creates one Pi `ModelRuntime` for provider discovery and authentication, -then creates three isolated agent sessions: +Flect creates one Pi `ModelRuntime` for provider discovery and authentication. +Its primary session set contains three isolated agent sessions: - **Guardian** has immutable recovery instructions. It has no user extensions, skills, templates, themes, context files, or tools. It accepts only a closed set of typed recovery reasons and returns a bounded plain-text diagnostic; it cannot write revisions or perform recovery. -- **App Agent** is the Run-mode agent for using an accepted product experience. +- **App Agent** is the Use agent for an accepted product experience. It has its own prompt, history, operation controller, and role-owned browser-shell workspace. It does not receive shaping context or revision authority. Configured external Pi extensions remain disabled unless the user explicitly enables them for App Agent. - **Shaper** receives the current validated document and a shaping instruction. - It has no ambient host resources. Its only Pi tool is Flect's custom `bash`, - which runs in a disposable browser workspace and returns through a typed - request/result bridge. Configured external Pi extensions remain disabled - unless the user explicitly enables them for Shaper. A shaped document still - returns as an untrusted candidate for Flect to validate. + It has no ambient host resources. Its only Pi tool is custom `bash`, which + runs in a disposable browser workspace and returns through a typed + request/result bridge. The reserved `flect interface validate/propose` + commands are the terminating proposal path. + Configured external Pi extensions remain disabled unless the user explicitly + enables them for Shaper. A shaped document still returns as an untrusted + candidate for Flect to validate. + +While an external candidate exists, the client acquires another Pi session set and uses +its App session as **Preview App Agent**. It receives only a bounded public +projection of the candidate document, the candidate revision identifier, and +the user's request. It has its own history, lifecycle, cancellation, Pi session, +and disposable browser-shell workspace; it cannot see accepted-product history +or activation, discard, shaping, recovery, credential, or host authority. +Repeated corrections keep this candidate conversation warm. Activate or +Discard disposes its candidate session authority. Each session has its own in-memory `SessionManager`, `SettingsManager`, and `DefaultResourceLoader`. Their only shared object is the provider/model runtime. Prompts and responses are not persisted by Flect. Disposing the Effect runtime -unsubscribes and disposes all three sessions. The client closes its current -agent set when the model changes, the runtime is refreshed, an operation fails, -or the UI unmounts. Session handles are keyed by model selection, and the -runtime evicts and disposes the oldest set before exceeding 32 active sets. +unsubscribes and disposes every acquired session set. The client closes its +primary and candidate handles when the model changes, the runtime is refreshed, +an operation fails, or the UI unmounts. Session handles are keyed by model +selection, and the runtime evicts and disposes the oldest set before exceeding +32 active sets. Each protected session admits one active operation at a time: overlapping shape requests fail with a typed busy conflict, while prompt-stream conflicts become typed non-destructive busy events. App and Shaper cancellation and @@ -145,17 +246,36 @@ browser-shell completion carry an explicit role and cannot affect the other role. The client preserves a busy set, and the shell disables its composer while a shaping proposal is running. Closing or evicting a set interrupts its active operations, waits for completion for up to two seconds, and then -disposes all three sessions. +disposes every session in that set. Raw Shaper output is capped at 256 KiB and raw Guardian output at 16 KiB before either can cross the runtime boundary. -## Role-aware protected shell +## Continuous protected shell React derives four workspace phases from the validated revision snapshot: -blank, preview, accepted, and safe. Blank and preview use Edit/Shaper; accepted -opens in Run/App Agent; safe mode replaces both with protected recovery. -Switching roles changes the visible role-owned timeline without relabeling -messages or submitting the other role's draft. +blank, preview, accepted, and safe. A typed `WorkbenchSnapshot` retains internal +routing and accepted/candidate bindings, but those trust domains are not user +modes. One composer and one chronological conversation stay mounted while Flect +routes product work and edit work. Valid local changes become the running canvas +immediately; external candidates expose only **Activate app** and **Discard**. +Safe mode replaces the canvas with deterministic protected recovery. + +App Agent does not rely on a semantic text router. Questions and product work +stay in Use. Its Pi session has a bounded `request_interface_edit` tool; only a +typed tool event can request the controller to hand an explicit edit to Shaper. +The controller correlates revision and operation identifiers and routes the +result through validation and atomic local acceptance. Internal authority +selection never mounts a second composer or asks the person to choose an agent. + +Explicit element targeting adds one protected overlay outside guest authority. +The isolated frame publishes only a bounded semantic selector, role/text +summary, source hint, layout box, curated computed styles, viewport, and current +workspace revision; form values and unrelated DOM never cross the channel. +Pointer, touch, and keyboard selection are inactive during normal app use. +Move/resize/spacing/style intents and conversational targeted prompts enter the +same revision-checked Shaper handoff, so the agent remains the implementation +brain and a successful manipulation creates the same automatic Git checkpoint +as any other visible edit. At wide sizes the agent rail is inline, 400 px by default, and keyboard- or pointer-resizable from 340–520 px. At 761–980 px it becomes a right sheet; at @@ -164,8 +284,32 @@ restoration, and reduced-motion behavior remain owned by the compiled shell. The revision decision, model picker, safe mode, rollback, send, and stop controls are protected rather than part of a shaped document. -Pi remains the sole owner of provider login state. Flect neither creates a -credential format nor exposes provider tokens to the WebView, browser APIs, +Turn and tool lifecycle are visible as separate instruments rather than +generic chat sentences. Tool cards show queued/running/succeeded/failed state, +duration, bounded command and result detail, exit status, preview links, and +proposal validation issues. Diagnostics exposes the latest safe correlated +operation evidence and the protected local-control toggle. + +Each role owns a sticky-follow viewport. New content follows only while the +reader remains within 48 px of the bottom. Scrolling away preserves position, +tracks unread updates, and presents a keyboard-operable **Jump to latest** +control; streaming never steals focus. + +Pi remains the sole owner of provider login state. One scoped Effect +authentication coordinator adapts Pi's discovered auth methods into bounded +public status and login events. It permits at most four concurrent provider +logins, keeps at most 32 public events per login, expires unfinished logins +after ten minutes, and normalizes every expected failure into Flect-authored +copy. Active login events live in a private auth `SubscriptionRef`; they never +enter `FlectWorkspaceSnapshot`, operation records, control SSE, AXI, MCP, +agent tools, revision storage, or shaped interfaces. + +Safe selection replies carry only correlated login, prompt, and option +identifiers. Every free-text Pi prompt is sensitive and opens through an +unguessable, one-use `127.0.0.1` form owned by the private runtime. The form is +no-store, script-free, origin-checked, size-bounded, abortable, and passes an +Effect `Redacted` value directly to Pi before wiping it. Flect neither creates +a credential format nor exposes provider tokens to the WebView, browser APIs, logs, fixtures, or interface documents. ## Browser host @@ -181,11 +325,29 @@ sanitized public errors. This loopback API exists for browser development; it is not used by the packaged desktop app and is not approved for network exposure. +Authenticated remote execution is intentionally not implemented. The proposed +user-hosted-first trust boundary, key lifecycle, replay/reconnect rules, +revocation behavior, offline semantics, and independent security-review gate +are recorded in +[`docs/decisions/0004-authenticated-remote-runtime.md`](docs/decisions/0004-authenticated-remote-runtime.md). +The executable companion is a pure protocol state-machine fixture only; it +opens no listener and carries no production cryptography. + +The connected browser workspace also registers its controller with the local +control broker through origin-protected internal routes. Those routes are not +the public control API and reject missing or foreign origins. + ## Desktop host -Tauri packages the same Vite build. The Rust host starts one external sidecar, -limits frontend authority to `core:default`, and exposes one private -`rpc_send` command. That command: +Tauri packages the same Vite build with two executables: public `flect` and +private `flect-runtime`. Finder or explicit `flect app` launches the GUI. A +terminal invocation dispatches AXI arguments or `mcp` to the sibling runtime, +inherits stdio, and propagates its exit status. Rust selects only the host mode; +it does not parse domain commands, duplicate Effect policy, or render output. + +In GUI mode the Rust host starts `flect-runtime`, limits frontend authority to +`core:default`, and exposes the private `rpc_send` command plus narrow, +main-window-only native setup and updater commands. `rpc_send`: - accepts only Effect RPC request, acknowledgement, interrupt, EOF, and ping message tags; @@ -194,25 +356,360 @@ limits frontend authority to `core:default`, and exposes one private - emits parsed sidecar responses back to the WebView. The sidecar is a compiled Bun executable running the same `FlectRuntime` -handlers through Effect RPC NDJSON. It does not bind a TCP port. - -This RPC boundary owns Pi runtime operations: health, model discovery and -selection, session creation and close, turns, interruption, shaping proposals, -the narrow Guardian diagnostic, browser-shell results, and their streams. +handlers through Effect RPC NDJSON. Pi traffic never binds a TCP port. The +control broker owns a separate random loopback listener; without an enabled +grant it publishes no descriptor and rejects every request. + +This RPC boundary owns Pi runtime operations: health, provider status and +authentication, model discovery and selection, session creation and close, +turns, interruption, shaping proposals, the narrow Guardian diagnostic, +browser-shell results, and their streams. The client Effect kernel deliberately owns the revision journal so browser and desktop hosts share one client-side state machine. Revision operations are not duplicated in the sidecar. +Diagnostics exposes fixed native setup capabilities. Shell-link commands may +inspect, install, repair, or remove only `~/.local/bin/flect` targeting the +current installed app. Codex and Claude hook mutation and the OpenCode local +plugin are implemented by one Effect `AgentIntegration` service with injected +filesystem and path Layers, strict unknown JSON decoding, atomic private +writes, stable ownership markers, conflict detection, and removal of only +Flect-owned entries. Browser mode reports these host mutations as unavailable. + +The `Uninstall` Effect service composes those ownership-aware operations into a +closed inspect/prepare plan. It derives the application path from the packaged +executable, disables Local control in the protected UI, preserves conflicts and +user data, and never receives a recursive-delete or app-removal operation. AXI +can inspect or prepare the same plan but cannot remove the app. + +The official Tauri updater plugin is registered only when a non-empty public +key was compiled into a release. Rust fixes the HTTPS GitHub manifest endpoint, +checks the `main` window label, retains a plugin candidate behind a single-use +opaque token, and projects only bounded state through four commands. The Effect +adapter decodes every response and invalidates stale tokens; React owns only the +protected review/progress UI. Browser Flect receives an explicit unavailable +Layer. No capsule, agent, extension, product operation, AXI command, MCP method, +or embedded Bash route receives updater authority. + The Tauri window uses isolation mode and a restrictive content security policy. `freezePrototype` is disabled because the current Tauri/React bootstrap fails when it is enabled; it is not treated as a security boundary. The isolation iframe, CSP, capability manifest, strict schemas, narrow command validation, and private process transport remain active. -The current local app bundle is ad-hoc signed so macOS can validate its nested -sidecar and app resources during development. It is not claimed to be Developer -ID signed, notarized, hardened-runtime audited, or protected by the macOS App -Sandbox entitlement. +The first product-facing native adapter is deliberately narrower still. A +fixed Swift function reads AppKit's real control accent and returns one packed +RGBA value to a main-window-only Rust command. `NativePlatform` validates the +closed projection. The Tauri composition root registers +`native.appearance.current`, and the normal product-capability broker must +reserve and validate an explicit grant before the operation reaches AppKit. +Browser composition returns typed unavailability and keeps the capsule +running. The reusable cross-platform pattern is documented in +[`docs/native-platform-adapters.md`](docs/native-platform-adapters.md). + +The current local app bundle is ad-hoc signed so macOS can validate its public +`flect` executable, private `flect-runtime` helper, and app resources during +development. It contains no separately shipped CLI or MCP companion. It is not +claimed to be Developer ID signed, notarized, hardened-runtime audited, or +protected by the macOS App Sandbox entitlement. + +## Local control plane + +`FlectControlBroker` is lifecycle-scoped inside the Bun browser runtime or +desktop sidecar. It binds only to `127.0.0.1` on a random port and stores no +parallel workspace state machine. When the protected UI enables control, the +connected workspace publishes its current snapshot, the broker creates a fresh +256-bit bearer, and `ControlDescriptor` writes the discovery record atomically +with private directory and file permissions. + +The public loopback surface provides authenticated status, instance, +workspace, log, SSE event, and command endpoints. Bodies are bounded to one +MiB. Commands are strict schema values, cannot enable their own grant, and are +queued through a bounded Effect `Queue`; exact results use `Deferred`. +Multiple delivered commands run in scoped fibers so a cancel command can reach +an active App or Shaper turn. Disable is acknowledged through the shared +controller before the broker removes the descriptor, shuts down the queue, +fails pending requests, and invalidates the bearer. + +The browser bridge uses origin-restricted HTTP. The desktop bridge uses the +existing private Effect RPC/Tauri channel. Both publish the same controller +snapshots, events, command outcomes, and named-client attribution. React +subscribes to the controller itself, so an outside action becomes visible +without reload, DOM automation, storage polling, or shadow state. + +The public `flect` AXI program defaults to bounded TOON, supports explicit JSON +and one-event SSE-backed `watch`, and is embedded under the reserved command in +each role sandbox. The native executable dispatches command or MCP mode to the +private runtime without parsing domain arguments. MCP v2 advertises four +compact tools for inspect, command, event waiting, and logs; its command input +comes from the same Effect Schema union. Neither adapter prints or returns the +bearer. Complete invocation and security details are in +[`docs/local-control.md`](docs/local-control.md). + +## Portable capsule boundary + +The host-neutral codec in `shared/capsule.ts` is the executable `.flect` +format contract. It produces deterministic bounded ustar archives, strictly +decodes the versioned manifest, verifies every SHA-256 payload, and rejects +unknown fields, unsafe paths, duplicate entries, unsupported versions, and +authority-bearing state. Browser and desktop loaders enter through this same +decoder. + +The end-user flow exports an accepted interface and imports a verified capsule +as an isolated proposal. Import never replaces accepted state directly; the +external preview/activate/discard boundary remains authoritative. Declarative +entrypoints use the trusted closed renderer. Compiled HTML entrypoints run in +an opaque-origin `allow-scripts` iframe with a network-denying CSP and one +rate/size-bounded Effect Schema `MessageChannel`. Capsule messages and host +replies are JSON-only, limited to 64 KiB, correlated by an intent identifier, +and closed over a versioned success/failure union. Capsules receive no direct +host authority. Safe mode bypasses the frame. Shaper may invoke import through its +reserved sandboxed `flect capsule import` command; App Agent may not. +Before activation, the protected shell projects a bounded review from the decoded +manifest: publisher, version, source revision, signature presence, contents, +platforms, and all requested capabilities. Required capabilities are activation +preconditions. The shell evaluates the declared semver range against the actual +Flect package version and the declared platform set against the browser or +native host; incompatibility blocks activation at the UI and controller while +leaving the isolated preview inspectable. A required request without a +registered grant keeps the preview inspectable but blocks activation in both +the UI and controller; optional requests remain ungranted. Protected review +projects availability separately from requested, granted, denied, expired, and +revoked lifecycle state. + +Named product operations use an Effect decision store, capability broker, +registry, and adapter. A trusted host maps a stable operation ID to one strict +manifest capability, operation/resource/data scope, permitted confirmation +policies, optional limits, and bounded request/response projections. The +controller hashes the exact capsule archive and binds each decision to that +digest, provenance revision, capsule ID, workspace ID, and declared request. +Session and one-use decisions stay in memory; workspace and persistent +decisions use the strict version-2 store and matching legacy boolean state is +migrated without widening authority. No decision is copied into the capsule. +Capsule, App Agent, embedded `flect`, outside +CLI, JSON, and MCP calls enter the same closed `invoke-product-operation` +command and workspace controller. Capsule-origin commands additionally bind the +current accepted/candidate capsule ID and intent ID; undeclared, stale, +unregistered, or ungranted operations fail before the adapter. + +The broker atomically reserves one-use and rate allowance before independent +product authorization, validates the product's exact operation/resource/data +projection against that reservation, and then invokes the adapter. Approval +does not override product denial. Every attempted registry invocation adds +bounded structured capability metadata to the operation journal without raw +input, output, headers, or credentials. The public AXI snapshot includes the +same reactive projections; `flect permissions list` can inspect them and paired +outside control can revoke a visible decision, but no agent-facing command can +create one. + +`ProductHttp` owns HTTPS origin, path prefix, +method, header, request/response byte, and deadline policy. Callers supply only +the registered operation input. Absolute/cross-origin paths, undeclared methods +or headers, caller authorization/cookie headers, oversized traffic, redirects, +and deadlines fail through a typed sanitized error. Host credential headers are +injected privately, `fetch` omits browser credentials, only allowlisted response +headers and bounded bytes return, and neither capsule nor Pi receives raw +`fetch`. `ProductGraphql` builds on that service with an exact endpoint, +operation kind/name, SHA-256-pinned document, bounded variables/result, and +sanitized GraphQL failures. `ProductEvents` owns a scoped connector and bounded +backpressure queue, validates canonical decimal sequence order, resumes from +the last accepted cursor for a finite number of retries, and aborts on caller +cancellation. `ProductEventRegistry` holds the exact broker reservation open +and interrupts the connector when that decision expires, changes, or is +revoked. + +Public adopter contracts and transport-only services live in the independently +packable `packages/product` workspace as `@flect/product`. Its Effect Schema +metadata separates product identity/compatibility, recommended capsule digest, +capability and extension sets, declarative migrations, inference policy, prior +connection state, and user-owned fork/export references. A validated branded +`ProductIntegration` supplies only named bounded closures. Flect's private +`product-integration` Layer bridge composes those public operation/event types +with the protected broker, decision store, and registries; the package has no +route to grant, activate, write workspace state, or replace recovery. + +Adoption evaluation is deterministic and model-free. It compares a validated +integration with host facts and the prior connection record and returns ordered +public diagnostics for ready, offline, update, review, compatibility, +authentication, migration, and detach states. Product connection records are +independent from `ProductUserState`, so detaching a product retains personal +Git/export references for protected continuation or export. Model/inference +ownership is not an authorization input. + +The stock Flect distribution registers no business-product operations; +adopters compose their policies and operations at the trusted runtime root. +The desktop composition registers only the optional brokered native-appearance +read described above. Browser and the current desktop WebView use the same +provider-neutral service contracts for product integrations. +Ordinary HTTP/GraphQL uses CORS-aware fetch. Protected review offers once, +session, workspace, +persistent, deny, and revoke actions only when permitted by the host manifest; +safe mode uses the same model-free protected projection. One-use consumption, +expiry, and rate enforcement are implemented in the broker. Custom duration or +rate editing in the protected UI and a privileged native credential transport +are not yet shipped. + +The public-boundary reference set exercises offline state, browser-direct fixed +GraphQL/events, a named authenticated broker, and a closure-private sharing +source. The three product integrations ship recommended capsules with public +App Agent guidance and an optional Shaper role; the private-sharing reference +composes only the trusted source adapter. The Flect-owned harness supplies +grants and protected state. + +Ed25519 publisher-signature verification is implemented for `.flect-share` +manifests and canonical `.flect` capsule content. Capsule assessment separates +verified, unknown, revoked, expired, changed, invalid, unsigned, and local-fork +states; configurable publisher policy never alters capability authority. +Guarded personal forks and two-parent +merges are implemented by the sharing lifecycle, and standard single-entry +Vite JavaScript, TypeScript, React, Vue, and Svelte source projects compile +through the separate build adapter. Verified archive-local stylesheets, classic scripts, images, +fonts/media, and CSS URLs are projected into the generated `srcdoc`: text is +strict UTF-8, binary assets become `data:` URLs, and unresolved or remote +references remain unavailable under the deny-by-default CSP. Module graphs, +import maps, and source dependency resolution are not claimed. + +URL installation is a user-initiated protected-shell operation over HTTPS, with +loopback HTTP reserved for local development. The browser request omits +credentials, bypasses cache, follows CORS, and is bounded by a 20-second timeout +and the format's 32 MiB ceiling while streaming. Only bytes that pass the same +strict capsule decoder become a candidate; a fetch, CORS, size, timeout, or +integrity failure leaves accepted state untouched. + +If an installed and candidate capsule share an ID, the protected shell labels +the transition with both versions. A different ID is labeled as a replacement. +In both cases the accepted archive remains bound until activation, so Discard is a +lossless return to the installed version. Capsule personal-fork lineage and +compatible merge policy remain future layers rather than implicit overwrite +behavior. + +Static-site and supported single-entry Vite imports use a protected pre-capsule +adapter. It validates all directory-relative paths, ignores VCS/dependency/cache +and common credential/private-key entries without reading their contents, +requires one root `index.html`, applies the capsule bounds, and +encodes the unchanged supported files into a local capsule. Source is not +executed during inspection. The ordinary manifest review and opaque compiled +frame remain the only path to preview. The current adapter does not yet commit +source to accepted state directly: it checkpoints recognizable files under +`project/` on isolated `flect/authoring`; the existing proposal-source delta +promotes them to `flect/accepted` only on Activate. It does not yet analyze +multi-page routes or content-dependent secrets. Folder files, bounded ZIP/POSIX +TAR archives, and public credential-free HTTPS Git repositories at an exact +commit all converge on this adapter. Archive validation rejects traversal, +encryption, ZIP64, unsupported entry types, excessive expansion, and unsafe +paths before packaging; Git clones and checkouts run in a disposable WASM-Git +workspace. Its bounded text inspection reports forms, module graphs, remote +URLs, storage, and workers as visible manifest requests; +unsupported required assumptions block activation. + +Compiled capsule bytes persist through `CapsuleStore`, independently from the +user-controlled interface Git repository. The production store uses the +pinned `@riftydev/vfs` OPFS adapter and falls back to an in-memory VFS only +when OPFS is unavailable. It writes immutable archive objects first at +`/flect-capsules/default/objects/.flect`, then atomically advances the +versioned accepted, candidate, and last-known-good bindings in +`/flect-capsules/default/bindings.json`. Startup re-decodes and hash-verifies +every bound archive before reconstructing presentation; a candidate is exposed +only when the shaping kernel also reports a proposal. Invalid or mismatched +bindings fail closed without replacing accepted state. Export reads the exact +accepted archive object, preserving the original bytes across reload. +The store exposes whether this binding is durable or session-only through the +public workspace snapshot. Diagnostics keeps a session-only warning visible +even while collapsed and states exactly which compiled state will be lost; +the fallback is never presented as durable persistence. + +This capsule persistence contract currently supports compiled HTML entrypoints +plus the bounded local asset classes above. Framework source builds and module +graphs are compiled before capsule persistence and are not part of the runtime +capsule format. Additional capability adapters and capsule-level three-way +update merging remain open. Canonical signing and explicit unsigned local-fork +lineage are implemented. Restored candidates can be +activated after worker restart; the guarded Wasm-Git transaction advances the +accepted snapshot before the decision completes. + +## Restricted browser build boundary + +`BrowserBuild` is an Effect service over a schema-decoded, one-build-per-Worker +protocol. A request contains an exact source revision, entrypoint, and bounded +mirrored file set. The Worker validates every path and byte limit, copies only +that set into Rolldown's disposable memfs, compiles browser JavaScript, +TypeScript, JSX, TSX, Vue SFCs, and Svelte components, and returns bounded output files plus deterministic +SHA-256 input and artifact digests. Completion, failure, timeout, and +interruption terminate the Worker. The service updates its in-memory +last-successful artifact only after a valid success response, so a later +compiler failure cannot replace the preview fallback. + +Vue's and Svelte's official compilers are separate dynamic Worker boundaries +selected only when a mirrored `.vue` or `.svelte` module is actually loaded. +They produce ordinary browser modules and deterministic CSS for the same +Rolldown graph; neither compiler, framework runtime, nor Vite plugin enters the +Astro activation bootstrap or a vanilla/React build. Unsupported preprocessors +and external component blocks fail with bounded source diagnostics. + +Rolldown 1.2 removed its earlier experimental CSS bundling. Flect therefore +owns a deliberately smaller CSS adapter: local relative `.css` imports resolve +only to files in the mirrored input, become inert modules for the JavaScript +graph, and their strict-UTF-8 contents are emitted in deterministic path order +as `app.css`. It is not a Vite plugin host and does not claim CSS modules, +PostCSS, preprocessors, remote imports, or `url(...)` rewriting. + +`ProposalBuild` reads only the exact proposal commit from embedded Git, guarded +by the expected accepted and last-known-good commits. It strips the protected +`project/` prefix and hands that immutable snapshot to `BrowserBuild`; a dirty +authoring mirror or stale ref cannot enter the artifact. Successful artifacts +are written object-first to `/flect-builds/default/objects//`, with a +strict manifest and per-output hashes, before the last-successful binding is +advanced. Startup reconstructs and rehashes every output from OPFS; unsupported +hosts fall back to memory without changing the build authority boundary. +The workspace controller projects dependency resolution, lock checkpoint, +compile, package, success, and sanitized failure as typed `build-progress` +events and a reactive build snapshot. Active or failed work stays visible in +the protected rail, and outside clients observing the public snapshot see the +same phases; progress is not inferred from prose or private Worker logs. + +Production Chromium proves this substrate with a real guarded Git proposal +containing React 19 TSX, stateful interaction, and imported local CSS, then a +new broken proposal commit, last-successful retention, explicit +cross-origin-isolation gating, Worker disposal, and OPFS restoration after page +reload. The protected **Import app project** flow also recognizes standard Vite +browser entrypoints, checkpoints source on `flect/authoring`, supersedes the +candidate from that source, compiles the exact guarded proposal, packages only +the verified outputs plus the inert import report, and opens the normal +Activate/Discard review. The review exposes the exact source revision and artifact +digest. Chromium proves Vite TypeScript activation/reload/export and a React JSX +import whose cached dependency graph rebuilds with the npm registry blocked. +The same production-browser contract covers interactive Vue and Svelte +fixtures and an offline reload from their verified cached package graphs. + +`BrowserPackageResolver` supplies the package-lock/cache part of that boundary. +For the portable import path, Flect derives an inert manifest containing only +package identity and runtime `dependencies`; scripts and development tools +remain recognizable in Git source but cannot enter package resolution or run. +The resolver hashes that exact portable manifest plus an optional lock, checks the +content-addressed OPFS cache first, and otherwise delegates registry resolution +to the existing Rifty npm client behind Flect's credential-free HTTPS registry +broker. The installer stages into a disposable VFS, validates tarball +integrity, runs no lifecycle scripts, and returns a bounded delta. Flect then +requires npm lockfile version 3, exact semantic versions, SHA-512 integrity, +and approved-registry HTTPS tarball sources for every non-root entry. + +The resolved `node_modules` graph and lock are bounded, deterministically +hashed, written object-first under `/flect-packages/default/objects//`, +and bound from the package-input digest only after every file exists. Cache +loads revalidate the manifest, lock, every file hash, and aggregate graph hash. +Before compilation, `ProposalBuild` compares the resolved lock with the exact +guarded proposal. A new or changed lock is checkpointed as +`project/package-lock.json` on `flect/authoring`; the shaping kernel then +supersedes the candidate through its normal receipt-guarded proposal +transaction. Compilation rereads that new proposal commit and passes its lock +back into the resolver. `ProposalBuild` replaces any source-tree dependency +directory with this verified graph and records its graph digest in the compiler +request, capsule build receipt, and persisted build artifact. Production +Chromium proves the accepted lock, exact versions, and integrity fields are +present in an ordinary exported Git repository, then proves the warm graph is +reused with npm registry access blocked. General registry selection, lock +conflict UX, cache management, and server/native framework compatibility remain +outside this browser contract. ## QuickJS logic sandbox @@ -253,11 +750,19 @@ the response. Prompt turns and Shaper proposals both carry this typed event; the bridge times out, cleans up on interruption and session disposal, and never carries a filesystem handle or credential. -`SandboxedShell` uses `just-bash@3.2.0` with a memory VFS, hardened execution -limits, and one reserved `bun` command. Static AST rewriting prevents aliases, -functions, PATH changes, workspace files, packages, and extensions from -shadowing that command. Direct-network, JavaScript-evaluation, Python, SQLite, -and compression commands are excluded. The Vite build replaces the package's +`SandboxedShell` uses `just-bash@3.2.0` with a role-isolated working mirror, +hardened execution limits, and reserved `bun`, `flect`, and `git` commands. +Supported browser and WebView hosts persist each mirror under a separate +namespaced OPFS root; an unavailable OPFS surface falls back to a disposable +memory mirror without changing the capability boundary. Static AST rewriting +prevents +aliases, functions, PATH changes, workspace files, packages, and extensions +from shadowing any reserved command. The `flect` adapter captures the trusted +role, +session, parent operation, and tool call; it uses a bounded Effect queue and +cannot be reclassified through shell input. Direct-network, +JavaScript-evaluation, Python, SQLite, and compression commands are excluded. +The Vite build replaces the package's otherwise reachable `node:zlib` import with a fail-closed adapter, so compressed ripgrep input is unsupported without pulling Node compatibility into the browser. @@ -279,13 +784,30 @@ Flect storage, credentials, native bridge, or parent DOM. Effect scopes, deadlines, interruption, and finalizers own every Worker, iframe, active run, and preview. -The role workspace is currently disposable memory. It is not the future -canonical OPFS/libgit2 workspace, and changing it does not activate an -interface revision. Rifty and just-bash are cooperative execution substrates, +The role workspace has no handle to the canonical OPFS/libgit2 repository, +and changing it does not activate an interface revision. The reserved Git +adapter exposes role-bound `status`, `branch`, `rev-parse`, and `log`; Shaper +observes the actual proposal ref once one exists. A guarded full-ref snapshot +seeds the mirror. Shaper alone may run bounded `add -A`, `commit -m`, and +`restore .`; accepted and proposal transitions carry the source delta. Patch +producing `git diff` stays unavailable until the browser engine proves it. +Rifty and just-bash are cooperative execution substrates, not hostile-code containment. The trust boundary is the isolated realm plus strict schemas, typed brokers, bounds, capability denial, validation, and deterministic recovery. +Retained sharing source uses separate opaque `flect/shared/...` base, upstream, +fork, and candidate refs in the same Worker. Shaper's embedded `flect share +checkpoint` reads only explicitly named files from its sandbox and submits a +strict optimistic command; the controller and `ShareRepository` guard every +other ref and update the observable installation record. Clean upstream +updates pass a deterministic three-way resolved snapshot into the Worker. The +Worker writes and verifies the exact tree and a two-parent merge commit before +moving the candidate. Conflicts use Flect's deterministic byte-level three-way +policy so different Git engines cannot silently choose different review paths; +Shape resolution rechecks the exact refs and every recorded conflict path. See +[`docs/sharing.md`](docs/sharing.md) for the user lifecycle and current limits. + Build-gated diagnostics still exercise fixed JavaScript, WASI Preview 1, npm fixture, Bun command, and preview flows. The ordinary composer is separately tested in production Chromium with a full Pi event -> browser shell -> result @@ -294,11 +816,48 @@ round trip. The exact surface is maintained in ## Recovery and failure behavior +Accepted and candidate interface state remains solely owned by the shaping +kernel and its Effect-owned Git repository. The repository is an ordinary Git +tree persisted in OPFS by a dedicated Wasm/libgit2 Worker. Guarded checkpoint +transactions verify expected accepted, proposal, and last-known-good refs +under a cross-context Web Lock before updating `flect.json` and the validated +snapshot. A protected activation receipt lives outside user-controlled Git +state; ref or receipt disagreement fails closed. Complete export includes +`.git`, and `flect repository status` projects bounded reactive ref and conflict +state through the shared controller. On the first load of a new repository, +the repository service commits the built-in interface and establishes matching +accepted, last-known-good, and activation state before exposing the workspace. +This makes a no-edit reload durable without weakening receipt/ref +reconciliation. Legacy state follows the separate, explicit migration path. +The Git service serializes every operation before selecting its current Worker; +the Worker is recycled after a bounded lease so long sessions release libgit2 +state without handing queued work a terminated instance. Main-realm durable +stores share one initialized asynchronous OPFS surface under disjoint roots, +which lets lazy build and package services start without reopening storage while +the Git worker is active. Safe-mode entry records only the separate guarded +recovery marker and does not rewrite the accepted product ref. +A separate bounded role-continuity projection stores one visible compatibility +draft and completed App, Preview App, and Shaper messages. Each internal +projection retains at most 12 messages and eight activities. It is not +interface history and can be discarded without +touching revisions. Preview continuity is restored only for an exact candidate +revision match; partial assistant streams, activities, credentials, auth +events, Pi sessions, control grants, and provider state are excluded. + +The continuity repository uses strict Effect Schemas, a 512 KiB aggregate +limit, generation checks, and Web Locks where available. It rereads inside the +lock and replaces one complete Web Storage value, so a stale tab or failed +quota write cannot silently replace the prior valid record. Safe mode does not +hydrate continuity content. Its compiled controls may inspect bounded +metadata, export a valid decoded record, or discard continuity independently +of last-known-good restoration. The exact lifecycle and current proof boundary +are in [`docs/recovery.md`](docs/recovery.md). + - invalid interface state -> compiled recovery shell; - safe mode -> bypass customized state; - invalid Shaper output -> no proposal; -- rejected preview -> active state unchanged; -- accepted preview -> previous active state becomes last-known-good; +- discarded external candidate -> active state unchanged; +- activated external candidate -> previous active state becomes last-known-good; - rollback -> last-known-good becomes active; - rollback failure -> the protected kernel remains authoritative and may ask Guardian for a bounded, inert explanation; @@ -309,6 +868,16 @@ round trip. The exact surface is maintained in - public runtime failures -> stable redacted messages, never raw provider errors. +## Performance boundary + +Flect measures production-browser startup, initial resources, protected +composer interaction, local patches, external candidate rebuilds, Markdown, +cancellation, and repeated-cycle heap growth without adding telemetry or +another state owner. The one machine-readable release contract is +`shared/performance-budgets.ts`; the measurement environment, variance policy, +native-host complement, and rationale are documented in +[`docs/performance.md`](docs/performance.md). + ## Pinned implementation sources The implementation was checked against: @@ -319,11 +888,14 @@ The implementation was checked against: `b4f293684bba718d59cc1157679bcf6157b3a7f5`; - Rifty leaf packages `0.2.0`, evaluated upstream commit `207e0ee9f108d6457e2448c956b84c2758e62671`; +- `@rolldown/browser` `1.2.1`, release tag `v1.2.1` at + `93c535d8875daacde3afa84c0d4e9d26e87453e9`; - `just-bash` `3.2.0` and `esbuild-wasm` `0.28.1`; - Tauri CLI `2.11.4`, JavaScript API `2.11.1`, Rust crate `2.11.5`, and shell plugin `2.3.5`; - `quickjs-emscripten-core` and the QuickJS-NG release-sync variant `0.32.0`; - and -- Playwright `1.62.0`. +- Playwright `1.62.0`; and +- Model Context Protocol split server/client packages `2.0.0` and Zod + `4.2.0`. Exact package versions are recorded in `package.json` and `bun.lock`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d5e08be..c8cddb3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ the browser/native trust boundaries. ## Requirements -- Bun 1.4 or newer +- Bun 1.3.14 exactly - Rust and Cargo - macOS command-line developer tools for native builds - a Playwright-supported Chromium installation @@ -65,21 +65,30 @@ This runs: 1. Biome; 2. TypeScript project checking; 3. Vitest unit and integration tests; -4. Playwright against a production Vite build in real Chromium; -5. Rust host tests; and +4. Playwright against a production Astro-on-Vite build in real Chromium; +5. Rust formatting and host tests; and 6. a release-mode macOS application bundle build. +The pinned, least-privilege GitHub workflow runs this canonical command for +every pull request and every change to `main`. Live Pi, Apple signing, +notarization, and other credentialed release proof remain separate authorized +gates; the public workflow must never silently represent them as completed. + Playwright uses `FLECT_TEST_MODE=1`, a deterministic in-memory runtime, and no -provider credentials. It covers a streamed turn, model-backed-shaping behavior -through the test Layer, accept/reject, persistence, rollback, corrupt-journal -recovery, keyboard submission, reduced motion, the QuickJS isolation check, and -compact layout. Unexpected browser console errors, page errors, and failed -local application requests fail the test. +provider credentials. It covers streamed turns, schema-driven Shaper tool +activity, accept/reject, persistence, rollback, corrupt-journal recovery, +sticky follow, keyboard submission, reduced motion, QuickJS isolation, compact +layout, reserved browser `flect` role policy and shell composition, plus a real +public `flect` process driving the same reactive browser workspace. Unexpected +browser console errors, page errors, and failed local application requests +fail the test. Unit and integration coverage additionally proves the protected fallback composer, typed Guardian diagnostic, session close across both transports, model/refresh lifecycle invalidation, non-destructive busy conflicts in both -directions, and the 32-pair runtime bound. +directions, the 32-pair runtime bound, strict local-control authentication and +descriptor permissions, concurrent cancellation, token rotation, SSE +decoding, CLI behavior, and MCP protocol interoperability. After authenticating Pi, verify the real Guardian/Shaper construction: @@ -91,12 +100,41 @@ For a local bundle: ```bash bun run build:desktop -- --bundles app +bun run test:desktop:local open src-tauri/target/release/bundle/macos/Flect.app ``` -The local bundle is ad-hoc signed for development. It is not a substitute for -Developer ID signing, notarization, hardened-runtime review, App Sandbox -entitlements, or distribution testing. +`build:desktop` requests an explicit ad-hoc hardened-runtime signature so the +development bundle is internally valid. `build:desktop:inferred-signing` is +reserved for the release pipeline, where Tauri infers an imported signing +certificate. Do not use the inferred-signing path as a local trust claim. +`test:desktop:local` copies that bundle under a random test-only identifier, +uses the real macOS Accessibility tree to verify actionable clean-profile +setup, hard sidecar loss, private-draft restoration, relaunch, and single-window +ownership, then removes only the isolated test profile and temporary Pi home. +It never consumes a provider credential or the ordinary Flect/Pi profiles. + +The application bundle must contain public `flect` and private +`flect-runtime` in `Contents/MacOS`, with no separately shipped command +companions. +After enabling local control from Diagnostics, smoke-test the installed app +through the public executable rather than a private test hook: + +```bash +src-tauri/target/release/bundle/macos/Flect.app/Contents/MacOS/flect +src-tauri/target/release/bundle/macos/Flect.app/Contents/MacOS/flect inspect +src-tauri/target/release/bundle/macos/Flect.app/Contents/MacOS/flect mcp +``` + +See [`docs/local-control.md`](docs/local-control.md). + +The local bundle is ad-hoc signed with hardened runtime for development. It is +not a substitute for Developer ID signing, notarization, App Sandbox +entitlement review, independent reproducibility, or clean-machine distribution +testing. `bun run release:package` stages the DMG, checksum, demo MP4, and +release evidence under ignored `dist-release/`; it mounts and verifies the DMG +before succeeding. `FLECT_PUBLIC_RELEASE=1 bun run release:package` fails +closed at every public-trust boundary and must not be bypassed. ## Change expectations diff --git a/DESIGN.md b/DESIGN.md index e49435a..eca9e87 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -54,7 +54,7 @@ components: size: "40px" button-primary-hover: backgroundColor: "{colors.flect-rose-hover}" - textColor: "{colors.ink}" + textColor: "{colors.void}" rounded: "{rounded.pill}" size: "40px" prompt-surface: @@ -86,17 +86,100 @@ affordances, short labels, and restrained state motion. - Near-black neutral architecture with one precise rose signal. - System typography tuned for calm density and high legibility. - Tonal layering before shadows; boundaries appear only when useful. -- A centered shaping prompt that expands naturally into a conversation. +- One centered agent composer that expands naturally into a conversation rail. - Protected recovery controls that remain quiet but always reachable. -## 2. Colors +## 2. Platform-native quality contract + +Flect must feel like first-party software on every platform it claims to +support. This is behavioral fidelity, not decoration and not pixel-for-pixel +uniformity. The shared Flect identity remains recognizable while each host +uses the interaction conventions people already trust there. + +### Architecture rule + +The agent, canonical workspace, history, capability, and recovery contracts are +shared. Window chrome, system menus, keyboard routing, focus, scrolling, +selection, drag and drop, file pickers, notifications, appearance, safe areas, +touch, haptics, and lifecycle behavior belong to platform adapters. + +A WebView is acceptable only while it meets the platform contract. If a +protected control cannot match native behavior, latency, accessibility, or +visual integration in the WebView, implement that control in the host and +expose it through a narrow typed boundary. Do not ship a CSS imitation of a +native control that behaves incorrectly. + +### Browser contract + +- Preserve browser history, URLs, text selection, clipboard, context menus, + focus navigation, zoom, responsive reflow, and expected keyboard shortcuts. +- Never draw fake desktop title bars, traffic lights, system dialogs, or + application chrome in the web product. +- Use responsive browser and touch behavior rather than shrinking the desktop + composition. +- Respect light/dark preference, forced colors, reduced motion, text scaling, + pointer type, and the browser's back/forward lifecycle. +- Keep scroll containers intentional. Ordinary page and canvas scrolling must + retain platform momentum, overscroll, and input semantics. + +### macOS contract + +- Respect the title-bar and traffic-light safe region, window resizing, + full-screen behavior, app activation, reopen, quit, and state restoration. +- Provide a real menu bar with standard application, File, Edit, View, Window, + and Help behavior where those actions exist. +- Use macOS shortcut, focus-ring, clipboard, drag-and-drop, open/save panel, + context-menu, trackpad, inertial-scroll, and text-editing conventions. +- Follow the system appearance and accessibility settings, including light, + dark, increased contrast, reduced transparency, reduced motion, text size, + and VoiceOver. +- Use SF typography and platform metrics without making every product canvas + look like Flect chrome. +- Prefer host-native sheets, menus, permission prompts, and file surfaces when + the WebView equivalent is observably foreign or less accessible. + +### Future mobile contract + +iOS and Android are not supported merely because the web UI fits a narrow +viewport. A supported mobile host must prove native back behavior, safe areas, +software-keyboard avoidance, touch targets, gestures, scrolling, sheets, +menus, haptics, share/open flows, lifecycle restoration, and platform +accessibility on real devices. + +### Responsiveness and motion gates + +- Composer input and ordinary protected-shell interactions have p95 response + below 50ms and release-gated INP below 100ms. +- Scrolling, selection overlays, resizing, dragging, and direct manipulation + stay within a 16.7ms frame budget on the 60Hz reference device. Supported + 120Hz paths target 8.3ms. +- No ordinary interaction introduces a main-thread task longer than 50ms. +- Menus, sheets, popovers, focus changes, and navigation acknowledge input in + the same frame and use the platform's expected motion curve and duration. +- The running canvas never flashes blank, jumps layout, loses focus, or resets + application state because the agent or compiler is working. +- Reduced-motion mode removes nonessential interpolation without removing + state feedback. + +### Release evidence + +Every supported host requires real production-build evidence for cold and warm +launch, input, keyboard/focus, scrolling, direct manipulation, appearance, +reduced motion, accessibility, failure recovery, long-session memory, and +resize or rotation. Screenshot similarity alone is not acceptance evidence. + +Reviewers must reject a release for visible hitching, fake platform chrome, +foreign control behavior, theme mismatch, clipped safe areas, nonstandard +keyboard behavior, or a design that only works at the demo viewport. + +## 3. Colors The palette is monochrome at rest and reveals color only when state or agency needs to be communicated. ### Primary -- **Flect Rose** (`oklch(0.630 0.180 340)`): focus, active shaping state, +- **Flect Rose** (`oklch(0.630 0.180 340)`): focus, active agent state, selected controls, and the rare brand signal. - **Flect Rose Hover** (`oklch(0.690 0.170 340)`): interactive emphasis when a primary action needs more presence. @@ -127,7 +210,7 @@ needs to be communicated. **The One Signal Rule.** Flect Rose occupies less than ten percent of a screen. Its rarity makes agency unmistakable. -## 3. Typography +## 4. Typography **Display Font:** SF Pro Display (with system sans-serif fallbacks) @@ -154,7 +237,7 @@ decorative display face. **The Quiet Weight Rule.** Use weight before size to establish product hierarchy. Nothing in the working shell needs to shout. -## 4. Elevation +## 5. Elevation Flect is flat by default. Depth comes from adjacent tonal surfaces and occlusion. A focused prompt may use one compact structural shadow; menus may use @@ -172,7 +255,7 @@ a tighter shadow because they temporarily sit above the working plane. **The Flat-Until-Active Rule.** Resting surfaces use tone. Elevation appears only to communicate focus, movement, or temporary hierarchy. -## 5. Components +## 6. Components ### Buttons @@ -213,32 +296,39 @@ Navigation stays sparse and uses familiar icon-plus-label controls. Active state is conveyed by weight, tone, and accessible state, not a bright persistent sidebar. -### The Shaping Prompt +### The Agent Composer -The prompt is Flect's signature component: a centered work surface that begins -as an invitation, then becomes the stable composer beneath the conversation. -Its input, model source, attachment entry, voice entry, and submit/cancel state -share one visual grammar. The prompt itself is customizable; safe mode always -restores the compiled default. +The composer is Flect's signature component: one centered work surface that +begins as an invitation, then becomes the stable instrument beside the running +interface. Its input, model source, attachment entry, voice entry, selected +canvas target, tool activity, and submit/cancel state share one visual grammar. -The active role is explicit inside the composer before send: -**Edit · Shaper** changes the interface and **Run · App Agent** uses the -accepted product. Each role keeps its own draft and conversation. Switching -roles changes context; it never submits text or relabels history. +There is one continuous conversation. The user does not choose Edit versus +Run, App versus Shaper, a candidate state, or a review mode before speaking. +The agent infers whether the request changes the interface, uses an approved +capability, answers a question, or repairs a failure. Capability expansion and +destructive outside effects remain explicit confirmations. + +A valid local UI change appears directly on the running canvas and creates a +quiet checkpoint. A failed change leaves the last-known-good canvas in place +and gives the same agent actionable diagnostics. Undo is one visible action; +History is progressive disclosure. The protected fallback can restore the +composer and recovery controls, but internal recovery modes are not normal +workspace navigation. ### Adaptive Agent Rail Flect does not bolt a second chat onto the product. The signature composer is one mounted instrument whose position reflects the workspace phase: -- a blank workspace centers the Edit/Shaper composer beneath “What should we - shape?”; -- the first message reveals the canvas and moves that same composer into the - right conversation rail; -- a validated proposal adds a compact Keep/Reject decision immediately above - the composer; -- an accepted product defaults to Run/App Agent while Edit remains one explicit - switch away. +- a blank workspace centers the composer beneath “What do you need?”; +- the first valid result becomes the running canvas and moves that same + composer into the right conversation rail; +- selecting an element adds a compact semantic target to the composer without + creating another inspector workflow; +- agent, build, and capability activity appear as calm bounded status near the + composer; and +- Undo and History stay reachable without turning the rail into a Git client. Above 980px, the rail is inline and resizable from 340–520px, with 400px as the default. From 761–980px it becomes a full-height right sheet. At 760px and @@ -247,29 +337,79 @@ it, reopening restores focus to its first enabled control, and the protected reopen control remains available on the canvas. The transition uses measured layout motion for at most 220ms. Under -`prefers-reduced-motion: reduce`, layout changes are immediate. A role change, -resized rail, collapse, or breakpoint must never create a second composer, -horizontal page overflow, or hidden recovery control. - -## 6. Do's and Don'ts +`prefers-reduced-motion: reduce`, layout changes are immediate. A canvas +update, selected target, resized rail, collapse, or breakpoint must never +create a second composer, horizontal page overflow, focus loss, application +state reset, or hidden recovery control. + +### Chat Markdown + +Agent output uses the same SF/system family as the shell at `1rem` with a +`1.55` dark-surface line height and a maximum assistant measure of `70ch`. +Blocks follow a `0.65rem` rhythm. Headings use a compact fixed-rem hierarchy: +`1.25rem`, `1.125rem`, `1rem`, then `0.875rem` for levels four through six. +The final three levels retain their semantic rank while sharing one quiet +visual band to suit the narrow rail. + +Code and tables are contained instruments, not new cards. They use the +existing Surface, Raised Surface, Line, Ink, and Muted tokens; code is +`0.875rem` mono and table content is `0.8125rem`. Their own viewports own +horizontal overflow, while copy, wrap, and expand actions stay dense on +desktop and reach `44px` at compact widths. Details remain native disclosures, +links use Flect Rose only as an interaction cue, and footnotes remain subdued. +The complete rendering and trust contract lives in +[`docs/superpowers/specs/2026-07-31-flect-chat-markdown-design.md`](docs/superpowers/specs/2026-07-31-flect-chat-markdown-design.md). + +### Activity, Follow, and Diagnostics + +Tool use is a compact instrument in the conversation timeline, not a generic assistant +sentence and not a developer-console dump. A card always names the tool and +shows queued, running, completed, or failed state. Duration stays visible; +bounded commands, output, exit status, preview links, validation paths, and +operation identifiers live in a native disclosure. Ready Mint and Failure Red +support the label but never carry meaning alone. + +Conversation follow respects the reader. Content follows while the viewport is +within 48px of its bottom. Once the person scrolls away, streaming and tool +updates preserve that position and surface a quiet, keyboard-operable **Jump +to latest** control with an unread count. Following never focuses the timeline +or composer. + +Diagnostics is a protected disclosure above the composer. At rest it shows +only local-control state and connected-client count. When opened, it exposes +the explicit enable/revoke action and the latest correlated, redacted +operation evidence. It must remain legible and useful without turning the +ordinary product surface into infrastructure chrome. + +## 7. Do's and Don'ts ### Do: - **Do** keep the person's work and current prompt visually central. - **Do** reserve Flect Rose for focus, selection, and active shaping. - **Do** use known platform affordances with visible keyboard focus. +- **Do** use host-native surfaces when the WebView cannot meet the platform + contract. +- **Do** test real light/dark, pointer/touch, keyboard, scrolling, and resize + behavior on every supported host. - **Do** make runtime failure explain the next action: reconnect or start the local runtime. -- **Do** keep safe mode reachable independently of user interface state. +- **Do** keep protected Undo and recovery reachable independently of user + interface state. ### Don't: - **Don't** turn Flect into a fixed widget dashboard. - **Don't** present the agent as a second chatbot bolted onto a static application. +- **Don't** expose internal agent roles, candidate states, Keep/Reject, branch, + or reset-mode decisions in the ordinary editing flow. - **Don't** use terminal cosplay, neon gradients, decorative glass panels, or loud generative-AI activity chrome. - **Don't** use radii above 16px on cards, sections, or prompt surfaces. - **Don't** use controls whose novelty makes ordinary actions harder to recognize. +- **Don't** ship the same generic shell unchanged on browser, macOS, and mobile. +- **Don't** trade interaction latency or correct platform behavior for visual + effects. - **Don't** pair a decorative 1px border with a broad soft shadow. diff --git a/PRODUCT.md b/PRODUCT.md index 42f4a3b..f534052 100644 --- a/PRODUCT.md +++ b/PRODUCT.md @@ -38,9 +38,12 @@ running UI can be changed from inside itself. ## Brand Personality -Professional, elegant, and calm, with the precision of a first-party Apple -tool. The product should feel capable without looking technical for its own -sake. Its voice is concise, direct, and quietly confident. +Professional, elegant, and calm, with the precision of first-party software on +each supported platform. The macOS host should feel at home beside Apple's own +tools; the browser and future mobile hosts should be equally faithful to their +own environments rather than imitating macOS. The product should feel capable +without looking technical for its own sake. Its voice is concise, direct, and +quietly confident. ## Anti-references @@ -55,10 +58,19 @@ harder to recognize. - The default is excellent, but never a cage. - The agent is the product backbone, not an accessory beside it. - The work stays central; infrastructure and model mechanics stay quiet. +- Shared product logic adapts to native platform behavior instead of imposing + one generic shell everywhere. - Every customizable surface has a protected way back. - Changes should be inspectable, reversible, and attributable before they become more powerful. +## Product Quality + +[`docs/product-quality.md`](docs/product-quality.md) is the canonical contract +for Flect's stable user outcomes, release gates, and required proof. Current +maturity belongs in dated verification evidence and the Flect delivery +project, not in this product context. + ## Accessibility & Inclusion The shell targets WCAG 2.2 AA for text, controls, focus visibility, keyboard diff --git a/README.md b/README.md index 1299254..ce9df57 100644 --- a/README.md +++ b/README.md @@ -2,34 +2,105 @@ > The interface that takes your shape. -![Flect adapting across product interfaces](assets/flect-hero.png) - -Flect is an open-source, agent-native interface shell whose running UI can be -changed from inside itself. It works as a local macOS app and in a browser, -uses models already authenticated through [Pi](https://pi.dev), and keeps a -protected path back when a customized interface fails. - -**Flect is a public developer preview of the protected vertical slice:** start -with one excellent composer, shape an interface in Edit mode, inspect and keep -the validated preview, then use the resulting product through its separate App -Agent in Run mode. +[![Flect quality](https://github.com/akua-dev/flect/actions/workflows/quality.yml/badge.svg)](https://github.com/akua-dev/flect/actions/workflows/quality.yml) -[Download Flect for Apple Silicon macOS](https://github.com/akua-dev/flect/releases/latest/download/Flect_0.2.0_aarch64.dmg) -· -[SHA-256 checksum](https://github.com/akua-dev/flect/releases/latest/download/Flect_0.2.0_aarch64.dmg.sha256) +![Flect adapting across product interfaces](assets/flect-hero.png) -## Install Flect +Flect is an open-source, agent-native interface shell. You describe what you +need, the agent builds and repairs it, and the running interface remains the +place where you keep shaping the work. + +The agent is not a chatbot beside a static application. It is the programmable +backbone of the interface. Git quietly protects the work underneath, while +typed capabilities keep outside effects inspectable, approved, and revocable. + +## A glimpse of the final Flect + +Mara opens Flect because her logistics company has outgrown its spreadsheet. +There is no project wizard or framework selector, just an empty canvas and one +question: _What do you need?_ + +She asks for a live view of today's deliveries. Flect requests read-only access +to the delivery API, then a working interface appears. Mara selects a late +delivery badge and asks the agent to make it calmer. The valid change appears +directly on the running canvas. She drags the driver summary above the map and +Flect updates the ordinary source project behind it. + +When a later edit fails to build, the working interface never disappears. The +agent reads the source and runtime diagnostics, repairs the problem, and keeps +going. History shows human descriptions such as _Improved the small-screen +layout_, not a wall of Git terminology. Mara can Undo or restore any earlier +state immediately; her developer can still open the same work as a normal Git +repository. + +Flect mostly disappears. What remains is software that is alive, +understandable, and owned by the person using it. + +Read the complete story and product boundary in [VISION.md](VISION.md). + +## The product promise + +- The running interface is the canvas; there is no mandatory preview or review + ceremony for a valid local UI edit. +- One continuous agent conversation can create, inspect, modify, and repair the + frontend while it is running. +- People can edit by describing an outcome, selecting what they see, or using + direct manipulation where it is safe and unambiguous. +- A persistent incremental workspace keeps the agent, compiler, running + canvas, Git history, and exported source on one canonical revision. +- The last-known-good interface remains usable when an edit or build fails. +- History feels like Undo, Redo, and Restore. Ordinary Git remains available as + progressive disclosure and as the portable source of truth. +- External effects remain behind typed, bounded capabilities. Flect asks for + confirmation when authority changes, not for every visual iteration. +- Every supported host feels first-party to its platform. Shared product logic + never excuses lag, fake native controls, mismatched appearance, or generic + WebView behavior. + +## Project status + +The checked-out repository now implements the continuous live-canvas workflow: +one visible conversation, automatic routing between internally isolated agent +authorities, atomic acceptance of valid local UI changes, quiet Git-backed +history, deterministic recovery, responsive platform-aware layout, and an +Astro-on-Vite activation shell. Imported apps, shared artifacts, and new +capabilities still require an explicit **Activate app** or **Discard** decision +because they can change authority. + +The static Astro document loads first. Focus or pointer intent arms only the +tiny activation bootstrap; sending a prompt, using the Flect shortcut, or +opening an agent action hydrates the protected Effect workspace through the +custom `client:flect` Astro island. Its stylesheet is a declarative component +resource, and the Effect activation coordinator keeps the static shell visible +until that stylesheet has loaded and the island is ready. Compiler, package, +shell, Worker, and Wasm substrates remain on demand until a typed operation +needs them. Production Astro uses Preact's React compatibility renderer for the +existing workspace components; the direct Vite SPA remains a React fallback. +The measured production gates and exact budgets are documented below. + +Flect remains under active development. The published v0.2.0 macOS preview is +older than the checked-out live-canvas implementation, and signed/notarized +multi-platform release artifacts still depend on release credentials and clean +platform builders. Delivery evidence is tracked by the +[Flect 1.0 epic](https://github.com/akua-dev/flect/issues/1) and the +[Flect project](https://github.com/orgs/akua-dev/projects/8). + +## Try the current developer preview + +![Current Flect developer-preview demo](assets/demo/flect-v0.2-demo.webp) ### Apple Silicon macOS -The native preview requires Apple Silicon, macOS 12 or newer, and a one-time Pi -provider login. With [Bun](https://bun.sh) installed: +The current native preview requires Apple Silicon and macOS 12 or newer. It +contains its own Pi runtime; no terminal login or separate Pi installation is +required. -```bash -bunx pi -``` +[Download Flect v0.2.0 for Apple Silicon macOS](https://github.com/akua-dev/flect/releases/latest/download/Flect_0.2.0_aarch64.dmg) +· +[SHA-256 checksum](https://github.com/akua-dev/flect/releases/latest/download/Flect_0.2.0_aarch64.dmg.sha256) +· +[Release evidence](https://github.com/akua-dev/flect/releases/latest/download/Flect_0.2.0_aarch64.release.json) -Run `/login` inside Pi, authenticate a supported provider, then quit Pi. Download the DMG and checksum into the same directory and verify them: ```bash @@ -39,104 +110,189 @@ shasum -a 256 -c Flect_0.2.0_aarch64.dmg.sha256 Open the DMG and drag Flect into Applications. The v0.2.0 app is ad-hoc signed and unnotarized, so Gatekeeper may block the first launch. After verifying the -checksum, use Finder’s **Open** action from the context menu. If quarantine +checksum, use Finder's **Open** action from the context menu. If quarantine still blocks the app: ```bash xattr -dr com.apple.quarantine /Applications/Flect.app ``` +Launch Flect, open the model chooser, and connect a provider under **Pi +providers**. Provider credentials stay in Pi's private local store. Sensitive +manual values open in a separate one-use loopback page that Flect's interface +cannot read. + +Native update review and ownership-safe uninstall preparation live under +**Diagnostics**. Development builds do not contain an update trust key; public +builds fail closed unless the signed updater and Apple trust evidence are +complete. See [Updates and uninstall](docs/updates-and-uninstall.md). + ### Browser and source ```bash git clone https://github.com/akua-dev/flect.git cd flect bun install -bunx pi -``` - -Run `/login` inside Pi, quit Pi, then: - -```bash bun run dev ``` -Open [http://127.0.0.1:5173](http://127.0.0.1:5173). Vite serves the UI there; -the origin-restricted local Pi runtime listens on `127.0.0.1:3210`. Provider -credentials remain in Pi and never enter browser storage. - -## See it shape - -![Flect interface shaping demo](assets/demo/flect-v0.2-demo.webp) - -Blank workspaces begin with the Shaper in a centered, protected composer. Ask -for an interface and that same composer moves into the conversation rail while -the validated result appears on the canvas. +Open [http://127.0.0.1:5173](http://127.0.0.1:5173). Astro serves the static +activation shell through its Vite development pipeline; the origin-restricted +local Pi runtime listens on `127.0.0.1:3210`. Connect a +provider from the model chooser. Provider credentials remain in Pi and never +enter React state, workspace snapshots, control APIs, browser storage, or +shaped interfaces. + +## What the current slice proves + +- in-product Pi provider discovery, authentication, model selection, streamed + turns, cancellation, and redacted public failures; +- an Effect-owned continuous workspace controller with one protected composer, + schema-validated interface state, atomic local acceptance, and deterministic + last-known-good recovery; +- a canonical browser-portable Git repository in OPFS, guarded revision refs, + persistence across reloads, and complete ordinary-Git export; +- bounded static and single-entry Vite JavaScript, TypeScript, React, Vue, and + Svelte import from folders, archives, or exact public Git commits, a Worker + compiler, integrity-checked package resolution, and offline cache; +- deterministic `.flect` capsule import/export, protected provenance and + capability review, portable sharing, and user-owned forks; +- a typed product-capability registry plus the packable + [`@flect/product`](packages/product/) SDK and reference integrations; +- an opt-in local `flect` CLI, JSON/SSE, and MCP control surface using the same + workspace controller as visible UI actions; +- responsive light/dark, forced-colors, reduced-motion, keyboard, Markdown, + accessibility, 44 px compact touch targets, focus restoration, and bounded + conversation-continuity behavior; +- browser HTTP/SSE and native private-stdio transports behind the same Effect + capabilities; and +- optional pure extension logic in a disposable QuickJS/Wasm worker that can + return inert, schema-decoded intents only. -![Flect Edit mode with the centered Shaper composer](assets/screenshots/flect-edit-mode.png) +The native app does not start the browser development server. It launches a +compiled Bun/Pi sidecar and communicates through private NDJSON stdio exposed +to the webview by one narrow Tauri command. When the user enables outside +control, that sidecar additionally exposes the authenticated loopback broker. -The proposal is only a preview until you explicitly keep it. Reject and -rollback remain deterministic, and safe mode always bypasses shaped state. +## Adopt Flect in a product -![A validated Flect interface proposal](assets/screenshots/flect-shaper-preview.png) +`@flect/product` is the separately versioned, browser-portable Effect SDK for +product teams. It defines strict product metadata, recommended `.flect` +experiences, named unary and event operations, compatibility and declarative +migrations, inference ownership, user-state separation, and deterministic +adoption diagnostics. It also exports policy-fixed HTTP/GraphQL and bounded +event host Layers. -Keep the interface and switch to Run to speak with its App Agent. Edit and Run -retain distinct histories, drafts, Pi sessions, and sandbox workspaces. +Build and verify the current `0.1.0` preview tarball locally: -![Flect Run mode with the product App Agent](assets/screenshots/flect-run-mode.png) +```bash +bun run product:package +npm install ./dist-product-sdk/flect-product-0.1.0.tgz effect@4.0.0-beta.102 +``` -## What works today +This command installs the tarball into a clean temporary consumer, typechecks +it, and runs the smallest offline integration. It does not publish to npm. +Start with the [SDK quickstart](packages/product/README.md), then compare the +[offline, browser-direct, and brokered references](examples/product-sdk/). -- authenticated Pi model discovery, explicit selection, streamed turns, stop, - and redacted public failures; -- separate Guardian, App Agent, and Shaper Pi sessions with independent - policies and lifecycle state; Guardian is tool-free while the interactive - roles receive isolated browser-backed Bash workspaces; -- one role-explicit composer that starts centered, moves into an inline, - resizable right rail, and becomes an accessible sheet on compact screens; -- separate Edit/Shaper and Run/App Agent conversations, including per-role - drafts, cancellation, shell results, and visible authority before send; -- Effect Schema-validated interface documents and a closed trusted renderer; -- propose, preview, keep, reject, rollback, last-known-good recovery, and a - compiled `?safe=1` recovery shell; -- a protected composer even when a shaped document omits its own prompt; -- one Pi-visible `bash` tool per interactive role, backed by a role-owned - browser workspace with reserved Bun-compatible run, build, package, preview, - and stop commands; -- browser HTTP/SSE and native private-stdio transports behind the same Effect - capabilities; and -- optional pure extension logic in a disposable QuickJS/Wasm worker that may - return inert, schema-decoded intents only. +Flect still owns all grants, protected review, capsule activation, workspace +Git, safe mode, and recovery. Products supply only named, bounded closures. +Product denial overrides approval; credentials stay inside trusted host +closures; model-provider or inference-owner choice cannot change product +authorization. Product connection records remain separate from personal forks +and exports, and detach preserves that user-owned work. -The native app does not start the browser development server. It launches a -compiled Bun/Pi sidecar and communicates through private NDJSON stdio exposed -to the webview by one narrow Tauri command. +## Security and product boundary -## Current security and product boundary +> Interfaces may reshape the user experience, but may affect the outside world +> only through inspectable, approved, and revocable capabilities. -The QuickJS worker and browser agent workspace are defense-in-depth execution -realms, not operating-system sandboxes. The source build can execute generated -workspace code through its bounded browser shell, but it cannot invoke a host +The generated frontend and browser agent workspace are defense-in-depth +execution realms, not operating-system sandboxes. They cannot invoke a host shell, native process, system Bun, ambient filesystem, or ambient network. -Flect does not yet ship portable `.flect` capsules, a component registry, -canonical OPFS/Git workspaces, in-Flect provider login, product/API adapters, -privileged host brokerage, remote runtimes, automatic updates, notarization, a -macOS App Sandbox entitlement, or Intel, Windows, and Linux packages. - -User-shaped documents cannot replace deterministic validation, revision -storage, rollback, safe mode, or the compiled recovery path. See the -[capability and sandbox trust model](docs/trust-model.md) for the authority -boundary and the exact +Credentials remain outside user-generated source and model-visible project +state. + +Flect now exports and imports verified declarative `.flect` capsules through a +reviewable candidate flow. It also imports, isolates, persists, restores, and +byte-preservingly re-exports compiled HTML capsules with verified local CSS, +classic scripts, images, fonts, and media in supported browsers. +Configured hosts can verify canonical Ed25519 publisher signatures, show +unknown/revoked/expired/changed/invalid states, and require approved keys; +signatures never grant capabilities. A local fork records its parent and is +explicitly unsigned until its owner signs it again. + +The packaged macOS host also includes the first real native capability adapter: +it reads AppKit's system accent color through a fixed Swift/Rust boundary. The +operation is absent in browsers, remains optional to the running capsule, and +cannot execute before an explicit, revocable broker grant. The reusable adapter +contract is documented in +[`docs/native-platform-adapters.md`](docs/native-platform-adapters.md). +Arbitrary Vite plugins/config transforms, CSS modules/preprocessors and asset +URL rewriting, multi-entry routing, capsule-level personal-fork merges +outside the implemented `.flect-share` lifecycle, a public component registry, +custom duration/rate editing in the protected permission UI, database adapters, +privileged native credential transport, remote runtimes, a published signed +updater, notarization, a +macOS App Sandbox entitlement, and Intel, Windows, and Linux packages are not +yet shipped. + +See the [capability and sandbox trust model](docs/trust-model.md) for the +authority boundary and the [browser Bun compatibility matrix](docs/bun-compatibility.md) for supported commands and deliberate omissions. -## Architecture and vision - -- [Vision and intentional non-capabilities](VISION.md) +## Import an existing interface + +Open the composer’s **Actions** menu and choose **Import app project** for a +folder, **Import project archive** for a bounded ZIP/POSIX TAR, or **Import from +Git** for a credential-free public HTTPS repository plus its exact 40-character +commit. Flect recognizes plain static sites and standard single-entry Vite +browser projects, including React JSX/TSX, Vue SFC, and Svelte components. It +checks paths and compatibility without executing source, excludes +secret-shaped and generated dependency files, checkpoints recognizable source +into embedded Git, and builds the exact isolated proposal locally. Git cloning +runs in the isolated WASM Git worker and never accepts a mutable branch name. +When runtime dependencies need resolution, Flect generates or verifies an npm +v3 lock, checkpoints it into the candidate's ordinary Git source, supersedes +the guarded proposal, and compiles only that locked commit. +The current boundary accepts at most 255 retained source files (the capsule +reserves one metadata entry), 32 MiB total, and 100 characters per portable +relative path. Archive preflight also rejects encryption, ZIP64, unsupported +links/types, excessive entries, and expansion beyond 32 MiB. Named unsupported +Vite plugins, `resolve.alias`, `node:` built-ins, CSS preprocessors, and +external Vue blocks are reported before a candidate exists, with a +browser-portable alternative. + +The resulting external app opens as an isolated import candidate. Review its +source revision, artifact digest, adaptations, ignored files, capabilities, and +compatibility; exercise the isolated UI; then choose **Activate app** or +**Discard**. This explicit decision exists because imported code can introduce +new authority. Ordinary UI edits requested in the Flect conversation validate, +activate, and checkpoint automatically. An activated build exports as a complete +`.flect` capsule and runs without Vite, npm, or a Flect-hosted service. Vite +config and package scripts are preserved as source but never run; only runtime +dependencies enter the portable package graph. + +## Architecture, product, and vision + +- [Vision, final product story, and intentional non-capabilities](VISION.md) +- [Users, positioning, and product principles](PRODUCT.md) +- [Visible design system](DESIGN.md) - [Implemented architecture](ARCHITECTURE.md) +- [Capability and sandbox trust model](docs/trust-model.md) +- [Current Astro/live-canvas performance verification](docs/verification/2026-08-10-astro-live-canvas-verification.md) +- [Packaged macOS local verification](docs/verification/2026-08-10-packaged-macos-local-verification.md) +- [Open-issue implementation audit](docs/verification/2026-08-10-open-issue-audit.md) +- [Final delivery verification](docs/verification/2026-08-11-final-delivery-verification.md) +- [Historical pre-migration performance baseline](docs/verification/2026-08-10-performance-and-native-feel-baseline.md) +- [Astro activation-shell architecture decision](docs/decisions/0003-astro-activation-shell.md) +- [Local agent control](docs/local-control.md) +- [Product capability adoption](docs/product-capabilities.md) - [Browser Bun compatibility](docs/bun-compatibility.md) -- [Users and product principles](PRODUCT.md) -- [Design system](DESIGN.md) +- [Performance and memory budgets](docs/performance.md) +- [Session continuity and recovery](docs/recovery.md) +- [Updates and uninstall](docs/updates-and-uninstall.md) - [Contributor guide](CONTRIBUTING.md) - [Flect delivery project](https://github.com/orgs/akua-dev/projects/8) @@ -147,15 +303,34 @@ bun install --frozen-lockfile bun run check:all ``` -`check:all` runs Effect preparation, lint, type checking, unit and contract -tests, production Chromium workflows, Rust tests, and the native application -build. `bun run test:pi-smoke` is separate because it makes one real private -turn with the developer’s existing Pi provider login. - -Release maintainers can reproduce the screenshots, demo, hero, DMG, checksum, -and MP4 with `bun run media:release` and `bun run release:package`. The media -pipeline additionally needs FFmpeg and the WebP tools `cwebp`, `dwebp`, and -`img2webp`. +`check:all` runs Effect preparation, the Effect-boundary architecture gate, +lint, type checking, unit and contract tests, production Chromium workflows, +Rust formatting and tests, and the native application build. The architecture +gate rejects native promise fan-out everywhere and ad hoc Promise constructors +or native Promise serialization tails outside tests. Concurrency, callback +lifetimes, cancellation, and failure composition therefore stay explicit in +Effect. The credential-free GitHub quality workflow runs this same command on +every pull request and every change to `main`; branch protection requires its +exact `Flect quality gate` context on a current revision, including for +administrators. The workflow uploads only bounded Playwright failure evidence. +`bun run +test:pi-smoke` is separate +because it makes one real private turn with the developer's existing Pi +provider login. + +Release maintainers can reproduce the screenshots, demo, and hero with +`bun run media:release`, then produce the DMG, checksum, MP4, and a +machine-readable evidence manifest with `bun run release:package`. Public mode +also produces the signed Tauri archive and static `latest.json`. The package +gate verifies the mounted DMG, exact executable inventory and architecture, +deep/strict signing, hardened runtime, and observed Gatekeeper/stapling state. +Public mode (`FLECT_PUBLIC_RELEASE=1`) additionally requires updater signing +material from the release environment and fails closed unless source, Developer +ID, notarization, updater signature verification, and independent +reproducibility proof are all present. Tauri's current Isolation Pattern intentionally generates fresh +per-build security material, so independent native-content reproducibility is +recorded as blocked rather than claimed. The media pipeline additionally needs +FFmpeg and the WebP tools `cwebp`, `dwebp`, and `img2webp`. ## License diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4599945..082e324 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,17 +1,20 @@ # Flect v0.2.0 -Flect v0.2.0 replaces the developer launcher with the first complete -role-aware interface loop: describe a product in Edit, review the validated -result, keep it, then use the resulting experience through its separate App -Agent in Run. +Flect v0.2.0 ships the first portable, role-aware product foundation: describe +an interface in Shape, review the validated candidate, keep it, then use the +resulting experience through its separate App Agent. The release also includes +browser-portable OPFS/Git workspaces, sandboxed Bash/Bun role mirrors, +reviewable `.flect` capsules and imports, portable product capabilities, and +the packable `@flect/product` SDK with reference products. ## Role-aware interface shell - A blank workspace starts with one centered, T3Code-inspired Shaper composer. The same mounted composer moves into an adaptive conversation rail when the interface appears. -- Edit/Shaper and Run/App Agent have visibly separate authority, Pi sessions, - histories, drafts, cancellation, and browser-shell workspaces. +- Shape/Shaper, candidate Use/Preview App Agent, and accepted Use/App Agent + have visibly separate authority, Pi sessions, histories, drafts, + cancellation, and browser-shell workspaces. - The rail is resizable inline on wide screens, a right sheet at medium widths, and a full-width accessible sheet on compact screens. - Searchable, provider-grouped Pi model selection includes favorites, keyboard @@ -21,9 +24,10 @@ Agent in Run. ## Runtime and sandbox -- Guardian, App Agent, and Shaper now run as three independent Pi sessions. -- App and Shaper shell requests are explicitly role-tagged through browser HTTP - and private native RPC. +- Guardian, App Agent, and Shaper run as three independent primary Pi sessions; + candidate Use acquires a separate Preview App Agent session set. +- App, Preview App, and Shaper shell requests are explicitly role-tagged through + browser HTTP and private native RPC. - Each interactive role receives its own just-bash/Rifty browser workspace; neither receives ambient host Bash, filesystem, process, or network access. - The Effect shaping kernel and schema-validated renderer remain authoritative @@ -35,9 +39,9 @@ The native preview supports Apple Silicon Macs running macOS 12 or newer. Download `Flect_0.2.0_aarch64.dmg`, verify it with `Flect_0.2.0_aarch64.dmg.sha256`, and drag Flect into Applications. -Flect uses the provider login already managed by Pi. Before opening Flect for -the first time, run `bunx pi`, use `/login` to authenticate a supported model -provider, then quit Pi. +Launch Flect, open the model chooser, and connect a provider under **Pi +providers**. Provider credentials remain in Pi's private local store; sensitive +manual values use a separate one-use loopback page that Flect cannot read. This build is ad-hoc signed and unnotarized. macOS Gatekeeper may block the first launch. After verifying the checksum, use Finder’s **Open** action from @@ -55,11 +59,10 @@ The same shell works in a browser: git clone https://github.com/akua-dev/flect.git cd flect bun install -bunx pi ``` -Use `/login` inside Pi, quit Pi, then run `bun run dev` and open -`http://127.0.0.1:5173`. +Run `bun run dev`, open `http://127.0.0.1:5173`, and connect a provider from +the model chooser under **Pi providers**. Release assets: @@ -69,12 +72,14 @@ Release assets: ## Current boundary -This preview does not yet ship portable `.flect` capsules, canonical OPFS/Git -workspaces, arbitrary React or JavaScript UI imports, a public component -registry, in-Flect provider login, native extensions, product/API capability -adapters, remote runtimes, automatic updates, Intel, Windows, or Linux -packages. It is not notarized and does not use the macOS App Sandbox -entitlement. +This release does not yet ship Vue/Svelte adapters, general multi-entry +routing, arbitrary Vite plugins or transforms, CSS modules or preprocessors, +archive/Git project import, a public component registry, general capsule +personal-fork lineage and compatible merge, database adapters, privileged +native product transport, remote runtimes, +notarization, the macOS App Sandbox entitlement, or Intel, Windows, and Linux +packages. The documented release artifact remains an ad-hoc signed, +Apple-Silicon macOS preview. See [VISION.md](VISION.md) for the destination and [docs/trust-model.md](docs/trust-model.md) for the authority model. diff --git a/VISION.md b/VISION.md index e03f6d4..7af0a6b 100644 --- a/VISION.md +++ b/VISION.md @@ -41,6 +41,98 @@ Most people will use good defaults. The point is not to make everyone design software. The point is to ensure that nobody is trapped by a fixed interface when their needs differ. +## A day with Flect + +The following story describes the destination. It is a product test for what +Flect should feel like, not a claim that the current developer preview already +implements every part. + +Mara does not open Flect to write code. She opens it because the small +logistics company she runs has outgrown its spreadsheet. + +The window appears immediately. There is no project wizard, framework +selection, or agent mode. There is an empty canvas and a quiet prompt: + +> What do you need? + +Mara asks for a live view of today's deliveries, with late orders first, +drivers grouped clearly, and urgent work impossible to miss. + +The agent explains that it needs read-only access to deliveries and drivers. +Flect shows exactly what that capability permits and what it does not. Mara +approves it. Seconds later, the empty canvas becomes a working application. + +Real deliveries appear. Cards move as statuses change. A small map shows where +drivers are. The application is already running; there is no separate preview +mode or review screen between Mara and a valid local UI change. + +Mara selects the red _Late_ badge and asks the agent to make it calmer without +making urgent orders easier to miss. The agent changes the color, contrast, +spacing, and icon treatment while she looks at the result. It checks the +accessible contrast in the background and briefly explains why a paler red +would not be safe enough. + +She drags the driver summary above the map. Flect understands the gesture as a +change to the real interface, not as temporary canvas state. The canonical +source changes, the running app updates incrementally, and a quiet history +checkpoint is created. No Save or Keep button interrupts her. + +Later, the page feels crowded on Mara's laptop. She selects the delivery list +and says: + +> On small screens, collapse completed deliveries and keep the driver names +> visible. + +The agent can inspect the running layout, the selected element, its computed +styles, the source that produced it, and the current viewport. It makes the +change without asking Mara which file or framework component to edit. + +Something breaks during the next request. The build status turns amber, but +the working application never disappears. Flect keeps the last-known-good +revision running while the agent reads the compiler diagnostic, finds the +incorrect component property, repairs it, and continues. + +Mara sees one useful sentence: + +> I hit a build error and fixed it. Your working version stayed available. + +At the end of the afternoon, Mara realizes that she preferred the map from +three changes ago. She opens History. It does not look like a Git client. It +shows a small sequence of understandable changes: + +- _Made late deliveries calmer_ +- _Moved the driver summary above the map_ +- _Improved the small-screen layout_ +- _Changed map grouping_ + +She chooses the earlier map and restores it. The running canvas changes +immediately. Underneath, Flect performs an ordinary Git operation in an +ordinary repository. Nothing is trapped inside a proprietary design file. + +The next morning, Mara reopens Flect. The application, conversation, +permissions, and history are where she left them. The shell is responsive +before the model or network has fully reconnected. + +Her developer, Leo, opens the same project in his editor. He finds normal +source code, readable commits, standard dependencies, and no mysterious +generated format. He improves an API type and pushes the change. Flect picks it +up and keeps going. + +A week later, Mara shares the application with her team. Reading deliveries is +already approved. Updating delivery status requires a new capability, so Flect +asks for the one confirmation that matters: whether the interface may gain +that outside authority. Mara grants it only to supervisors. + +The interface can reshape itself. It cannot quietly gain power. + +Months pass. The delivery view becomes the company's daily operating surface. +Mara still changes it by describing problems and manipulating what she sees. +Leo still owns understandable code. Git still records everything. The agent +handles the machinery between intention and implementation. + +Flect itself mostly disappears. What remains is the feeling that software is +not a finished object handed to Mara. It is alive, understandable, and hers. + ## Product boundary > Interfaces may reshape the user experience, but may affect the outside world @@ -66,7 +158,7 @@ Flect will let people: including the normal agent composer and rail; - import and adapt supported React, Vue, Svelte, HTML, and CSS source projects into portable Flect experiences; -- author, build, and preview interfaces locally in a normal browser without a +- author, build, and run interfaces locally in a normal browser without a proprietary hosted development runtime; - install compiled `.flect` capsules that continue to run without their build tool or package registry; @@ -76,6 +168,9 @@ Flect will let people: SQL capability; - ask the built-in agent to use approved product capabilities as well as shape their presentation; +- explicitly pair a local outside agent that can inspect, operate, debug, and + subscribe to the same live workspace through the same user-visible command + and recovery boundaries; - use model access they control through Pi or another approved runtime instead of requiring every product to operate an inference service; - begin without an existing product backend and create local, offline-capable @@ -87,8 +182,8 @@ Flect will let people: - run the shared interface in browsers and desktop hosts, extend it to mobile, and add genuinely native platform experiences through narrow Swift, Kotlin, or Rust capabilities; and -- preview, accept, reject, compare, version, undo, and recover every - attributable interface revision. +- see valid local changes in the running interface immediately, compare and + version them, undo or restore them, and recover every attributable revision. These primitives can produce dashboards, internal tools, API consoles, research environments, personal workspaces, agent control surfaces, and many @@ -108,17 +203,18 @@ A shared interface, component, or extension cannot: - access Pi credentials, model-provider tokens, or another product's secrets; - bypass product authentication, authorization, rate limits, or API policy; - grant itself capabilities or silently expand a previous grant; -- modify the Guardian, recovery shell, capability broker, validation rules, or +- modify the protected recovery shell, capability broker, validation rules, or required recovery journal; - erase attribution required to explain and recover a change; -- replace the accepted interface without a validated, attributable revision; - or +- replace the last-known-good interface with an invalid or unattributed + revision; or - become trusted merely because it was generated by a model or signed by a publisher. -Recovery cannot depend on a model being available. The Guardian may assist -diagnosis and repair, but validation, safe mode, permission revocation, and -last-known-good rollback remain deterministic protected-core behavior. +Recovery cannot depend on a model being available. The agent may assist +diagnosis and repair when it is available, but validation, permission +revocation, last-known-good rollback, and the minimal recovery path remain +deterministic protected-core behavior. ### What Flect does not promise @@ -149,6 +245,29 @@ Customization is not a separate design phase followed by an export. The running interface is the canvas. Users change it through conversation and direct manipulation, see the result immediately, and continue from there. +### Every host feels native + +Platform-native quality is a release condition, not optional polish. Flect +shares its agent, workspace, history, capability, and recovery contracts across +hosts; it does not force every host into one lowest-common-denominator shell. + +The browser must behave like an excellent web application. The macOS app must +respect macOS windowing, menus, focus, keyboard shortcuts, trackpad behavior, +appearance, accessibility, and lifecycle expectations. Future iOS and Android +hosts must adopt their own navigation, back, keyboard, touch, safe-area, +haptic, and system-surface conventions before they can be called supported. + +Shared web UI is an implementation option, not an excuse for imitation. When a +WebView cannot meet a platform's behavior, latency, accessibility, or visual +quality, the protected host shell provides a native surface through a narrow +adapter. Flect does not ship a fake macOS control, a desktop-shaped mobile UI, +or browser behavior hidden behind simulated application chrome. + +No supported host may exhibit input lag, scroll hitching, avoidable full-page +reloads, layout jumps, mismatched system appearance, or motion that fights the +platform. These claims are proven on real supported browsers and devices, not +only with screenshots or a shared DOM test. + ### Products expose capabilities In an agent-native world, a product's durable value is its capabilities, data, @@ -230,26 +349,46 @@ interface can become personal, situational, and continuously useful. Flect is that foundation. -## The first working slice - -The repository now implements a protected vertical slice in the browser and a -macOS Tauri app. A user can ask the Shaper Pi to revise a schema-defined -interface, preview the validated result, keep or reject it, then use the -accepted experience through its separate App Agent. Recovery remains available -through last-known-good rollback or the compiled recovery shell. - -Guardian, App Agent, and Shaper use separate in-memory Pi sessions behind one -private runtime boundary. The same protected composer routes a blank workspace -to Edit/Shaper and an accepted experience to Run/App Agent. The desktop app -carries that runtime as a compiled sidecar over stdio instead of exposing it on -localhost. Optional pure extension logic can run in a disposable, -resource-limited QuickJS WebAssembly worker and return only inert typed intents. - -This slice intentionally does not run generated React, native extensions, or -product API capabilities. Interactive roles may use the bounded +## The current implementation + +The repository now implements the continuous live-canvas loop in the browser +and the shared macOS Tauri frontend: one visible conversation and draft, no +Edit/Run or agent-role switcher, direct validated local UI changes without +Keep/Reject ceremony, responsive protected controls, quiet Git-backed history, +and deterministic last-known-good recovery. External capsules, shared code, +and authority changes remain explicit Activate/Discard decisions. + +An Astro static document sits on Vite. Focus and pointer intent arm a tiny +coordinator; submitting the first prompt, using the keyboard shortcut, or +invoking an agent action hydrates a custom `client:flect` island. The protected +Flect workspace and its declarative CSS resource do not load for a view-only +visit. The compiler, package resolver, shell, Workers, and Wasm runtimes are +separately lazy. This makes the opened product useful without preloading its +authoring system while preserving the existing typed boundaries. + +Internally, Guardian, accepted App Agent, Shaper, and candidate Preview App +Agent still use separate Pi sessions behind one private runtime boundary. The +Effect workspace controller accepts visible UI actions and explicitly +authorized local CLI, JSON/SSE, and MCP requests, publishes their changes +reactively, and retains bounded redacted diagnostic evidence. Effect Layers +own platform transports and optional native lifecycles; Effect concurrency +combinators own fan-out and cancellation across product, tooling, and release +code. Outside control remains off by default and cannot grant itself authority. + +The current foundation includes a canonical browser-portable Git repository in +OPFS, capsule import and export, bounded source-project import, typed product +capabilities, a product-adoption SDK, in-product Pi authentication, portable +extensions, accessibility and appearance gates, and a native update/uninstall +boundary. Supported static and single-entry Vite JavaScript, TypeScript, and +React projects can be imported into isolated compiled candidates. Candidate +ceremony exists only where code or authority crosses a trust boundary. + +The desktop app carries Pi traffic through a compiled sidecar over private +stdio. Optional pure extension logic runs in a disposable, resource-limited +QuickJS WebAssembly worker and returns only inert typed intents. The bounded browser-portable shell described in -[`docs/bun-compatibility.md`](docs/bun-compatibility.md), but it does not grant -host-shell, native-process, system-Bun, or ambient-network authority. The slice -proves the model, credential, shaping, preview, transport, logic-sandbox, and -deterministic recovery boundaries on which the larger ecosystem can safely -build. +[`docs/bun-compatibility.md`](docs/bun-compatibility.md) grants no host shell, +native process, system Bun, or ambient network authority. The next stage keeps +those boundaries while making the agent, canonical frontend workspace, running +canvas, direct manipulation, and quiet Git history one coherent product +experience. diff --git a/assets/agent-integrations/opencode/flect.js b/assets/agent-integrations/opencode/flect.js new file mode 100644 index 0000000..37a30e8 --- /dev/null +++ b/assets/agent-integrations/opencode/flect.js @@ -0,0 +1,82 @@ +// dev.akua.flect-context +const MAX_CONTEXT_BYTES = 1200; + +const boundedContext = async () => { + const process = Bun.spawn(["flect", "context", "--host", "opencode"], { + stdout: "pipe", + stderr: "ignore", + }); + const reader = process.stdout.getReader(); + const chunks = []; + let size = 0; + let truncated = false; + while (size < MAX_CONTEXT_BYTES) { + const next = await reader.read(); + if (next.done) break; + const remaining = MAX_CONTEXT_BYTES - size; + const chunk = next.value.subarray(0, remaining); + chunks.push(chunk); + size += chunk.byteLength; + if (chunk.byteLength < next.value.byteLength) { + truncated = true; + process.kill(); + break; + } + } + const bytes = new Uint8Array(size); + let offset = 0; + for (const chunk of chunks) { + bytes.set(chunk, offset); + offset += chunk.byteLength; + } + const exitCode = await process.exited; + if (exitCode !== 0 && !truncated) return ""; + const text = new TextDecoder().decode(bytes).trim(); + return truncated ? `${text}\n[bounded by Flect]` : text; +}; + +const eventValue = (envelope) => envelope?.event ?? envelope; +const eventSession = (event) => + event?.sessionID ?? event?.properties?.sessionID ?? event?.data?.sessionID; + +export default { + id: "dev.akua.flect-context", + setup: async (ctx) => { + const injected = new Set(); + const controller = new AbortController(); + const eventTask = (async () => { + try { + const subscription = await ctx.event.subscribe({ + signal: controller.signal, + }); + const stream = subscription?.stream ?? subscription; + for await (const envelope of stream) { + const event = eventValue(envelope); + if (event?.type === "session.compacted") { + const sessionID = eventSession(event); + if (typeof sessionID === "string") injected.delete(sessionID); + } + } + } catch { + // OpenCode stops or reloads the plugin by aborting the subscription. + } + })(); + + await ctx.session.hook("request", async (event) => { + const sessionID = eventSession(event) ?? "default"; + if (injected.has(sessionID)) return; + injected.add(sessionID); + const context = await boundedContext(); + if (context.length === 0) { + injected.delete(sessionID); + return; + } + event.system.push({ type: "text", text: context }); + }); + + return async () => { + controller.abort(); + await eventTask; + }; + }, +}; diff --git a/astro.config.ts b/astro.config.ts new file mode 100644 index 0000000..4006935 --- /dev/null +++ b/astro.config.ts @@ -0,0 +1,21 @@ +import preact from "@astrojs/preact"; +import { defineConfig } from "astro/config"; +import { flectIntegration } from "./src/astro/flect-integration"; +import { flectViteConfig } from "./vite.config"; + +export default defineConfig({ + output: "static", + integrations: [preact({ compat: true }), flectIntegration()], + outDir: "./dist", + build: { + assets: "assets", + inlineStylesheets: "never", + }, + vite: { + ...flectViteConfig, + build: { + ...flectViteConfig.build, + assetsInlineLimit: 0, + }, + }, +}); diff --git a/biome.json b/biome.json index 3ae60f7..64b580e 100644 --- a/biome.json +++ b/biome.json @@ -3,9 +3,11 @@ "files": { "includes": [ "**", + "!**/.astro", "!**/.repos", "!**/node_modules", "!**/dist", + "!**/dist-spa", "!**/coverage", "!**/playwright-report", "!**/test-results", diff --git a/bun.lock b/bun.lock index b246923..1bfea2d 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,5 @@ { - "lockfileVersion": 2, + "lockfileVersion": 1, "configVersion": 1, "workspaces": { "": { @@ -9,24 +9,46 @@ "@earendil-works/pi-coding-agent": "0.82.1", "@effect/platform-browser": "4.0.0-beta.102", "@effect/platform-bun": "4.0.0-beta.102", + "@flect/product": "workspace:*", "@jitl/quickjs-ng-wasmfile-release-sync": "0.32.0", + "@modelcontextprotocol/server": "2.0.0", "@riftydev/npm-client": "0.2.0", "@riftydev/runtime-js": "0.2.0", "@riftydev/runtime-wasi": "0.2.0", "@riftydev/vfs": "0.2.0", + "@rolldown/browser": "1.2.1", "@tauri-apps/api": "2.11.1", + "@toon-format/toon": "4.1.0", + "@types/semver": "7.7.1", + "@vue/compiler-sfc": "3.5.41", "acorn": "8.18.0", "effect": "4.0.0-beta.102", "esbuild-wasm": "0.28.1", + "fflate": "0.8.3", "just-bash": "3.2.0", + "preact": "10.29.8", "quickjs-emscripten-core": "0.32.0", "react": "19.2.8", "react-dom": "19.2.8", + "react-markdown": "10.1.0", + "rehype-raw": "7.0.0", + "rehype-sanitize": "6.0.0", + "remark-breaks": "4.0.0", + "remark-gfm": "4.0.1", + "scheduler": "0.27.0", + "semver": "7.8.5", + "shiki": "4.3.1", + "svelte": "5.56.8", "typebox": "1.1.38", + "wasm-git": "0.0.17", + "zod": "4.2.0", }, "devDependencies": { + "@astrojs/preact": "6.0.2", + "@axe-core/playwright": "4.12.1", "@biomejs/biome": "2.5.6", "@effect/vitest": "4.0.0-beta.102", + "@modelcontextprotocol/client": "2.0.0", "@playwright/test": "1.62.0", "@tauri-apps/cli": "2.11.4", "@testing-library/jest-dom": "7.0.0", @@ -37,11 +59,24 @@ "@types/react": "19.2.17", "@types/react-dom": "19.2.3", "@vitejs/plugin-react": "6.0.4", + "astro": "7.2.0", "concurrently": "10.0.4", "jsdom": "30.0.1", "typescript": "7.0.2", "vite": "8.1.5", "vitest": "4.1.10", + "yaml": "2.9.0", + }, + }, + "packages/product": { + "name": "@flect/product", + "version": "0.1.0", + "devDependencies": { + "effect": "4.0.0-beta.102", + "typescript": "7.0.2", + }, + "peerDependencies": { + "effect": "4.0.0-beta.102", }, }, }, @@ -54,6 +89,38 @@ "@asamuzakjp/dom-selector": ["@asamuzakjp/dom-selector@8.3.0", "", { "dependencies": { "bidi-js": "^1.0.3", "css-tree": "^3.2.1", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.5.2" } }, "sha512-UJLfKXBhrc8i1vH2eJXuYQMwlsLKWFw3O+CPqXSuVEiikeAim3UgrfWX0k4tA/X8cRFM8iZ7OaqBokFGbYusdg=="], + "@astrojs/compiler-binding": ["@astrojs/compiler-binding@0.3.2", "", { "optionalDependencies": { "@astrojs/compiler-binding-darwin-arm64": "0.3.2", "@astrojs/compiler-binding-darwin-x64": "0.3.2", "@astrojs/compiler-binding-linux-arm64-gnu": "0.3.2", "@astrojs/compiler-binding-linux-arm64-musl": "0.3.2", "@astrojs/compiler-binding-linux-x64-gnu": "0.3.2", "@astrojs/compiler-binding-linux-x64-musl": "0.3.2", "@astrojs/compiler-binding-wasm32-wasi": "0.3.2", "@astrojs/compiler-binding-win32-arm64-msvc": "0.3.2", "@astrojs/compiler-binding-win32-x64-msvc": "0.3.2" } }, "sha512-8w/9CWmYrAJJ8N0SY3O43ws2BgxoW6u3QsD8u2mE140lMYAlwh+tlNoUeSBq22wVheFuiBbR212l6ixZ2IIgCQ=="], + + "@astrojs/compiler-binding-darwin-arm64": ["@astrojs/compiler-binding-darwin-arm64@0.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MM8tn8CSimcfytaOla4b6acN8mKWiL/rlAA1fpT3/Wl7dNGSE4y8FjTN/zJVNnb63CsLWG5zZwCt01TXtDKh9g=="], + + "@astrojs/compiler-binding-darwin-x64": ["@astrojs/compiler-binding-darwin-x64@0.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-2lXOlzf8xb7jLomRsf/aswh61/NnGusynB2OwFkK6k4pmOtpfXMYnG0PLfXrEvxXYj69NdCnmUYXtHDd+JOOag=="], + + "@astrojs/compiler-binding-linux-arm64-gnu": ["@astrojs/compiler-binding-linux-arm64-gnu@0.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-BmU3kWj7qnLrd4vzm49zFEPJ5oFnn1tCT4Vt9hZbqdU5Cmb8GZl7fn6VFsnNfe7B18a2gIFtVzbLINtYl5kBjQ=="], + + "@astrojs/compiler-binding-linux-arm64-musl": ["@astrojs/compiler-binding-linux-arm64-musl@0.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-f0heT9ZZEseSu5bHCeb80eL2DH07ArE6U9xi1WT/PEusNjzPmEr3GJsjG1tRLo5VYUUYX7h3ScaqGmGrMOVGmw=="], + + "@astrojs/compiler-binding-linux-x64-gnu": ["@astrojs/compiler-binding-linux-x64-gnu@0.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-M8fOUt0itRpqiGyoEA/ij184s8O+hqbCz3+YozRusOOM3osgGljpDThhbKAJjqh82wOo6FioQ4w8PBvU1XMD5Q=="], + + "@astrojs/compiler-binding-linux-x64-musl": ["@astrojs/compiler-binding-linux-x64-musl@0.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-/Kebk8sO6HnLeSd691JkaAPfN7CqR9/KEXmWvyNPkaKNGmj8rTZ/lf2uXtnPu92Lan84UrKdIKVPy1fSo2encQ=="], + + "@astrojs/compiler-binding-wasm32-wasi": ["@astrojs/compiler-binding-wasm32-wasi@0.3.2", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.2.0" }, "cpu": "none" }, "sha512-pUA6xbcOSB7DhfzIArB8BCAkFfAIqriiR7zl5zOStd6oU2G0kIKj+GUdGnyXyhfiv881Hffyk5tC0mR18sDjDw=="], + + "@astrojs/compiler-binding-win32-arm64-msvc": ["@astrojs/compiler-binding-win32-arm64-msvc@0.3.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-ESruf+6Qkl1trHUFxI6GSf6t52j8yN2kCNSzMWdzt7V/T09tFHrYzrVaJQohb2C9bJUH76pNvX6Zb51+xCQc9Q=="], + + "@astrojs/compiler-binding-win32-x64-msvc": ["@astrojs/compiler-binding-win32-x64-msvc@0.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-wzzVrEbOwbsLWOdEbocskjMRx2aZPxJ7ZbmL+jnpBamFwmigm+2M/wzuM6JWncocgYwLic1csSpalBh96kQKXA=="], + + "@astrojs/compiler-rs": ["@astrojs/compiler-rs@0.3.2", "", { "dependencies": { "@astrojs/compiler-binding": "0.3.2" } }, "sha512-xlx/T7JovIKduu4ucbTQUxQ5+Q8wxkHxhLjnZk3VlJbhbQ9RLvvuDk1p2YYFYFQ5y14dVm3FGGO4isQXa4F+Tg=="], + + "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.10.2", "", { "dependencies": { "@types/hast": "^3.0.4", "@types/mdast": "^4.0.4", "js-yaml": "^4.3.0", "picomatch": "^4.0.4", "retext-smartypants": "^6.2.0", "shiki": "^4.0.2", "smol-toml": "^1.6.0", "unified": "^11.0.5" } }, "sha512-yt7fMgPYqSM4Tmr+taTW6Per+hjJ8Pk6lA1PAcDyqzOt8HzJ6Kje5WzCxA2Sd+9wsUW7uhkLeoTMK0cXPwH9rQ=="], + + "@astrojs/markdown-satteri": ["@astrojs/markdown-satteri@0.3.5", "", { "dependencies": { "@astrojs/internal-helpers": "0.10.2", "@astrojs/prism": "4.0.2", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "satteri": "^0.9.1" } }, "sha512-CvWVEFAbay7YO+i9SaqDJubipA5ckiVB89QWoMJ5XC0m5CtFg8JwZ7Kau6X9sYY7FZURH0w2l03ISH2jOS/RDQ=="], + + "@astrojs/preact": ["@astrojs/preact@6.0.2", "", { "dependencies": { "@astrojs/internal-helpers": "0.10.2", "@preact/preset-vite": "^2.10.5", "@preact/signals": "^2.8.2", "devalue": "^5.8.1", "preact-render-to-string": "^6.6.6", "vite": "^8.0.13" }, "peerDependencies": { "preact": "^10.6.5" } }, "sha512-OoV/1KeGpRU8f9a+jBk2q2GK05jqjnRg7H+ZN8i48FBKrLJQj+4nU/Vg+JSsvhZ9PZtku0kS2vyFBJ8SGXoTiQ=="], + + "@astrojs/prism": ["@astrojs/prism@4.0.2", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA=="], + + "@astrojs/telemetry": ["@astrojs/telemetry@3.3.3", "", { "dependencies": { "ci-info": "^4.4.0", "dset": "^3.1.4", "is-docker": "^4.0.0", "package-manager-detector": "^1.6.0" } }, "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ=="], + "@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="], "@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="], @@ -102,12 +169,52 @@ "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + "@axe-core/playwright": ["@axe-core/playwright@4.12.1", "", { "dependencies": { "axe-core": "~4.12.1" }, "peerDependencies": { "playwright-core": ">= 1.0.0" } }, "sha512-rMd7xriptqKpP+w5265i4Hdkv2X5kbu6uiBi/B2I7uf3hieRBM3qDCfaKPtxfiYb2mKXfF+yLODJwIx+Jv1GDw=="], + "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="], + "@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="], + + "@babel/core": ["@babel/core@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-module-transforms": "^7.29.7", "@babel/helpers": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA=="], + + "@babel/generator": ["@babel/generator@7.29.8", "", { "dependencies": { "@babel/parser": "^7.29.8", "@babel/types": "^7.29.8", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg=="], + + "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="], + + "@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.29.7", "", {}, "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw=="], + + "@babel/helpers": ["@babel/helpers@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg=="], + + "@babel/parser": ["@babel/parser@7.29.8", "", { "dependencies": { "@babel/types": "^7.29.8" }, "bin": "./bin/babel-parser.js" }, "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA=="], + + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A=="], + + "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/types": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A=="], + + "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.29.7", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g=="], + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], + "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="], + + "@babel/traverse": ["@babel/traverse@7.29.8", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.8", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.8", "@babel/template": "^7.29.7", "@babel/types": "^7.29.8", "debug": "^4.3.1" } }, "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg=="], + + "@babel/types": ["@babel/types@7.29.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg=="], + "@biomejs/biome": ["@biomejs/biome@2.5.6", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.6", "@biomejs/cli-darwin-x64": "2.5.6", "@biomejs/cli-linux-arm64": "2.5.6", "@biomejs/cli-linux-arm64-musl": "2.5.6", "@biomejs/cli-linux-x64": "2.5.6", "@biomejs/cli-linux-x64-musl": "2.5.6", "@biomejs/cli-win32-arm64": "2.5.6", "@biomejs/cli-win32-x64": "2.5.6" }, "bin": { "biome": "bin/biome" } }, "sha512-lxVNjv7UF6KfhMJfL9gaUHbWdJdHbsAj6OSmwSYNdhRuG67NxNQ4Xdvh3TUxsSK9sBzJBQhEJj3AopmmNJ5pSA=="], "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zMOLZP4oMrjh6m1zcSj1ud2awUPgTuMVbmQhYYWL7J8HwCnbHHBvTm7VBTRuY7epT5bez76IpKYQ11ZAqHFlnw=="], @@ -130,6 +237,30 @@ "@bramus/specificity": ["@bramus/specificity@2.4.2", "", { "dependencies": { "css-tree": "^3.0.0" }, "bin": { "specificity": "bin/cli.js" } }, "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw=="], + "@bruits/satteri-darwin-arm64": ["@bruits/satteri-darwin-arm64@0.9.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow=="], + + "@bruits/satteri-darwin-x64": ["@bruits/satteri-darwin-x64@0.9.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q=="], + + "@bruits/satteri-linux-arm64-gnu": ["@bruits/satteri-linux-arm64-gnu@0.9.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA=="], + + "@bruits/satteri-linux-arm64-musl": ["@bruits/satteri-linux-arm64-musl@0.9.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ=="], + + "@bruits/satteri-linux-x64-gnu": ["@bruits/satteri-linux-x64-gnu@0.9.5", "", { "os": "linux", "cpu": "x64" }, "sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw=="], + + "@bruits/satteri-linux-x64-musl": ["@bruits/satteri-linux-x64-musl@0.9.5", "", { "os": "linux", "cpu": "x64" }, "sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q=="], + + "@bruits/satteri-wasm32-wasi": ["@bruits/satteri-wasm32-wasi@0.9.5", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.1.6" }, "cpu": "none" }, "sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ=="], + + "@bruits/satteri-win32-arm64-msvc": ["@bruits/satteri-win32-arm64-msvc@0.9.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg=="], + + "@bruits/satteri-win32-x64-msvc": ["@bruits/satteri-win32-x64-msvc@0.9.5", "", { "os": "win32", "cpu": "x64" }, "sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g=="], + + "@capsizecss/unpack": ["@capsizecss/unpack@4.0.1", "", { "dependencies": { "fontkitten": "^1.0.3" } }, "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ=="], + + "@clack/core": ["@clack/core@1.4.3", "", { "dependencies": { "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ=="], + + "@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="], + "@csstools/color-helpers": ["@csstools/color-helpers@6.1.0", "", {}, "sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg=="], "@csstools/css-calc": ["@csstools/css-calc@3.3.0", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ=="], @@ -158,16 +289,124 @@ "@effect/vitest": ["@effect/vitest@4.0.0-beta.102", "", { "peerDependencies": { "effect": "^4.0.0-beta.102", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-4dipFAYG6imOzrY3zy3BgzCJkbb9xESyzUef0WSx8bsK0/SpITqbJpdwKeOyDWLZ+rimjua8IbTFMAde865pIQ=="], - "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], + "@emnapi/core": ["@emnapi/core@2.0.0-alpha.3", "", { "dependencies": { "@emnapi/wasi-threads": "2.0.1", "tslib": "^2.4.0" } }, "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g=="], + + "@emnapi/runtime": ["@emnapi/runtime@2.0.0-alpha.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@2.0.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], - "@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], "@exodus/bytes": ["@exodus/bytes@1.15.1", "", { "peerDependencies": { "@noble/hashes": "^1.8.0 || ^2.0.0" }, "optionalPeers": ["@noble/hashes"] }, "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q=="], + "@flect/product": ["@flect/product@workspace:packages/product"], + "@google/genai": ["@google/genai@1.52.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q=="], + "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.2" }, "os": "darwin", "cpu": "arm64" }, "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.2" }, "os": "darwin", "cpu": "x64" }, "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w=="], + + "@img/sharp-freebsd-wasm32": ["@img/sharp-freebsd-wasm32@0.35.3", "", { "dependencies": { "@img/sharp-wasm32": "0.35.3" }, "os": "freebsd" }, "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.2", "", { "os": "linux", "cpu": "arm" }, "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA=="], + + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.3.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw=="], + + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.3.2", "", { "os": "linux", "cpu": "none" }, "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.2" }, "os": "linux", "cpu": "arm" }, "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ=="], + + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.3.2" }, "os": "linux", "cpu": "ppc64" }, "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA=="], + + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.3.2" }, "os": "linux", "cpu": "none" }, "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.2" }, "os": "linux", "cpu": "s390x" }, "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.3", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w=="], + + "@img/sharp-webcontainers-wasm32": ["@img/sharp-webcontainers-wasm32@0.35.3", "", { "dependencies": { "@img/sharp-wasm32": "0.35.3" }, "cpu": "none" }, "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.35.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.3", "", { "os": "win32", "cpu": "x64" }, "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA=="], + "@jitl/quickjs-ffi-types": ["@jitl/quickjs-ffi-types@0.32.0", "", {}, "sha512-v9T+GQpmk43VDJ7d72sf0Nexhk+ArvtUihW27dy7lqAl0zBObFKtSBBIm5RBjwIhE8VwsPPm9PNuvPvNqLWUEg=="], "@jitl/quickjs-ng-wasmfile-release-sync": ["@jitl/quickjs-ng-wasmfile-release-sync@0.32.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.32.0" } }, "sha512-XAX2jjZWWh3M0YaRqi82xMKNW/gkF6mo3MpW3UY2cmVxnQai1JuboVsJQVoLU629iEL4XWvHtO4h5lo7NRnAcg=="], @@ -180,8 +419,16 @@ "@jitl/quickjs-wasmfile-release-sync": ["@jitl/quickjs-wasmfile-release-sync@0.32.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.32.0" } }, "sha512-BKNDI/TPBfGlLNGYpLrhcDGXmIk4xHm4MRAisOBnOzpXVn9HZWsfmMAc9WMBrAHjvvds6HOikKeaOBKdPdpVrg=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@mariozechner/clipboard": ["@mariozechner/clipboard@0.3.9", "", { "optionalDependencies": { "@mariozechner/clipboard-darwin-arm64": "0.3.9", "@mariozechner/clipboard-darwin-universal": "0.3.9", "@mariozechner/clipboard-darwin-x64": "0.3.9", "@mariozechner/clipboard-linux-arm64-gnu": "0.3.9", "@mariozechner/clipboard-linux-arm64-musl": "0.3.9", "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-gnu": "0.3.9", "@mariozechner/clipboard-linux-x64-musl": "0.3.9", "@mariozechner/clipboard-win32-arm64-msvc": "0.3.9", "@mariozechner/clipboard-win32-x64-msvc": "0.3.9" } }, "sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA=="], "@mariozechner/clipboard-darwin-arm64": ["@mariozechner/clipboard-darwin-arm64@0.3.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ=="], @@ -208,6 +455,12 @@ "@mixmark-io/domino": ["@mixmark-io/domino@2.2.0", "", {}, "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw=="], + "@modelcontextprotocol/client": ["@modelcontextprotocol/client@2.0.0", "", { "dependencies": { "@modelcontextprotocol/core": "2.0.0", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "jose": "^6.1.3", "pkce-challenge": "^5.0.0", "zod": "^4.2.0" } }, "sha512-8f1OghQ2rjzIOfqgUCP+8GiUWqRs89njoWLNqAe8kWmDePv3s1fZXseej+QXemssEuuOvLLmLO/kqM3IQHtISw=="], + + "@modelcontextprotocol/core": ["@modelcontextprotocol/core@2.0.0", "", { "dependencies": { "zod": "^4.2.0" } }, "sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA=="], + + "@modelcontextprotocol/server": ["@modelcontextprotocol/server@2.0.0", "", { "dependencies": { "@modelcontextprotocol/core": "2.0.0", "zod": "^4.2.0" } }, "sha512-YhHWdHfpFMQfd0prsEnxKeS3Qz3ytIGmsS0sth4KDjnacIT7hxk6hXHkJ9KysxlkvTM+WZAtQbbcUhdoP4Hvtw=="], + "@mongodb-js/zstd": ["@mongodb-js/zstd@7.0.0", "", { "dependencies": { "node-addon-api": "^8.5.0", "prebuild-install": "^7.1.3" } }, "sha512-mQ2s0pYYiav+tzCDR05Zptem8Ey2v8s11lri5RKGhTtL4COVCvVCk5vtyRYNT+9L8qSfyOqqefF9UtnW8mC5jA=="], "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="], @@ -230,10 +483,26 @@ "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.43.0", "", {}, "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg=="], + "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="], + "@oxc-project/types": ["@oxc-project/types@0.139.0", "", {}, "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw=="], "@playwright/test": ["@playwright/test@1.62.0", "", { "dependencies": { "playwright": "1.62.0" }, "bin": { "playwright": "cli.js" } }, "sha512-9zOJ6ZQRAena31MpOH9VSzIz8Ou3YJ/wtY/eQm5T2uhfhG7/U3COrMS8xOtUrZrp9OgdmzEnIYODye3nY1VqzA=="], + "@preact/preset-vite": ["@preact/preset-vite@2.10.6", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@prefresh/vite": "^2.4.11", "@rollup/pluginutils": "^5.0.0", "babel-plugin-transform-hook-names": "^1.0.2", "debug": "^4.4.3", "magic-string": "^0.30.21", "picocolors": "^1.1.1", "vite-prerender-plugin": "^0.5.8", "zimmerframe": "^1.1.4" }, "peerDependencies": { "@babel/core": "7.x", "vite": "2.x || 3.x || 4.x || 5.x || 6.x || 7.x || 8.x" } }, "sha512-ZZ5RIT2ZVXg8UxRA8VZpoT8CdpDG7RFIqOT4bELqNBp85+HKvQBbgmh3gsoW1UOQXx26TLe+ZRNKI7q281Kckw=="], + + "@preact/signals": ["@preact/signals@2.11.0", "", { "dependencies": { "@preact/signals-core": "^1.14.4" }, "peerDependencies": { "preact": ">= 10.25.0 || >=11.0.0-0" } }, "sha512-mmrZ8I/Wef+tmSsQSjZySLRlnvuYAVfSZEy1+HrFvSwBtQf8/zSM+bV7odllUXIhKzUkBjsNk+TLZ20nt7p6Gg=="], + + "@preact/signals-core": ["@preact/signals-core@1.14.4", "", {}, "sha512-HNB6HYeYKhQbJ1aKl+YRjrS4+QWHLKX6qKoUsfS/m0vqzsVaEBiZiaKbG/e+NKk2ch5ALQr/ihWaMHxiCuuWHA=="], + + "@prefresh/babel-plugin": ["@prefresh/babel-plugin@0.5.3", "", {}, "sha512-57LX2SHs4BX2s1IwCjNzTE2OJeEepRCNf1VTEpbNcUyHfMO68eeOWGDIt4ob9aYlW6PEWZ1SuwNikuoIXANDtQ=="], + + "@prefresh/core": ["@prefresh/core@1.5.10", "", { "peerDependencies": { "preact": "^10.0.0 || ^11.0.0-0" } }, "sha512-7yPTFbG56sutaFu8krp3B4a200KOFUvrtlllKWRuLjsYXo9UUucHOZRcer+gtgMkFTpv6ob8TGcTwA32bSwa1w=="], + + "@prefresh/utils": ["@prefresh/utils@1.2.1", "", {}, "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw=="], + + "@prefresh/vite": ["@prefresh/vite@2.4.12", "", { "dependencies": { "@babel/core": "^7.22.1", "@prefresh/babel-plugin": "^0.5.2", "@prefresh/core": "^1.5.0", "@prefresh/utils": "^1.2.0", "@rollup/pluginutils": "^4.2.1" }, "peerDependencies": { "preact": "^10.4.0 || ^11.0.0-0", "vite": ">=2.0.0" } }, "sha512-FY1fzXpUjiuosznMV0YM7XAOPZjB5FIdWS0W24+XnlxYkt9hNAwwsiKYn+cuTEoMtD/ZVazS5QVssBr9YhpCQA=="], + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], @@ -296,8 +565,28 @@ "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA=="], + "@rolldown/browser": ["@rolldown/browser@1.2.1", "", { "dependencies": { "@emnapi/core": "2.0.0-alpha.3", "@emnapi/runtime": "2.0.0-alpha.3", "@napi-rs/wasm-runtime": "^1.2.0" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-wdWNMUba40WNB7IkqI1UoATBJ0ygLUiosUeQXF1jn0HAjcJtpNjNE5/Qchxi+rEppeHoh1dBwJ06jbWs1RQq0g=="], + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], + "@rollup/pluginutils": ["@rollup/pluginutils@5.4.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg=="], + + "@shikijs/core": ["@shikijs/core@4.3.1", "", { "dependencies": { "@shikijs/primitive": "4.3.1", "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA=="], + + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.3.1", "", { "dependencies": { "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" } }, "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ=="], + + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@4.3.1", "", { "dependencies": { "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg=="], + + "@shikijs/langs": ["@shikijs/langs@4.3.1", "", { "dependencies": { "@shikijs/types": "4.3.1" } }, "sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ=="], + + "@shikijs/primitive": ["@shikijs/primitive@4.3.1", "", { "dependencies": { "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A=="], + + "@shikijs/themes": ["@shikijs/themes@4.3.1", "", { "dependencies": { "@shikijs/types": "4.3.1" } }, "sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA=="], + + "@shikijs/types": ["@shikijs/types@4.3.1", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g=="], + + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + "@silvia-odwyer/photon-node": ["@silvia-odwyer/photon-node@0.3.4", "", {}, "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA=="], "@smithy/core": ["@smithy/core@3.31.0", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-sylYk2l9d7CmRv8ts8p0SDQUr3VO+HMeS1nrjL6+UtbO8ktJHTOeQ1McX+aAyvGGccp5aZX9eNtdcXrSwzoZaw=="], @@ -320,6 +609,8 @@ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.12", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-J1jNYG23QWd67UfrQSFHtjhV37r9mVi0gdc12A3MWPldOjRK35Xk+um+qACPVjgw3AleiqoyEAhok8Wm3q46NA=="], + "@tauri-apps/api": ["@tauri-apps/api@2.11.1", "", {}, "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA=="], "@tauri-apps/cli": ["@tauri-apps/cli@2.11.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.11.4", "@tauri-apps/cli-darwin-x64": "2.11.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4", "@tauri-apps/cli-linux-arm64-gnu": "2.11.4", "@tauri-apps/cli-linux-arm64-musl": "2.11.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-musl": "2.11.4", "@tauri-apps/cli-win32-arm64-msvc": "2.11.4", "@tauri-apps/cli-win32-ia32-msvc": "2.11.4", "@tauri-apps/cli-win32-x64-msvc": "2.11.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ=="], @@ -358,6 +649,8 @@ "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], + "@toon-format/toon": ["@toon-format/toon@4.1.0", "", {}, "sha512-dBB3pkEx9QYvHnHR6rtkaBAh+7x4W/oA5ONur4G0fh7Ow69PbPuM7OFxzNRABqyxC0t6SZ3RixiGbCuaFjPDAQ=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="], @@ -366,10 +659,22 @@ "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], + "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + + "@types/hast": ["@types/hast@3.0.5", "", { "dependencies": { "@types/unist": "*" } }, "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], + + "@types/nlcst": ["@types/nlcst@2.0.3", "", { "dependencies": { "@types/unist": "*" } }, "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA=="], + "@types/node": ["@types/node@26.1.2", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg=="], "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="], @@ -378,6 +683,12 @@ "@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], + "@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="], + + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], @@ -420,6 +731,8 @@ "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.3", "", {}, "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg=="], + "@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.4", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg=="], "@vitest/expect": ["@vitest/expect@4.1.10", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA=="], @@ -436,60 +749,126 @@ "@vitest/utils": ["@vitest/utils@4.1.10", "", { "dependencies": { "@vitest/pretty-format": "4.1.10", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA=="], + "@vue/compiler-core": ["@vue/compiler-core@3.5.41", "", { "dependencies": { "@babel/parser": "^7.29.8", "@vue/shared": "3.5.41", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg=="], + + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.41", "", { "dependencies": { "@vue/compiler-core": "3.5.41", "@vue/shared": "3.5.41" } }, "sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw=="], + + "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.41", "", { "dependencies": { "@babel/parser": "^7.29.8", "@vue/compiler-core": "3.5.41", "@vue/compiler-dom": "3.5.41", "@vue/compiler-ssr": "3.5.41", "@vue/shared": "3.5.41", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.19", "source-map-js": "^1.2.1" } }, "sha512-XJhip7R2wy6vX3knCxdZN4KracFaZUef58s1KYewqluedHIJaPIVfXoYT7MF1F8nCvv6k8bWWxDC8opMkg1VTQ=="], + + "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.41", "", { "dependencies": { "@vue/compiler-dom": "3.5.41", "@vue/shared": "3.5.41" } }, "sha512-U3v5OejKEGqOI0Wy0+Sz7hGuIFZHA4LSXzrNM3IMIeDyJEBBfTpX26n3SDgToRpP2bLc9FfI2j/kSgcJ8Emq5A=="], + + "@vue/shared": ["@vue/shared@3.5.41", "", {}, "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA=="], + "acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], + "am-i-vibing": ["am-i-vibing@0.4.0", "", { "dependencies": { "process-ancestry": "^0.1.0" }, "bin": { "am-i-vibing": "dist/cli.mjs" } }, "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg=="], + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + "anynum": ["anynum@1.0.1", "", {}, "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + "astro": ["astro@7.2.0", "", { "dependencies": { "@astrojs/compiler-rs": "^0.3.2", "@astrojs/internal-helpers": "0.10.2", "@astrojs/markdown-satteri": "0.3.5", "@astrojs/telemetry": "3.3.3", "@capsizecss/unpack": "^4.0.0", "@clack/prompts": "^1.1.0", "@oslojs/encoding": "^1.1.0", "am-i-vibing": "^0.4.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^2.0.1", "devalue": "^5.8.1", "diff": "^8.0.3", "dset": "^3.1.4", "es-module-lexer": "^2.0.0", "esbuild": "^0.28.0", "flattie": "^1.1.1", "fontace": "~0.4.1", "get-tsconfig": "5.0.0-beta.4", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "js-yaml": "^4.3.0", "jsonc-parser": "^3.3.1", "magic-string": "^1.0.0", "magicast": "^0.5.2", "mrmime": "^2.0.1", "neotraverse": "^1.0.1", "obug": "^2.1.1", "p-limit": "^7.3.0", "p-queue": "^9.1.0", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.4", "semver": "^7.7.4", "shiki": "^4.0.2", "smol-toml": "^1.6.0", "svgo": "^4.0.1", "tinyclip": "^0.1.12", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", "ultrahtml": "^1.6.0", "unifont": "~0.7.4", "unstorage": "^1.17.5", "vite": "^8.0.13", "vitefu": "^1.1.2", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", "zod": "^4.3.6" }, "optionalDependencies": { "sharp": "^0.34.0 || ^0.35.0" }, "peerDependencies": { "@astrojs/markdown-remark": "7.2.2" }, "optionalPeers": ["@astrojs/markdown-remark"], "bin": { "astro": "./bin/astro.mjs" } }, "sha512-lLTYzx3fOvCmtwD3JVBLQcbORbIOW1/j0R+3IvJx/XKwMGrk7mFnF0BYSOeRiNw1qHUR5mdA6+hRnyvyDfqrWQ=="], + + "axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="], + + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + + "babel-plugin-transform-hook-names": ["babel-plugin-transform-hook-names@1.0.2", "", { "peerDependencies": { "@babel/core": "^7.12.10" } }, "sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw=="], + + "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.11.12", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA=="], + "bidi-js": ["bidi-js@1.0.3", "", { "dependencies": { "require-from-string": "^2.0.2" } }, "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw=="], "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], "brace-expansion": ["brace-expansion@5.0.8", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg=="], + "browserslist": ["browserslist@4.28.7", "", { "dependencies": { "baseline-browser-mapping": "^2.10.44", "caniuse-lite": "^1.0.30001806", "electron-to-chromium": "^1.5.393", "node-releases": "^2.0.51", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw=="], + "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001809", "", {}, "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], + + "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="], + "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], + "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], - "commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="], + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + + "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="], "concurrently": ["concurrently@10.0.4", "", { "dependencies": { "chalk": "5.6.2", "rxjs": "7.8.2", "shell-quote": "1.9.0", "supports-color": "10.2.2", "tree-kill": "1.2.2", "yargs": "18.0.0" }, "bin": { "conc": "dist/bin/index.js", "concurrently": "dist/bin/index.js" } }, "sha512-trZql+7l/0+WRAsAnEdctr4+iiOS6ZrViI6H8QWcCF9MFS/LT0dKpe8vluB1to6it+OxSI4VospFTIFMW8DJRw=="], "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + "cookie": ["cookie@2.0.1", "", {}, "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w=="], + + "cookie-es": ["cookie-es@1.2.3", "", {}, "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="], + + "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], + "css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="], + "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], + "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="], + "csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="], + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], @@ -500,22 +879,44 @@ "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="], + "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], + "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], + "defu": ["defu@6.1.7", "", {}, "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ=="], + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "devalue": ["devalue@5.9.0", "", {}, "sha512-RWrqdArjvPbsATEhOPUo6Wndc/iWnkWKlhIrdlF3zMMYo/c3CVtoaVAyLtWxz5h8nSlkHzxnzV2uLydPXmtF+A=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + "diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="], "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="], + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="], + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], "effect": ["effect@4.0.0-beta.102", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "multipasta": "^0.2.8", "toml": "^4.1.2", "uuid": "^14.0.1", "yaml": "^2.9.0" } }, "sha512-z8Y+Q76Hh/kjLFZrXu8tGn6e+tDsg45R+UHhxd190pXxD53OGwf/G/zDxXTkse4HJ5mobNZfitLfUCp4fMvu6w=="], + "electron-to-chromium": ["electron-to-chromium@1.5.402", "", {}, "sha512-/oOpMaPT6Yg+6/1XQhyIPlzgj7Ye9zf+nNM2Uh6OcE2G2oNptWazFa+qB2Pdqqbsc9KnIDzgAntoYN0dbwOXwA=="], + "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], @@ -524,11 +925,27 @@ "es-module-lexer": ["es-module-lexer@2.3.1", "", {}, "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA=="], + "esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + "esbuild-wasm": ["esbuild-wasm@0.28.1", "", { "bin": { "esbuild": "bin/esbuild" } }, "sha512-p/GD4E8oYRjg3kjdKrnMb0s4PzXgJF42e0MF4H0+ACyK/kIlFRp3e0fzOleIG+wBBm6MM3XQrbpe7soEA+vJIA=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], - "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], + + "esrap": ["esrap@2.3.1", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-MXjVkrBAjuwIZ8xq9+a1MOOnLIwANZOx/4gtdWHfSJtXOrUh2QQK2I5mMC3urLli559jTlq2j+kSqht80uRgog=="], + + "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], + + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], + + "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], + + "eventsource-parser": ["eventsource-parser@3.1.0", "", {}, "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg=="], "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], @@ -538,6 +955,12 @@ "fast-check": ["fast-check@4.9.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg=="], + "fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="], + + "fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="], + + "fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="], + "fast-xml-builder": ["fast-xml-builder@1.3.0", "", { "dependencies": { "path-expression-matcher": "^1.6.2", "xml-naming": "^0.3.0" } }, "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ=="], "fast-xml-parser": ["fast-xml-parser@5.10.1", "", { "dependencies": { "@nodable/entities": "^3.0.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^2.0.0", "path-expression-matcher": "^1.6.2", "strnum": "^2.4.1", "xml-naming": "^0.3.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw=="], @@ -546,10 +969,18 @@ "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], + "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="], + "file-type": ["file-type@21.3.4", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g=="], "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="], + "flattie": ["flattie@1.1.1", "", {}, "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ=="], + + "fontace": ["fontace@0.4.1", "", { "dependencies": { "fontkitten": "^1.0.2" } }, "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw=="], + + "fontkitten": ["fontkitten@1.0.3", "", { "dependencies": { "tiny-inflate": "^1.0.3" } }, "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw=="], + "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], @@ -560,12 +991,18 @@ "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="], + "get-tsconfig": ["get-tsconfig@5.0.0-beta.4", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ=="], + "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], + "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], + "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], "google-auth-library": ["google-auth-library@10.9.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw=="], @@ -574,12 +1011,44 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "h3": ["h3@1.15.11", "", { "dependencies": { "cookie-es": "^1.2.3", "crossws": "^0.3.5", "defu": "^6.1.6", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg=="], + + "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="], + + "hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="], + + "hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="], + + "hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="], + + "hast-util-sanitize": ["hast-util-sanitize@5.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "unist-util-position": "^5.0.0" } }, "sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg=="], + + "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], + + "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="], + + "hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="], + + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], + + "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="], + + "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], + "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], "hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="], "html-encoding-sniffer": ["html-encoding-sniffer@6.0.0", "", { "dependencies": { "@exodus/bytes": "^1.6.0" } }, "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg=="], + "html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="], + + "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], + + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], + + "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], + "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], @@ -594,28 +1063,58 @@ "ini": ["ini@7.0.0", "", {}, "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w=="], + "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], + + "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], + + "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], + + "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], + + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], + + "is-docker": ["is-docker@4.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA=="], + + "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="], + "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], + "is-unsafe": ["is-unsafe@2.0.0", "", {}, "sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA=="], "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], + "jose": ["jose@6.2.5", "", {}, "sha512-2E5L2yRp03FnwreJLJX8/r7mHiZICCf8kG7fAsTWkSQTDAcc46NIZoQLKy+EJ8sPoJlxyS4OQR5H70LjIZZlIQ=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "js-yaml": ["js-yaml@4.3.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="], + "jsdom": ["jsdom@30.0.1", "", { "dependencies": { "@asamuzakjp/css-color": "^6.0.5", "@asamuzakjp/dom-selector": "^8.3.0", "@bramus/specificity": "^2.4.2", "@csstools/css-syntax-patches-for-csstree": "^1.1.7", "@exodus/bytes": "^1.15.1", "css-tree": "^3.2.1", "data-urls": "^7.0.0", "decimal.js": "^10.6.0", "html-encoding-sniffer": "^6.0.0", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.5.2", "parse5": "^8.0.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^6.0.2", "undici": "^8.9.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.1", "whatwg-mimetype": "^5.0.0", "whatwg-url": "^17.1.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.2.3" }, "optionalPeers": ["canvas"] }, "sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA=="], + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + "just-bash": ["just-bash@3.2.0", "", { "dependencies": { "diff": "^8.0.2", "fast-xml-parser": "^5.7.3", "file-type": "^21.2.0", "ini": "^6.0.0", "minimatch": "^10.1.1", "modern-tar": "^0.7.3", "papaparse": "^5.5.3", "quickjs-emscripten": "^0.32.0", "re2js": "^1.2.1", "seek-bzip": "^2.0.0", "smol-toml": "^1.6.0", "sprintf-js": "^1.1.3", "sql.js": "^1.13.0", "turndown": "^7.2.2", "undici": "^7.25.0", "yaml": "^2.8.2" }, "optionalDependencies": { "@mongodb-js/zstd": "^7.0.0", "node-liblzma": "^2.0.3" }, "bin": { "just-bash": "dist/bin/just-bash.js", "just-bash-shell": "dist/bin/shell/shell.js" } }, "sha512-hRTLLWBXCKuosjaNFJR7uPYBza+T2vjG3NdPBz4wxlctlnxwrbLjtLQf6RtSKmy/jzNJ6/URCtvxrXjy6yFGeQ=="], "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], + "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], + "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="], "lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="], @@ -642,18 +1141,114 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="], + "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], + "lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="], - "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "magic-string": ["magic-string@1.1.0", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-kS3VHe0nEPST2saQV4Rbkchcd3UBRkVTQHo1D3h/ZTwFDhai/mfKkmtPAtD129EOI7K3HlHIsFOt0WrI2/oU9g=="], + + "magicast": ["magicast@0.5.4", "", { "dependencies": { "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7", "source-map-js": "^1.2.1" } }, "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w=="], + + "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], "marked": ["marked@18.0.5", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w=="], + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], + + "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="], + + "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="], + + "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="], + + "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="], + + "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], + + "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], + + "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], + + "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="], + + "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.2.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q=="], + + "mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="], + + "mdast-util-newline-to-break": ["mdast-util-newline-to-break@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-find-and-replace": "^3.0.0" } }, "sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog=="], + + "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], + + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], + + "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="], + + "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], + "mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="], + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], + + "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], + + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], + + "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], + + "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="], + + "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="], + + "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="], + + "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], + + "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="], + + "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="], + + "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="], + + "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], + + "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="], + + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="], + + "micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="], + + "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="], + + "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="], + + "micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], + + "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="], + + "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="], + + "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], @@ -668,6 +1263,8 @@ "modern-tar": ["modern-tar@0.7.7", "", {}, "sha512-t9VmxaqrmANnEOBhpSDI6HD192Ge48k8vmWqQQL7hSFEqHEYwZbbsu49+aKLWZeRvFs3j1pMhXOqqF4kPlvjkQ=="], + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "msgpackr": ["msgpackr@2.0.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA=="], @@ -680,6 +1277,10 @@ "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], + "neotraverse": ["neotraverse@1.0.1", "", {}, "sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w=="], + + "nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="], + "node-abi": ["node-abi@3.94.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g=="], "node-addon-api": ["node-addon-api@8.9.0", "", {}, "sha512-ekZMeaaIzSQTSpr7X2X3iJM7lTzgnx8ahAG9pJfT/7+14mlEM8ZYQ9cgCDvSSRbReFK0oHli3WrZdCiRsgAT9Q=="], @@ -688,22 +1289,52 @@ "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], + "node-html-parser": ["node-html-parser@6.1.13", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg=="], + "node-liblzma": ["node-liblzma@2.2.0", "", { "dependencies": { "node-addon-api": "^8.5.0", "node-gyp-build": "^4.8.4" }, "bin": { "nxz": "lib/cli/nxz.js" } }, "sha512-s0KzNOWwOJJgPG6wxg6cKohnAl9Wk/oW1KrQaVzJBjQwVcUGPQCzpR46Ximygjqj/3KhOrtJXnYMp/xYAXp75g=="], + "node-mock-http": ["node-mock-http@1.0.5", "", {}, "sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw=="], + + "node-releases": ["node-releases@2.0.53", "", {}, "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + "obug": ["obug@2.1.4", "", {}, "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA=="], + "ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], + + "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + "oniguruma-parser": ["oniguruma-parser@0.12.2", "", {}, "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw=="], + + "oniguruma-to-es": ["oniguruma-to-es@4.3.6", "", { "dependencies": { "oniguruma-parser": "^0.12.2", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA=="], + "openai": ["openai@6.26.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA=="], + "p-limit": ["p-limit@7.3.1", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q=="], + + "p-queue": ["p-queue@9.3.3", "", { "dependencies": { "eventemitter3": "^5.0.4", "p-timeout": "^7.0.0" } }, "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA=="], + "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], + "p-timeout": ["p-timeout@7.0.1", "", {}, "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg=="], + + "package-manager-detector": ["package-manager-detector@1.8.0", "", {}, "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A=="], + "papaparse": ["papaparse@5.5.4", "", {}, "sha512-SwzWD9gl/ElwYLCI0nUja1mFJzjq2D8ziShfNBa7zCHzkOozeOGDwHWQ+tvCzEZcewecWZ5U7kUopDnG+DFYEQ=="], + "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], + "parse5": ["parse5@8.0.1", "", { "dependencies": { "entities": "^8.0.0" } }, "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw=="], "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], @@ -716,22 +1347,36 @@ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], + "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], + "playwright": ["playwright@1.62.0", "", { "dependencies": { "playwright-core": "1.62.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw=="], "playwright-core": ["playwright-core@1.62.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA=="], "postcss": ["postcss@8.5.25", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw=="], + "preact": ["preact@10.29.8", "", { "peerDependencies": { "preact-render-to-string": ">=5" }, "optionalPeers": ["preact-render-to-string"] }, "sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q=="], + + "preact-render-to-string": ["preact-render-to-string@6.7.0", "", { "peerDependencies": { "preact": ">=10 || >= 11.0.0-0" } }, "sha512-Z4WR8fmLMRpdYqJ9i7vrlXSsSrxVJydwrkEXHapexfARbWfGb7vGcnvNQnIzN0cXciMVOlz/XLoiMCi9gUsy9Q=="], + "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], "pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="], + "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], + + "process-ancestry": ["process-ancestry@0.1.0", "", {}, "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg=="], + "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], + "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="], + "protobufjs": ["protobufjs@7.6.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw=="], "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], @@ -744,6 +1389,8 @@ "quickjs-emscripten-core": ["quickjs-emscripten-core@0.32.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.32.0" } }, "sha512-QFnPfjFey8EqknSrSxe1hZrf1/8z7/6s1QzGOmKo6++02r7QRRX7ZoyNaZh7JuVjWsVW87KnQrbZqnHkOAzUyg=="], + "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], + "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], "re2js": ["re2js@1.4.0", "", {}, "sha512-KTOIcZTSOpOxbu3i0+T6mFQ6tkxXKlTxfcMFs1trQbsMnG84qNq+DjXr8Afu+FEFjvF1NNlldpC7roPyazFI8g=="], @@ -754,12 +1401,40 @@ "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], + "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + "readdirp": ["readdirp@5.1.1", "", {}, "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA=="], + "redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="], + "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], + + "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], + + "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], + + "rehype-raw": ["rehype-raw@7.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-raw": "^9.0.0", "vfile": "^6.0.0" } }, "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww=="], + + "rehype-sanitize": ["rehype-sanitize@6.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-sanitize": "^5.0.0" } }, "sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg=="], + + "remark-breaks": ["remark-breaks@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-newline-to-break": "^2.0.0", "unified": "^11.0.0" } }, "sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ=="], + + "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], + + "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], + + "remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="], + + "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "retext-smartypants": ["retext-smartypants@6.2.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ=="], + "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], "rolldown": ["rolldown@1.1.5", "", { "dependencies": { "@oxc-project/types": "=0.139.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.1.5", "@rolldown/binding-darwin-arm64": "1.1.5", "@rolldown/binding-darwin-x64": "1.1.5", "@rolldown/binding-freebsd-x64": "1.1.5", "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", "@rolldown/binding-linux-arm64-gnu": "1.1.5", "@rolldown/binding-linux-arm64-musl": "1.1.5", "@rolldown/binding-linux-ppc64-gnu": "1.1.5", "@rolldown/binding-linux-s390x-gnu": "1.1.5", "@rolldown/binding-linux-x64-gnu": "1.1.5", "@rolldown/binding-linux-x64-musl": "1.1.5", "@rolldown/binding-openharmony-arm64": "1.1.5", "@rolldown/binding-wasm32-wasi": "1.1.5", "@rolldown/binding-win32-arm64-msvc": "1.1.5", "@rolldown/binding-win32-x64-msvc": "1.1.5" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA=="], @@ -768,13 +1443,19 @@ "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "satteri": ["satteri@0.9.5", "", { "dependencies": { "@types/estree-jsx": "^1.0.5", "@types/hast": "^3.0.4", "@types/mdast": "^4.0.4", "@types/unist": "^3.0.3" }, "optionalDependencies": { "@bruits/satteri-darwin-arm64": "0.9.5", "@bruits/satteri-darwin-x64": "0.9.5", "@bruits/satteri-linux-arm64-gnu": "0.9.5", "@bruits/satteri-linux-arm64-musl": "0.9.5", "@bruits/satteri-linux-x64-gnu": "0.9.5", "@bruits/satteri-linux-x64-musl": "0.9.5", "@bruits/satteri-wasm32-wasi": "0.9.5", "@bruits/satteri-win32-arm64-msvc": "0.9.5", "@bruits/satteri-win32-x64-msvc": "0.9.5" } }, "sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w=="], + + "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="], + "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="], "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], "seek-bzip": ["seek-bzip@2.0.0", "", { "dependencies": { "commander": "^6.0.0" }, "bin": { "seek-bunzip": "bin/seek-bunzip", "seek-table": "bin/seek-bzip-table" } }, "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg=="], - "semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="], + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + + "sharp": ["sharp@0.35.3", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.5" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.3", "@img/sharp-darwin-x64": "0.35.3", "@img/sharp-freebsd-wasm32": "0.35.3", "@img/sharp-libvips-darwin-arm64": "1.3.2", "@img/sharp-libvips-darwin-x64": "1.3.2", "@img/sharp-libvips-linux-arm": "1.3.2", "@img/sharp-libvips-linux-arm64": "1.3.2", "@img/sharp-libvips-linux-ppc64": "1.3.2", "@img/sharp-libvips-linux-riscv64": "1.3.2", "@img/sharp-libvips-linux-s390x": "1.3.2", "@img/sharp-libvips-linux-x64": "1.3.2", "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", "@img/sharp-libvips-linuxmusl-x64": "1.3.2", "@img/sharp-linux-arm": "0.35.3", "@img/sharp-linux-arm64": "0.35.3", "@img/sharp-linux-ppc64": "0.35.3", "@img/sharp-linux-riscv64": "0.35.3", "@img/sharp-linux-s390x": "0.35.3", "@img/sharp-linux-x64": "0.35.3", "@img/sharp-linuxmusl-arm64": "0.35.3", "@img/sharp-linuxmusl-x64": "0.35.3", "@img/sharp-webcontainers-wasm32": "0.35.3", "@img/sharp-win32-arm64": "0.35.3", "@img/sharp-win32-ia32": "0.35.3", "@img/sharp-win32-x64": "0.35.3" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -782,22 +1463,34 @@ "shell-quote": ["shell-quote@1.9.0", "", {}, "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA=="], + "shiki": ["shiki@4.3.1", "", { "dependencies": { "@shikijs/core": "4.3.1", "@shikijs/engine-javascript": "4.3.1", "@shikijs/engine-oniguruma": "4.3.1", "@shikijs/langs": "4.3.1", "@shikijs/themes": "4.3.1", "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw=="], + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "simple-code-frame": ["simple-code-frame@1.3.0", "", { "dependencies": { "kolorist": "^1.6.0" } }, "sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w=="], + "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="], "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + "smol-toml": ["smol-toml@1.7.1", "", {}, "sha512-PPlsspAZ4jbMBu5DMFhfUGDQLu/vrL4SyBROVS37x8ynnVmFIs1VPBz1Co8Xks3TvpIaZXmU85y4DrQ+UyVFoQ=="], + "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], "sql.js": ["sql.js@1.14.1", "", {}, "sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A=="], + "stack-trace": ["stack-trace@1.0.0", "", {}, "sha512-H6D7134xi6qONvh7ZHKgviXf+rd3vhGBSvebPZCaUkd8zvQ+7PtDw6CljPTe4cXWNf2IKZGNqw6VJXSb9IgBpA=="], + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], @@ -806,6 +1499,8 @@ "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], @@ -816,16 +1511,28 @@ "strtok3": ["strtok3@10.3.5", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA=="], + "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="], + + "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], + "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + "svelte": ["svelte@5.56.8", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.10", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.8.1", "esm-env": "^1.2.1", "esrap": "^2.2.12", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-PY8LOw7xP6c8IOiVqdo0sbbZVYhXRSfklOQLAUyGBKqjTX0wx/z4l/9J+PmBpmlLnxzEb1NqltxQ5/wZme/Cmg=="], + + "svgo": ["svgo@4.0.2", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng=="], + "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="], "tar-fs": ["tar-fs@2.1.5", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw=="], "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], + "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + "tinyclip": ["tinyclip@0.1.15", "", {}, "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A=="], + "tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="], "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], @@ -846,6 +1553,10 @@ "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + + "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -858,22 +1569,60 @@ "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], + "ufo": ["ufo@1.6.4", "", {}, "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA=="], + "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], + "ultrahtml": ["ultrahtml@1.7.0", "", {}, "sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g=="], + + "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], + "undici": ["undici@8.9.0", "", {}, "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA=="], "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], + "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], + + "unifont": ["unifont@0.7.4", "", { "dependencies": { "css-tree": "^3.1.0", "ofetch": "^1.5.1", "ohash": "^2.0.11" } }, "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg=="], + + "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], + + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + + "unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="], + + "update-browserslist-db": ["update-browserslist-db@1.3.0", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA=="], + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], "uuid": ["uuid@14.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew=="], + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + + "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="], + + "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + "vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="], + "vite-prerender-plugin": ["vite-prerender-plugin@0.5.13", "", { "dependencies": { "kolorist": "^1.8.0", "magic-string": "0.x >= 0.26.0", "node-html-parser": "^6.1.12", "simple-code-frame": "^1.3.0", "source-map": "^0.7.4", "stack-trace": "^1.0.0-pre2" }, "peerDependencies": { "vite": "5.x || 6.x || 7.x || 8.x" } }, "sha512-IKSpYkzDBsKAxa05naRbj7GvNVMSdww/Z/E89oO3xndz+gWnOBOKOAbEXv7qDhktY/j3vHgJmoV1pPzqU2tx9g=="], + + "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="], + "vitest": ["vitest@4.1.10", "", { "dependencies": { "@vitest/expect": "4.1.10", "@vitest/mocker": "4.1.10", "@vitest/pretty-format": "4.1.10", "@vitest/runner": "4.1.10", "@vitest/snapshot": "4.1.10", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.10", "@vitest/browser-preview": "4.1.10", "@vitest/browser-webdriverio": "4.1.10", "@vitest/coverage-istanbul": "4.1.10", "@vitest/coverage-v8": "4.1.10", "@vitest/ui": "4.1.10", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw=="], "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="], + "wasm-git": ["wasm-git@0.0.17", "", {}, "sha512-eAWLe2BQrx23t9jjffV5BkwbVW1c9nfUh4KDzPgMMKynNPGGTqztGYuJZY0x60hyO6clIn4eFUNkFnY535XtHw=="], + + "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], + "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], "webidl-conversions": ["webidl-conversions@8.0.1", "", {}, "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ=="], @@ -898,46 +1647,134 @@ "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="], + "xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="], + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], "yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], "yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], - "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], + + "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="], + + "zod": ["zod@4.2.0", "", {}, "sha512-Bd5fw9wlIhtqCCxotZgdTOMwGm1a0u75wARVEY9HMs1X17trvA/lMi4+MGK5EUfYkXVTbX8UDiDKW4OgzHVUZw=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + "@aws-sdk/credential-provider-http/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.12", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-dWW5KRt4mnEvjNzbGqGeCuAvgum85Y9ZoyuMQqcTEfapndyVJ1k9BEHK7kdXJZ32enyRmmwcFjMwlB/KgLKI3Q=="], "@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1097.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.2", "@aws-sdk/nested-clients": "^3.997.37", "@aws-sdk/types": "^3.974.2", "@smithy/core": "^3.29.8", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-EIsdmy/f5IGc5r01RjKWNvrbBra6z0xudQM0D6Wf8DeGuPoRlubkLqr7VgWijFucO4kg0mtev9H3RX/ZOubUhg=="], "@aws-sdk/nested-clients/@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.12", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-dWW5KRt4mnEvjNzbGqGeCuAvgum85Y9ZoyuMQqcTEfapndyVJ1k9BEHK7kdXJZ32enyRmmwcFjMwlB/KgLKI3Q=="], + "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@bruits/satteri-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], + + "@bruits/satteri-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + + "@earendil-works/pi-coding-agent/semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="], + "@earendil-works/pi-coding-agent/undici": ["undici@8.5.0", "", {}, "sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg=="], + "@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + + "@mistralai/mistralai/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "@modelcontextprotocol/client/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "@modelcontextprotocol/core/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "@modelcontextprotocol/server/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "@preact/preset-vite/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "@prefresh/vite/@rollup/pluginutils": ["@rollup/pluginutils@4.2.1", "", { "dependencies": { "estree-walker": "^2.0.1", "picomatch": "^2.2.2" } }, "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ=="], + "@riftydev/runtime-js/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "@rolldown/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], + + "@rolldown/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + "@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="], "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], + "@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "@vitest/mocker/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "@vitest/snapshot/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + + "@vue/compiler-sfc/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + + "astro/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], + "data-urls/whatwg-url": ["whatwg-url@16.0.1", "", { "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", "webidl-conversions": "^8.0.1" } }, "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw=="], + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + + "hast-util-raw/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + "just-bash/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], "just-bash/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="], + "node-abi/semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="], + "p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], "rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], + "seek-bzip/commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="], + "strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "svelte/aria-query": ["aria-query@5.3.1", "", {}, "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g=="], + + "svelte/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "vite-prerender-plugin/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "vitest/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "@bruits/satteri-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + + "@prefresh/vite/@rollup/pluginutils/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + + "@rolldown/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + + "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], + + "hast-util-from-html/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + + "hast-util-raw/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], } } diff --git a/cli/flect-client.test.ts b/cli/flect-client.test.ts new file mode 100644 index 0000000..6b87ba2 --- /dev/null +++ b/cli/flect-client.test.ts @@ -0,0 +1,165 @@ +import { mkdtemp } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { assert, describe, it, vi } from "@effect/vitest"; +import { Effect, Stream } from "effect"; +import { + makeControlToken, + writeControlDescriptor, +} from "../server/control-descriptor"; +import { + FlectWorkspaceEvent, + SetMode, + UserCommandSource, +} from "../shared/control"; +import { ControlDescriptor } from "../shared/control-channel"; +import { + FlectControlClient, + makeFlectControlClientLayer, +} from "./flect-client"; + +describe("FlectControlClient", () => { + it.effect( + "discovers the private descriptor without exposing its bearer", + () => + Effect.gen(function* () { + const directory = yield* Effect.promise(() => + mkdtemp(join(tmpdir(), "flect-client-test-")), + ); + const token = makeControlToken(); + yield* writeControlDescriptor( + ControlDescriptor.make({ + version: 1, + instanceId: "instance-client-test", + workspaceId: "workspace-client-test", + url: "http://127.0.0.1:43127", + token, + pid: process.pid, + createdAt: 1, + }), + directory, + ); + const fetcher = vi.fn().mockImplementation(() => + Promise.resolve( + new Response( + JSON.stringify({ + status: "succeeded", + receipt: { + version: 1, + commandId: "cmd-client-test-response", + workspaceId: "workspace-client-test", + operationId: "operation-client-test", + sequence: 2, + status: "completed", + }, + }), + { + headers: { "content-type": "application/json" }, + }, + ), + ), + ); + + return yield* Effect.gen(function* () { + const client = yield* FlectControlClient; + const receipt = yield* client.command( + SetMode.make({ type: "set-mode", mode: "run" }), + ); + const [input, init] = fetcher.mock.calls[0] ?? []; + const body = JSON.parse(String(init?.body)) as { + readonly source: { + readonly kind: string; + readonly clientName: string; + }; + readonly command: { readonly type: string }; + }; + + assert.strictEqual( + String(input), + "http://127.0.0.1:43127/v1/workspaces/workspace-client-test/commands", + ); + assert.strictEqual( + new Headers(init?.headers).get("authorization"), + `Bearer ${token}`, + ); + assert.strictEqual(body.source.kind, "control"); + assert.strictEqual(body.source.clientName, "Outside test"); + assert.strictEqual(body.command.type, "set-mode"); + assert.strictEqual(receipt.operationId, "operation-client-test"); + assert.isFalse(JSON.stringify(receipt).includes(token)); + + yield* client.disable; + const [, disableInit] = fetcher.mock.calls[1] ?? []; + const disableBody = JSON.parse(String(disableInit?.body)) as { + readonly command: { readonly type: string }; + }; + assert.strictEqual(disableBody.command.type, "disable-control"); + }).pipe( + Effect.provide( + makeFlectControlClientLayer({ + stateDirectory: directory, + clientName: "Outside test", + clientId: "client-client-test", + fetch: fetcher, + }), + ), + ); + }), + ); + + it.effect("strictly decodes the authenticated SSE event stream", () => + Effect.gen(function* () { + const directory = yield* Effect.promise(() => + mkdtemp(join(tmpdir(), "flect-client-events-test-")), + ); + yield* writeControlDescriptor( + ControlDescriptor.make({ + version: 1, + instanceId: "instance-client-events", + workspaceId: "workspace-client-test", + url: "http://127.0.0.1:43129", + token: makeControlToken(), + pid: process.pid, + createdAt: 1, + }), + directory, + ); + const event = FlectWorkspaceEvent.make({ + version: 1, + id: "event-client-test", + sequence: 3, + timestamp: 3, + workspaceId: "workspace-client-test", + source: UserCommandSource.make({ kind: "user" }), + type: "state-changed", + }); + const fetcher = vi.fn().mockResolvedValue( + new Response(`id: 3\ndata: ${JSON.stringify(event)}\n\n`, { + headers: { "content-type": "text/event-stream" }, + }), + ); + + return yield* Effect.gen(function* () { + const client = yield* FlectControlClient; + const events = yield* client + .events(2) + .pipe(Stream.take(1), Stream.runCollect); + + assert.strictEqual(events.length, 1); + assert.strictEqual(events[0]?.sequence, 3); + assert.isTrue( + String(fetcher.mock.calls[0]?.[0]).endsWith( + "/v1/workspaces/workspace-client-test/events?after=2", + ), + ); + }).pipe( + Effect.provide( + makeFlectControlClientLayer({ + stateDirectory: directory, + fetch: fetcher, + }), + ), + ); + }), + ); +}); diff --git a/cli/flect-client.ts b/cli/flect-client.ts new file mode 100644 index 0000000..d8f7e4b --- /dev/null +++ b/cli/flect-client.ts @@ -0,0 +1,299 @@ +import { Context, Effect, Layer, Schema, type SchemaAST, Stream } from "effect"; +import { + type ControlDescriptorError, + readControlDescriptor, +} from "../server/control-descriptor"; +import { + ControlCommandSource, + DisableControl, + type FlectCommand, + FlectCommandEnvelope, + type FlectCommandError, + type FlectCommandReceipt, + FlectWorkspaceEvent, + FlectWorkspaceSnapshot, +} from "../shared/control"; +import { + ControlBrokerStatus, + ControlCommandOutcome, + ControlLogsResponse, +} from "../shared/control-channel"; + +const strictOptions: SchemaAST.ParseOptions = { + errors: "all", + onExcessProperty: "error", +}; + +export class FlectControlClientError extends Schema.TaggedErrorClass()( + "FlectControlClientError", + { + reason: Schema.Literals([ + "unavailable", + "unauthorized", + "invalid-response", + ]), + message: Schema.String.check( + Schema.isMinLength(1), + Schema.isMaxLength(240), + ), + }, +) {} + +const clientError = ( + reason: FlectControlClientError["reason"], + message: string, +) => FlectControlClientError.make({ reason, message }); + +export interface FlectControlClientShape { + readonly status: Effect.Effect< + ControlBrokerStatus, + FlectControlClientError | ControlDescriptorError + >; + readonly inspect: Effect.Effect< + FlectWorkspaceSnapshot, + FlectControlClientError | ControlDescriptorError + >; + readonly logs: Effect.Effect< + ControlLogsResponse, + FlectControlClientError | ControlDescriptorError + >; + readonly events: ( + after?: number, + ) => Stream.Stream< + FlectWorkspaceEvent, + FlectControlClientError | ControlDescriptorError + >; + readonly command: ( + command: FlectCommand, + expectedSequence?: number, + ) => Effect.Effect< + FlectCommandReceipt, + FlectCommandError | FlectControlClientError | ControlDescriptorError + >; + readonly disable: Effect.Effect< + void, + FlectCommandError | FlectControlClientError | ControlDescriptorError + >; +} + +export class FlectControlClient extends Context.Service< + FlectControlClient, + FlectControlClientShape +>()("flect/FlectControlClient") {} + +export interface FlectControlClientOptions { + readonly stateDirectory?: string; + readonly clientName?: string; + readonly clientId?: string; + readonly fetch?: typeof fetch; +} + +const sseData = async function* ( + body: ReadableStream, +): AsyncGenerator { + const reader = body.getReader(); + const decoder = new TextDecoder(); + let buffer = ""; + let data: Array = []; + try { + while (true) { + const part = await reader.read(); + buffer += decoder.decode(part.value, { stream: !part.done }); + let newline = buffer.indexOf("\n"); + while (newline >= 0) { + const raw = buffer.slice(0, newline); + buffer = buffer.slice(newline + 1); + const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw; + if (line.length === 0) { + if (data.length > 0) { + yield JSON.parse(data.join("\n")) as unknown; + data = []; + } + } else if (line.startsWith("data:")) { + data.push(line.slice(5).trimStart()); + } + newline = buffer.indexOf("\n"); + } + if (part.done) { + break; + } + } + if (data.length > 0) { + yield JSON.parse(data.join("\n")) as unknown; + } + } finally { + reader.releaseLock(); + } +}; + +export const makeFlectControlClientLayer = ( + options: FlectControlClientOptions = {}, +) => + Layer.effect( + FlectControlClient, + Effect.gen(function* () { + const clientName = options.clientName ?? "flect"; + const clientId = options.clientId ?? `client-${crypto.randomUUID()}`; + const fetcher = options.fetch ?? globalThis.fetch; + + const execute = Effect.fn("Flect.ControlClient.execute")(function* ( + path: string, + init: RequestInit = {}, + ) { + const descriptor = yield* readControlDescriptor(options.stateDirectory); + const response = yield* Effect.tryPromise({ + try: (signal) => + fetcher(`${descriptor.url}${path}`, { + ...init, + signal, + headers: { + ...init.headers, + authorization: `Bearer ${descriptor.token}`, + }, + }), + catch: () => + clientError("unavailable", "Flect local control is unavailable."), + }); + if (response.status === 401) { + return yield* Effect.fail( + clientError( + "unauthorized", + "Flect local control authorization was revoked.", + ), + ); + } + return response; + }); + + const decode = ( + schema: Schema.ConstraintDecoder, + response: Response, + ) => + Effect.tryPromise({ + try: () => response.json(), + catch: () => + clientError( + "invalid-response", + "Flect returned an invalid control response.", + ), + }).pipe( + Effect.flatMap((input) => + Schema.decodeUnknownEffect( + schema, + strictOptions, + )(input).pipe( + Effect.mapError(() => + clientError( + "invalid-response", + "Flect returned an invalid control response.", + ), + ), + ), + ), + ); + + const status = execute("/v1/status").pipe( + Effect.flatMap((response) => decode(ControlBrokerStatus, response)), + ); + + const workspacePath = readControlDescriptor(options.stateDirectory).pipe( + Effect.map( + (descriptor) => + `/v1/workspaces/${encodeURIComponent(descriptor.workspaceId)}`, + ), + ); + + const inspect = workspacePath.pipe( + Effect.flatMap(execute), + Effect.flatMap((response) => decode(FlectWorkspaceSnapshot, response)), + ); + + const logs = workspacePath.pipe( + Effect.flatMap((path) => execute(`${path}/logs`)), + Effect.flatMap((response) => decode(ControlLogsResponse, response)), + ); + + const events = (after = 0) => + Stream.unwrap( + workspacePath.pipe( + Effect.flatMap((path) => + execute(`${path}/events?after=${Math.max(0, after)}`), + ), + Effect.flatMap((response) => + response.ok && response.body !== null + ? Effect.succeed( + Stream.fromAsyncIterable(sseData(response.body), () => + clientError( + "invalid-response", + "Flect returned an invalid event stream.", + ), + ).pipe( + Stream.mapEffect((input) => + Schema.decodeUnknownEffect( + FlectWorkspaceEvent, + strictOptions, + )(input).pipe( + Effect.mapError(() => + clientError( + "invalid-response", + "Flect returned an invalid event.", + ), + ), + ), + ), + ), + ) + : Effect.fail( + clientError( + "unavailable", + "Flect event streaming is unavailable.", + ), + ), + ), + ), + ); + + const command = Effect.fn("Flect.ControlClient.command")(function* ( + value: FlectCommand, + expectedSequence?: number, + ) { + if (value.type === "enable-control") { + return yield* Effect.fail( + clientError( + "unauthorized", + "Outside clients cannot enable Flect control.", + ), + ); + } + const descriptor = yield* readControlDescriptor(options.stateDirectory); + const commandPath = `/v1/workspaces/${encodeURIComponent(descriptor.workspaceId)}/commands`; + const envelope = FlectCommandEnvelope.make({ + version: 1, + commandId: `cmd-${crypto.randomUUID()}`, + workspaceId: descriptor.workspaceId, + source: ControlCommandSource.make({ + kind: "control", + clientId, + clientName, + }), + ...(expectedSequence === undefined ? {} : { expectedSequence }), + command: value, + }); + const response = yield* execute(commandPath, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify(envelope), + }); + const outcome = yield* decode(ControlCommandOutcome, response); + return outcome.status === "succeeded" + ? outcome.receipt + : yield* Effect.fail(outcome.error); + }); + + const disable = command( + DisableControl.make({ type: "disable-control" }), + ).pipe(Effect.asVoid); + + return { status, inspect, logs, events, command, disable }; + }), + ); diff --git a/cli/flect.test.ts b/cli/flect.test.ts new file mode 100644 index 0000000..414651b --- /dev/null +++ b/cli/flect.test.ts @@ -0,0 +1,96 @@ +import { assert, describe, it, vi } from "@effect/vitest"; +import { Effect, Layer, Stream } from "effect"; +import { ControlUnauthorized } from "../shared/control"; +import { ControlBrokerStatus } from "../shared/control-channel"; +import { + FlectCommandGateway, + type FlectCommandGatewayShape, +} from "../src/axi/gateway"; +import { type FlectCliIo, runFlectCli } from "./flect"; + +const makeHarness = (stdin = "") => { + const stdout: Array = []; + const stderr: Array = []; + const launch = vi.fn(async () => undefined); + const command = vi.fn(() => + Effect.fail( + ControlUnauthorized.make({ message: "Test command boundary reached." }), + ), + ); + const layer = Layer.succeed(FlectCommandGateway)({ + audience: "native", + bin: "flect", + status: Effect.succeed( + ControlBrokerStatus.make({ + version: 1, + enabled: false, + connected: false, + port: 43128, + url: "http://127.0.0.1:43128", + }), + ), + inspect: Effect.die("unused"), + logs: Effect.die("unused"), + events: () => Stream.empty, + command, + }); + const io: FlectCliIo = { + readStdin: async () => stdin, + stdout: (value) => stdout.push(value), + stderr: (value) => stderr.push(value), + launch, + }; + return { command, io, launch, layer, stderr, stdout }; +}; + +describe("flect CLI adapter", () => { + it.effect("writes one TOON home result and no stderr", () => { + const harness = makeHarness(); + return Effect.gen(function* () { + const code = yield* runFlectCli([], harness.io); + assert.strictEqual(code, 0); + assert.strictEqual(harness.stdout.length, 1); + assert.include(harness.stdout[0] ?? "", "control: disabled"); + assert.deepStrictEqual(harness.stderr, []); + }).pipe(Effect.provide(harness.layer)); + }); + + it.effect("materializes --stdin before sending a Shaper command", () => { + const harness = makeHarness("Make the dashboard denser\n"); + return Effect.gen(function* () { + const code = yield* runFlectCli(["shape", "--stdin"], harness.io); + assert.strictEqual(code, 1); + assert.strictEqual(harness.command.mock.calls.length, 1); + const sent = harness.command.mock.calls[0]?.[0]; + assert.strictEqual(sent?.type, "submit-shaper-instruction"); + assert.strictEqual( + sent?.type === "submit-shaper-instruction" ? sent.instruction : "", + "Make the dashboard denser", + ); + assert.include(harness.stdout[0] ?? "", "code: unauthorized"); + assert.deepStrictEqual(harness.stderr, []); + }).pipe(Effect.provide(harness.layer)); + }); + + it.effect("opens the graphical app through the native adapter", () => { + const harness = makeHarness(); + return Effect.gen(function* () { + const code = yield* runFlectCli(["app"], harness.io); + assert.strictEqual(code, 0); + assert.strictEqual(harness.launch.mock.calls.length, 1); + }).pipe(Effect.provide(harness.layer)); + }); + + it.effect("keeps usage errors structured on stdout", () => { + const harness = makeHarness(); + return Effect.gen(function* () { + const code = yield* runFlectCli( + ["--json", "mode", "guardian"], + harness.io, + ); + assert.strictEqual(code, 2); + assert.include(harness.stdout[0] ?? "", '"code":"invalid-argument"'); + assert.deepStrictEqual(harness.stderr, []); + }).pipe(Effect.provide(harness.layer)); + }); +}); diff --git a/cli/flect.ts b/cli/flect.ts new file mode 100644 index 0000000..7e7815e --- /dev/null +++ b/cli/flect.ts @@ -0,0 +1,195 @@ +import { homedir } from "node:os"; +import * as BunFileSystem from "@effect/platform-bun/BunFileSystem"; +import * as BunPath from "@effect/platform-bun/BunPath"; +import { Effect, Layer, Schema } from "effect"; +import { makeBrokerFlectCommandGatewayLayer } from "../src/axi/broker-gateway"; +import { runFlect } from "../src/axi/program"; +import { makeAgentIntegrationLayer } from "../src/lib/agent-integration"; +import { makeShellLinkLayer } from "../src/lib/shell-link"; +import { + flectApplicationPathFromExecutable, + makeUninstallLayer, +} from "../src/lib/uninstall"; +import { makeFlectControlClientLayer } from "./flect-client"; + +export interface FlectCliIo { + readonly readStdin: () => Promise; + readonly stdout: (text: string) => void; + readonly stderr: (text: string) => void; + readonly launch: () => Promise; +} + +export class FlectCliError extends Schema.TaggedErrorClass()( + "FlectCliError", + { + operation: Schema.Literals(["stdin", "launch"]), + message: Schema.String, + }, +) {} + +const defaultIo: FlectCliIo = { + readStdin: () => Bun.stdin.text(), + stdout: (text) => process.stdout.write(text), + stderr: (text) => process.stderr.write(text), + launch: async () => { + const child = Bun.spawn(["open", "-a", "Flect"], { + stdout: "ignore", + stderr: "ignore", + }); + if ((await child.exited) !== 0) { + throw new Error("launch failed"); + } + }, +}; + +const materializeStdin = Effect.fn("Flect.Cli.materializeStdin")(function* ( + argv: ReadonlyArray, + io: FlectCliIo, +) { + const index = argv.indexOf("--stdin"); + if (index < 0) { + return argv; + } + const text = yield* Effect.tryPromise({ + try: io.readStdin, + catch: () => + FlectCliError.make({ + operation: "stdin", + message: "Standard input is unavailable.", + }), + }).pipe(Effect.orElseSucceed(() => "")); + return [...argv.slice(0, index), text.trim(), ...argv.slice(index + 1)]; +}); + +const commandNoun = (argv: ReadonlyArray) => + argv.find((value) => value !== "--json" && value !== "--full"); + +export const runFlectCli = Effect.fn("Flect.Cli.run")(function* ( + argv: ReadonlyArray, + io: FlectCliIo = defaultIo, +) { + const materialized = yield* materializeStdin(argv, io); + if (commandNoun(materialized) === "app") { + yield* Effect.tryPromise({ + try: io.launch, + catch: () => + FlectCliError.make({ + operation: "launch", + message: "The Flect app could not be opened.", + }), + }).pipe(Effect.ignore); + } + const result = yield* runFlect(materialized); + if (result.stdout.length > 0) { + yield* Effect.sync(() => io.stdout(result.stdout)); + } + if (result.stderr.length > 0) { + yield* Effect.sync(() => io.stderr(result.stderr)); + } + return result.exitCode; +}); + +interface PrivateOptions { + readonly argv: ReadonlyArray; + readonly stateDirectory?: string; + readonly clientName?: string; +} + +export interface NativeFlectGatewayOptions { + readonly stateDirectory?: string; + readonly clientName?: string; + readonly bin?: string; + readonly configRoot?: string; + readonly publicExecutable?: string; +} + +export const makeNativeFlectGatewayLayer = ( + options: NativeFlectGatewayOptions = {}, +) => { + const client = makeFlectControlClientLayer({ + stateDirectory: options.stateDirectory, + clientName: options.clientName ?? "flect", + }); + const gateway = makeBrokerFlectCommandGatewayLayer({ + audience: "native", + bin: options.bin ?? "flect", + }).pipe(Layer.provide(client)); + const platform = Layer.merge(BunFileSystem.layer, BunPath.layer); + const integrations = makeAgentIntegrationLayer( + options.configRoot ?? homedir(), + ).pipe(Layer.provide(platform)); + const publicExecutable = + options.publicExecutable ?? process.env.FLECT_PUBLIC_EXECUTABLE; + if (publicExecutable === undefined || !publicExecutable.startsWith("/")) { + return Layer.merge(gateway, integrations); + } + const shell = makeShellLinkLayer({ + home: options.configRoot ?? homedir(), + executable: publicExecutable, + }).pipe(Layer.provide(platform)); + const applicationPath = flectApplicationPathFromExecutable(publicExecutable); + if (applicationPath === undefined) { + return Layer.mergeAll(gateway, integrations, shell); + } + const setup = Layer.merge(integrations, shell); + const uninstall = makeUninstallLayer({ applicationPath }).pipe( + Layer.provide(setup), + ); + return Layer.mergeAll(gateway, setup, uninstall); +}; + +const privateOptions = (argv: ReadonlyArray): PrivateOptions => { + const publicArguments: Array = []; + let stateDirectory: string | undefined; + let clientName: string | undefined; + for (let index = 0; index < argv.length; index += 1) { + const value = argv[index]; + if (value === "--state-dir" || value === "--client-name") { + const option = argv[index + 1]; + if (option !== undefined) { + if (value === "--state-dir") { + stateDirectory = option; + } else { + clientName = option; + } + index += 1; + } else { + publicArguments.push(value); + } + } else if (value !== undefined) { + publicArguments.push(value); + } + } + return { + argv: publicArguments, + ...(stateDirectory === undefined ? {} : { stateDirectory }), + ...(clientName === undefined ? {} : { clientName }), + }; +}; + +export const runFlectCliMain = ( + argv: ReadonlyArray, + io: FlectCliIo = defaultIo, + options: Omit = {}, +) => { + const parsed = privateOptions(argv); + return runFlectCli(parsed.argv, io).pipe( + Effect.provide( + makeNativeFlectGatewayLayer({ + ...options, + stateDirectory: parsed.stateDirectory, + clientName: parsed.clientName ?? options.clientName, + }), + ), + ); +}; + +if (import.meta.main) { + Effect.runPromise( + runFlectCliMain(process.argv.slice(2), defaultIo, { + bin: process.argv[1] ?? "flect", + }), + ).then((code) => { + process.exitCode = code; + }); +} diff --git a/docs/capsule-format.md b/docs/capsule-format.md new file mode 100644 index 0000000..449a00c --- /dev/null +++ b/docs/capsule-format.md @@ -0,0 +1,288 @@ +# `.flect` capsule format + +Status: version 1 + +A `.flect` file is a deterministic, offline-installable product-interface +artifact. Every Flect host uses this contract. A capsule is data: decoding it +does not execute code, grant capabilities, authenticate a product, or activate +an interface. + +## Archive + +The container is an uncompressed POSIX `ustar` archive. It has normalized +ownership, permissions, and timestamps. `flect.json` is the first entry. Every +payload follows in bytewise lexical path order, then two zero blocks. Identical +manifest input and payload bytes must produce byte-identical archives. + +Version 1 permits at most 256 payload files, 8 MiB per file, and 32 MiB for the +complete archive. Paths are relative slash-separated names of at most 100 UTF-8 +bytes. Absolute paths, empty components, `.`/`..`, `.git`, links, devices, +duplicate entries, extra archive data, and unsupported tar entry types are +invalid. + +## Manifest + +`flect.json` is strict UTF-8 JSON. Unknown fields are invalid. + +- `formatVersion`: `1`. +- `id`, `name`, `version`: stable reverse-domain identifier, display name, and + semantic artifact version. +- `entrypoints`: stable identifiers and payload paths for compiled web entry + documents. +- `files`: path, byte count, and lowercase SHA-256 for every payload, in archive + order. +- `capabilities`: requested capability identifiers and whether the product + considers each required. These are requests, never grants. +- optional `extensions`: bounded portable App Agent and Shaper extension + packages described below. Declarations are requests and inert metadata; + decoding never activates them. +- `compatibility`: supported Flect range, capsule schema version, and platforms. +- `provenance`: publisher label, source reference, source revision, and builder. +- optional `build`: the exact source revision plus SHA-256 input, artifact, and + optional verified dependency-graph digests for a restricted source build. +- optional `lineage`: a local-fork marker binding the parent signed-content + digest, source, and revision. Forking deliberately removes upstream + signatures. +- `signatures`: detached Ed25519 records containing the publisher key ID, + canonical signed-content SHA-256, UTC signing time, and signature. Presence or + validity establishes provenance only; it never grants a capability. + +Every entrypoint must name a declared payload. Every payload byte count and hash +is verified before a decoder returns a capsule. + +## Portable extension packages + +Version 1 may declare at most 32 portable packages. A package contains a stable +ID, display name, description, semantic version, verified bundle path, one or +both target roles (`app`, `shaper`), compatible Flect range, portable Extension +API version `1`, supported hosts, requested capabilities, bounded public +instructions, command/tool discovery metadata, host-capped resources, and +publisher/source/revision provenance. Guardian is not a package role. + +Each bundle is a declared capsule payload and its lowercase SHA-256 must match +the package provenance record. An optional source map must likewise name a +declared payload and match its declared digest. Duplicate package, role, +capability, command, or tool IDs are invalid. Missing bundles, mismatched +digests, unsupported API versions, excessive resource requests, and unknown +fields fail capsule decoding before any code can run. + +The package resource declaration cannot exceed 100 ms execution time, 16 MiB +memory, 1 MiB input, 1 MiB output, or 20 inert intents per call. Hosts may apply +stricter limits. The verified executable bundle is capped at 256 KiB, matching +the worker request boundary; a larger bundle is rejected during capsule +verification rather than staged as an unusable package. These values are +ceilings, not authority. + +Packages contain no grants, decisions, credentials, conversations, local paths, +or mutable installation state. Installation review and role activation remain +protected host decisions. Portable bundles execute only through Flect's +QuickJS worker and capability broker; ordinary external Pi extensions remain a +separate explicitly trusted host-code path. The lifecycle and isolation design +is recorded in +[`docs/superpowers/specs/2026-08-02-flect-portable-extension-lifecycle-design.md`](superpowers/specs/2026-08-02-flect-portable-extension-lifecycle-design.md). + +## Review and activation + +Import opens a candidate; it never activates the capsule directly. The +protected Flect shell shows the publisher, artifact version, source revision, +signature count, contents, supported platforms, and every requested capability +before activation is available. A capability marked `required` is a hard activation +precondition. Until a trusted broker reports that it can grant that capability, +Flect leaves the isolated preview available for inspection but disables Activate at +the UI boundary and rejects acceptance again in the controller. Optional +capabilities remain ungranted unless a later explicit grant flow says otherwise. + +The protected review projects the canonical requested, available, granted, +denied, expired, or revoked lifecycle together with the separate fact of host +availability. A trusted host may register a stable product operation whose +required capability matches the manifest request. Registration and decisions +remain trusted host state; neither is copied into the archive. + +A decision binds the capsule scope ID, exact archive SHA-256, capability-request +digest, workspace when applicable, provenance revision, and the approved +operation/resource/data intersection and decision policy. Changing the archive, +request, workspace-bound context, or registered limits cannot widen an older +decision. See [`docs/product-capabilities.md`](product-capabilities.md) for the +adopter contract and complete lifecycle. + +The host reconstructs the deterministic capsule with an empty signature array, +hashes those canonical bytes, and verifies the signature over a versioned +domain-separated payload containing that digest, key ID, and signing time. +Protected review distinguishes unsigned, verified, unknown-key, revoked, +expired, changed-after-signing, invalid, and locally-forked states. Host policy +may allow unverified local artifacts, require a valid configured key, or limit +installation to approved keys. Invalid/revoked/changed claims always fail +closed. Key rotation is expressed by validity windows and an optional +replacement key; revocation remains host policy, not mutable capsule state. +The trust decision reports explicitly that permission authority is unchanged. +The host also evaluates the declared semver range against Flect's package +version and checks the actual browser/native platform. An incompatible range or +unsupported host follows the same inspectable-preview, blocked-activation path. + +Portable packages appear in the same protected review but remain visibly +separate from product capabilities and trusted external Pi extensions. Flect +shows package publisher/source/revision, declared roles, resource ceilings, and +required versus optional authority. App Agent and Shaper start off +independently. Each is enabled only by an explicit protected action, and +optional authority is off by default. An enabled candidate must complete one +bounded worker test before activation; a failed candidate must be disabled or fixed +before acceptance. The controller repeats this check even if customized UI is +bypassed. + +Pins and local-fork revision markers survive as update conflicts. A raw update +to the single primary app is never silently combined: the user either accepts +the upstream archive or keeps the current fork. Provider-neutral shared sources +add the guarded personal-fork lifecycle on top of capsule artifacts: immutable +base, upstream, and fork Git refs drive a deterministic three-way file merge; +overlapping edits become explicit conflict paths and require a reviewed +resolution. Flect never silently combines or relabels package bytes. + +Removing a shared source first detaches only that source's installed parts and +preserves its personal fork for export. Deleting local data is a separate, +guarded action that is refused while the source is installed. The primary +capsule store likewise removes only archives named by its strict binding file; +unknown files, unrelated Git history, workspace documents, grants, and other +storage namespaces are not deletion targets. Corrupt bindings fail closed +instead of broadening cleanup. + +## Runtime intents + +Compiled entrypoints have no network authority. Their only host bridge is +`globalThis.flect.post(...)` over an opaque-frame `MessagePort`. Each projected +document receives a new 128-bit cryptographic nonce; the host accepts the +ready/connect handshake only when its protocol version, type, and nonce all +match. The nonce authenticates the frame instance while the transferred port +becomes the bounded capability channel. Unrelated window messages, stale +frames, surplus pending ports, and late traffic are ignored or failed closed. +Version 1 accepts JSON-only intents of this shape: + +```json +{ + "version": 1, + "type": "intent", + "id": "intent-projects1", + "action": "projects.list", + "input": { "limit": 20 } +} +``` + +The action is a stable host-registered operation ID, not a URL or tool name. +Flect constructs a capsule-bound command source, verifies that the current +accepted or candidate capsule declares the operation's capability, applies the +host grant, and invokes the protected adapter through the shared workspace +controller. A matching `flect:host` custom event returns either bounded JSON +output or one sanitized `unavailable`, `denied`, `failed`, or `invalid-result` +failure. The complete message is limited to 64 KiB and must repeat the intent +ID. Malformed, oversized, flooding, stale-frame, and mismatched replies fail +closed. Credentials, transport exceptions, response cookies, and unapproved +headers are not representable in this protocol. A source that misses the +bounded ready deadline is stopped without poisoning a later capsule revision. + +## Compiled asset projection + +For a compiled HTML entrypoint, Flect resolves capsule-relative stylesheet, +classic script, image, poster, font, audio, video, and CSS `url(...)` references +only against verified files in the same archive. Text assets are decoded as +strict UTF-8; binary assets become bounded `data:` URLs. Stylesheets and classic +scripts are inlined into one generated document, so the opaque frame needs no +host filesystem, object URL, package registry, CDN, or network access. Missing, +remote, malformed, and unsupported references remain unavailable under the +frame's deny-by-default CSP. + +Browser hosts load that exact document from a self-contained base64 `data:` +URL. The packaged Tauri host keeps it only in a bounded in-memory registry and +serves the exact token through the local `flect-capsule` custom protocol with +`no-store`, no-referrer, and no-sniff response policy. This is an internal +process transport, not network authority or persisted capsule state. It avoids +weakening the protected host's CSP when WebKit applies the parent policy to +inline scripts in `srcdoc` or `data:` frames. Native registration accepts only +128-bit hexadecimal tokens, at most eight live documents, and at most 16 MiB +per generated document; release removes the exact token. Missing and unknown +tokens return no document. + +Both routes execute the document in an iframe sandbox that grants scripts but +not same-origin authority. The child keeps its own deny-by-default CSP, and the +Tauri shell does not add `unsafe-inline`. The host canvas supplies a readable +light baseline for unstyled portable products without changing authored +styles. The archive limits above remain the canonical product-artifact limits; +the native document limits bound only the generated projection transport. + +This is an artifact runtime, not the source builder. The restricted +`BrowserBuild` service compiles browser-local JavaScript, TypeScript, JSX/TSX, +React, and local CSS in a disposable Worker from an exact guarded Git proposal. +Its package resolver produces and caches an integrity-bearing npm v3 lock. A +successful framework capsule records source revision, input digest, artifact +digest, and optional dependency-graph digest in its `build` receipt, then ships +only the portable HTML shell, verified build outputs, and inert import report. +It does not ship source or require the builder at runtime. Import maps, +`srcset`, CSS asset URLs/modules/preprocessors, arbitrary Vite plugins, and +additional framework adapters remain separate compatibility work. + +## URL installation + +The protected actions menu accepts an HTTPS `.flect` URL; loopback HTTP is +allowed only for local development. Flect sends no credentials, bypasses the +HTTP cache, follows ordinary browser redirects/CORS, aborts after 20 seconds, +and bounds both declared and streamed response bytes to 32 MiB. Downloaded +bytes pass through the same strict decoder and payload-hash checks as a local +file, then open the same reviewable candidate. Browser CORS policy is an honest +host boundary: a publisher must make the artifact readable to the user's +browser or the install fails without changing accepted state. + +When the candidate and installed capsule IDs match, the protected review names +the exact installed-to-candidate version transition. The installed archive and +accepted revision remain authoritative until explicit activation; Discard restores the +installed presentation without mutation. A different capsule ID is presented +as an explicit replacement rather than an update. Compatible three-way merging +of a personalized capsule fork is not yet implemented; the separate sharing +fork lifecycle is documented in [`docs/sharing.md`](sharing.md). + +## Project directory import + +The protected actions menu can select an ordinary static-site or standard Vite +browser project directory with one root `index.html`. Flect validates every +relative path before reading source, +ignores `.git`, `node_modules`, `.DS_Store`, `.env` variants, package-manager +auth files, private-key names, and key/certificate extensions before reading +their contents, applies the capsule file/byte limits, and never executes +project source, Vite config, package scripts, or development dependencies +during inspection. Static inputs package directly. A local module entrypoint is +checkpointed as recognizable source in embedded Git and compiled only from the +exact guarded proposal before the resulting artifact enters the same review +and candidate flow. A directory import may contribute at most 255 source files +because Flect reserves one of the capsule's 256 payload entries for the import +report; relative paths share the capsule's 100-character limit. Ambiguous +roots, traversal, reserved metadata collisions, named unsupported Vite plugins, +`resolve.alias`, and `node:` built-ins fail before a candidate is created and +name the portable alternative. + +The versioned compatibility report identifies the project class, root +entrypoint, included-file count, ignored paths, adaptations, forms, remote +URLs, storage, and workers. It is carried as inert capsule metadata and shown +in protected review together with the build receipt. +Unsupported authority/runtime assumptions become visible manifest requests and +required ones block activation. Multi-page routing, archive/Git inputs, +content-aware secret scanning and a complete preserved/adapted/unsupported +per-feature matrix remain open. Supported files +are checkpointed first on the isolated `flect/authoring` branch and flow through +the proposal into `flect/accepted` only on Activate; exported ordinary Git contains +the recognizable `project/` source tree. + +## Prohibited state + +Credentials, tokens, cookies, provider sessions, capability grants, user +conversations, local paths, host settings, mutable runtime state, and recovery +metadata have no representation in version 1. Strict decoding rejects attempts +to add them to the manifest. + +## Migration + +Decoders accept only versions for which they implement an explicit migration. +Version 1 is canonical and has no predecessor. A future version must add a +pure, bounded `N -> N+1` manifest migration, retain integrity verification of +the original archive, document semantic changes, and ship golden fixtures. +Unknown versions fail closed; they are never interpreted as the latest version. + +The executable Effect Schema and codec live in `shared/capsule.ts`. This +document describes that source of truth; tests in `shared/capsule.test.ts` +provide determinism, strictness, and integrity evidence. diff --git a/docs/decisions/0003-astro-activation-shell.md b/docs/decisions/0003-astro-activation-shell.md new file mode 100644 index 0000000..e22ea99 --- /dev/null +++ b/docs/decisions/0003-astro-activation-shell.md @@ -0,0 +1,278 @@ +# ADR 0003: Use Astro on Vite as the browser activation shell + +- **Status:** Accepted and implemented +- **Date:** 2026-08-10 + +## Context + +Flect has two distinct browser responsibilities: + +1. run the interface a person opened; and +2. provide the Flect system that can inspect, edit, build, repair, version, and + recover that interface. + +Those responsibilities previously shared one eager direct Vite/React SPA entry +graph. Astro does not replace Vite: Astro itself uses Vite for development, +transformation, plugins, and production bundling. Flect now uses Astro's +document and activation layer above Vite while keeping the protected workspace +as an on-demand React/Effect application. + +The +production baseline at commit `f5503b0` transfers approximately 539 KiB of +compressed initial JavaScript and decodes 1.89 MiB before the user invokes an +agent, compiler, package manager, sandbox, or history operation. The entry +runtime statically composes the role-owned browser shell, which reaches +`just-bash/browser` even when the user only opens the current interface. + +Flect should instead make an opened interface useful immediately and load the +authoring system only when the person asks Flect to act. This is especially +important for shared browser interfaces, where most visits may never enter an +editing flow. + +Astro's islands architecture renders ordinary components to HTML without a +client runtime and hydrates only explicitly selected client islands. It can +also build React, Preact, Svelte, Vue, and Solid components through framework +integrations. Static generation is Astro's default route behavior, which is +compatible in principle with a browser deployment and a packaged Tauri +WebView. + +These properties match the outer-host problem, but they do not by themselves +solve Flect's runtime, workspace, or arbitrary-framework problem. + +## Decision + +Flect adopts Astro as the browser document and activation shell. + +Astro owns: + +- the static browser document, metadata, loading and unavailable states; +- the smallest protected visual frame needed before Flect activation; +- static or selectively hydrated product surfaces that are known at build + time; and +- the explicit activation boundary that loads the Flect system. + +Astro does not own: + +- agent orchestration or Pi sessions; +- the canonical source workspace, Git history, builds, or last-known-good + runtime; +- untrusted-code execution, package installation, or capability grants; +- the platform-native host boundary; or +- runtime interpretation of arbitrary React, Vue, Svelte, HTML, or CSS + projects. + +Those responsibilities remain behind typed Effect services and host-specific +Layers. + +## Activation model + +Opening a shared interface and activating Flect are different lifecycle +events. + +### Opened interface + +The browser first receives the smallest complete document that can display and +run the opened product experience. It must not construct the Flect agent, +workspace, Git, compiler, sandbox, package manager, or model client merely +because the page opened. + +The opened interface may load its own application JavaScript when its behavior +requires it. That application payload is measured separately from the Flect +authoring payload. + +### Flect activation + +Flect arms its tiny coordinator after low-cost intent such as focus or pointer +entry. It hydrates the protected workspace only after an explicit action such +as: + +- submitting the first Flect prompt; +- using the Flect keyboard shortcut; or +- invoking an operation that requires a Flect capability. + +The activation control acknowledges intent in the same frame. A reviewed +custom `client:flect` directive then asks Astro to load and hydrate the island; +the host does not imperatively mount the component or append its stylesheet. +The island renders the Vite-emitted stylesheet as a declarative resource and +signals readiness only after its load event, so the Effect coordinator can keep +the static shell visible until the styled workspace is committed. Astro's +built-in `client:load`, `client:idle`, and `client:visible` policies are useful +for ordinary islands, but none represents "load only after this product action" +exactly. + +Loading the Flect client runtime still does not load every capability. Agent +tools acquire compiler, shell, sandbox, package, Worker, and Wasm Layers only +when the selected typed operation needs them. Their Effect scopes own cleanup +and disposal. + +## Target topology + +```text +Astro browser document +├─ opened product interface +│ └─ only the product JavaScript required by that interface +├─ tiny Flect activation control +└─ explicit user activation + └─ Flect client island + ├─ protected canvas and composer + ├─ typed Effect runtime client + └─ runtime coordinator + ├─ one visible conversation + ├─ isolated App, Shaper, and Guardian trust domains + ├─ capability policy + ├─ workspace, Git, build, and last-known-good services + └─ on-demand execution substrates + ├─ browser Workers + └─ private desktop sidecar +``` + +The person experiences one agent with one continuous conversation. Existing +internal trust separation remains an implementation and authority boundary; +it is not exposed as Edit/Run modes, separate drafts, or role switches. + +## Effect composition roots + +The implementation must replace the current universal client runtime with +explicit subsystem boundaries: + +- `BrowserDocumentLayer` provides only environment detection, minimal + appearance, activation, and unavailable-state behavior. +- `FlectClientLayer` is constructed once when Flect activates and owns the + typed transport, session projection, workspace projection, preferences, and + platform-capability contracts required by the protected UI. +- `WorkspaceRuntimeLayer` owns canonical workspace, Git, build, preview, and + last-known-good lifecycles outside the UI main thread. +- `ToolExecutionLayer` is acquired only for a typed tool operation and owns + disposable Workers, shell workspaces, Wasm runtimes, package operations, and + cancellation. +- Browser, Tauri, and test composition roots provide different platform Layers + without platform checks inside React components. + +Layers that own transports, Workers, sidecars, subscriptions, or workspaces +must have scoped acquisition and release. Layer values are constructed once at +their runtime boundary so Effect memoization and resource sharing remain +explicit. + +React renders validated snapshots and owns ephemeral input state. It does not +coordinate proposal, build, Git, recovery, or capability workflows. + +## Framework boundary + +Astro's framework integrations are a build-time composition feature, not a +universal runtime for arbitrary user projects. + +Flect may use Astro to combine known host components from different supported +frameworks, but it must not install every framework integration into the host +or download multiple framework runtimes speculatively. A component island is +implemented in one framework, and each hydrated framework brings its required +client runtime. + +User projects continue to enter through Flect's independent project-adapter +and build contracts: + +- detect and validate the project type; +- build it in the isolated workspace runtime; +- produce an attributable runnable artifact; +- run that artifact behind the canvas isolation boundary; and +- expose semantic inspection and editing through typed Flect tools. + +React, Vue, Svelte, Astro, HTML, and CSS support is therefore a property of the +workspace/build adapter system. Astro is the host gate into those +possibilities, not the mechanism that makes arbitrary source projects mutually +compatible at runtime. + +## Browser and native hosts + +The browser uses Astro's static output by default. Server islands and +server-only Astro features are outside the initial local/browser-host decision. + +The Tauri application may package the same static document and shared +protected UI, but it activates the Flect client as part of opening the Flect +workspace. Tauri remains responsible for platform-native window, menu, +shortcut, file, appearance, accessibility, notification, and lifecycle +surfaces. Astro does not provide native feel. + +On desktop, workspace, Git, build, agent, and sandbox work belong in the +private sidecar or explicitly isolated workers rather than the WebView main +thread. Moving a tool out of the WebView must not turn it into ambient native +shell access; the same typed capability, virtual-filesystem, package, network, +and resource limits remain mandatory. + +## Performance gates + +Production builds must continue to prove all of the following: + +- a view-only route requests no Flect agent, Effect runtime, workspace, + compiler, shell, package, sandbox, Worker, or Wasm chunk; +- the Flect activation bootstrap is at most 10 KiB gzip; +- the protected interactive Flect client is at most 200 KiB gzip and 600 KiB + decoded before optional tools; +- esbuild, Rifty, QuickJS, `just-bash`, package clients, and their Worker/Wasm + artifacts load only on the typed operation that needs them; +- activation acknowledges input in the same frame and presents stable progress + without layout shift or focus loss; +- the warmed protected composer is usable within 300ms locally and 1,000ms on + the Fast 4G / 4x CPU reference profile; +- opening and using the product interface remains possible if the Flect runtime + is offline; and +- static Astro output packages and runs under the existing Tauri CSP and + isolation boundary without an Astro server. + +The browser and packaged-host performance gates in issue #36 remain mandatory. + +## Validation result + +The measured comparison used an Astro-on-Vite static host and a direct Vite SPA +with the same event-driven activation boundary. Both variants used Vite. The +implemented Astro path includes: + +1. a static opened-interface route; +2. focus/pointer arming plus prompt, keyboard-shortcut, and agent-action + activation through `client:flect`; +3. the existing React-compatible protected shell rendered by Preact in the + Astro production build; +4. the real typed Effect client Layer constructed only after activation; +5. real compiler, package, shell, Worker, and Wasm Layers loaded only after a + typed tool request; +6. production bundle and request-graph evidence; +7. production Chromium and AXI checks for open, activation, reload, keyboard, + narrow viewport, reduced motion, appearance, focus, and request boundaries; + and +8. static output compatible with the existing Tauri bundle and CSP boundary. + +The accepted build requests four view-only resources. Its activation bootstrap +is 2,199 bytes gzip / 4,646 bytes decoded and its initial CSS is 1,094 bytes +gzip / 2,976 bytes decoded. The view-only route requests no Flect workspace, +Effect runtime, Git, compiler, shell, package, Worker, or Wasm code. The first +protected JavaScript graph is 184,615 bytes gzip / 594,425 bytes decoded across +41 modules; its separately gated deferred CSS is 12,018 bytes gzip / 64,796 +bytes decoded. Shell, compiler, package, Worker, and Wasm boundaries remain +independently on demand. Local production measurements record 223 ms cold +activation, 211 ms warm activation, 501 ms warmed activation on Fast 4G with +4× CPU throttling, and 4 ms p95 composer acknowledgement. The full evidence is +recorded in +[`2026-08-10-astro-live-canvas-verification.md`](../verification/2026-08-10-astro-live-canvas-verification.md). + +## Consequences + +- Shared browser interfaces can open without paying for Flect authoring. +- Flect can acknowledge activation immediately while loading the system behind + a deliberate boundary. +- The host can use more than one UI framework where a known component justifies + it, but this is not the default and does not replace project adapters. +- Browser and Tauri can share static output while retaining different platform + capability Layers. +- The former eager singleton entry is replaced by an event-driven activation + module and scoped lazy build/shell services. +- Build, CSP, service-worker, routing, and test configuration become more + complex and must be justified by measured payload and lifecycle improvements. + +## Primary references + +- [Astro islands architecture](https://docs.astro.build/en/concepts/islands/) +- [Astro client directives](https://docs.astro.build/en/reference/directives-reference/#client-directives) +- [Astro framework components](https://docs.astro.build/en/guides/framework-components/) +- [Astro static route behavior](https://docs.astro.build/en/reference/routing-reference/#prerender) +- [Astro/live-canvas verification](../verification/2026-08-10-astro-live-canvas-verification.md) +- [Historical performance and platform-native baseline](../verification/2026-08-10-performance-and-native-feel-baseline.md) +- [ADR 0002: Browser Bun command](0002-browser-bun-command.md) diff --git a/docs/decisions/0004-authenticated-remote-runtime.md b/docs/decisions/0004-authenticated-remote-runtime.md new file mode 100644 index 0000000..8fca453 --- /dev/null +++ b/docs/decisions/0004-authenticated-remote-runtime.md @@ -0,0 +1,178 @@ +# ADR 0004: Authenticated remote runtime contract + +- Status: proposed for independent security review +- Date: 2026-08-10 +- Decision owners: Flect maintainers and security reviewers + +## Context + +A normal browser or future mobile host cannot safely inherit the packaged +desktop application's Pi process, native capabilities, or credentials. The +existing loopback development runtime is explicitly local, origin-bound, and +not suitable for network exposure. TLS alone would authenticate a server name, +not the exact Flect runtime, browser device, user, grant, session, or message. + +Remote execution therefore needs a new trust boundary. This ADR defines that +boundary before any non-loopback listener or remote capability adapter exists. + +## Decision + +The first implementation will be **user-hosted**: a runtime owned by the same +person and installed on a device they control. The protocol remains +provider-neutral so a later audited peer-hosted or product-hosted transport can +implement the same contract, but those deployment models are not implicitly +trusted and require separate policy and review. + +The browser/mobile client renders cached accepted interfaces without a remote +connection. Agent turns and privileged operations are unavailable until a +specific device is explicitly paired and an authenticated session is active. +Pi and product credentials remain on the runtime. Pairing and transport never +copy them to browser storage. + +## Authorities and assets + +Authorities: + +- the protected local user surface approves pairing, capability decisions, + revocation, and lost-device recovery; +- the client device owns a non-exportable device signing key; +- the runtime owns a non-exportable runtime signing key and credential store; +- the Flect capability broker authorizes every projected operation independently + of transport authentication; and +- products retain their own authorization and may still deny an approved user + operation. + +Protected assets include Pi/provider credentials, product credentials, private +conversation content, source workspaces, capsule bytes, capability decisions, +operation input/output, audit metadata, device/runtime keys, pairing codes, +resumption tickets, and revocation state. + +## Adversaries + +The design assumes hostile networks, malicious sites, stolen bearer material, +replayed/reordered frames, compromised or lost client devices, a compromised +runtime, malicious capsules, confused-deputy requests between products/users, +and operators able to observe infrastructure metadata. It does not claim to +protect secrets already present on a fully compromised endpoint. Recovery must +nevertheless stop that endpoint from receiving new authority. + +## Pairing and key lifecycle + +1. The runtime displays a short-lived, single-use pairing invitation through a + local protected surface. The invitation names the runtime, expiry, and an + out-of-band comparison code; it contains no credential. +2. Client and runtime exchange ephemeral X25519 keys and prove their persistent + Ed25519 device/runtime keys over a mutually authenticated transcript. +3. The user compares the code and confirms on the protected runtime surface. + Neither a capsule nor a remote message can confirm itself. +4. Both sides store only the peer public key, a random pairing identifier, + creation time, key epoch, and revocation state. Browser keys must be + non-exportable WebCrypto keys where supported; weaker storage is an explicit + unsupported-host result, not a silent downgrade. +5. Routine rotation advances the key epoch with a transcript signed by the old + and new keys. Recovery rotation uses a locally protected recovery key and + revokes every earlier device epoch. + +Invitations expire after five minutes, are consumed once, and are rate limited. +Pairing endpoints expose no runtime discovery over the public internet; +discovery is an explicit user-entered address, reviewed deep link, or local +proximity mechanism. + +## Session protocol + +Transport uses TLS 1.3 plus mutual application authentication. After TLS, both +sides sign a channel-binding transcript containing protocol version, pairing +ID, device ID, runtime ID, key epoch, both fresh nonces, and the TLS exporter. +A successful transcript creates a random session ID and derives directional +AEAD keys. + +Every encrypted frame contains the session ID, key epoch, strictly increasing +64-bit sequence, operation ID, message type, ciphertext length, and ciphertext. +The header is authenticated additional data. A receiver rejects an old epoch, +wrong session, duplicate or lower sequence, gap beyond the bounded reorder +window, oversized frame, unknown message, or expired session before decoding +product data. Accepted sequence state is persisted atomically with any durable +effect so reconnect cannot replay a completed operation. + +Resumption uses a single-use, short-lived ticket bound to pairing ID, both key +epochs, last accepted client/server sequence, workspace digest, and capability +projection digest. The runtime rotates the ticket before accepting new work. +Failure falls back to a fresh mutually authenticated session, never to bearer +authentication. + +Interruption is an idempotent typed message for one operation ID. Disconnect +triggers an interruption deadline; after it expires, the runtime cancels the +Effect scope and records only bounded redacted outcome metadata. Reconnect may +observe the outcome but cannot cause the operation to execute twice. + +## Capability and user boundaries + +Transport authentication grants no product or native capability. The runtime +reconstructs capsule/product identity, workspace, exact revision/digest, user, +and paired device from protected state and asks the normal broker for the +current projection. Requests carry named operation IDs and schema-validated +inputs, never URLs, shell commands, credentials, or arbitrary native calls. + +Remote confirmation is a signed request/decision exchange displayed by a +protected Flect surface. The decision binds user, device, runtime, capsule, +workspace, request digest, operation/resource/data scope, expiry, and rate. +Sensitive policy may require confirmation on the credential-owning runtime +even when the browser user is authenticated. Multi-user runtimes isolate keys, +credentials, workspaces, decisions, logs, quotas, and process scopes by an +immutable server-derived user ID. + +Revocation is checked at session admission and before every reserved operation. +It closes sessions, interrupts active scopes, invalidates tickets, advances the +revocation generation, and prevents reconnect. Lost-device recovery uses a +different trusted device or local runtime console, revokes the pairing, rotates +affected epochs, and shows which operations completed before revocation. + +## Offline behavior + +The client may retain only integrity-checked accepted capsule assets, a bounded +public history projection, unsent prompt drafts, and explicit offline status. +It does not cache credentials, grants as authority, remote operation outputs +marked sensitive, or model/provider session material. Cached UI is interactive +only for local behavior; remote actions fail closed with one actionable +reconnect surface and never queue silently. A draft may be sent exactly once +after an authenticated reconnect with current revision confirmation. + +## Deployment and operations + +The user-hosted runtime binds only the explicitly configured TLS endpoint, +runs without root, stores keys in the platform credential facility, separates +users/workspaces, caps sessions and bytes, and applies pairing/authentication +rate limits. Logs contain stable redacted event codes, durations, byte counts, +key epochs, and hashed correlation IDs—never prompts, source, credentials, +tokens, pairing secrets, signatures, or response bodies. Retention is bounded +and user-controlled. Abuse controls include connection quotas, exponential +backoff, frame/decompression limits, operation deadlines, and an emergency +local revoke-all action. + +Backups exclude live session keys and credentials by default. Restoring a +runtime creates a new runtime identity unless an explicitly protected identity +backup is restored; all clients must then pair again. Compromise response +revokes all pairings, rotates runtime identity and credentials, terminates +sessions, preserves a redacted completion ledger, and warns affected users +through an independent channel. + +## Protocol fixtures and review gate + +`shared/remote-runtime-protocol-fixture.ts` is deliberately a pure state-machine +fixture, not production cryptography or transport. Its tests pin the required +ordering behavior for pairing, reconnect, replay rejection, interruption, +revocation, and lost-device recovery. + +No non-loopback listener, discovery service, remote credential adapter, or +mobile capability projection may be merged until an independent security +review approves this ADR, cryptographic choices, concrete wire schema, key +storage on each supported platform, and an implementation-specific threat +model. Review findings update this ADR rather than being waived by the fixture. + +## Consequences + +The architecture preserves offline interface usefulness and keeps credentials +at the runtime, but remote agent readiness requires explicit pairing and may be +unavailable on hosts without protected key storage. User-hosting limits the +first deployment's operator trust and multi-tenant complexity. Provider-neutral +contracts leave room for later deployments without treating them as approved. diff --git a/docs/local-control.md b/docs/local-control.md new file mode 100644 index 0000000..4f5f283 --- /dev/null +++ b/docs/local-control.md @@ -0,0 +1,256 @@ +# Flect command and local control + +Flect has one public command surface: `flect`. The installed macOS executable +opens the graphical app when launched by Finder and runs the agent-first +command program when invoked from a terminal. App Agent and Shaper receive the +same language as a reserved command inside their browser-portable Bash +sandboxes. MCP and JSON/SSE are adapters over that same Effect command and +workspace-controller authority. + +## Start here + +From a source checkout: + +```bash +bun run flect -- +bun run flect -- inspect +``` + +From an installed app: + +```bash +/Applications/Flect.app/Contents/MacOS/flect +/Applications/Flect.app/Contents/MacOS/flect inspect +``` + +The no-argument result is content-first discovery for the live workspace, not +a static manual. Use `flect --help` for the command reference and a command's +trailing `--help` for local help. `flect app` opens or focuses the graphical +application. + +Diagnostics can install the fixed user link `~/.local/bin/flect`, or the same +opt-in operation can be requested through the full bundle path: + +```bash +/Applications/Flect.app/Contents/MacOS/flect setup shell install +flect setup shell remove +``` + +Flect never accepts an arbitrary link target, overwrites a regular file or +foreign symlink, copies a second executable, or requests administrator access. +It repairs only a stale link that points into another Flect app bundle. + +## Output contract + +Successful results and expected failures use stdout. Stderr is reserved for +optional progress and debug diagnostics. The default format is bounded TOON: + +```bash +flect inspect +flect --json inspect +flect --full logs --limit 20 +``` + +Global `--json` and `--full` flags precede the command. Without `--full`, long +strings are truncated with their original size and a recovery hint. The total +encoded result is capped. Exit `0` means success or an already-satisfied +idempotent operation, exit `1` means an operational or authorization failure, +and exit `2` means invalid usage. Errors remain structured and carry stable +codes such as `unauthorized`, `conflict`, `rejected`, `unavailable`, and +`unsupported`. + +Commands are non-interactive and set-shaped: `target use`, +`trusted-extensions enable`, and `rail width` state the intended result rather +than toggling hidden state. +`mode set` remains a compatibility alias for older automation. +Use `--stdin` for native `prompt` or `shape` text that should not appear in +process arguments. + +## Command reference + +| Command | Result | +| --- | --- | +| `flect` | Bounded live discovery and relevant next commands. | +| `flect app` | Open or focus the graphical application. | +| `flect status` | Inspect local-control connectivity. | +| `flect inspect [--fields ]` | Read validated workspace state. | +| `flect logs [--limit ] [--role ] [--operation ]` | Read bounded correlated evidence. | +| `flect watch [--after ]` | Wait for one newer workspace event. | +| `flect target ` | Select the visible protected workbench target. | +| `flect mode set ` | Compatibility alias for Shape or Use. | +| `flect prompt \|--stdin` | Ask App Agent to use the accepted product. | +| `flect shape \|--stdin` | Ask Shaper to prepare a proposal. | +| `flect cancel ` | Stop the selected running agent turn. | +| `flect action list` | List actions projected from the visible interface. | +| `flect action inspect ` | Inspect one projected action. | +| `flect action invoke ` | Invoke one currently available action. | +| `flect product invoke [--input ]` | Invoke one registered, granted product operation and return its bounded JSON result. | +| `flect permissions list` | Read the reactive, payload-free product permission lifecycle. | +| `flect permissions revoke ` | Revoke one visible decision; there is deliberately no grant command. | +| `flect interface inspect` | Read the visible interface document. | +| `flect interface schema` | Read the closed interface vocabulary. | +| `flect interface validate ` | Validate a Shaper sandbox file. | +| `flect interface propose ` | Submit a validated Shaper sandbox file. | +| `flect proposal accept\|reject` | Resolve the current preview. | +| `flect revision list\|rollback` | Inspect or roll back revision state. | +| `flect repository status` | Inspect canonical Git refs, candidate isolation, dirtiness, and conflicts. | +| `flect share list\|inspect []` | Inspect inactive review and retained share state. | +| `flect share open-url\|open-git\|reject\|export` | Route supported source and export operations through the protected sharing lifecycle. | +| `flect share checkpoint --at ...` | In Shaper's embedded Bash only, checkpoint bounded sandbox files onto that exact guarded user fork. | +| `flect share resolve --base --upstream --fork ...` | In Shaper's embedded Bash only, resolve every reviewed conflict path against the exact guarded lineage. | +| `flect model list` | List Pi-backed models. | +| `flect model select ` | Select a model explicitly. | +| `flect model favorite ` | Set a favorite explicitly. | +| `flect extensions list` | Discover portable packages visible to the authenticated role and accepted/candidate binding. | +| `flect extensions describe ` | Inspect bounded lifecycle, role, grant, version, digest, and provenance state without bundle source. | +| `flect extensions call [--input ]` | Invoke one enabled portable package through its role-owned QuickJS worker and capability broker. | +| `flect trusted-extensions ` | Set explicitly trusted outside Pi extension loading for one role. The older `extensions enable\|disable` spelling remains a compatibility alias. | +| `flect safe enter\|restore` | Enter recovery or restore last-known-good state. | +| `flect rail collapse\|expand\|width <340-520>` | Set protected rail presentation. | +| `flect control status\|disable` | Inspect or revoke paired outside control. | +| `flect context --host ` | Emit bounded ambient agent guidance. | +| `flect setup status` | Inspect the shell link and agent integrations. | +| `flect setup shell install\|remove` | Manage only `~/.local/bin/flect`. | +| `flect setup agent install\|remove ` | Manage one ownership-marked context integration. | +| `flect mcp` | Serve the compact MCP adapter over stdio. | + +Help visibility is not authorization. The trusted adapter supplies the caller +identity; flags, environment variables, aliases, functions, PATH entries, +workspace files, and model text cannot select or impersonate a role. + +Portable extension discovery is deferred: a model receives no complete package +or tool catalog on every turn. Inside App Agent or Shaper Bash, the embedded +command fixes the role and accepted/candidate binding from the authenticated +tool call. Native callers follow the visible workbench target and binding. +Calls fail closed unless exactly one enabled package record matches. Package +activation, grants, pins, forks, update resolution, and removal remain +protected controller decisions and are not exposed as agent grant commands. + +| Caller | Intended authority | +| --- | --- | +| Outside `flect` | Broad control only after the user enables Local control. It cannot enable control or grant product capabilities; it may inspect and revoke a visible product decision. | +| App Agent | Inspect the accepted product and permission lifecycle, list/inspect/invoke its visible actions, invoke registered product operations, and read bounded evidence. It cannot grant or revoke. | +| Shaper | Inspect schema/state and permission lifecycle, validate its own sandbox file, submit a preview proposal, checkpoint bounded files onto an exact retained share fork, and submit an exact reviewed conflict resolution. It cannot accept that proposal or change permissions. | +| Guardian | No Bash and no `flect` command. | + +## Browser-hosted Flect + +Flect remains usable in a normal browser. App Agent and Shaper run `flect` +inside their role-owned `just-bash` workspace, so no native executable or host +shell is required. The reserved command is registered under a hidden identity +after parsing, which prevents shadowing by an alias, function, PATH change, or +workspace executable. + +The browser command supports workspace inspection, logs, interface shaping, +and role-authorized actions through an in-process bounded command bus. It does +not install shell links or host integrations, read files outside the role's +disposable `/workspace`, expose the control bearer, or provide embedded event +watching. Its default output remains pipeable and redirectable: + +```sh +flect action list | grep available +flect product invoke projects.list --input '{"limit":2}' +flect interface schema | head +flect inspect > /workspace/state.toon +``` + +## Enable and revoke outside control + +Outside control is off by default. Open **Diagnostics** and choose **Enable +local control**. Only the protected Flect shell can create the grant. Enabling +it creates a fresh 256-bit bearer and atomically publishes an owner-private +descriptor (`0700` directory, `0600` file): + +- macOS: `~/Library/Application Support/Flect/control.json` +- Linux: `${XDG_STATE_HOME:-~/.local/state}/flect/control.json` +- tests or custom hosts: `FLECT_CONTROL_STATE_DIR` + +Use **Disable local control** or `flect control disable` to revoke it. Flect +removes the descriptor, invalidates the bearer, closes subscriptions, fails +queued requests, and clears visible client state without a restart. Never copy +the descriptor or put its bearer in a prompt, argument, log, fixture, or +artifact. The public clients discover it privately and never print it. + +Every mutation receives a unique command ID. The underlying JSON API also +supports `expectedSequence`; a stale optimistic request returns a typed +conflict instead of mutating newer state. + +## MCP + +The public executable selects MCP mode explicitly: + +```bash +flect mcp +``` + +Configure an MCP client with +`/Applications/Flect.app/Contents/MacOS/flect` and the single argument `mcp`. +The stdio server exposes four compact tools: + +- `flect_inspect` reads the current non-secret workspace snapshot; +- `flect_command` accepts the exact closed `FlectCommand` schema; +- `flect_wait` waits for a live event and returns fresh state; and +- `flect_logs` returns bounded, redacted operation evidence. + +The small tool count is deliberate. The command tool carries one schema union +instead of permanently loading hundreds of narrow model tools. + +## Optional coding-agent context + +Flect can install an ambient discovery hook for Codex, Claude Code, or +OpenCode: + +```bash +flect setup agent install codex +flect setup agent install claude +flect setup agent install opencode +flect setup status +``` + +Codex and Claude receive bounded output from `flect context --host ...` at +session start/resume/clear/compact. OpenCode receives the same context once per +session and again after compaction through a dependency-free local plugin. +Install and removal are explicit, idempotent, atomic, and ownership-marked; +unrelated hooks and settings are preserved. Invalid JSON or an occupied +OpenCode plugin path is reported as a conflict and is never overwritten. + +## JSON and SSE adapter + +The private descriptor points to an ephemeral server on `127.0.0.1` and a +random port. All public routes require its exact bearer: + +```text +GET /v1/status +GET /v1/instances +GET /v1/workspaces/:workspaceId +GET /v1/workspaces/:workspaceId/logs +GET /v1/workspaces/:workspaceId/events?after=:sequence +POST /v1/workspaces/:workspaceId/commands +``` + +SSE accepts `after` or `Last-Event-ID` and emits schema-decoded monotonic +events. Command bodies are capped at one MiB and decoded as strict +`FlectCommandEnvelope`s. Unknown fields or tags, wrong workspace IDs, +self-enablement, invalid bounds, and missing authorization fail closed. + +Use the public `flect` or MCP surfaces instead of hand-written bearer-bearing +HTTP. The lower-level client module exists for these adapters, not as a public +product surface. + +## Evidence and host boundary + +Flect retains at most 500 operation records and two MiB of encoded evidence in +memory. Records correlate workspace, command, operation, role, session, tool, +revision, and named outside-client IDs. Secret-shaped text is redacted. This +evidence helps users and agents debug the same reactive state; it is not a +second revision store or durable audit database. + +Browser development registers the Vite client with the origin-restricted Bun +runtime. The packaged WebView registers through private Effect RPC and Tauri +with the broker in `flect-runtime`. Both publish through the same controller. +A static page without its approved local runtime cannot expose outside +control. Flect does not bind to a LAN, pair remotely, run an unattended daemon, +or keep a grant after its owning runtime exits. + +See [`ARCHITECTURE.md`](../ARCHITECTURE.md) for implemented topology and +[`docs/trust-model.md`](trust-model.md) for the authority model. diff --git a/docs/native-platform-adapters.md b/docs/native-platform-adapters.md new file mode 100644 index 0000000..9af0fe3 --- /dev/null +++ b/docs/native-platform-adapters.md @@ -0,0 +1,53 @@ +# Native platform adapters + +Flect keeps product state, the live canvas, Git history, agent coordination, +and capability decisions in the shared Effect application. Native adapters are +small host-owned enhancements behind that boundary; they are not a second +application architecture and do not make WebView controls pretend to be native +controls. + +## Implemented macOS adapter + +The first adapter reads the current macOS control accent color: + +1. `FlectNative.swift` asks AppKit for `NSColor.controlAccentColor` and returns + one packed RGBA value through a fixed C ABI symbol. +2. The Tauri Rust host converts that value to a closed, versioned JSON result + containing only a CSS color and readable black/white contrast color. +3. `NativePlatform` schema-decodes the result and returns a typed unavailable + or invalid-result failure without exposing native error details. +4. The product operation registry exposes `native.appearance.current` only on + the Tauri composition root and only after the protected capability broker + has reserved and validated an explicit grant for + `product:native-appearance:read`. + +The Swift adapter cannot see interface revisions, Git, Pi, credentials, +capsules, or the capability store. It owns no long-lived resource. Browser +composition uses the same `NativePlatform` contract with a typed unavailable +result, while the shared capsule continues rendering without the enhancement. +Revocation is checked before every invocation, so it prevents another AppKit +read immediately. + +## Adapter rules + +Every additional Windows, Linux, iOS, Android, or macOS adapter must follow the +same pattern: + +- define the smallest versioned input and output schema in shared code; +- expose a fixed host command rather than a general native bridge; +- keep native code unable to read application state it does not require; +- register the operation and manifest only in composition roots that genuinely + support it; +- reserve, authorize, validate, execute, and audit through the product + capability broker; +- map unsupported hosts and rejected native results to bounded typed failures; +- put allocated handles, listeners, streams, and tasks in an Effect scope so + interruption, revocation, and shutdown release them; and +- prove absence before approval, success after approval, denial after + revocation, and explicit unsupported-host behavior in tests. + +Platform chrome still belongs to the platform. Menus, dialogs, window +lifecycle, shortcuts, safe areas, accessibility, and input behavior should use +the actual host facilities when a web surface cannot satisfy the native-feel +gate. A platform adapter is never permission to load capsule-provided native +libraries or executables. diff --git a/docs/performance.md b/docs/performance.md new file mode 100644 index 0000000..8d992f9 --- /dev/null +++ b/docs/performance.md @@ -0,0 +1,77 @@ +# Flect performance and memory budgets + +This is the human decision record for Flect's release performance contract. The +exact thresholds live once in +[`shared/performance-budgets.ts`](../shared/performance-budgets.ts); tests and +release measurements import or report those values rather than copying them. + +## Product budgets + +On the supported Apple Silicon development/release baseline, production Flect +must stay within these user-visible classes: + +- browser cold activation within 1,000 ms and warm activation within 300 ms; +- protected pre-tool client at or below 200 KiB gzip / 600 KiB decoded and + initial CSS at or below 25 KiB gzip; +- composer p95 acknowledgement within 50 ms and ordinary interaction within + 100 ms; +- text/CSS patch within 150 ms and component patch within 500 ms; +- external candidate rebuild and representative complete Markdown within + 1,000 ms; +- browser cancellation acknowledgement within 250 ms; +- Fast 4G LCP within 1,000 ms and Slow 4G LCP within 2,500 ms; +- 16.7 ms frame and 50 ms long-task thresholds; +- garbage-collected Chromium heap at or below 64 MiB, growing by no more than + 8 MiB across 50 complete product cycles; +- packaged-macOS cold window within 2,000 ms and reopen within 500 ms; +- packaged cancellation acknowledgement within 250 ms; and +- packaged steady RSS at or below 250 MiB, growing by no more than 32 MiB over + the release repetition run. + +The budgets include Flect orchestration and rendering, not provider inference +latency. Model latency is reported separately and never hidden by extending a +spinner budget. + +## Measurement contract + +Mandatory browser gates use a production Astro-on-Vite build, Playwright Chromium, one +worker, deterministic Flect fixtures, a 1180 × 781 desktop viewport unless the +scenario names another size, and no network other than the origin-restricted +test runtime. Resource measurements use browser `PerformanceResourceTiming`. +Heap gates expose Chromium's precise memory information. The strict long-session +gate deliberately performs no intermediate garbage collection: it measures 50 +real create/use cycles and fails above 8 MiB retained growth. A final collected +sample may be reported separately as diagnostic evidence. + +Timing diagnostics contain only metric names, durations, byte counts, and +iteration counts. They must not contain prompts, model output, product data, +credentials, URLs, or tool content. Each mandatory interaction is exercised +at least once per gate. Warm target switching uses multiple samples and fails +on the worst sample; release dogfood records three native samples and uses the +median while also rejecting any sample above 150 percent of its budget. + +The dedicated supported-device browser run and release dogfood fail warm +activation at the exact 300 ms product threshold. Shared hosted CI cannot be a +hardware baseline: it reports that same metric, restores the browser cache +before measuring it, and rejects warm activation at the existing 1,000 ms cold +ceiling so scheduler contention cannot create a false release claim or hide a +major regression. Native measurements complement CI on the supported macOS +release host and are recorded in the dated verification report. A different +supported-device baseline requires a reviewed update to the one TypeScript +budget contract and this rationale. + +## Resource behavior + +Flect keeps deterministic limits on sessions, queues, messages, activities, +output, frames, QuickJS work, auth logins, and auth events. The hot workspace +path uses shallow trusted snapshot evolution instead of recursively decoding +unchanged history on every streamed update. Public operation projection is 12 +records; the internal journal is bounded to 128 records / 512 KiB. Internal +conversation projections retain 12 messages and eight activities per authority. +Performance instrumentation creates no telemetry, identifier, daemon, cache, +or second runtime state. A failed budget is fixed by reducing user-visible +work—such as lazy-loading a large optional surface—rather than by suppressing +the measurement or retaining more hidden work. + +The current measured release evidence is in +[`docs/verification/2026-08-10-astro-live-canvas-verification.md`](verification/2026-08-10-astro-live-canvas-verification.md). diff --git a/docs/product-capabilities.md b/docs/product-capabilities.md new file mode 100644 index 0000000..49be54e --- /dev/null +++ b/docs/product-capabilities.md @@ -0,0 +1,197 @@ +# Product capability adoption + +Flect products expose named operations, never raw network access. A capsule or +App Agent may request `projects.list`; only trusted host composition knows that +this maps to a particular API, which credentials and policy apply, and which +bounded result is safe to return. + +This document owns the adopter mechanics. The authority model lives in +[`docs/trust-model.md`](trust-model.md), and the implemented topology lives in +[`ARCHITECTURE.md`](../ARCHITECTURE.md). + +## Effect services + +An adopter composes the transport services it needs at the trusted runtime +root: + +1. `ProductCapabilityDecisionStore` persists strict version-2 decisions through + protected `InterfaceStorage` and migrates matching legacy boolean state. +2. `ProductCapabilityBroker` owns lifecycle, exact request binding, scope, + lifetime, rate limits, atomic reservation, and revocation. +3. `ProductCapabilityRegistry` maps stable unary operation IDs to one + capability, independent product authorization, and bounded input/output + projections. +4. `ProductHttp` owns HTTPS origin, path prefix, method, header, byte, deadline, + transport, and private credential policy. +5. `ProductGraphql` pins an exact HTTPS endpoint, operation metadata, canonical + document digest, document bytes, variable/result bounds, deadline, and + private credential Effect behind a named operation. +6. `ProductEvents` owns a scoped connector, bounded backpressure queue, strict + event decoding, canonical decimal sequence, finite reconnect policy, cursor + resume, and cancellation. `ProductEventRegistry` binds that stream to the + same broker reservation and live revocation lifecycle. + +All are `Context.Service` contracts with named Layers. Capsules and agents see +only stable operation IDs plus bounded JSON. They never receive an origin, +GraphQL document, credential, cookie, socket, queue, or reconnect primitive. + +## Public SDK boundary + +The separately versioned [`@flect/product`](../packages/product/) package owns +the public contracts and transport-only Layers. Its supported exports are the +root module, `/contracts`, and `/host`; it has an exact Effect peer and no React, +Tauri, Node-runtime, or Flect application dependency. A built tarball contains +only declarations/ESM, package metadata, README, and license and is executed in +a clean consumer by `bun run product:package`. + +`defineProductIntegration` joins strict product metadata, capability manifests, +named unary/event closures, a selected inference owner, and one digest-verified +recommended capsule. `evaluateProductAdoption` compares that integration with +host facts, a prior product connection record, and separate user state. Its +ordered diagnostics cover ready, offline, product update, capability/extension +review, incompatible host/Flect, unavailable authentication, required/blocked +migration, preserved fork, and detach. `detachProduct` clears the product +connection only; Flect remains responsible for any protected grant revocation +and never deletes the user's workspace, Git ref, capsule, or export. + +The package deliberately does not export the decision store, capability broker, +protected permission UI, operation journal, workspace storage, capsule +activation, or safe mode. Those remain Flect-owned. The internal runtime bridge +consumes the same public operation/event types, so SDK and application contracts +cannot drift. + +## Immutable request binding + +Each decoded capsule becomes a `ProductCapabilityRequestContext` containing: + +- capsule scope ID; +- Flect workspace ID; +- SHA-256 of the exact `.flect` archive; +- capsule provenance revision; and +- the exact requested capability IDs and required flags. + +A decision matches all of that binding. Updating archive bytes, changing the +declared request, or replacing the capsule cannot silently widen an older +decision. Two apps requesting the same capability remain independent. + +The host registers a strict `ProductCapabilityManifest` for every capability: +operation IDs, resource IDs, data classes, permitted confirmation policies, and +optional maximum duration and rate. Capsule content and model output cannot +register or expand a manifest. + +## Lifecycle and user choices + +Protected review projects one lifecycle value per request: + +- `requested`: declared by the capsule and awaiting a decision; +- `available`: registered by the host but not requested by this capsule; +- `granted`: currently usable within the approved scope; +- `denied`: explicitly denied by the protected user; +- `expired`: its duration elapsed or its one-use allowance was consumed; or +- `revoked`: explicitly revoked. + +Availability is separate: an unavailable request stays visible and blocks activation +when required. The protected component shows operation/resource/data scope, +lifetime, rate, and decision identity without showing payloads or credentials. + +An allow decision chooses one of the policies permitted by the manifest: + +- `once`: in memory and atomically consumed by the next attempted operation; +- `session`: in memory until this Flect runtime ends; +- `workspace`: durable and valid only for the matching workspace; or +- `persistent`: durable for the exact capsule request binding. + +Denial is durable. Revocation updates the existing decision and immediately +blocks later capsule and App Agent calls. A failed durable write leaves live +authority unchanged. + +Only the protected user source can create a decision. Paired outside control may +run `flect permissions list` and revoke a visible decision with +`flect permissions revoke `; App Agent and Shaper may inspect but +cannot grant or revoke through their embedded command. There is deliberately no +agent-facing grant command. + +## Invocation order + +For each operation, Flect: + +1. verifies the current accepted/candidate capsule binding and registered + operation; +2. atomically reserves the matching decision, consuming one-use and rate + allowance before product work; +3. runs the product's independent authorization projection; +4. validates its exact operation/resource/data scope against the reservation; +5. invokes the bounded unary adapter or opens the bounded event scope; and +6. decodes the bounded result. + +User approval never overrides product authorization. Product denial and scope +widening stop before transport. Every attempted invocation adds structured, +payload-free capability metadata to the bounded operation journal: capsule +binding, decision, policy, operation, revision, and stable result reason. + +## Host composition + +Define `ProductCapabilityManifest` and operation definitions through +`@flect/product`, then select only the host adapters the product needs. Flect +composes the private decision store, broker, and registry at the protected +runtime root. The executable [`examples/product-sdk/`](../examples/product-sdk/) +directory contains independent offline, browser-direct, authenticated-brokered, +and private-sharing integrations; the older combined +[`examples/product-adapter/`](../examples/product-adapter/) remains an +end-to-end adapter exercise. + +For each operation: + +- use a stable dotted operation ID such as `projects.list`; +- validate JSON input before constructing a transport request; +- keep HTTP paths, GraphQL endpoints/documents, and event connectors inside + trusted host code; +- return an exact `AuthorizedProductOperation` resource/data projection; +- project the bounded response into JSON without secrets or raw transport + errors; and +- keep registration and credentials in host-owned code. + +Credential headers come from the host's Effect callback. They are inserted only +after caller input and headers are checked. Resolver defects are sanitized, and +credentials never appear in a response, permission projection, receipt, +journal, workspace snapshot, capsule, Pi prompt, interface document, revision, +or sandbox. A browser product should use its own protected same-origin session +or host endpoint; it must not embed a long-lived bearer secret in client code. + +Fixed GraphQL registration validates the exact document SHA-256 and operation +kind/name before the Layer becomes available. Invocation sends only +`{ operationName, query, variables }` to that registration and treats private +GraphQL errors as `product-denied`. + +Event connectors emit through the supplied Effect callback only. The queue +applies backpressure instead of dropping or growing. Each event is decoded and +byte-bounded before enqueue; duplicate or regressing decimal sequence values +fail closed. Reconnect passes only the last accepted cursor and stops at the +declared attempt count. Caller cancellation, component disposal, grant expiry, +or revocation aborts the same scoped connector. + +## Current platform boundary + +The stock distribution intentionally registers no product operation. The +browser and current desktop WebView execute the same schema-defined HTTP, +GraphQL, and event contracts. Browser-direct HTTP/GraphQL remains subject to +CORS, omits ambient browser credentials, and rejects redirects. OS-keystore +credentials or CORS-independent transport require a protected native adapter +behind the same contract; that adapter is not yet included. Database adapters, +arbitrary transport plugins, SDK registry publication, and stable 1.0 +compatibility remain later work. + +## Verification + +Executable public contracts live in `packages/product/src`; the old `shared/` +and transport import paths are compatibility re-exports rather than duplicate +implementations. Store, broker, transport, authorization, receipt, +protected-UI, persistence, cancellation, resume, and production-Chromium proofs +live beside their implementations, in +`tests/e2e/product-capability.spec.ts`, and in +`tests/e2e/product-adapter.spec.ts`, `tests/e2e/product-adoption.spec.ts`, and +`scripts/product-sdk-package.test.ts`. Run `bun run check:all` and +`bun run product:package` before distributing a product integration. Adapter +evidence is recorded in +[`docs/verification/2026-08-03-product-adapter-verification.md`](verification/2026-08-03-product-adapter-verification.md); +SDK evidence is recorded in the dated verification report beside it. diff --git a/docs/product-quality.md b/docs/product-quality.md new file mode 100644 index 0000000..247f0cc --- /dev/null +++ b/docs/product-quality.md @@ -0,0 +1,558 @@ +# Flect product-quality contract + +This document is the canonical definition of the outcomes that matter to Flect +users and the evidence required to prove them. It defines the destination. It +does not claim that the current release implements every outcome. + +Current observations belong in dated reports under `docs/verification/`. +Executable work belongs in GitHub issues, and live priority and status belong +in the dedicated Flect organization project. + +## Constituencies + +- **User:** a person using a Flect application or personal workspace. +- **Maker:** a person shaping, importing, testing, or maintaining an interface. +- **Extension author:** a person publishing a component, capsule, workflow, or + role-scoped extension. +- **Product team:** an organization adopting Flect for a product or service. + +## Maturity + +A dated evaluation assigns every criterion exactly one state: + +- `unimplemented`: no observable implementation exists; +- `partial`: some behavior exists but the complete promise does not; +- `implemented`: behavior exists but required proof is missing or stale; +- `proven`: all required evidence is current and passes; +- `regressed`: a previously proven outcome currently fails. + +Source inspection, documentation, compilation, screenshots without behavioral +checks, or an agent assertion cannot establish `proven` alone. + +## Proof classes + +- **Contract:** Effect unit or integration tests through exported contracts and + typed boundaries. +- **Browser:** real Chromium behavior against a production browser build. +- **Native:** packaged supported-host behavior through public UI and AXI + surfaces. +- **Security:** adversarial capability, sandbox, credential, or recovery tests. +- **Accessibility:** automated checks plus keyboard and assistive-technology + walkthroughs where automation is insufficient. +- **Experience:** bounded dogfooding or usability evidence for behavior that + depends on human comprehension, perceived latency, or visual quality. +- **Release:** clean-install, update, artifact, checksum, compatibility, and + reproducibility evidence. +- **Adoption:** an integration fixture or real adopter using only public + contracts. + +Evidence names the date, revision, host, exact command or workflow, result, and +applicable limitations. Sensitive values remain redacted. + +## Release interpretation + +- **Every release:** every behavior currently advertised by that release must + be proven. Security, credential isolation, deterministic recovery, data + ownership, and honest boundaries are non-waivable. +- **Public beta:** additionally requires the protected continuous + create–use–edit–recover loop, trustworthy installation, responsive operation, + and explicit compatibility boundaries. +- **Stable:** additionally requires every advertised portability, extension, + adoption, collaboration, and supported-host promise to be proven. + +An outcome identifier remains stable when its wording improves. Retire an +identifier instead of silently reusing it for a different promise. + +## FQ-01 Installation and first run + +**Constituencies:** User, Maker, Product team +**Gate:** Every advertised host; complete pillar for public beta +**Primary proof:** Browser, Native, Release, Experience + +- **FQ-01.1:** Native installation is trustworthy and simple. +- **FQ-01.2:** Browser Flect works without requiring a desktop application. +- **FQ-01.3:** Provider authentication can be completed inside Flect without a + terminal prerequisite. +- **FQ-01.4:** Existing approved Pi authentication is detected without copying + credentials into Flect state. +- **FQ-01.5:** Users can determine where models, workspaces, and credentials + live. +- **FQ-01.6:** Updating and uninstalling have documented, predictable behavior. +- **FQ-01.7:** A blank installation is immediately useful without an existing + product backend. + +## FQ-02 Immediate comprehension + +**Constituencies:** User, Maker +**Gate:** Public beta +**Primary proof:** Browser, Accessibility, Experience + +- **FQ-02.1:** A first-time user can understand what Flect is and begin a + meaningful task without reading external documentation. +- **FQ-02.2:** The running canvas, continuous composer, bounded activity, and + protected recovery controls are understandable without an internal state + model. +- **FQ-02.3:** The selected visible element or other active context is clear + before send without asking the user to select an agent role or mode. +- **FQ-02.4:** The interface distinguishes an ordinary reversible local edit + from an operation that needs new authority or has an outside effect. +- **FQ-02.5:** Model, workspace, capability, and permission state are + discoverable without dominating the work surface. +- **FQ-02.6:** Ordinary use does not require understanding an IDE, agent + harness, runtime, or infrastructure terminology. + +## FQ-03 Conversational shaping + +**Constituencies:** User, Maker +**Gate:** Public beta +**Primary proof:** Contract, Browser, Experience + +- **FQ-03.1:** A user can create a useful interface from a blank workspace by + describing the desired outcome. +- **FQ-03.2:** A user can make a precise change without unrelated interface + changes. +- **FQ-03.3:** Questions are answered without being mistaken for edit + instructions. +- **FQ-03.4:** The agent explains its intended or completed change in user + language. +- **FQ-03.5:** Follow-up instructions retain the correct workspace revision, + selected context, and conversation. +- **FQ-03.6:** Images, files, examples, and supported source projects can supply + shaping context without bypassing validation. +- **FQ-03.7:** Direct manipulation and conversational changes converge on the + same revision model. +- **FQ-03.8:** Explicitly approved authoring extensions may extend agent + behavior without extending their own authority. + +## FQ-04 Continuous live editing + +**Constituencies:** User, Maker, Extension author +**Gate:** Public beta +**Primary proof:** Contract, Browser, Experience, Performance evidence + +- **FQ-04.1:** The running product is the editing canvas; a valid UI-only change + appears directly without a separate preview screen. +- **FQ-04.2:** The one visible composer, conversation, canvas, workspace, and + relevant agent sessions remain warm during editing. +- **FQ-04.3:** Ten consecutive UI edits require no Use/Shape, App/Shaper, + candidate, Keep/Reject, Review, branch, or reset decision. +- **FQ-04.4:** Draft, conversation position, selected element, focus, scroll, + and unaffected application state survive valid incremental updates. +- **FQ-04.5:** Every valid visible edit creates an attributable automatic Git + checkpoint and remains immediately undoable. +- **FQ-04.6:** A request such as “fix what just happened” carries the bounded + failure, operation trace, workspace revision, and relevant UI state to the + same visible agent. +- **FQ-04.7:** Automatic intent and target routing is observable when useful and + instantly correctable without exposing internal agent roles. +- **FQ-04.8:** Ambiguity, a failed build, stale context, or incorrect routing + cannot replace the last-known-good canvas, grant authority, publish, or + perform an irreversible action. + +## FQ-05 Product usage + +**Constituencies:** User, Product team +**Gate:** Every advertised product capability; complete pillar for public beta +**Primary proof:** Contract, Browser, Adoption, Security + +- **FQ-05.1:** The running interface remains useful without invoking a model. +- **FQ-05.2:** The agent's product-usage trust domain understands only the + capabilities and bounded public context exposed to it. +- **FQ-05.3:** The same visible agent can answer questions and perform approved + product actions through typed capabilities. +- **FQ-05.4:** Tool execution, status, and results appear coherently in the + product experience. +- **FQ-05.5:** A product adopting Flect does not need to ship a separate + assistant surface. +- **FQ-05.6:** Users may select model access they control where product policy + permits. +- **FQ-05.7:** Product authentication and authorization remain authoritative + regardless of model or interface customization. + +## FQ-06 History, authority, and recovery + +**Constituencies:** All +**Gate:** Every release +**Primary proof:** Contract, Browser, Native, Security + +- **FQ-06.1:** Every valid local UI edit activates automatically as an + attributable checkpoint; failed attempts never become visible history. +- **FQ-06.2:** Users can understand, compare, undo, redo, and restore visible + changes without Git or proposal-state-machine terminology. +- **FQ-06.3:** New capabilities, destructive outside actions, imported shared + artifacts, publication, and protected recovery remain explicit decisions. +- **FQ-06.4:** History, comparison, undo, redo, restore, and rollback preserve + attribution and canonical-workspace integrity. +- **FQ-06.5:** Visible checkpoints record sufficient attribution for + explanation and recovery. +- **FQ-06.6:** Last-known-good recovery works without a model provider. +- **FQ-06.7:** Shaped UI and extensions cannot remove or replace safe mode. +- **FQ-06.8:** Broken extensions can be disabled through the protected shell. +- **FQ-06.9:** A crash during editing cannot destroy or silently replace the + last-known-good product. + +## FQ-07 Git-backed ownership + +**Constituencies:** Maker, Extension author, Product team +**Gate:** Stable when Git-backed authoring is advertised +**Primary proof:** Contract, Browser, Native, Release + +- **FQ-07.1:** A canonical Flect workspace is a real Git repository. +- **FQ-07.2:** Browser and desktop hosts provide Git behavior without requiring + system Git. +- **FQ-07.3:** The agent and protected history use ordinary Git rather than + proprietary shadow state. +- **FQ-07.4:** In-progress changes are isolated until they validate; each valid + visible result advances the canonical checkpoint automatically. +- **FQ-07.5:** Users can inspect, export, and continue the repository outside + Flect. +- **FQ-07.6:** Conflicts and interrupted operations have understandable, + recoverable states. +- **FQ-07.7:** Protected Flect metadata does not take ownership of or corrupt + the user's repository. + +## FQ-08 Import and export + +**Constituencies:** Maker, Product team +**Gate:** Stable for every advertised framework +**Primary proof:** Browser, Native, Release, Adoption + +- **FQ-08.1:** Advertised React, Vue, Svelte, HTML, and CSS project classes have + versioned import compatibility. +- **FQ-08.2:** Unsupported dependencies are reported before destructive work. +- **FQ-08.3:** Supported assets, routing, styling, and state survive import. +- **FQ-08.4:** Imported source remains recognizable and maintainable. +- **FQ-08.5:** Users can export ordinary source and Git history. +- **FQ-08.6:** Exported projects are not locked to a proprietary Flect service. +- **FQ-08.7:** Failed import leaves the source project and canonical workspace + recoverable. + +## FQ-09 Portable `.flect` applications + +**Constituencies:** User, Maker, Extension author, Product team +**Gate:** Stable when capsules are advertised +**Primary proof:** Contract, Browser, Native, Release, Security + +- **FQ-09.1:** Capsules install without a proprietary hosted service. +- **FQ-09.2:** Installed capsules run without their original build tool or + package registry. +- **FQ-09.3:** Capsule contents, provenance, permissions, and compatibility are + inspectable before activation. +- **FQ-09.4:** A capsule can carry UI, public agent instructions, and + role-scoped extensions under one versioned contract. +- **FQ-09.5:** Users can fork and personalize an installed capsule. +- **FQ-09.6:** Upstream updates do not silently overwrite personal changes. +- **FQ-09.7:** Browser and supported desktop hosts agree on the portable + capsule contract. + +## FQ-10 Extensions + +**Constituencies:** User, Maker, Extension author, Product team +**Gate:** Every release that loads extensions +**Primary proof:** Contract, Security, Browser, Native, Release + +- **FQ-10.1:** Extensions are explicitly enabled per workspace and target role. +- **FQ-10.2:** App Agent and Shaper extensions remain isolated from each + other's private session and authority. +- **FQ-10.3:** Permissions are understandable before activation. +- **FQ-10.4:** Extensions cannot access provider credentials or unrelated + product data. +- **FQ-10.5:** Users can inspect, disable, update, pin, fork, and remove + extensions. +- **FQ-10.6:** A failed extension cannot prevent protected startup or recovery. +- **FQ-10.7:** Components and extensions can be shared without becoming trusted + merely because of publisher or signature. +- **FQ-10.8:** Compatibility and migration failures explain a safe recovery + path. + +## FQ-11 Sandbox and capabilities + +**Constituencies:** All +**Gate:** Every release +**Primary proof:** Contract, Security, Browser, Native + +- **FQ-11.1:** Generated UI and logic cannot escape their declared execution + realm through supported interfaces. +- **FQ-11.2:** Agent Bash is useful inside its role sandbox without exposing a + host shell or native process authority. +- **FQ-11.3:** Browser workspaces use a durable browser-native filesystem where + canonical persistence is required. +- **FQ-11.4:** Filesystem, network, SQL, product, model, and native effects cross + explicit typed capabilities. +- **FQ-11.5:** Capabilities are least-privilege, inspectable, attributable, and + revocable. +- **FQ-11.6:** Capsules, shaped UI, and extensions cannot grant themselves + authority. +- **FQ-11.7:** Credentials never enter prompts, Git, screenshots, logs, or + extension-visible state. +- **FQ-11.8:** CPU, memory, storage, output, and execution limits prevent + unbounded resource use. +- **FQ-11.9:** Security claims distinguish browser or worker isolation from an + operating-system sandbox. + +## FQ-12 Models and authentication + +**Constituencies:** User, Maker, Product team +**Gate:** Public beta +**Primary proof:** Contract, Browser, Native, Security, Experience + +- **FQ-12.1:** Provider login and recovery are available inside Flect. +- **FQ-12.2:** Users can discover and select authenticated compatible models. +- **FQ-12.3:** Missing, expired, or unsupported authentication produces a clear + recovery action. +- **FQ-12.4:** Switching models preserves valid conversation and revision + state. +- **FQ-12.5:** Reasoning effort and other exposed controls use understandable + product language. +- **FQ-12.6:** Provider credentials remain outside shaped applications and + role extensions. +- **FQ-12.7:** Products may provide inference but are not required to do so. +- **FQ-12.8:** Deterministic recovery remains available without any model. + +## FQ-13 Agent transparency + +**Constituencies:** User, Maker +**Gate:** Public beta +**Primary proof:** Browser, Accessibility, Experience + +- **FQ-13.1:** Available authority and selected context are discoverable before + send without exposing internal agent roles. +- **FQ-13.2:** Tool calls are distinguishable from assistant prose. +- **FQ-13.3:** Queued, running, completed, failed, and cancelled states are + explicit. +- **FQ-13.4:** Duration and bounded useful output are inspectable. +- **FQ-13.5:** Errors name the failed operation and a safe next action. +- **FQ-13.6:** Ordinary use is not overwhelmed by infrastructure activity. +- **FQ-13.7:** Markdown, code, tables, disclosures, and links render safely and + legibly. +- **FQ-13.8:** Streaming and activity updates do not steal scroll position or + focus. + +## FQ-14 External agent control + +**Constituencies:** Maker, Extension author, Product team +**Gate:** Every release advertising outside control +**Primary proof:** Contract, Browser, Native, Security + +- **FQ-14.1:** Public AXI commands can inspect and operate the same live + workspace as the UI. +- **FQ-14.2:** Embedded role Bash exposes the applicable AXI language without + a separate model-visible tool catalog. +- **FQ-14.3:** JSON, SSE, MCP, native, and browser adapters converge on the same + reactive state and Effect controller. +- **FQ-14.4:** Authorized external actions appear immediately in the visible + interface. +- **FQ-14.5:** External agents can inspect bounded evidence, cancel work, and + debug through public surfaces. +- **FQ-14.6:** External control cannot bypass validation, permissions, + checkpointing, last-known-good protection, or recovery. +- **FQ-14.7:** Outside control is disabled by default and immediately + revocable. +- **FQ-14.8:** Browser Flect offers a portable in-app equivalent without + requiring an additional installed binary. + +## FQ-15 Performance and responsiveness + +**Constituencies:** User, Maker +**Gate:** Public beta +**Primary proof:** Browser, Native, Experience, measured performance evidence + +- **FQ-15.1:** Supported-host startup meets a documented interactive budget. +- **FQ-15.2:** Flect activation, composer reveal, element targeting, and warm + intent routing meet documented response budgets. +- **FQ-15.3:** Typing remains responsive while agents, builds, and previews + run. +- **FQ-15.4:** Streaming remains visually smooth under representative output. +- **FQ-15.5:** Long conversations and bounded tool output remain responsive. +- **FQ-15.6:** Preview rebuilds avoid unnecessary full-workspace work. +- **FQ-15.7:** Background agents and extension hosts remain within explicit + resource budgets. +- **FQ-15.8:** Cancellation gives prompt feedback and terminates owned work. +- **FQ-15.9:** Repeated long-running sessions do not exhibit unbounded memory + growth. + +## FQ-16 Reliability + +**Constituencies:** All +**Gate:** Public beta +**Primary proof:** Contract, Browser, Native, Security + +- **FQ-16.1:** Refreshing or restarting preserves the latest valid work. +- **FQ-16.2:** Applicable drafts, conversation, selected context, in-progress + diagnostics, and canvas state recover consistently. +- **FQ-16.3:** Network interruption does not corrupt revision or conversation + state. +- **FQ-16.4:** Stale edits and tool results cannot overwrite newer canonical + work. +- **FQ-16.5:** Concurrent operations are rejected, serialized, or reconciled + explicitly. +- **FQ-16.6:** Runtime and shell version incompatibility is detected before + unsafe operation. +- **FQ-16.7:** Browser-storage exhaustion has a deterministic recovery path. +- **FQ-16.8:** Partial updates and process crashes repair forward or return to + last-known-good state. + +## FQ-17 Privacy and data ownership + +**Constituencies:** All +**Gate:** Every release +**Primary proof:** Contract, Security, Release + +- **FQ-17.1:** Workspaces and personal customizations belong to the user. +- **FQ-17.2:** Users can determine what remains local, is synchronized, or is + sent to a selected model. +- **FQ-17.3:** Telemetry is absent or explicitly disclosed and controlled. +- **FQ-17.4:** Product connections cannot take ownership of personal + customizations. +- **FQ-17.5:** User data can be exported and deleted through documented paths. +- **FQ-17.6:** Credentials remain in the approved credential owner. +- **FQ-17.7:** Diagnostics and operation evidence are bounded and redacted. +- **FQ-17.8:** Local-only and offline-capable workflows remain possible where + their declared capabilities permit. + +## FQ-18 Accessibility + +**Constituencies:** User, Maker +**Gate:** Every user-visible release +**Primary proof:** Accessibility, Browser, Native + +- **FQ-18.1:** The complete protected shell is keyboard operable. +- **FQ-18.2:** Focus is visible, ordered, and restored across canvas updates, + sheets, menus, history, capability decisions, and recovery. +- **FQ-18.3:** Assistive technology receives meaningful agent, tool, validation, + and status changes. +- **FQ-18.4:** Color is never the only state signal. +- **FQ-18.5:** Text, placeholders, icons, and controls meet WCAG 2.2 AA contrast + requirements. +- **FQ-18.6:** Reduced-motion preferences preserve complete behavior. +- **FQ-18.7:** Zoom, text scaling, narrow layouts, and reflow remain usable. +- **FQ-18.8:** Touch targets meet the applicable supported-platform guidance. +- **FQ-18.9:** Safe mode remains accessible when shaped UI is inaccessible. + +## FQ-19 Visual and interaction quality + +**Constituencies:** User, Maker, Product team +**Gate:** Public beta +**Primary proof:** Browser, Native, Accessibility, Experience + +- **FQ-19.1:** The protected shell feels calm, professional, coherent, and + first-party on each supported host. +- **FQ-19.2:** The user's work remains more prominent than agent and runtime + infrastructure. +- **FQ-19.3:** Controls use familiar product affordances and complete + interaction states. +- **FQ-19.4:** Information density is space-efficient without becoming cramped. +- **FQ-19.5:** Motion communicates state and does not delay work. +- **FQ-19.6:** Responsive layouts never duplicate, hide, or trap access to the + protected composer and recovery controls. +- **FQ-19.7:** Supported light and dark appearances are deliberate rather than + mechanically inverted. +- **FQ-19.8:** Product interfaces may establish their own design language + without weakening the protected shell. +- **FQ-19.9:** Customization of Flect's own composer and rail has a deterministic + protected fallback. + +## FQ-20 Cross-platform behavior + +**Constituencies:** User, Maker, Product team +**Gate:** Every advertised host +**Primary proof:** Browser, Native, Release, Adoption + +- **FQ-20.1:** The browser is a first-class Flect host rather than a reduced + remote viewer. +- **FQ-20.2:** macOS uses native host behavior where it materially improves the + experience. +- **FQ-20.3:** Shared product behavior comes from one typed application core. +- **FQ-20.4:** Swift, Kotlin, Rust, or another native adapter enters through + narrow reviewed capabilities. +- **FQ-20.5:** Unsupported platform capabilities degrade explicitly. +- **FQ-20.6:** Every advertised Windows, Linux, mobile, and desktop host has a + current compatibility contract. +- **FQ-20.7:** Workspaces and capsules remain portable across compatible hosts. + +## FQ-21 Product-team adoption + +**Constituencies:** Product team, User, Extension author +**Gate:** Stable when product adoption is advertised +**Primary proof:** Adoption, Contract, Security, Release + +- **FQ-21.1:** Products expose approved APIs and capabilities without replacing + the Flect shell. +- **FQ-21.2:** A team can ship an excellent recommended default experience. +- **FQ-21.3:** Users can personalize locally without changing the product for + other users. +- **FQ-21.4:** Product policy remains authoritative over available + capabilities. +- **FQ-21.5:** Product branding cannot obscure or weaken protected recovery. +- **FQ-21.6:** Products can adopt Flect incrementally through public contracts. +- **FQ-21.7:** Teams can test, version, distribute, and update their Flect + experience. +- **FQ-21.8:** Stable compatibility and migration contracts protect adopters + across Flect upgrades. + +## FQ-22 Open-source and ecosystem trust + +**Constituencies:** All +**Gate:** Every public release +**Primary proof:** Release, Contract, Adoption + +- **FQ-22.1:** The protected core remains small enough to inspect and maintain. +- **FQ-22.2:** Published builds are reproducible from the released source and + declared toolchain. +- **FQ-22.3:** Releases are signed or checksummed, attributable, and documented. +- **FQ-22.4:** Capsule, extension, capability, and host contracts are versioned. +- **FQ-22.5:** Breaking changes provide explicit migrations or compatibility + failures. +- **FQ-22.6:** Documentation distinguishes current observable behavior from + future design. +- **FQ-22.7:** Fundamental local and browser workflows require no proprietary + Flect service. +- **FQ-22.8:** Licensing and governance permit understandable community and + commercial adoption. + +## FQ-23 Sharing and collaboration + +**Constituencies:** User, Maker, Extension author, Product team +**Gate:** Stable when sharing is advertised +**Primary proof:** Contract, Security, Release, Adoption + +- **FQ-23.1:** Experiences, components, themes, workflows, and extensions can be + shared independently where their contracts permit. +- **FQ-23.2:** Recipients can inspect provenance, compatibility, and requested + authority before activation. +- **FQ-23.3:** Personal changes survive compatible upstream updates. +- **FQ-23.4:** Teams can review proposed interface and capability changes like + code. +- **FQ-23.5:** Forking preserves attribution without creating authority. +- **FQ-23.6:** Private sharing does not require public publication. +- **FQ-23.7:** Untrusted shared artifacts open in a safe inspectable state before + approval. + +## FQ-24 Honest boundaries + +**Constituencies:** All +**Gate:** Every release +**Primary proof:** Contract, Browser, Native, Release, Experience + +- **FQ-24.1:** Flect clearly reports which source, dependency, and execution + classes it cannot run. +- **FQ-24.2:** Browser compatibility problems are reported before destructive + build or import work. +- **FQ-24.3:** CORS, backend, authorization, and product-data limitations are + explained in user language. +- **FQ-24.4:** Web UI is not falsely represented as a native platform control. +- **FQ-24.5:** Flect does not claim to replace a product backend, database, + business logic, or authorization model. +- **FQ-24.6:** Unsupported packages and capabilities fail with actionable + alternatives where available. +- **FQ-24.7:** Isolation claims name their actual browser, worker, process, or OS + boundary. +- **FQ-24.8:** Marketing, release notes, screenshots, and documentation do not + advertise behavior absent from the shipped release. + +## Ultimate user outcome + +A Flect user can install it, understand it, create something useful, keep using +and editing the running result, trust what it does, recover from mistakes, own +and export the work, and use it anywhere Flect claims to support—without +becoming dependent on Flect or surrendering control of their data. diff --git a/docs/recovery.md b/docs/recovery.md new file mode 100644 index 0000000..0e2ff7e --- /dev/null +++ b/docs/recovery.md @@ -0,0 +1,90 @@ +# Session continuity and recovery + +Flect keeps interface history and session continuity deliberately separate. +The shaping kernel and revision repository are the only authority for the +accepted interface, last-known-good revision, and validated candidate. The +role-continuity record is a bounded convenience projection for unsent drafts +and completed conversations; deleting it never deletes accepted interface +work. + +## What survives a refresh or restart + +- the one visible Flect conversation, reconstructed chronologically from its + internally isolated App, Preview, and Shaper records; +- one visible Flect draft (`acceptedUse` in the version-1 compatibility record); + legacy candidate and Shape draft fields are decoded but not exposed; and +- the canonical accepted, last-known-good, and external-candidate interface + revisions. + +An in-flight user message may be retained, but a partial assistant stream is +not. Active sessions, tool calls, raw tool output, shell processes, and partial +model output are cancelled and recreated as needed. Provider credentials, Pi +session internals, authentication events, protected-entry references, outside +control grants, connected-client state, and provider/model payloads never +enter the continuity record. + +The continuity record remains strict Effect Schema data under +`flect.role-continuity.v1` for backward compatibility. It is limited to 512 +KiB. Runtime projections retain at most 12 messages and eight activities per +internal authority; persisted message text and the visible draft remain +individually bounded. Tool activities are not persisted. + +## Conflicts and storage failures + +Every successful write increments a generation. Flect serializes same-origin +writes with Web Locks where available, rereads under that lock, and rejects a +stale generation instead of merging tabs or replacing newer state. One +`localStorage.setItem` atomically replaces the complete encoded record; quota +or host failures leave the prior record intact. + +Malformed, oversized, unknown-version, and incompatible records are rejected +before runtime mutation. Flect does not opportunistically rewrite them. A +candidate mismatch discards only its internal candidate continuity. The visible +Flect history remains available and does not expose those storage partitions as +product modes. + +## Protected recovery + +Open `/?safe=1` or choose **Safe mode** from the protected composer. Safe mode +does not hydrate stored drafts or conversations into the UI. It can show only +bounded generation/revision metadata and a closed recovery reason. + +The `?safe=1` URL is a one-shot protected launcher, not a durable repository +mode. Entering safe mode writes a guarded marker on +`flect/shared/recovery` without changing `flect/accepted`. A successful +**Restore interface** writes the recovered snapshot through +the guarded Git repository, removes only the `safe=1` query parameter while +preserving other URL state, and remains restored after reload or process +restart. A failed restore keeps the launcher and prior protected refs intact. +If an activation receipt is missing or disagrees with its protected refs, +Flect reconstructs bounded recovery metadata from `flect/last-known-good`, +enters safe mode, and requires the same explicit restore before realigning the +accepted and last-known-good refs. + +Without Pi or a model, safe mode can: + +- restore the last-known-good interface; +- export a valid, schema-decoded continuity record; +- discard session continuity while preserving interface revisions; +- retry strict decoding after the underlying storage condition changes; and +- keep the compiled protected shell available when customized state fails. + +Export is disabled for an invalid continuity record because Flect does not +render or repackage undecoded stored content. Discard remains available. + +## Current proof boundary + +Production Chromium tests cover the merged Flect conversation over isolated +internal records, one visible draft, candidate refresh, discard cleanup, active +interruption, safe-mode non-hydration, valid export, isolated discard, a real +same-origin stale second tab, injected browser quota exhaustion, unchanged +accepted product state on safe-mode entry, guarded restoration, and restoration +after reload. +Unit tests additionally inject malformed, incompatible, oversized, stale, +rejected, missing-receipt, legacy-ref, and receipt/ref-mismatch states. + +The packaged macOS proof in +[`docs/verification/2026-08-02-permission-lifecycle-verification.md`](verification/2026-08-02-permission-lifecycle-verification.md) +repairs a real legacy receipt/ref mismatch, advances the protected commit, and +survives a complete app quit and relaunch. Future interrupted-migration proof +and complete private-state canary evidence remain tracked in GitHub issue #21. diff --git a/docs/sharing.md b/docs/sharing.md new file mode 100644 index 0000000..5a2ff10 --- /dev/null +++ b/docs/sharing.md @@ -0,0 +1,99 @@ +# Sharing and personal forks + +Flect can review portable `.flect-share` archives from a local file, a +credential-free HTTPS URL, an exact public Git descriptor commit, or a named +private adapter supplied by a trusted host. Every source converges on the same +inactive review. Opening it never replaces the accepted app. + +A share may contain experiences, components, themes, workflows, and portable +extensions. Flect checks the archive, manifest, source paths, compatibility, +provenance, signature state, dependencies, migrations, and requested authority +before any artifact reaches its existing preview or activation boundary. A +signature identifies a claim; it never grants a capability. + +## Retain, personalize, and update + +Retaining a source imports only its exact reachable Git objects and creates +opaque namespaced `base`, `upstream`, and user-owned `fork` refs in Flect's +OPFS-backed repository. It imports no credentials or grants. The accepted app +continues to run until the user explicitly previews and activates selected parts. + +Shaper can personalize a retained fork from its browser-portable Bash sandbox: + +```sh +flect share inspect dev.flect.weather +flect share checkpoint dev.flect.weather \ + --at \ + --write components/weather/personal-note.md ./personal-note.md \ + --message 'Personalize weather workspace' +``` + +`--write` and `--remove` may repeat. Paths must remain inside the shared source, +the expected commit provides optimistic concurrency, and the command advances +only that share's guarded fork. App Agent cannot run it. The checkpoint does +not activate UI, accept a proposal, import authority, or modify recovery. + +When an exact upstream update arrives, Flect fast-forwards an untouched fork or +computes a bounded three-way merge. A clean personalized merge is a real Git +commit with the personal fork and exact upstream revision as its two parents; +the Worker verifies both the parents and the complete resolved tree before the +candidate ref moves. The user still previews and activates it through the normal +protected decision. + +Conflicting updates remain inactive and activation stays disabled. Flect preserves +the base, upstream, fork, and bounded conflict paths. The review offers three +explicit choices: continue with the retained fork, resolve the conflict with +Flect, or discard the update. Continue still creates an inactive candidate for Preview +and activation; it does not silently discard the update. + +Resolve with Flect materializes only the recorded conflict versions below +`/workspace/.flect/share-conflicts/`. Shaper writes exactly one result +or removal for every listed path and submits the exact guarded refs: + +```sh +flect share resolve dev.flect.weather \ + --base \ + --upstream \ + --fork \ + --write components/weather/index.ts \ + /workspace/.flect/share-conflicts/dev.flect.weather/resolved/components/weather/index.ts \ + --message 'Resolve weather conflict' +``` + +Flect's bounded byte-level three-way comparison is the portable conflict +policy. It does not depend on engine-specific merge heuristics: wasm-git may +auto-merge a source file that another Git build reports as conflicted. Exact +ref guards, the reviewed conflict set, the complete resolved tree, and the two +verified commit parents remain mandatory in either case. Restart restores the +inactive resolved candidate. Flect never asks a model to silently choose or +activate a merge result. + +## Export, remove, and delete + +Export emits a deterministic `.flect-share` containing the exact guarded fork +or prepared candidate history. Derived exports clear publisher signatures and +bind provenance to the exported commit. The embedded repository opens in +ordinary Git and is checked by Flect's production workflow with `git fsck`. + +Removing a share detaches its active parts from the app but retains the local +fork and export. Deleting local data is a separate, explicitly confirmed action +available only after removal. It deletes only that namespaced share ref; +unrelated repositories, grants, settings, and accepted interface state remain. + +## Host and browser boundaries + +The browser implementation uses OPFS, a single Wasm/libgit2 Worker, and Web +Locks; it does not require native Git, Bun, or a host shell. Private source +adapters are closure-private host capabilities registered before startup and +return only archive bytes for an opaque reference. Their credentials never +enter DOM, Git, Flect state, logs, prompts, or exports. + +HTTPS sources currently require direct CORS-readable responses and reject +credential-bearing URLs. Public Git requires an exact 40-character commit and +a CORS-capable HTTPS Git server. Real-time collaboration, publisher signature +verification, a public component registry, and automatic conflict resolution +are not implied by the current sharing lifecycle. + +See [the trust model](trust-model.md) for authority boundaries and +[the command reference](local-control.md) for agent and outside-control +surfaces. diff --git a/docs/superpowers/plans/2026-07-31-flect-chat-markdown.md b/docs/superpowers/plans/2026-07-31-flect-chat-markdown.md new file mode 100644 index 0000000..ab80481 --- /dev/null +++ b/docs/superpowers/plans/2026-07-31-flect-chat-markdown.md @@ -0,0 +1,794 @@ +# Flect Chat Markdown Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use +> superpowers:executing-plans to implement this plan task-by-task. Steps use +> checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Replace Flect's plain-text/fence splitter with a complete, +sanitized, T3Code-quality Markdown experience for browser and desktop chat. + +**Architecture:** `react-markdown` owns CommonMark rendering, with GFM and +role-aware hard-break plugins followed by raw-HTML parsing and a closed +sanitizer. Focused Flect components own safe links, native details, contained +tables, and rich code blocks; clipboard access crosses an Effect service, and +syntax highlighting is a lazy, bounded Effect workflow with escaped fallback. + +**Tech Stack:** React 19, Effect 4 beta, react-markdown 10.1.0, remark-gfm +4.0.1, remark-breaks 4.0.0, rehype-raw 7.0.0, rehype-sanitize 6.0.0, Shiki +4.3.1, Vitest/Testing Library, Playwright Chromium, Tauri 2. + +## Global Constraints + +- Preserve all existing uncommitted T3Code UX audit changes. +- Do not commit, push, publish, or release; the repository boundary does not + authorize those operations. +- Treat every message as untrusted text. +- Keep T3Code's file, editor, preview, skill, provider, settings, toast, and + local-API integrations out of Flect. +- Accept link schemes only for `http`, `https`, `mailto`, and local fragments. +- Do not add code execution, filesystem, storage, Pi, native, or network + authority to Markdown. +- Clipboard writes use an Effect `Context.Service`, named `Layer`, and typed + error. +- Keep Shiki outside the initial application chunk through dynamic import. +- Skip highlighting during streaming and preserve escaped code on every + loading or failure path. +- Desktop controls stay dense; compact controls remain at least 44 px. +- Test observable DOM and behavior, not implementation-file strings. +- Run every production change through a witnessed RED/GREEN cycle. + +--- + +### Task 1: Add and verify the Markdown dependency foundation + +**Files:** + +- Modify: `package.json` +- Modify: `bun.lock` + +**Interfaces:** + +- Consumes: current Bun/Vite React application. +- Produces: pinned imports for `react-markdown`, `remark-gfm`, + `remark-breaks`, `rehype-raw`, `rehype-sanitize`, and `shiki`. + +- [ ] **Step 1: Record the current dependency absence** + +Run: + +```bash +rg -n '"(react-markdown|remark-gfm|remark-breaks|rehype-raw|rehype-sanitize|shiki)"' package.json +``` + +Expected: no matches. + +- [ ] **Step 2: Install exact current compatible releases** + +Run: + +```bash +bun add react-markdown@10.1.0 remark-gfm@4.0.1 remark-breaks@4.0.0 rehype-raw@7.0.0 rehype-sanitize@6.0.0 shiki@4.3.1 +``` + +Expected: `package.json` and `bun.lock` contain the six exact versions. + +- [ ] **Step 3: Verify licenses and the dependency graph** + +Run: + +```bash +bun pm ls | rg 'react-markdown|remark-gfm|remark-breaks|rehype-raw|rehype-sanitize|shiki' +npm view react-markdown@10.1.0 license +npm view remark-gfm@4.0.1 license +npm view remark-breaks@4.0.0 license +npm view rehype-raw@7.0.0 license +npm view rehype-sanitize@6.0.0 license +npm view shiki@4.3.1 license +``` + +Expected: all packages resolve and every license is MIT. + +### Task 2: Put clipboard writes behind Effect + +**Files:** + +- Create: `src/lib/clipboard.ts` +- Create: `src/lib/clipboard.test.ts` +- Modify: `src/lib/runtime.ts` + +**Interfaces:** + +- Produces: + +```ts +export class ClipboardWriteError extends Schema.TaggedErrorClass()( + "ClipboardWriteError", + { message: Schema.Literal("Flect could not copy this content.") }, +) {} + +export class Clipboard extends Context.Service< + Clipboard, + { + readonly writeText: ( + value: string, + ) => Effect.Effect; + } +>()("Flect/Clipboard") {} + +export const ClipboardLive: Layer.Layer; +``` + +- [ ] **Step 1: Write failing service tests** + +Create `src/lib/clipboard.test.ts` with tests that: + +```ts +it.effect("writes text through the browser clipboard", () => + Effect.gen(function* () { + const clipboard = yield* Clipboard; + yield* clipboard.writeText("exact Markdown"); + expect(writeText).toHaveBeenCalledWith("exact Markdown"); + }).pipe(Effect.provide(ClipboardLive)), +); + +it.effect("keeps clipboard rejection typed", () => + Effect.gen(function* () { + const clipboard = yield* Clipboard; + const exit = yield* Effect.exit(clipboard.writeText("blocked")); + expect(Exit.isFailure(exit)).toBe(true); + expect(Cause.failureOption(exit.cause).pipe(Option.getOrThrow)._tag).toBe( + "ClipboardWriteError", + ); + }).pipe(Effect.provide(ClipboardLive)), +); +``` + +Use `vi.stubGlobal("navigator", ...)` or a configurable +`navigator.clipboard.writeText` property, restoring it after every test. + +- [ ] **Step 2: Run the tests and witness RED** + +Run: + +```bash +bunx vitest run src/lib/clipboard.test.ts +``` + +Expected: FAIL because `src/lib/clipboard.ts` does not exist. + +- [ ] **Step 3: Implement the service and live layer** + +Implement `ClipboardLive` with: + +```ts +const unavailable = () => + ClipboardWriteError.make({ + message: "Flect could not copy this content.", + }); + +export const ClipboardLive = Layer.succeed(Clipboard)({ + writeText: Effect.fn("Flect.Clipboard.writeText")((value: string) => + Effect.tryPromise({ + try: () => { + if (globalThis.navigator?.clipboard?.writeText === undefined) { + return Promise.reject(new Error("Clipboard API unavailable")); + } + return globalThis.navigator.clipboard.writeText(value); + }, + catch: unavailable, + }), + ), +}); +``` + +Merge `ClipboardLive` into `BrowserLive` and add `Clipboard` to +`FlectBrowserServices`. + +- [ ] **Step 4: Run the service tests and typecheck** + +Run: + +```bash +bunx vitest run src/lib/clipboard.test.ts +bun run typecheck +``` + +Expected: both commands exit 0. + +### Task 3: Implement pure Markdown policies and serializers + +**Files:** + +- Create: `src/components/markdown-policy.ts` +- Create: `src/components/markdown-policy.test.ts` +- Create: `src/components/markdown-table-serialization.ts` +- Create: `src/components/markdown-table-serialization.test.ts` + +**Interfaces:** + +- Produces: + +```ts +export const markdownUrlTransform: UrlTransform; +export const isExternalMarkdownHref: (href: string) => boolean; +export const normalizeSanitizedFragmentId: (id: string) => string; +export const extractFenceLanguage: (className?: string) => string; +export const extractFenceTitle: (meta?: string) => string | undefined; +export const serializeTableToMarkdown: (table: HTMLTableElement) => string; +export const serializeTableToCsv: (table: HTMLTableElement) => string; +``` + +- [ ] **Step 1: Write failing URL and fence-policy tests** + +Cover: + +```ts +expect(markdownUrlTransform("https://example.com")).toBe( + "https://example.com", +); +expect(markdownUrlTransform("mailto:team@example.com")).toBe( + "mailto:team@example.com", +); +expect(markdownUrlTransform("#summary")).toBe("#summary"); +expect(markdownUrlTransform("javascript:alert(1)")).toBe(""); +expect(markdownUrlTransform("data:text/html,boom")).toBe(""); +expect(extractFenceLanguage("language-ts")).toBe("typescript"); +expect(extractFenceTitle('title="src/app.ts"')).toBe("src/app.ts"); +expect(extractFenceTitle("filename=server.ts")).toBe("server.ts"); +``` + +Normalize common aliases: `js -> javascript`, `ts -> typescript`, +`sh -> shell`, `bash -> shell`, `yml -> yaml`, `md -> markdown`, +`text/plaintext/txt -> text`, and `gitignore -> ini`. + +- [ ] **Step 2: Write failing table-serialization tests** + +Create a real DOM table and assert: + +```ts +expect(serializeTableToMarkdown(table)).toBe( + "| Name | Note |\\n| --- | --- |\\n| Flect | A \\\\| B |", +); +expect(serializeTableToCsv(table)).toBe( + "Name,Note\\r\\nFlect,A | B", +); +``` + +Add a separate row containing `A, B` and assert that CSV quotes it. Also cover +quotes, newlines, empty cells, pipes, and header-only tables. + +- [ ] **Step 3: Run policy tests and witness RED** + +Run: + +```bash +bunx vitest run src/components/markdown-policy.test.ts src/components/markdown-table-serialization.test.ts +``` + +Expected: FAIL because both implementation modules are absent. + +- [ ] **Step 4: Implement minimal pure policies** + +Use `react-markdown`'s `defaultUrlTransform` only after the explicit +allow-list has accepted a URL. Return an empty string for relative paths, +protocol-relative URLs, `file:`, `data:`, `javascript:`, and unknown schemes. + +Implement serializers by reading `table.rows` and `row.cells`, normalizing +whitespace, escaping pipes/backslashes for Markdown, and applying RFC-style +double-quote escaping for CSV fields containing comma, quote, CR, or LF. + +- [ ] **Step 5: Run policy tests GREEN** + +Run: + +```bash +bunx vitest run src/components/markdown-policy.test.ts src/components/markdown-table-serialization.test.ts +``` + +Expected: all tests pass. + +### Task 4: Build the sanitized semantic renderer + +**Files:** + +- Replace: `src/components/message-content.tsx` +- Create: `src/components/message-content.test.tsx` + +**Interfaces:** + +- Consumes: Task 3 URL/fence policy. +- Produces: + +```ts +export interface MessageContentProps { + readonly content: string; + readonly messageRole: "user" | "assistant" | "activity"; + readonly streaming?: boolean; +} + +export function MessageContent(props: MessageContentProps): ReactElement; +``` + +- [ ] **Step 1: Write failing semantic rendering tests** + +Render one assistant message containing: + +```md +# Release notes + +**Strong**, *emphasis*, ~~removed~~, and `inline()`. + +> A quoted decision. + +1. First +2. Second + +- [x] Complete +- [ ] Remaining + +A footnote.[^1] + +[^1]: Supporting detail. +``` + +Assert semantic roles/tags: level-one heading, strong/em/del, blockquote, +ordered list, disabled checked/unchecked checkboxes, inline code, footnote +link, and no literal Markdown markers. + +- [ ] **Step 2: Write failing role-aware line-break tests** + +Assert `line one\nline two` produces a `
` for `messageRole="user"` and +remains one normal paragraph for `messageRole="assistant"`. + +- [ ] **Step 3: Write failing sanitizer and safe-link tests** + +Render: + +```md + +Safe text +[unsafe](javascript:alert(1)) +[safe](https://example.com/docs) +
MoreSafe detail
+``` + +Assert: + +- no `script`, `style`, `onclick`, iframe, object, form, media, or image node; +- “Safe text” and “Safe detail” remain; +- unsafe link has no actionable href; +- safe link has `target="_blank"` and `rel="noopener noreferrer"`; +- details and summary remain semantic and keyboard-native. + +- [ ] **Step 4: Run renderer tests and witness RED** + +Run: + +```bash +bunx vitest run src/components/message-content.test.tsx +``` + +Expected: FAIL because the existing fence splitter cannot render semantics. + +- [ ] **Step 5: Implement the Markdown pipeline** + +Use: + +```tsx +const REMARK_PLUGINS = [remarkGfm, remarkPreserveCodeMeta]; +const REMARK_PLUGINS_WITH_BREAKS = [ + remarkGfm, + remarkBreaks, + remarkPreserveCodeMeta, +]; +const REHYPE_PLUGINS = [ + rehypeRaw, + [rehypeSanitize, FLECT_MARKDOWN_SANITIZE_SCHEMA], +]; +``` + +Build `FLECT_MARKDOWN_SANITIZE_SCHEMA` from `defaultSchema`, explicitly adding +only `details`, `summary`, code metadata, `open`, GFM task-list class names, +and footnote identifiers. Remove `img`, form/media/embed tags, `style`, +`title`, and all event-like attributes. + +Use custom `a`, `details`, `code`, `pre`, and `table` components. At this task, +`pre` and `table` may use semantic, contained plain fallbacks; Tasks 5 and 6 +replace them with interactive components. + +Wrap rendering in a class error boundary whose fallback is: + +```tsx +

{content}

+``` + +- [ ] **Step 6: Run semantic tests GREEN** + +Run: + +```bash +bunx vitest run src/components/message-content.test.tsx +bun run typecheck +``` + +Expected: all tests and typecheck pass. + +### Task 5: Add lazy, bounded syntax highlighting and rich code blocks + +**Files:** + +- Create: `src/components/markdown-highlighter.ts` +- Create: `src/components/markdown-highlighter.test.ts` +- Create: `src/components/markdown-code-block.tsx` +- Create: `src/components/markdown-code-block.test.tsx` +- Modify: `src/components/message-content.tsx` +- Modify: `src/components/icons.tsx` + +**Interfaces:** + +- Produces: + +```ts +export class MarkdownHighlightError extends Schema.TaggedErrorClass()( + "MarkdownHighlightError", + { language: Schema.String }, +) {} + +export const highlightMarkdownCode: ( + code: string, + language: string, +) => Effect.Effect; + +export interface MarkdownCodeBlockProps { + readonly code: string; + readonly language: string; + readonly title?: string; + readonly streaming: boolean; +} +``` + +- [ ] **Step 1: Write failing highlighter tests** + +Assert JavaScript output includes a Shiki `
` and escaped highlighted
+source, unsupported languages fall back to `text`, repeated source returns
+the cached result, and more than the configured cache limit evicts the oldest
+entry. Expose only a test reset/introspection helper under an explicit
+`__markdownHighlightTest` export.
+
+- [ ] **Step 2: Write failing code-block interaction tests**
+
+Provide this Markdown fixture:
+
+````md
+```ts title="src/app.ts"
+const answer: number = 42
+```
+````
+
+Assert:
+
+- header text is `src/app.ts`;
+- the block exposes `data-language="typescript"`;
+- source code is visible before highlighting;
+- `Wrap lines` toggles to `Disable line wrap` and `aria-pressed=true`;
+- `Copy code` writes the exact source through `Clipboard`;
+- success becomes `Copied`;
+- failure becomes `Copy failed` in an `aria-live` status;
+- `streaming` keeps plain code and does not render `.shiki`.
+
+- [ ] **Step 3: Run highlighter/code tests and witness RED**
+
+Run:
+
+```bash
+bunx vitest run src/components/markdown-highlighter.test.ts src/components/markdown-code-block.test.tsx
+```
+
+Expected: FAIL because the modules do not exist.
+
+- [ ] **Step 4: Implement the bounded Effect highlighter**
+
+Use `Effect.tryPromise` around a dynamic:
+
+```ts
+const loadShiki = () => import("shiki/bundle/web");
+```
+
+Call the module's cached `codeToHtml` shorthand with
+`theme: "github-dark-default"`. Retry once with `lang: "text"` after an
+unsupported language. Bound Flect's HTML-result cache to 100 entries and
+5 MiB by evicting oldest insertion-order entries.
+
+- [ ] **Step 5: Implement `MarkdownCodeBlock`**
+
+Keep code source in React text while highlighting is loading. Start the
+highlighter Effect only when `streaming === false`; own its fiber and interrupt
+it from the effect cleanup. Insert only locally generated Shiki HTML.
+
+Copy by yielding `Clipboard` inside a named Effect and running it through
+`browserRuntime` at the event boundary. Use local `idle | copied | failed`
+state, reset acknowledgement after 1.2 seconds, and clear timers on unmount.
+
+Add `CopyIcon`, `CheckIcon`, and `WrapIcon` to `icons.tsx`.
+
+- [ ] **Step 6: Run code tests GREEN**
+
+Run:
+
+```bash
+bunx vitest run src/components/markdown-highlighter.test.ts src/components/markdown-code-block.test.tsx src/components/message-content.test.tsx
+bun run typecheck
+```
+
+Expected: all tests and typecheck pass.
+
+### Task 6: Add contained, copyable tables
+
+**Files:**
+
+- Create: `src/components/markdown-table.tsx`
+- Create: `src/components/markdown-table.test.tsx`
+- Modify: `src/components/message-content.tsx`
+- Modify: `src/components/icons.tsx`
+
+**Interfaces:**
+
+- Consumes: Task 2 Clipboard, Task 3 serializers.
+- Produces:
+
+```ts
+export function MarkdownTable(
+  props: React.ComponentProps<"table">,
+): ReactElement;
+```
+
+- [ ] **Step 1: Write failing table interaction tests**
+
+Render a GFM table and assert:
+
+- semantic table, row, columnheader, and cell roles;
+- wrapper starts with `data-expanded="false"`;
+- `Expand table cells` toggles to `Collapse table cells`;
+- Copy Markdown writes the exact normalized Markdown table;
+- Copy CSV writes CRLF CSV with correct quoting;
+- copy success/failure is announced;
+- Escape or focus behavior is not hijacked by the table.
+
+- [ ] **Step 2: Run table tests and witness RED**
+
+Run:
+
+```bash
+bunx vitest run src/components/markdown-table.test.tsx
+```
+
+Expected: FAIL because `MarkdownTable` does not exist.
+
+- [ ] **Step 3: Implement the table surface**
+
+Use one horizontally scrollable viewport containing the table and a footer
+with `Expand table cells`, `Copy table as Markdown`, and
+`Copy table as CSV` buttons. Run clipboard Effects through `browserRuntime`;
+do not introduce a menu dependency or T3Code's toast system.
+
+Add `ExpandIcon` and `CollapseIcon` to `icons.tsx`.
+
+- [ ] **Step 4: Run table and renderer tests GREEN**
+
+Run:
+
+```bash
+bunx vitest run src/components/markdown-table.test.tsx src/components/message-content.test.tsx
+bun run typecheck
+```
+
+Expected: all tests and typecheck pass.
+
+### Task 7: Integrate role and streaming state into the protected rail
+
+**Files:**
+
+- Modify: `src/components/agent-rail.tsx`
+- Modify: `src/components/agent-rail.test.tsx`
+
+**Interfaces:**
+
+- Consumes: `MessageContentProps` from Task 4.
+- Produces: the latest active assistant message receives
+  `streaming={true}`, and every message receives its actual role.
+
+- [ ] **Step 1: Write failing rail integration tests**
+
+Add an assistant fixture with Markdown and assert it renders a semantic
+heading. Render the controller with `status="streaming"` and assert the latest
+assistant code block remains plain; render `status="ready"` and wait for its
+highlighted state.
+
+- [ ] **Step 2: Run rail tests and witness RED**
+
+Run:
+
+```bash
+bunx vitest run src/components/agent-rail.test.tsx
+```
+
+Expected: FAIL because `AgentRail` does not pass role/streaming props.
+
+- [ ] **Step 3: Pass role and streaming state**
+
+Render:
+
+```tsx
+
+```
+
+- [ ] **Step 4: Run integration tests GREEN**
+
+Run:
+
+```bash
+bunx vitest run src/components/agent-rail.test.tsx src/components/message-content.test.tsx
+```
+
+Expected: all tests pass.
+
+### Task 8: Apply T3Code-quality Flect typography and responsive containment
+
+**Files:**
+
+- Modify: `src/styles.css`
+- Modify: `tests/e2e/flect.spec.ts`
+- Modify: `server/test-runtime.ts`
+
+**Interfaces:**
+
+- Consumes: semantic classes from Tasks 4–7.
+- Produces: production-browser visual and geometry evidence.
+
+- [ ] **Step 1: Add the deterministic Markdown showcase**
+
+Make `FlectTestRuntimeLive.prompt(sessionId, text)` return a representative
+Markdown delta when `text === "Show the Markdown showcase"`; preserve the
+existing deterministic response for every other prompt.
+
+The showcase must contain a heading, paragraph emphasis, quote, task list,
+safe link, details, footnote, table, inline code, and titled TypeScript fence.
+
+- [ ] **Step 2: Write failing production-Chromium assertions**
+
+Add an E2E flow that enters Run, sends the showcase prompt, and verifies:
+
+- heading, quote, task checkbox, details, link, table, and code block appear;
+- external link safety attributes are present;
+- code highlighting completes;
+- wrap and table expansion work;
+- copy buttons acknowledge success;
+- at 720 × 780, `.role-shell` and document scroll widths equal viewport width;
+- code/table inner viewports own any horizontal overflow;
+- all Markdown chrome buttons meet 44 px at compact width; and
+- no console errors are emitted.
+
+- [ ] **Step 3: Run the E2E test and witness RED**
+
+Run:
+
+```bash
+bunx playwright test tests/e2e/flect.spec.ts --grep "renders complete Markdown"
+```
+
+Expected: FAIL because the showcase and visual styles are not complete.
+
+- [ ] **Step 4: Replace minimal message CSS with the Flect Markdown system**
+
+Implement the spec's typography with:
+
+- 0.65 rem block rhythm and zero outer first/last margins;
+- compact 1.25/1.125/1/0.875 rem headings;
+- nested list markers and 0.25 rem list-item rhythm;
+- disabled task-checkbox alignment;
+- rose interaction links with visible keyboard focus;
+- two-pixel blockquote rule;
+- quiet bordered inline-code chip;
+- contained code/table surfaces using existing tokens;
+- code header/action styles and Shiki background bridge;
+- table row separators, collapsed ellipsis, expanded wrapping;
+- native details summary with a rotating chevron marker;
+- thin internal scrollbars;
+- 44 px Markdown action targets at `max-width: 760px`; and
+- reduced-motion acknowledgement/disclosure behavior.
+
+- [ ] **Step 5: Run focused browser tests GREEN**
+
+Run:
+
+```bash
+bunx playwright test tests/e2e/flect.spec.ts --grep "renders complete Markdown"
+bunx playwright test tests/e2e/flect.spec.ts --grep "compact breakpoints"
+```
+
+Expected: both tests pass.
+
+### Task 9: Document evidence and run completion verification
+
+**Files:**
+
+- Create: `docs/verification/2026-07-31-chat-markdown-verification.md`
+- Modify if behavior changed: `DESIGN.md`
+
+**Interfaces:**
+
+- Produces: reproducible source comparison, security evidence, test evidence,
+  browser screenshots, and installed-app smoke evidence.
+
+- [ ] **Step 1: Update the visible design-system owner**
+
+Add a concise `Chat Markdown` section to `DESIGN.md` documenting only the
+shipped visual contract: semantic rhythm, compact headings, code/table
+instruments, token usage, and compact targets. Link to the design spec for
+implementation detail rather than duplicating it.
+
+- [ ] **Step 2: Run full static and automated verification**
+
+Run:
+
+```bash
+bun run check:all
+```
+
+Expected: Effect preparation, Rifty verification, Biome, TypeScript, all
+Vitest tests, all Playwright tests, Rust tests, and the macOS app build exit 0.
+
+- [ ] **Step 3: Inspect the production build in real Chromium**
+
+Start the deterministic runtime and Vite production preview, then use Chrome
+to:
+
+- render the Markdown showcase at desktop and compact widths;
+- exercise details, wrap, table expansion, and copy;
+- inspect accessibility roles and focus;
+- confirm unsafe content is absent;
+- capture desktop, code, table, and compact screenshots;
+- inspect console and network errors; and
+- record exact code/table/document overflow geometry.
+
+- [ ] **Step 4: Rebuild, install, and smoke-test macOS**
+
+Use the app bundle produced by `check:all`. Quit only Flect, move the current
+`/Applications/Flect.app` to a timestamped recoverable Trash backup, install
+the new bundle with `ditto`, verify its ad-hoc signature, launch it, confirm
+the 1180 × 781 native window, and confirm the packaged frontend completes
+`GetRuntime` and `ListModels` over the private Effect RPC bridge.
+
+- [ ] **Step 5: Write the verification record**
+
+Document:
+
+- T3Code reference commit and adapted/excluded behavior;
+- dependency versions and licenses;
+- sanitizer and unsafe-link evidence;
+- unit/E2E/Rust test counts;
+- production bundle sizes and lazy Shiki chunk evidence;
+- real-Chromium interaction and geometry results;
+- installed bundle signature/window/RPC results; and
+- any remaining non-blocking performance follow-up.
+
+- [ ] **Step 6: Run final hygiene checks**
+
+Run:
+
+```bash
+bun run lint
+git diff --check
+git status --short
+```
+
+Expected: lint and diff checks exit 0; status contains only intended,
+uncommitted Flect changes.
diff --git a/docs/superpowers/plans/2026-07-31-flect-embedded-axi.md b/docs/superpowers/plans/2026-07-31-flect-embedded-axi.md
new file mode 100644
index 0000000..fa20699
--- /dev/null
+++ b/docs/superpowers/plans/2026-07-31-flect-embedded-axi.md
@@ -0,0 +1,1372 @@
+# Flect Embedded AXI Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use
+> `superpowers:executing-plans` to implement this plan task-by-task. Steps use
+> checkbox (`- [ ]`) syntax for tracking. This repository currently forbids
+> commits without separate user authorization, so each task ends with a diff
+> and test checkpoint instead of a commit.
+
+**Goal:** Replace the separately shipped `flectctl` and `flect-mcp` binaries
+with one AXI-compliant `flect` command surface embedded in the native app and
+the role-owned browser shell, backed by one Effect command/state authority.
+
+**Architecture:** A reusable Effect `FlectAxiProgram` parses commands and
+renders bounded TOON through source-specific gateways. Native invocations use
+the authenticated loopback broker; App Agent and Shaper use a bounded
+in-process Effect queue whose source identity is captured by their sandbox.
+The Tauri executable remains the only public native executable and forwards
+CLI/MCP modes to the existing private Bun runtime.
+
+**Tech Stack:** TypeScript 7, Effect 4 beta, `@effect/vitest`,
+`@toon-format/toon@4.1.0`, Bun 1.4+, just-bash 3.2.0, Pi 0.82.1, React 19,
+Tauri 2/Rust, MCP v2, Vitest, Playwright/Chromium.
+
+## Global Constraints
+
+- Follow
+  [`../specs/2026-07-31-flect-embedded-axi-design.md`](../specs/2026-07-31-flect-embedded-axi-design.md).
+- Preserve all existing uncommitted T3-style composer, Markdown, control,
+  shell, release, and documentation work.
+- Do not commit, push, merge, publish, release, or modify real agent
+  configuration without separate user authorization.
+- Start every behavior change with a failing observable test and verify that it
+  fails for the intended missing behavior before adding production code.
+- Keep application behavior in Effect: strict Effect Schema boundaries,
+  `Context.Service`, named Layers, `Effect.fn`, typed failures, `Queue`,
+  `Deferred`, `Stream`, `Ref`/`SubscriptionRef`, Scope, and interruption.
+- Use the pinned `.repos/effect` checkout and the repository Effect guides for
+  exact APIs; keep all Effect package versions aligned at `4.0.0-beta.102`.
+- Use the official `@toon-format/toon` package pinned exactly to `4.1.0`; TOON
+  is an output encoding, never application state or transport state.
+- Guardian stays tool-free. App and Shaper stay isolated and cannot forge
+  their command source or broaden their role authority.
+- Browser `flect` must run entirely inside the existing just-bash sandbox and
+  must not call localhost, spawn native processes, expose credentials, or gain
+  host filesystem/network access.
+- Outside control remains disabled by default, loopback-only, explicitly
+  user-enabled, authenticated, attributable, bounded, and revocable.
+- Default stdout follows AXI; stderr is diagnostics only; exit codes are `0`
+  success/no-op, `1` operational failure, and `2` usage failure.
+- Test observable exports, protocols, rendered UI, and real artifacts; never
+  assert that implementation source contains a chosen string.
+
+---
+
+## File map
+
+### New files
+
+- `src/axi/contracts.ts` — AXI invocation, audience, output, exit-code, public
+  failure, and result schemas.
+- `src/axi/output.ts` — bounded projections and official TOON/JSON encoding.
+- `src/axi/output.test.ts` — AXI formatting, truncation, empty-state, channel,
+  and byte-limit behavior.
+- `src/axi/gateway.ts` — transport-neutral `FlectCommandGateway` Effect
+  service.
+- `src/axi/broker-gateway.ts` — gateway backed by `FlectControlClient`.
+- `src/axi/command.ts` — strict noun-first parser and command-local help.
+- `src/axi/command.test.ts` — parser, unknown-input, idempotent syntax, and help
+  behavior.
+- `src/axi/program.ts` — content-first home view and command orchestration.
+- `src/axi/program.test.ts` — gateway-level AXI behavior.
+- `src/axi/agent-command-bus.ts` — bounded in-process request queue with exact
+  Deferred responses.
+- `src/axi/agent-command-bus.test.ts` — capacity, interruption, timeout, and
+  shutdown tests.
+- `src/axi/agent-command-bridge.ts` — source-aware controller consumer.
+- `src/axi/agent-command-bridge.test.ts` — controller/gateway parity and role
+  denial tests.
+- `src/axi/agent-gateway.ts` — role-bound gateway used by the virtual command.
+- `src/shell/flect-command.ts` — just-bash custom command adapter.
+- `src/shell/flect-command.test.ts` — argv, output, source binding, and error
+  projection tests.
+- `cli/flect.ts` — unbundled native-development AXI entrypoint.
+- `cli/flect.test.ts` — native broker adapter and process-facing I/O tests.
+- `server/sidecar-mode.ts` — strict private runtime mode selection.
+- `server/sidecar-mode.test.ts` — RPC/AXI/MCP selection tests.
+- `src/lib/agent-integration.ts` — idempotent Codex, Claude Code, and OpenCode
+  integration planning and mutation service.
+- `src/lib/agent-integration.test.ts` — temporary-root install/repair/remove
+  behavior.
+- `assets/agent-integrations/opencode/flect.js` — dependency-free OpenCode V2
+  plugin template.
+- `.agents/skills/flect/SKILL.md` — generated static discovery skill.
+- `scripts/generate-flect-skill.ts` — generates/checks the skill from the AXI
+  static guidance.
+- `scripts/generate-flect-skill.test.ts` — deterministic generation test.
+- `tests/e2e/embedded-axi.spec.ts` — real-browser role and reactive-state proof.
+
+### Renamed or removed files
+
+- Replace `cli/flectctl.ts` and `cli/flectctl.test.ts` with `cli/flect.ts` and
+  `cli/flect.test.ts` after behavioral characterization is migrated.
+- Keep `cli/flect-mcp.ts` as a source module but remove its auto-running public
+  binary entrypoint; `flect mcp` invokes its exported server.
+- Delete generated `src-tauri/binaries/flectctl-aarch64-apple-darwin` and
+  `src-tauri/binaries/flect-mcp-aarch64-apple-darwin` only after packaging no
+  longer references them.
+- Delete `server/pi-proposal-tool.ts` and its test only after Shaper Bash
+  proposal parity passes.
+
+### Existing files modified
+
+- `package.json`, `bun.lock`
+- `shared/control.ts`, `shared/control.test.ts`
+- `shared/contracts.ts`, `shared/contracts.test.ts`
+- `shared/bun-command.ts`, `shared/bun-command.test.ts`
+- `src/lib/workspace-controller.ts`, `src/lib/workspace-controller.test.ts`
+- `src/lib/agent-workspace.ts`, `src/lib/agent-workspace.test.ts`
+- `src/lib/runtime.ts`
+- `src/shell/sandboxed-shell-service.ts`
+- `src/shell/sandboxed-shell.ts`, `src/shell/sandboxed-shell.test.ts`
+- `server/pi-runtime.ts`, `server/pi-runtime.test.ts`
+- `server/sidecar.ts`
+- `cli/flect-client.ts`, `cli/flect-client.test.ts`
+- `cli/flect-mcp.ts`, `cli/flect-mcp.test.ts`
+- `src-tauri/src/main.rs`, `src-tauri/src/lib.rs`
+- `src-tauri/tauri.conf.json`, `src-tauri/capabilities/main.json`
+- `scripts/build-sidecar.ts`
+- `scripts/package-release.ts`, `scripts/package-release.test.ts`
+- `scripts/smoke-pi.ts`
+- `src/components/diagnostics-panel.tsx` and its test
+- `src/lib/tauri-transport.ts` and its test
+- `tests/e2e/flect.spec.ts`, `playwright.config.ts`
+- `AGENTS.md`, `ARCHITECTURE.md`, `CONTRIBUTING.md`, `README.md`, `VISION.md`
+- `docs/local-control.md`, `docs/trust-model.md`
+
+---
+
+### Task 1: AXI result contract and TOON output boundary
+
+**Files:**
+
+- Create: `src/axi/contracts.ts`
+- Create: `src/axi/output.ts`
+- Create: `src/axi/output.test.ts`
+- Modify: `package.json`
+- Modify: `bun.lock`
+
+**Interfaces:**
+
+- Produces `AxiAudience`, `AxiInvocation`, `AxiPublicError`, `AxiRunResult`,
+  `renderAxiSuccess`, and `renderAxiFailure`.
+- `AxiRunResult` is the only value process and just-bash adapters write to
+  their output channels.
+
+- [ ] **Step 1: Write the failing output tests**
+
+Cover these exact cases in `src/axi/output.test.ts` with `@effect/vitest`:
+
+```ts
+it.effect("renders compact TOON with a definitive empty collection", () =>
+  Effect.gen(function* () {
+    const result = yield* renderAxiSuccess({
+      format: "toon",
+      value: { count: 0, actions: [] },
+    })
+    assert.strictEqual(result.exitCode, 0)
+    assert.strictEqual(result.stderr, "")
+    assert.match(result.stdout, /^count: 0\nactions\[0\]:$/)
+  }),
+)
+
+it.effect("puts structured errors on stdout with usage exit code 2", () =>
+  Effect.gen(function* () {
+    const result = yield* renderAxiFailure(
+      AxiPublicError.make({
+        code: "unknown-flag",
+        message: "Unknown flag --stat for action list.",
+        help: ["Run `flect action list --help`"],
+      }),
+      "toon",
+      2,
+    )
+    assert.strictEqual(result.exitCode, 2)
+    assert.strictEqual(result.stderr, "")
+    assert.include(result.stdout, "code: unknown-flag")
+  }),
+)
+```
+
+Also assert JSON compatibility, a 1,000-character default preview with total
+character count, `--full` preservation, newline termination, and rejection of
+encoded output above the shared byte limit.
+
+- [ ] **Step 2: Run the focused test and confirm RED**
+
+Run:
+
+```bash
+bunx vitest run src/axi/output.test.ts
+```
+
+Expected: failure because `src/axi/output.ts` does not exist.
+
+- [ ] **Step 3: Pin the official encoder**
+
+Run:
+
+```bash
+bun add --exact @toon-format/toon@4.1.0
+```
+
+Confirm `package.json` contains exactly `"@toon-format/toon": "4.1.0"`.
+
+- [ ] **Step 4: Implement typed AXI results and formatting**
+
+Use these public shapes in `src/axi/contracts.ts`:
+
+```ts
+export const AxiAudience = Schema.Literals(["native", "app", "shaper"])
+
+export class AxiInvocation extends Schema.Class(
+  "AxiInvocation",
+)({
+  audience: AxiAudience,
+  bin: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(2_048)),
+  format: Schema.Literals(["toon", "json"]),
+  full: Schema.Boolean,
+}) {}
+
+export class AxiPublicError extends Schema.Class(
+  "AxiPublicError",
+)({
+  code: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(80)),
+  message: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(500)),
+  help: Schema.Array(Schema.String.check(Schema.isMaxLength(500))).check(
+    Schema.isMaxLength(4),
+  ),
+}) {}
+
+export class AxiRunResult extends Schema.Class("AxiRunResult")({
+  exitCode: Schema.Literals([0, 1, 2]),
+  stdout: Schema.String,
+  stderr: Schema.String,
+}) {}
+```
+
+In `output.ts`, use `encode` from `@toon-format/toon`, `JSON.stringify` only
+inside `Effect.try`, a recursive bounded projection before encoding, and a
+final UTF-8 byte check. Map encoder defects to one `AxiFormatError` tagged
+error; never leak encoder details.
+
+- [ ] **Step 5: Run GREEN and the existing shared contract tests**
+
+```bash
+bunx vitest run src/axi/output.test.ts shared/control.test.ts
+```
+
+Expected: all selected tests pass without warnings.
+
+- [ ] **Step 6: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- package.json bun.lock src/axi/contracts.ts src/axi/output.ts src/axi/output.test.ts
+```
+
+---
+
+### Task 2: Strict noun-first AXI parser and transport-neutral program
+
+**Files:**
+
+- Create: `src/axi/gateway.ts`
+- Create: `src/axi/command.ts`
+- Create: `src/axi/command.test.ts`
+- Create: `src/axi/program.ts`
+- Create: `src/axi/program.test.ts`
+- Create: `src/axi/broker-gateway.ts`
+- Create: `cli/flect.ts`
+- Create: `cli/flect.test.ts`
+- Modify: `cli/flect-client.ts`
+- Remove after parity: `cli/flectctl.ts`, `cli/flectctl.test.ts`
+
+**Interfaces:**
+
+```ts
+export interface FlectCommandGatewayShape {
+  readonly audience: AxiAudience
+  readonly bin: string
+  readonly status: Effect.Effect
+  readonly inspect: Effect.Effect
+  readonly logs: Effect.Effect
+  readonly events: (
+    after: number,
+  ) => Stream.Stream
+  readonly command: (
+    command: FlectCommand,
+    expectedSequence?: number,
+  ) => Effect.Effect
+}
+```
+
+- `runFlect(argv)` returns `Effect`.
+- `BrokerFlectCommandGatewayLive` adapts the existing authenticated client and
+  translates its private errors into stable gateway errors.
+
+- [ ] **Step 1: Characterize and then replace the old CLI behavior**
+
+Copy the useful existing `flectctl` tests into `cli/flect.test.ts`, then change
+their required behavior:
+
+- no arguments request the live home view rather than help;
+- default output is TOON;
+- `--json` remains valid;
+- errors use stdout and exit `1` or `2`;
+- unknown flags fail before the gateway is called;
+- noun-first commands are required;
+- `favorite add|remove` and `extensions enable|disable` replace toggles; and
+- `--help` works at every noun and leaf.
+
+- [ ] **Step 2: Add parser RED tests**
+
+Use table-driven tests for the complete command catalog from the design. At
+minimum, assert these concrete parses:
+
+```ts
+yield* assertParse(["mode", "set", "run"], {
+  type: "set-mode",
+  mode: "run",
+})
+yield* assertParse(["action", "invoke", "run-report"], {
+  type: "invoke-interface-action",
+  nodeId: "run-report",
+})
+yield* assertParse(["extensions", "enable", "shaper"], {
+  type: "set-external-extensions",
+  role: "shaper",
+  enabled: true,
+})
+yield* assertUsage(["action", "list", "--stat"], "unknown-flag")
+```
+
+- [ ] **Step 3: Run parser/program/CLI tests and confirm RED**
+
+```bash
+bunx vitest run src/axi/command.test.ts src/axi/program.test.ts cli/flect.test.ts
+```
+
+Expected: failure because the AXI parser/program modules do not exist.
+
+- [ ] **Step 4: Implement the parser as closed command definitions**
+
+Represent each leaf with its exact path, allowed flags, usage, examples,
+audiences, and an Effect parser. Do not scan and remove global flags from
+arbitrary positions as `flectctl` currently does. Parse recognized global
+flags first, then reject every unconsumed argument by name.
+
+The only universal flags are `--help`, `--json`, and `--full`. `--stdin`,
+`--fields`, `--limit`, `--after`, `--role`, and `--operation` are leaf-local.
+The removed `raw` escape hatch is not part of AXI; MCP/HTTP retain the strict
+closed command schema for machine clients.
+
+- [ ] **Step 5: Implement content-first program behavior**
+
+The native no-argument output must contain `bin`, `description`, workspace
+mode/phase/sequence, compact role status, proposal summary when present, and
+two or three contextual commands. If control is disabled or no workspace is
+connected, return a successful, definitive state such as:
+
+```text
+bin: /Applications/Flect.app/Contents/MacOS/flect
+description: Inspect and operate the live Flect workspace
+control: disabled
+workspace: unavailable
+help[2]:
+  Open Flect and enable Local control in Diagnostics
+  Run `flect app` to open Flect
+```
+
+Mutations wait for the exact terminal receipt already provided by
+`FlectControlClient.command`, then fetch one relevant post-state projection in
+the same command response.
+
+- [ ] **Step 6: Implement broker and process adapters**
+
+`cli/flect.ts` exports `runFlectCli(argv, io)` and has a guarded
+`import.meta.main` boundary for repository development. `io.stdout` receives
+only `result.stdout`; `io.stderr` receives only `result.stderr`; the process
+exit code is `result.exitCode`.
+
+Keep state-directory and client-name selection as private adapter options, not
+public agent-facing help. Reject missing option values.
+
+- [ ] **Step 7: Run GREEN and remove the old entrypoint**
+
+```bash
+bunx vitest run src/axi/command.test.ts src/axi/program.test.ts cli/flect.test.ts cli/flect-client.test.ts
+```
+
+After the replacement tests pass, remove `cli/flectctl.ts` and
+`cli/flectctl.test.ts`; update imports and the package script from `flectctl`
+to `flect`.
+
+- [ ] **Step 8: Review the task diff without committing**
+
+```bash
+git diff --check
+rg -n "flectctl" cli package.json
+git diff -- cli src/axi package.json
+```
+
+Expected: no executable or script named `flectctl` remains in active CLI code.
+
+---
+
+### Task 3: Idempotent shared commands and agent source authorization
+
+**Files:**
+
+- Modify: `shared/control.ts`
+- Modify: `shared/control.test.ts`
+- Modify: `src/lib/workspace-controller.ts`
+- Modify: `src/lib/workspace-controller.test.ts`
+- Modify: `src/lib/agent-workspace.ts`
+- Modify: `src/lib/agent-workspace.test.ts`
+- Modify: `src/hooks/use-workspace.ts`
+- Modify: UI tests that construct the replaced commands
+
+**Interfaces:**
+
+Add these strict schema values:
+
+```ts
+export class AgentCommandSource extends Schema.Class(
+  "AgentCommandSource",
+)({
+  kind: Schema.Literal("agent"),
+  role: InteractiveAgentRole,
+  sessionId: Identifier,
+  parentOperationId: OperationId,
+  requestId: ToolCallId,
+}) {}
+
+export class SetModelFavorite extends Schema.Class(
+  "SetModelFavorite",
+)({
+  type: Schema.Literal("set-model-favorite"),
+  model: ModelSelection,
+  favorite: Schema.Boolean,
+}) {}
+
+export class SetExternalExtensions extends Schema.Class(
+  "SetExternalExtensions",
+)({
+  type: Schema.Literal("set-external-extensions"),
+  role: InteractiveAgentRole,
+  enabled: Schema.Boolean,
+}) {}
+```
+
+Remove `ToggleModelFavorite` and `ToggleExternalExtensions` only after every UI,
+CLI, MCP, and test caller uses explicit desired state.
+
+- [ ] **Step 1: Write schema and authorization RED tests**
+
+Test strict decoding of `AgentCommandSource`, excess-property rejection, and
+explicit state commands. Add a controller policy matrix with each command as a
+row and `user`, `control`, `app`, and `shaper` as columns.
+
+Mandatory denial assertions:
+
+- App cannot set mode, submit Shaper work, change revisions, safe mode,
+  models/extensions, control, rail, or another role.
+- Shaper cannot accept/reject/rollback, safe mode, product actions,
+  models/extensions, control, rail, or another role.
+- Any agent cannot enable control.
+- Control source cannot enable control.
+- Guardian is not representable as an interactive agent source.
+
+- [ ] **Step 2: Confirm RED**
+
+```bash
+bunx vitest run shared/control.test.ts src/lib/workspace-controller.test.ts
+```
+
+Expected: the new source and set commands are absent and policy tests fail.
+
+- [ ] **Step 3: Implement source and explicit-state schemas**
+
+Extend `FlectCommandSource` and `FlectCommand`. Update operation/message/event
+attribution branches so agent sources retain role and parent operation without
+being mistaken for outside clients.
+
+- [ ] **Step 4: Implement controller authorization before claim**
+
+Keep authorization inside `FlectWorkspaceController.authorize`. Use an
+exhaustive command switch by source kind; do not derive security from parser
+audiences or hidden help. Return `ControlUnauthorized` with bounded public copy.
+
+- [ ] **Step 5: Make state changes idempotent**
+
+Change AgentWorkspace methods to:
+
+```ts
+readonly setModelFavorite: (
+  selection: ModelSelection,
+  favorite: boolean,
+) => Effect.Effect
+readonly setExternalExtensions: (
+  role: InteractiveAgentRole,
+  enabled: boolean,
+) => Effect.Effect
+```
+
+If current state already equals the request, return success without refreshing
+or replacing Pi sessions. Add tests proving no close/create operation occurs
+for an already-satisfied request.
+
+- [ ] **Step 6: Migrate UI and adapters**
+
+Visible toggle controls calculate explicit desired state from the current
+snapshot and dispatch the set command. MCP's raw closed union automatically
+uses the new schema; old toggle commands fail strict decoding.
+
+- [ ] **Step 7: Run GREEN**
+
+```bash
+bunx vitest run shared/control.test.ts src/lib/workspace-controller.test.ts src/lib/agent-workspace.test.ts src/app.test.tsx src/components/model-menu.test.tsx cli/flect-mcp.test.ts
+```
+
+- [ ] **Step 8: Review the task diff without committing**
+
+```bash
+git diff --check
+rg -n "ToggleModelFavorite|ToggleExternalExtensions|toggle-model-favorite|toggle-external-extensions" shared src cli server
+```
+
+Expected: no old toggle schema or call site remains.
+
+---
+
+### Task 4: Bounded in-process agent command bus and controller bridge
+
+**Files:**
+
+- Create: `src/axi/agent-command-bus.ts`
+- Create: `src/axi/agent-command-bus.test.ts`
+- Create: `src/axi/agent-command-bridge.ts`
+- Create: `src/axi/agent-command-bridge.test.ts`
+- Create: `src/axi/agent-gateway.ts`
+- Modify: `src/lib/runtime.ts`
+
+**Interfaces:**
+
+```ts
+export type AgentGatewayOperation =
+  | { readonly type: "inspect" }
+  | { readonly type: "logs" }
+  | { readonly type: "command"; readonly command: FlectCommand }
+
+export interface AgentCommandBusShape {
+  readonly submit: (
+    source: AgentCommandSource,
+    operation: AgentGatewayOperation,
+  ) => Effect.Effect
+  readonly take: Effect.Effect
+  readonly shutdown: Effect.Effect
+}
+```
+
+`AgentCommandRequest` is internal and carries a typed `Deferred`; it is not a
+Schema boundary or persisted value. Queue capacity is 32 and each request has
+a 30-second deadline.
+
+- [ ] **Step 1: Write queue lifecycle RED tests**
+
+Test exact response delivery, interruption removing/failing a pending request,
+capacity rejection, timeout with `TestClock`, and scoped shutdown failing all
+pending requests. Assert no unbounded queue or orphan fiber remains.
+
+- [ ] **Step 2: Confirm RED**
+
+```bash
+bunx vitest run src/axi/agent-command-bus.test.ts
+```
+
+- [ ] **Step 3: Implement the bus with Queue and Deferred**
+
+Use `Queue.bounded(32)`, one `Deferred` per request, `Effect.timeout`, and a
+scoped finalizer that marks the service closed, shuts down the queue, and
+completes pending Deferreds with `AgentCommandBusUnavailable`. Do not use an
+EventEmitter, Promise map, module global, or polling.
+
+- [ ] **Step 4: Write bridge RED tests**
+
+Provide test Layers for controller and bus. Prove:
+
+- inspect and logs are returned without a transport round trip;
+- allowed App action dispatch gets an agent source envelope;
+- forbidden App shaping fails before controller mutation;
+- Shaper proposal-related child operations retain `parentOperationId`; and
+- controller errors arrive on the exact caller's Deferred.
+
+- [ ] **Step 5: Implement the scoped bridge**
+
+The bridge takes the controller's current workspace ID, creates a fresh command
+ID, dispatches the envelope, and completes the exact Deferred. It handles
+requests sequentially by default; controller long work may fork only where an
+existing cancellation requirement demands it. Name the consume and dispatch
+operations with `Effect.fn` and annotate role, parent operation, and command ID
+without logging payloads.
+
+- [ ] **Step 6: Compose the acyclic Layer graph**
+
+Build one shared bus first, provide it to the role-owned shell and
+AgentWorkspace, construct the controller, then start the bridge as a scoped
+consumer. `ManagedRuntime.make` remains the sole browser runtime boundary.
+
+- [ ] **Step 7: Run GREEN and current control bridge tests**
+
+```bash
+bunx vitest run src/axi/agent-command-bus.test.ts src/axi/agent-command-bridge.test.ts src/lib/workspace-control-bridge.test.ts src/lib/runtime.test.ts
+```
+
+If `src/lib/runtime.test.ts` does not exist, cover composition through the
+exported browser runtime in `src/hooks/use-workspace.test.tsx`; do not add a
+source-string test.
+
+- [ ] **Step 8: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- src/axi src/lib/runtime.ts
+```
+
+---
+
+### Task 5: Reserved `flect` command inside role-owned just-bash
+
+**Files:**
+
+- Create: `src/shell/flect-command.ts`
+- Create: `src/shell/flect-command.test.ts`
+- Modify: `src/shell/sandboxed-shell-service.ts`
+- Modify: `src/shell/sandboxed-shell.ts`
+- Modify: `src/shell/sandboxed-shell.test.ts`
+- Modify: `src/lib/agent-workspace.ts`
+
+**Interfaces:**
+
+Extend execution context without trusting environment variables:
+
+```ts
+export interface SandboxedAgentContext {
+  readonly sessionId: string
+  readonly parentOperationId: string
+  readonly requestId: string
+}
+
+export interface SandboxedShellExecuteOptions {
+  readonly signal?: AbortSignal
+  readonly agentContext?: SandboxedAgentContext
+}
+```
+
+The role remains the existing non-user-controlled `execute(role, ...)`
+argument. `makeFlectCommand(role, agentContext)` returns a just-bash custom
+command backed by `FlectAxiProgram` and `AgentFlectCommandGatewayLive`.
+
+- [ ] **Step 1: Write reserved-command RED tests**
+
+Prove all of the following for both roles:
+
+- `flect` prints `runtime: browser-embedded` and the role-specific home state;
+- `flect --help` is concise and role-specific;
+- pipes and redirection work;
+- `alias flect=false`, a shell function, a `/workspace/flect` file, and PATH
+  changes cannot shadow the command;
+- `FLECT_ROLE=shaper flect ...` cannot change an App source;
+- a missing `agentContext` fails safely rather than creating anonymous
+  authority; and
+- cancellation maps to exit `1` without stopping the shell workspace.
+
+- [ ] **Step 2: Confirm RED**
+
+```bash
+bunx vitest run src/shell/flect-command.test.ts src/shell/sandboxed-shell.test.ts
+```
+
+- [ ] **Step 3: Implement the custom command**
+
+Follow the existing reserved `bun` pattern: generate a randomized hidden
+command name, register one custom command, and use an AST transform to rewrite
+the visible `flect` command. Keep separate hidden names per role workspace.
+Pass args as an argv array directly to `FlectAxiProgram`; never reconstruct a
+shell command string.
+
+Return `AxiRunResult.stdout`, `stderr`, and `exitCode` through just-bash. AXI
+errors remain on command stdout; internal diagnostics remain stderr.
+
+- [ ] **Step 4: Supply authenticated shell-call context**
+
+In `AgentWorkspace.executeShellRequest`, pass the current Pi session ID,
+controller operation ID, and Pi shell request ID through
+`SandboxedShellExecuteOptions.agentContext`. Do not add them to shell env or
+workspace files.
+
+- [ ] **Step 5: Run GREEN and browser Bun regression tests**
+
+```bash
+bunx vitest run src/shell/flect-command.test.ts src/shell/sandboxed-shell.test.ts src/shell/bun-command-live.test.ts src/lib/agent-workspace.test.ts
+```
+
+- [ ] **Step 6: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- src/shell src/lib/agent-workspace.ts
+```
+
+---
+
+### Task 6: Shaper proposal completion through Bash
+
+**Files:**
+
+- Modify: `shared/contracts.ts`, `shared/contracts.test.ts`
+- Modify: `shared/bun-command.ts`, `shared/bun-command.test.ts`
+- Modify: `server/pi-runtime.ts`, `server/pi-runtime.test.ts`
+- Modify: `src/lib/agent-workspace.ts`, `src/lib/agent-workspace.test.ts`
+- Modify: `src/lib/workspace-controller.ts`,
+  `src/lib/workspace-controller.test.ts`
+- Modify: `src/shell/flect-command.ts`, `src/shell/flect-command.test.ts`
+- Remove after parity: `server/pi-proposal-tool.ts`,
+  `server/pi-proposal-tool.test.ts`
+
+**Interfaces:**
+
+The browser-only `flect interface validate|propose ` adapter reads from
+the role's existing just-bash `IFileSystem`, parses JSON as unknown, and runs
+the same strict `validateInterfaceDocument` boundary. A successful proposal
+command produces a bounded internal completion marker associated with the
+current Shaper request; only the validated `InterfaceDocument` crosses that
+marker.
+
+- [ ] **Step 1: Write RED tests for Shaper CLI proposal flow**
+
+Test a complete Shaper turn whose only Pi tool is Bash:
+
+1. Pi runs `flect interface schema`.
+2. Pi writes `/workspace/interface.json`.
+3. Pi runs `flect interface validate /workspace/interface.json`.
+4. Pi runs `flect interface propose /workspace/interface.json`.
+5. The existing outer `submit-shaper-instruction` controller operation creates
+   exactly one preview revision.
+6. The command returns revision/name/status in TOON.
+
+Also test invalid JSON, schema issues with field paths, path escape, two
+proposal calls in one turn, no proposal call, and App attempting the command.
+
+- [ ] **Step 2: Confirm RED**
+
+```bash
+bunx vitest run src/shell/flect-command.test.ts src/lib/agent-workspace.test.ts server/pi-runtime.test.ts src/lib/workspace-controller.test.ts
+```
+
+- [ ] **Step 3: Add a typed per-turn proposal latch**
+
+Own the latch in AgentWorkspace, keyed by `parentOperationId` and Shaper shell
+request ID. The first valid proposal wins; a second returns an idempotent no-op
+only when the document is identical and otherwise a conflict. Scope and clear
+it around the Shaper turn with `Effect.acquireUseRelease`; never persist it or
+expose it to App.
+
+- [ ] **Step 4: Change Pi Shaper from a dedicated proposal tool to Bash**
+
+Update the immutable Shaper instructions to name the exact four commands and
+state that `flect interface propose` must be its final action. Build the Shaper
+session with only the existing Bash tool. Keep Guardian tool-free and App Bash
+unchanged.
+
+Change Shape streaming so a normally completed Pi turn is terminal without
+requiring a server-owned proposal tool event. Browser AgentWorkspace requires
+the proposal latch before it considers the turn successful. If the first turn
+finishes without a valid proposal, issue one bounded corrective prompt in the
+same Shaper session; the second miss fails safely.
+
+- [ ] **Step 5: Preserve controller authority**
+
+AgentWorkspace returns the validated latched candidate to the existing outer
+controller command. The controller alone calls `ShapingKernel.propose`, emits
+the revision transition, and completes the parent operation. The latch is not
+revision state and cannot accept or activate its own candidate.
+
+- [ ] **Step 6: Remove the old Pi tool after parity**
+
+When all focused tests pass with Shaper configured as Bash-only, remove
+`pi-proposal-tool.ts`, its tests/imports, TypeBox proposal schema, and old
+`proposal_submitted` private event paths. Keep public validation-failure events
+if the UI still consumes them; now create them from CLI validation failures.
+
+- [ ] **Step 7: Run GREEN and Pi smoke**
+
+```bash
+bunx vitest run server/pi-runtime.test.ts server/pi-shell-bridge.test.ts src/lib/agent-workspace.test.ts src/lib/workspace-controller.test.ts src/shell/flect-command.test.ts shared/contracts.test.ts shared/bun-command.test.ts
+bun run test:pi-smoke
+```
+
+The credential-dependent smoke may report setup-required when Pi is not
+authenticated; that is not a pass. Before final completion, run it with the
+already configured Pi authentication and require the documented success.
+
+- [ ] **Step 8: Review the task diff without committing**
+
+```bash
+git diff --check
+rg -n "propose_interface|pi-proposal-tool" server src shared
+```
+
+Expected after removal: no active Pi tool or instruction references remain.
+
+---
+
+### Task 7: App action invocation through embedded Bash
+
+**Files:**
+
+- Modify: `src/axi/program.ts`, `src/axi/program.test.ts`
+- Modify: `src/axi/agent-command-bridge.ts`,
+  `src/axi/agent-command-bridge.test.ts`
+- Modify: `src/lib/workspace-controller.ts`,
+  `src/lib/workspace-controller.test.ts`
+- Modify: `src/components/interface-renderer.tsx` only if action projection is
+  currently UI-local
+
+**Interfaces:**
+
+- `flect action list` projects visible action node ID, label, action type, and
+  availability from the accepted validated document.
+- `flect action inspect ` returns declaration and current grant state.
+- `flect action invoke ` dispatches the existing
+  `InvokeInterfaceAction` command as an App agent child operation.
+
+- [ ] **Step 1: Write RED tests**
+
+Prove list has definitive zero state, invoke returns combined action outcome
+and post-state, missing node is structured exit `1`, and an App source cannot
+invoke an action absent from the accepted document or lacking its capability
+grant. Shaper invocation must be denied.
+
+- [ ] **Step 2: Confirm RED**
+
+```bash
+bunx vitest run src/axi/program.test.ts src/axi/agent-command-bridge.test.ts src/lib/workspace-controller.test.ts
+```
+
+- [ ] **Step 3: Move action discovery behind controller projection**
+
+Do not parse React DOM. Reuse the controller's validated `InterfaceDocument`
+walk and capability broker state. Expose one typed projection used by React and
+AXI so label/availability cannot drift.
+
+- [ ] **Step 4: Link child operation evidence**
+
+The nested action operation records `AgentCommandSource.parentOperationId`,
+role `app`, session ID, and shell request ID. Do not log prompt, bearer, or raw
+action payload. The parent turn remains interruptible.
+
+- [ ] **Step 5: Run GREEN**
+
+```bash
+bunx vitest run src/axi/program.test.ts src/axi/agent-command-bridge.test.ts src/lib/workspace-controller.test.ts src/components/interface-renderer.test.tsx
+```
+
+- [ ] **Step 6: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- src/axi src/lib/workspace-controller.ts src/components/interface-renderer.tsx
+```
+
+---
+
+### Task 8: One native `flect` executable with AXI and MCP modes
+
+**Files:**
+
+- Create: `server/sidecar-mode.ts`, `server/sidecar-mode.test.ts`
+- Modify: `server/sidecar.ts`
+- Modify: `cli/flect-mcp.ts`, `cli/flect-mcp.test.ts`
+- Modify: `src-tauri/src/main.rs`, `src-tauri/src/lib.rs`
+- Modify: `scripts/build-sidecar.ts`
+- Modify: `src-tauri/tauri.conf.json`
+- Modify: `package.json`
+
+**Interfaces:**
+
+Private runtime modes are exactly `rpc`, `axi`, and `mcp`. The Rust host passes
+one private mode marker before user arguments; unknown private modes fail
+closed.
+
+- [ ] **Step 1: Write sidecar mode RED tests**
+
+Test no args selects RPC, `--flect-private-mode=axi` selects AXI and strips
+only that marker, `mcp` selects MCP, and unknown/duplicate markers fail with a
+typed startup error.
+
+- [ ] **Step 2: Write Rust dispatch RED tests**
+
+Extract a pure `select_launch_mode(args, stdin_is_terminal)` function and test:
+
+- Finder-like no-tty/no-args -> GUI;
+- terminal/no-args -> AXI;
+- `app` -> GUI;
+- `mcp` -> MCP;
+- every other command -> AXI; and
+- private mode flags supplied by users are rejected.
+
+- [ ] **Step 3: Confirm RED**
+
+```bash
+bunx vitest run server/sidecar-mode.test.ts cli/flect-mcp.test.ts
+cargo test --manifest-path src-tauri/Cargo.toml
+```
+
+- [ ] **Step 4: Implement one multi-mode Bun runtime**
+
+Refactor `server/sidecar.ts` so it constructs exactly one selected Layer:
+
+- RPC: existing Effect RPC server, control broker, and Pi runtime;
+- AXI: `runFlectCli` with `BrokerFlectCommandGatewayLive`; or
+- MCP: exported `serveFlectMcp` with the same broker gateway.
+
+Keep `registerBunOAuthFlows()` in modes that need Pi/runtime provider support.
+Do not start RPC or Pi for a broker-only AXI/MCP client.
+
+- [ ] **Step 5: Implement the Rust public dispatcher**
+
+Before `flect_lib::run()`, use `std::io::IsTerminal` to select mode. AXI/MCP
+locate sibling `flect-runtime`, inherit stdio, pass the private marker plus
+arguments, and propagate exit status. Rust recognizes only host lifecycle
+`app`; it does not parse domain flags or render output.
+
+- [ ] **Step 6: Build only the private runtime helper**
+
+Change `scripts/build-sidecar.ts` to one compile target:
+
+```text
+src-tauri/binaries/flect-runtime-aarch64-apple-darwin
+```
+
+Remove `binaries/flectctl` and `binaries/flect-mcp` from Tauri `externalBin`.
+Package scripts expose `flect` and `flect:mcp` for source development, both
+through the shared modules, without compiling public companion executables.
+
+- [ ] **Step 7: Run GREEN and inspect the bundle**
+
+```bash
+bunx vitest run server/sidecar-mode.test.ts cli/flect.test.ts cli/flect-mcp.test.ts
+cargo test --manifest-path src-tauri/Cargo.toml
+bun run build:sidecar
+bun run build:desktop -- --bundles app
+find src-tauri/target/release/bundle/macos/Flect.app/Contents/MacOS -maxdepth 1 -type f -print
+```
+
+Expected files include `flect` and `flect-runtime`; `flectctl` and `flect-mcp`
+must be absent.
+
+- [ ] **Step 8: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- server cli src-tauri scripts/build-sidecar.ts package.json
+```
+
+---
+
+### Task 9: Safe command-line link and opt-in agent integrations
+
+**Files:**
+
+- Create: `src/lib/agent-integration.ts`,
+  `src/lib/agent-integration.test.ts`
+- Create: `assets/agent-integrations/opencode/flect.js`
+- Modify: `src-tauri/src/lib.rs`
+- Modify: `src/lib/tauri-transport.ts`, `src/lib/tauri-transport.test.ts`
+- Modify: `src/components/diagnostics-panel.tsx`,
+  `src/components/diagnostics-panel.test.tsx`
+- Modify: `src/axi/program.ts`, `src/axi/program.test.ts`
+
+**Interfaces:**
+
+- Native host commands inspect/install/remove only the fixed user link
+  `~/.local/bin/flect` targeting the current installed app executable.
+- Agent integrations implement `status`, `install`, and `remove` for `codex`,
+  `claude`, and `opencode` against an injected configuration root.
+
+- [ ] **Step 1: Write Rust link lifecycle RED tests**
+
+Using a temporary directory and explicit current-executable fixture, prove
+install creates the parent and symlink, reinstall is a no-op, repair updates a
+stale Flect-owned link, a regular file or foreign link is never overwritten,
+and removal deletes only a link targeting Flect.
+
+- [ ] **Step 2: Write agent integration RED tests**
+
+Use temporary roots; never inspect or modify the developer's real config.
+Assert exact idempotent merge/remove behavior:
+
+- Codex: `.codex/hooks.json`, `SessionStart` matcher
+  `startup|resume|clear|compact`, command `flect context --host codex`, and
+  `additionalContextLimit: 1200`; preserve unrelated hook groups.
+- Claude Code: `.claude/settings.local.json`, the same SessionStart matcher,
+  command `flect context --host claude`, and preserved unrelated settings.
+- OpenCode: `.opencode/plugins/flect.js`, a dependency-free V2 plugin with ID
+  `dev.akua.flect-context`; its request hook adds the bounded output of
+  `flect context --host opencode` to `event.system` once per session and after
+  a compaction signal; preserve unrelated plugins/config.
+
+Removal must delete only entries carrying Flect's stable ID/description and
+leave user-authored commands untouched even when text is similar.
+
+- [ ] **Step 3: Confirm RED**
+
+```bash
+cargo test --manifest-path src-tauri/Cargo.toml
+bunx vitest run src/lib/agent-integration.test.ts src/lib/tauri-transport.test.ts src/axi/program.test.ts
+```
+
+- [ ] **Step 4: Implement the fixed native link capability**
+
+Use Tauri's home-directory resolver and Rust symlink APIs. Accept no arbitrary
+source/destination from WebView or CLI. Return a typed status containing
+`absent`, `installed`, `stale`, or `conflict` plus the public link path. Expose
+buttons in Diagnostics with exact confirmation copy and browser-unavailable
+state.
+
+- [ ] **Step 5: Implement Effect-owned config mutations**
+
+Define a platform file capability injected in tests. Decode existing JSON as
+unknown through strict schemas that preserve unrelated JSON values while
+validating the owned subtree. Write atomically with private user permissions.
+Do not invoke host agent CLIs or interactive installers.
+
+Use current authoritative formats verified on 2026-07-31:
+
+- Codex hooks documentation in the current Codex manual;
+- Claude Code hooks at ; and
+- OpenCode V2 plugin request hooks at
+  .
+
+- [ ] **Step 6: Implement `context` and setup commands**
+
+`flect context --host ` emits a static discovery line plus bounded live
+workspace state and role/action suggestions; it never emits the control bearer.
+`flect setup agent install|remove ` uses the Effect integration service.
+`flect setup status` reports shell and all agent integrations with definitive
+states.
+
+- [ ] **Step 7: Run GREEN**
+
+```bash
+cargo test --manifest-path src-tauri/Cargo.toml
+bunx vitest run src/lib/agent-integration.test.ts src/lib/tauri-transport.test.ts src/components/diagnostics-panel.test.tsx src/axi/program.test.ts
+```
+
+- [ ] **Step 8: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- src/lib/agent-integration.ts src-tauri/src/lib.rs src/components/diagnostics-panel.tsx assets/agent-integrations
+```
+
+---
+
+### Task 10: Generated Flect skill and durable repository rules
+
+**Files:**
+
+- Create: `scripts/generate-flect-skill.ts`
+- Create: `scripts/generate-flect-skill.test.ts`
+- Create: `.agents/skills/flect/SKILL.md`
+- Modify: `package.json`
+- Modify: `AGENTS.md`
+
+**Interfaces:**
+
+- `generateFlectSkill({ check })` renders static agent guidance from the same
+  command metadata used by AXI help/home output.
+- `bun run check:flect-skill` fails if the committed skill is stale.
+
+- [ ] **Step 1: Write deterministic generation RED tests**
+
+Assert the generated skill has trigger-shaped frontmatter, names the public
+`flect` command, explains content-first discovery and role limits, contains no
+live workspace IDs/models/control state, and exactly matches the checked-in
+file. Mutating command metadata in the fixture must make check mode fail.
+
+- [ ] **Step 2: Confirm RED**
+
+```bash
+bunx vitest run scripts/generate-flect-skill.test.ts
+```
+
+- [ ] **Step 3: Implement generation and check scripts**
+
+Export static command metadata from `src/axi/command.ts`; do not scrape source
+or shell out to the built CLI. Generate through Effect file services and write
+with `apply_patch` during development. Add `check:flect-skill` to `check`.
+
+- [ ] **Step 4: Add the concise permanent rule to AGENTS.md**
+
+State that all agent-facing command surfaces must follow AXI, use the shared
+Effect command/controller authority, default to bounded TOON, preserve stable
+exit/channel behavior, and update the generated skill when command metadata
+changes. Link to `docs/local-control.md` and the design; do not duplicate the
+command catalog.
+
+- [ ] **Step 5: Run GREEN**
+
+```bash
+bunx vitest run scripts/generate-flect-skill.test.ts
+bun run check:flect-skill
+```
+
+- [ ] **Step 6: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- scripts/generate-flect-skill.ts .agents/skills/flect/SKILL.md AGENTS.md package.json
+```
+
+---
+
+### Task 11: Real-browser AXI and reactive UI verification
+
+**Files:**
+
+- Create: `tests/e2e/embedded-axi.spec.ts`
+- Modify: `tests/e2e/flect.spec.ts`
+- Modify: `server/test-runtime.ts`
+- Modify: `playwright.config.ts`
+
+**Interfaces:**
+
+- Test runtime supplies deterministic Pi turns that issue real Bash commands
+  through the same RPC/shell bridge as production.
+- Tests inspect behavior through UI accessibility, public HTTP/SSE, and
+  command results, never private React state or direct storage mutation.
+
+- [ ] **Step 1: Write the browser RED scenarios**
+
+Add Playwright scenarios that prove:
+
+1. Shaper runs embedded `flect`, validates a file, proposes it, and the preview
+   appears reactively without reload.
+2. Shaper's attempt to accept the proposal returns structured unauthorized
+   output and the protected Keep button remains a user decision.
+3. After Keep and Run mode, App lists and invokes a visible action through
+   embedded `flect`; the result appears in both activity and product UI.
+4. App attempts to shape or enter safe mode and is denied.
+5. Role spoofing through env, alias, function, file, and PATH fails.
+6. TOON output passes through `grep`, `head`, and redirection in just-bash.
+7. Tool use is visible with command, phase, bounded result, duration, and
+   failure state.
+8. Manual upward scrolling is not stolen by streamed CLI/tool activity.
+
+- [ ] **Step 2: Confirm RED in a real production Chromium build**
+
+```bash
+bunx playwright test tests/e2e/embedded-axi.spec.ts --project=chromium
+```
+
+Expected: new AXI scenarios fail before the deterministic runtime supports
+their command trajectories.
+
+- [ ] **Step 3: Extend only the deterministic test runtime inputs needed**
+
+Emit the same `AgentShellRequest`, completion, and stream contracts used by
+production. Do not add a DOM test hook or bypass `SandboxedShell`.
+
+- [ ] **Step 4: Run GREEN and full browser suite**
+
+```bash
+bunx playwright test tests/e2e/embedded-axi.spec.ts --project=chromium
+bun run test:e2e
+```
+
+Expected: all Chromium tests pass with zero unexpected console errors, page
+errors, or failed local application requests.
+
+- [ ] **Step 5: Review the task diff without committing**
+
+```bash
+git diff --check
+git diff -- tests/e2e server/test-runtime.ts playwright.config.ts
+```
+
+---
+
+### Task 12: Release packaging, documentation, installed-app dogfood, and completion audit
+
+**Files:**
+
+- Modify: `scripts/package-release.ts`, `scripts/package-release.test.ts`
+- Modify: `scripts/smoke-pi.ts`
+- Modify: `ARCHITECTURE.md`
+- Modify: `CONTRIBUTING.md`
+- Modify: `README.md`
+- Modify: `VISION.md` only if current-slice wording changes
+- Modify: `docs/local-control.md`
+- Modify: `docs/trust-model.md`
+- Modify: `docs/verification/*`
+
+**Interfaces:**
+
+- Release layout requires only app, DMG, demo/checksum assets, and the private
+  runtime helper inside the app.
+- The public smoke path invokes `Flect.app/Contents/MacOS/flect`; no test or
+  documentation invokes `flectctl` or `flect-mcp`.
+
+- [ ] **Step 1: Write release-layout RED tests**
+
+Change `ReleaseLayout` to remove `cli` and `mcp`. Assert validation succeeds
+with `flect` plus `flect-runtime`, fails without either, and explicitly fails
+when forbidden sibling executables `flectctl` or `flect-mcp` are present in
+`Contents/MacOS`.
+
+- [ ] **Step 2: Confirm RED**
+
+```bash
+bunx vitest run scripts/package-release.test.ts
+```
+
+- [ ] **Step 3: Update release and smoke mechanics**
+
+Remove companion-binary paths/copies/checks. Package one app/DMG. Change smoke
+commands to the public executable's AXI and MCP modes. Never print the control
+descriptor or bearer.
+
+- [ ] **Step 4: Update documentation ownership after implementation exists**
+
+- `ARCHITECTURE.md`: verified one-public-executable topology, embedded agent
+  bus, reserved command, Bash proposal, and role policy.
+- `docs/local-control.md`: complete AXI command/reference, TOON/JSON behavior,
+  exit codes, MCP mode, shell link, setup install/remove, and browser limits.
+- `docs/trust-model.md`: external versus captured-agent authority and failure
+  boundaries.
+- `CONTRIBUTING.md`: current build/test/bundle/dogfood commands and exact bundle
+  contents.
+- `README.md`: concise install, enable-control, `flect` home, browser embedded
+  use, and links; do not duplicate the full catalog.
+- `VISION.md`: only update the implemented-slice paragraph, not the durable
+  destination.
+
+- [ ] **Step 5: Run the complete credential-free verification**
+
+```bash
+bun run check:all
+bun run release:verify
+```
+
+Require clean success for Effect pin check, Rifty check, Biome, TypeScript,
+Vitest, Playwright Chromium, Rust tests, and release-mode app build.
+
+- [ ] **Step 6: Build and install the app**
+
+```bash
+bun run build:desktop -- --bundles app
+```
+
+Move the existing `/Applications/Flect.app` to a timestamped backup location
+only if replacement cannot be done atomically; do not delete it. Install the
+new verified bundle at `/Applications/Flect.app`, then open it with macOS
+LaunchServices.
+
+- [ ] **Step 7: Dogfood public native AXI**
+
+After enabling Local control through the protected UI, run:
+
+```bash
+/Applications/Flect.app/Contents/MacOS/flect
+/Applications/Flect.app/Contents/MacOS/flect inspect
+/Applications/Flect.app/Contents/MacOS/flect shape "Create a compact project dashboard"
+/Applications/Flect.app/Contents/MacOS/flect logs --limit 20
+```
+
+Verify TOON, exact terminal outcomes, reactive preview in the open app, visible
+operation/tool evidence, and no bearer/credential output.
+
+- [ ] **Step 8: Dogfood embedded browser AXI and MCP**
+
+Use a live Shaper turn that runs `flect interface propose`, keep it as the user,
+then use a live App turn that runs `flect action list`. Run a real MCP stdio
+initialize/list/call exchange through:
+
+```bash
+/Applications/Flect.app/Contents/MacOS/flect mcp
+```
+
+Capture bounded verification evidence in `docs/verification/` without secrets.
+
+- [ ] **Step 9: Audit every objective requirement**
+
+Create a table mapping each acceptance criterion in the design to authoritative
+evidence: source contract, focused test, full gate output, bundle listing,
+browser trace/screenshot, native command output, or installed-app observation.
+Treat missing or indirect evidence as incomplete and continue implementation.
+
+- [ ] **Step 10: Run stale-name and secret scans**
+
+```bash
+rg -n "flectctl|flect-mcp" --glob '!docs/superpowers/**' --glob '!docs/verification/**' .
+rg -n "Bearer |Authorization:|api[_-]?key|access[_-]?token" docs/verification dist-release 2>/dev/null
+git diff --check
+git status --short
+```
+
+Only deliberate historical migration references may remain outside active
+implementation/user documentation. Inspect every secret-shaped match.
+
+- [ ] **Step 11: Review the full diff without committing**
+
+```bash
+git diff --stat
+git diff --check
+git status --short
+```
+
+Do not commit, push, merge, publish, or create a release until the user gives
+that separate authorization.
+
+---
+
+## Plan self-review
+
+### Spec coverage
+
+- One public native executable: Tasks 8 and 12.
+- No public `flectctl`/`flect-mcp`: Tasks 2, 8, and 12.
+- AXI/TOON semantics: Tasks 1, 2, and 10.
+- One Effect command/state path: Tasks 3 and 4.
+- Browser-reserved command and role source capture: Task 5.
+- Shaper and App drive Flect through Bash: Tasks 6 and 7.
+- Guardian/tool and sandbox boundaries: Tasks 3, 5, and 6.
+- MCP/HTTP compatibility: Tasks 2, 4, and 8.
+- Shell link and Codex/Claude/OpenCode opt-in integrations: Task 9.
+- Generated Agent Skill and durable rule: Task 10.
+- Real-browser, native, package, install, open, and dogfood evidence: Tasks 11
+  and 12.
+- Documentation ownership and completion audit: Task 12.
+
+### Type consistency
+
+- `AxiRunResult` is produced only by the AXI formatter/program and consumed by
+  process/just-bash adapters.
+- `FlectCommandGateway` is the sole command program dependency; broker and
+  agent implementations share its exact shape.
+- `AgentCommandSource` is created by the sandbox adapter and enforced by the
+  controller.
+- `AgentCommandBus` carries typed gateway operations and exact Deferred
+  results; it is not persisted or schema-encoded.
+- Shaper's proposal latch holds only an already validated InterfaceDocument;
+  ShapingKernel remains revision authority.
+
+### Placeholder scan
+
+The plan contains no TBD/TODO/later placeholders. Conditional removal steps
+have explicit parity gates and commands. The only conditional smoke outcome is
+called out as not-a-pass and must be resolved before completion.
diff --git a/docs/superpowers/plans/2026-07-31-flect-observable-control.md b/docs/superpowers/plans/2026-07-31-flect-observable-control.md
new file mode 100644
index 0000000..b017b26
--- /dev/null
+++ b/docs/superpowers/plans/2026-07-31-flect-observable-control.md
@@ -0,0 +1,1351 @@
+# Flect Observable Control Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use
+> `superpowers:executing-plans` to implement this plan task-by-task. Steps use
+> checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Make Flect's live workspace reliable, observable, user-respecting,
+and fully controllable by an explicitly authorized local CLI, JSON/SSE API, or
+MCP client through the same Effect command authority used by the UI.
+
+**Architecture:** One schema-defined `FlectWorkspaceController` in the
+connected browser/WebView owns semantic commands and publishes one reactive
+snapshot and event stream. The Bun runtime owns only an authenticated,
+lifecycle-scoped loopback broker that forwards commands to the connected
+workspace; React, HTTP, CLI, and MCP remain adapters rather than alternate
+state machines. Pi emits exact proposal and tool lifecycle events, while a
+bounded in-memory `OperationJournal` keeps safe correlated evidence.
+
+**Tech Stack:** TypeScript 7, Bun, Effect 4 beta, Effect Schema/Layer/Stream/
+SubscriptionRef/Queue/Scope, Pi SDK, TypeBox, React 19, Effect HTTP/RPC,
+Tauri 2, Vitest with `@effect/vitest`, Playwright, Rust tests.
+
+## Global Constraints
+
+- Preserve all existing uncommitted T3 Code UX, Markdown, and verification
+  work.
+- Do not commit, push, merge, publish, or release without separate authority.
+- External control is loopback-only, disabled by default, explicitly enabled
+  in the protected UI, authenticated by a rotating 256-bit capability, and
+  immediately revocable.
+- No outside client may enable or expand its own authority.
+- The connected Flect workspace remains authoritative; the broker stores no
+  shadow revision, conversation, model, or UI state.
+- Every external value crosses an Effect Schema boundary with strict excess
+  property rejection.
+- Use `Schema.Class`, `Schema.TaggedClass`, and `Schema.TaggedErrorClass` for
+  reusable contracts; use `.make(...)`, never unsafe casts or `any`.
+- Define services with `Context.Service`, construct them in named Layers,
+  provide dependencies at composition edges, and use `ManagedRuntime` only at
+  host boundaries.
+- Use `Effect.fn` for named business operations, `SubscriptionRef` for
+  reactive state, `Stream` for events, `Queue`/`Deferred` for command
+  hand-off, and `Effect.acquireRelease`/Scope for broker and session cleanup.
+- Pi provider credentials and bearer capabilities never enter logs, events,
+  screenshots, model context, argv, or API response bodies.
+- App Agent, Shaper, and Guardian remain separate Pi roles; their sandbox and
+  extension policies remain intact.
+- The browser remains a first-class runtime; no feature may require a
+  machine-installed shell, Git, Bun, or native binary.
+- Operation history is in-memory only, bounded to 500 entries and 2 MiB, and
+  contains safe summaries rather than full prompt, output, or credential data.
+- Sticky follow uses a 48 px bottom threshold, suspends after the user moves
+  away, never steals focus, and exposes a keyboard-operable “Jump to latest”
+  control.
+- Test observable behavior through public services, HTTP/RPC contracts, DOM
+  semantics, CLI output, and real browser/native flows.
+
+---
+
+## File Structure
+
+### Shared contracts
+
+- `shared/control.ts` — versioned command envelope, command union, snapshots,
+  events, receipts, operation records, client metadata, and protocol errors.
+- `shared/contracts.ts` — Pi turn/tool/proposal event contracts shared by HTTP,
+  RPC, browser, and desktop.
+- `shared/rpc.ts` — private desktop workspace-channel RPCs in addition to the
+  existing Pi runtime RPCs.
+
+### Pi runtime
+
+- `server/pi-proposal-tool.ts` — exact TypeBox proposal tool and safe Effect
+  validation diagnostic mapping.
+- `server/pi-runtime.ts` — registers proposal and Bash tools, streams their
+  lifecycle, performs one bounded corrective retry, and preserves sessions on
+  validation failure.
+- `server/test-runtime.ts` — deterministic equivalents of the new events.
+
+### Connected workspace
+
+- `src/lib/operation-journal.ts` — bounded `OperationJournal` service.
+- `src/lib/agent-workspace.ts` — Effect-owned App/Shaper session lifecycle and
+  role timelines extracted from the React hook.
+- `src/lib/workspace-controller.ts` — sole semantic command/state authority.
+- `src/lib/workspace-control-bridge.ts` — browser HTTP and desktop RPC bridge
+  adapters that register the workspace, deliver commands, and publish
+  snapshots/events/receipts.
+- `src/hooks/use-workspace.ts` — thin React subscription and dispatch adapter.
+- `src/lib/runtime.ts` — one composed browser application runtime.
+
+### Interface
+
+- `src/components/activity-card.tsx` — live tool and operation instruments.
+- `src/components/diagnostics-panel.tsx` — filters and safe structured detail.
+- `src/hooks/use-sticky-follow.ts` — per-role viewport-follow policy.
+- `src/components/agent-rail.tsx` — consumes controller state and new
+  instruments without re-owning workflow state.
+- `src/components/role-aware-shell.tsx` — protected control toggle and client
+  visibility.
+- `src/app.tsx` — renders controller snapshot and dispatches typed commands.
+- `src/styles.css` — activity, diagnostics, sticky-follow, and attribution
+  styling.
+
+### Local broker and adapters
+
+- `server/control-descriptor.ts` — secure descriptor path, encode/decode,
+  permissions, stale-instance rejection, and cleanup.
+- `server/control-broker.ts` — scoped token, queue, state cache, waiters,
+  external loopback listener, and workspace registration.
+- `server/control-http.ts` — authenticated JSON/SSE external API.
+- `server/app.ts` — protected browser workspace-channel routes.
+- `server/rpc-handlers.ts` — private desktop workspace-channel handlers.
+- `server/index.ts` and `server/sidecar.ts` — compose one shared broker layer.
+- `cli/flect-client.ts` — descriptor discovery and schema-safe HTTP/SSE client.
+- `cli/flectctl.ts` — human and JSON CLI.
+- `cli/flect-mcp.ts` — MCP stdio adapter over the same client.
+- `scripts/build-sidecar.ts`, `src-tauri/tauri.conf.json`, and release
+  packaging files — build and bundle `flectctl`.
+
+### Verification and documentation
+
+- Unit tests adjacent to every new module.
+- `tests/e2e/flect.spec.ts` — real browser UI behavior.
+- `tests/e2e/control-plane.spec.ts` — browser plus real `flectctl`.
+- `tests/e2e/native-control.spec.ts` or the existing native smoke harness —
+  packaged-app control.
+- `ARCHITECTURE.md`, `DESIGN.md`, `PRODUCT.md`, `README.md`, `VISION.md`, and
+  `AGENTS.md` — only the information owned by each document.
+- `docs/verification/flect-observable-control/` — commands, screenshots, safe
+  logs, and final evidence.
+
+---
+
+### Task 1: Define the versioned command, snapshot, event, and error contracts
+
+**Files:**
+- Create: `shared/control.ts`
+- Create: `shared/control.test.ts`
+- Modify: `shared/contracts.ts`
+- Modify: `shared/contracts.test.ts`
+
+**Interfaces:**
+- Produces:
+  - `FlectCommandEnvelope`
+  - `FlectCommand`
+  - `FlectWorkspaceSnapshot`
+  - `FlectWorkspaceEvent`
+  - `FlectCommandReceipt`
+  - `FlectCommandError`
+  - `OperationRecord`
+  - `ToolActivity`
+  - `ControlClientSummary`
+- Consumes: existing `InterfaceDocument`, `InteractiveAgentRole`,
+  `ModelSummary`, `ShapingSnapshot`, and shell result summaries.
+
+- [ ] **Step 1: Write failing schema round-trip and rejection tests**
+
+```ts
+it.effect("round-trips every command and rejects unknown fields", () =>
+  Effect.gen(function* () {
+    const value = FlectCommandEnvelope.make({
+      version: 1,
+      commandId: "cmd-00000001",
+      workspaceId: "workspace-00000001",
+      source: UserCommandSource.make({ kind: "user" }),
+      command: SubmitShaperInstruction.make({
+        type: "submit-shaper-instruction",
+        instruction: "Make the headline quieter"
+      })
+    })
+    const encoded = yield* Schema.encodeEffect(FlectCommandEnvelope)(value)
+    const decoded = yield* decodeFlectCommandEnvelope(encoded)
+    assert.deepStrictEqual(decoded, value)
+    const exit = yield* Effect.exit(
+      decodeFlectCommandEnvelope({ ...encoded, invented: true })
+    )
+    assert.isTrue(Exit.isFailure(exit))
+  })
+)
+```
+
+Add table-driven cases for all commands and prove:
+
+- control sources require `clientId` and `clientName`;
+- `enable-control` decodes but is later authorizable only for user sources;
+- instruction, prompt, width, identifier, and log-detail bounds hold;
+- unknown command tags, button actions, and excess keys fail closed.
+
+- [ ] **Step 2: Run the focused tests and confirm red**
+
+Run:
+
+```bash
+bunx vitest run shared/control.test.ts shared/contracts.test.ts
+```
+
+Expected: FAIL because the new schemas and event variants do not exist.
+
+- [ ] **Step 3: Implement reusable named schemas and tagged unions**
+
+Use this public shape:
+
+```ts
+export class FlectCommandEnvelope extends Schema.Class(
+  "FlectCommandEnvelope"
+)({
+  version: Schema.Literal(1),
+  commandId: CommandId,
+  workspaceId: WorkspaceId,
+  source: FlectCommandSource,
+  expectedSequence: Schema.optionalKey(
+    Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))
+  ),
+  command: FlectCommand
+}) {}
+
+export const decodeFlectCommandEnvelope = Schema.decodeUnknownEffect(
+  FlectCommandEnvelope,
+  { errors: "all", onExcessProperty: "error" }
+)
+```
+
+Define each command as a `Schema.TaggedClass` with its literal `type`.
+Represent expected protocol failures as `Schema.TaggedErrorClass` variants:
+`InvalidControlCommand`, `ControlUnauthorized`, `WorkspaceUnavailable`,
+`CommandConflict`, `CommandRejected`, and `OperationFailed`.
+
+Extend Pi events with exact, bounded variants:
+
+```ts
+ToolExecutionStarted
+ToolExecutionUpdated
+ToolExecutionCompleted
+ProposalValidationFailed
+```
+
+Tool records carry role, call ID, tool name, phase, started/completed
+timestamps, duration, bounded command/result summaries, exit code, and optional
+preview URL; no raw credentials or unlimited output.
+
+- [ ] **Step 4: Run focused tests and typecheck**
+
+```bash
+bunx vitest run shared/control.test.ts shared/contracts.test.ts
+bun run typecheck
+```
+
+Expected: all focused tests PASS and TypeScript reports no errors.
+
+- [ ] **Step 5: Inspect the diff for duplicate contracts**
+
+```bash
+rg -n "FlectCommandEnvelope|OperationRecord|ToolActivity" shared src server
+git diff --check
+```
+
+Expected: each reusable contract has one shared source of truth and
+`git diff --check` prints nothing.
+
+### Task 2: Replace free-form Shaper JSON with a terminating proposal tool
+
+**Files:**
+- Create: `server/pi-proposal-tool.ts`
+- Create: `server/pi-proposal-tool.test.ts`
+- Modify: `server/pi-runtime.ts`
+- Modify: `server/pi-runtime.test.ts`
+- Modify: `server/test-runtime.ts`
+- Modify: `server/test-runtime.test.ts` if present
+
+**Interfaces:**
+- Consumes: `InterfaceDocument`, `validateInterfaceDocument`,
+  `ProposalValidationFailed`, and Pi `defineTool`.
+- Produces:
+  - `makePiProposalTool(onEvent)`
+  - `InterfaceProposalValidationError`
+  - shape streams that terminate only after a validated proposal or one
+    bounded corrective retry.
+
+- [ ] **Step 1: Write failing exact-schema and diagnostic tests**
+
+```ts
+it.effect("accepts only an exact InterfaceDocument proposal", () =>
+  Effect.gen(function* () {
+    const capture = yield* makeProposalCapture()
+    const tool = yield* makePiProposalTool(capture.emit)
+    const result = yield* Effect.promise(() =>
+      tool.execute("tool-1", { document: validDocument }, undefined)
+    )
+    assert.strictEqual(result.details.status, "accepted")
+    assert.deepStrictEqual(yield* capture.proposal, validDocument)
+  })
+)
+```
+
+Also prove that missing `text.style`, invented button actions,
+`agent-panel.children`, missing `agent-panel.title`, excess properties,
+oversized trees, and reused node IDs produce safe issues such as:
+
+```ts
+{
+  path: ["root", "children", 0, "style"],
+  code: "required",
+  message: "Required field is missing."
+}
+```
+
+- [ ] **Step 2: Run focused tests and confirm red**
+
+```bash
+bunx vitest run server/pi-proposal-tool.test.ts server/pi-runtime.test.ts
+```
+
+Expected: FAIL because `propose_interface` and validation issue events are
+absent.
+
+- [ ] **Step 3: Implement the TypeBox tool from the exact closed UI schema**
+
+Define `propose_interface` with:
+
+```ts
+defineTool({
+  name: "propose_interface",
+  label: "Propose interface",
+  description: "Submit one complete Flect InterfaceDocument.",
+  parameters: Type.Object(
+    { document: interfaceDocumentTypeBox },
+    { additionalProperties: false }
+  ),
+  executionMode: "sequential",
+  terminate: true,
+  promptSnippet: "Use propose_interface for the final complete interface.",
+  promptGuidelines: [
+    "Never invent node fields, node types, or button actions.",
+    "Every text node requires style.",
+    "Only stack nodes have children."
+  ],
+  execute
+})
+```
+
+Validate again with Effect Schema inside `execute`; TypeBox is model guidance,
+not the application trust boundary. Convert `SchemaError` issues to bounded
+safe paths and reasons.
+
+- [ ] **Step 4: Register tool lifecycle events and one corrective retry**
+
+In `server/pi-runtime.ts`:
+
+- subscribe to Pi `tool_execution_start`, `tool_execution_update`, and
+  `tool_execution_end`;
+- emit the shared lifecycle variants for Bash and proposal tools;
+- retain the Shaper Pi session when proposal validation fails;
+- append the safe validation issues as the single retry instruction;
+- permit exactly one retry per shape command;
+- return `ProposalValidationFailed` after the second invalid proposal;
+- remove the broad first-`{`/last-`}` JSON extraction path.
+
+- [ ] **Step 5: Update deterministic runtime fixtures**
+
+Make the test runtime emit the same event order:
+
+```text
+turn/tool started -> proposal tool started -> proposal tool completed
+-> shape completed
+```
+
+Add an instruction keyword used only by tests that yields a controlled
+validation failure event without weakening production validation.
+
+- [ ] **Step 6: Run focused runtime tests and the real Pi smoke**
+
+```bash
+bunx vitest run server/pi-proposal-tool.test.ts server/pi-runtime.test.ts server/app.test.ts server/rpc-handlers.test.ts
+bun run test:pi-smoke
+```
+
+Expected: unit tests PASS; real Pi smoke returns one validated document and no
+generic parse failure.
+
+### Task 3: Add the bounded structured operation journal
+
+**Files:**
+- Create: `src/lib/operation-journal.ts`
+- Create: `src/lib/operation-journal.test.ts`
+
+**Interfaces:**
+- Consumes: `OperationRecord`, `FlectWorkspaceEvent`, `ToolActivity`.
+- Produces:
+
+```ts
+interface OperationJournalShape {
+  readonly snapshot: Effect.Effect>
+  readonly changes: Stream.Stream>
+  readonly append: (
+    event: OperationJournalInput
+  ) => Effect.Effect
+  readonly query: (
+    filter: OperationFilter
+  ) => Effect.Effect>
+}
+```
+
+- [ ] **Step 1: Write failing retention, correlation, and redaction tests**
+
+Test:
+
+- lifecycle order and monotonic sequence;
+- `operationId`, `commandId`, `sessionId`, `toolCallId`, and revision
+  correlation;
+- eviction at 500 records;
+- eviction before encoded size exceeds 2 MiB;
+- query filters for role, status, operation, tool, revision, client, and
+  failures;
+- rejection/redaction of bearer tokens, authorization headers, provider
+  secrets, and full prompts.
+
+- [ ] **Step 2: Run and confirm red**
+
+```bash
+bunx vitest run src/lib/operation-journal.test.ts
+```
+
+Expected: FAIL because the service does not exist.
+
+- [ ] **Step 3: Implement the service with `SubscriptionRef`**
+
+Construct one named layer with:
+
+```ts
+export class OperationJournal extends Context.Service<
+  OperationJournal,
+  OperationJournalShape
+>()("flect/OperationJournal") {}
+
+export const OperationJournalLive = Layer.effect(
+  OperationJournal,
+  Effect.gen(function* () {
+    const state = yield* SubscriptionRef.make(JournalState.empty())
+    // append/query/snapshot/changes
+    return implementation
+  })
+)
+```
+
+Use `Schema.encodeEffect(OperationRecord)` to count encoded bytes. Redact at
+the append boundary, not in renderers.
+
+- [ ] **Step 4: Run focused tests**
+
+```bash
+bunx vitest run src/lib/operation-journal.test.ts
+bun run typecheck
+```
+
+Expected: PASS.
+
+### Task 4: Extract Pi session and role state into an Effect service
+
+**Files:**
+- Create: `src/lib/agent-workspace.ts`
+- Create: `src/lib/agent-workspace.test.ts`
+- Modify: `src/hooks/use-agent-session.ts`
+- Modify: `src/hooks/use-agent-session.test.tsx`
+
+**Interfaces:**
+- Consumes: `FlectClient`, `SandboxedShell`, `OperationJournal`,
+  `SessionSelection`, and the new Pi events.
+- Produces:
+
+```ts
+interface AgentWorkspaceShape {
+  readonly snapshot: Effect.Effect
+  readonly changes: Stream.Stream
+  readonly refresh: Effect.Effect
+  readonly selectModel: (
+    selection: ModelSelection | undefined
+  ) => Effect.Effect
+  readonly toggleExternalExtensions: (
+    role: InteractiveAgentRole
+  ) => Effect.Effect
+  readonly submitAppPrompt: (
+    operation: OperationContext,
+    text: string
+  ) => Effect.Effect
+  readonly submitShaperInstruction: (
+    operation: OperationContext,
+    instruction: string,
+    document: InterfaceDocument
+  ) => Effect.Effect
+  readonly cancel: (
+    role: InteractiveAgentRole
+  ) => Effect.Effect
+}
+```
+
+- [ ] **Step 1: Port current hook behavior into failing service tests**
+
+Cover session reuse, model-change session replacement, per-role busy guards,
+App/Shaper concurrency, cancellation, shell completion, extension selection,
+setup-required/unavailable states, tool activity updates, validation failure
+without session closure, and scoped finalization.
+
+- [ ] **Step 2: Run focused tests and confirm red**
+
+```bash
+bunx vitest run src/lib/agent-workspace.test.ts
+```
+
+Expected: FAIL because `AgentWorkspace` is absent.
+
+- [ ] **Step 3: Implement `AgentWorkspaceLive`**
+
+Move session handles, role fibers, cancellation flags, models, selections,
+messages, and tool activity into one `SubscriptionRef`. Use:
+
+```ts
+Effect.acquireRelease(createOrReuseSession, closeSession)
+Fiber.interrupt
+Effect.onInterrupt
+Stream.runForEach
+```
+
+Tool start creates an activity; update changes the same call ID; end records
+duration and bounded result. A proposal validation error becomes a structured
+Shaper timeline item and does not release an otherwise healthy Pi session.
+
+- [ ] **Step 4: Reduce the React hook to a compatibility adapter**
+
+Until Task 6 removes it from `App`, make `useAgentSession` subscribe to
+`AgentWorkspace.changes` and invoke service methods. It must not retain its
+own session, model, fiber, or message refs.
+
+- [ ] **Step 5: Run service and existing hook tests**
+
+```bash
+bunx vitest run src/lib/agent-workspace.test.ts src/hooks/use-agent-session.test.tsx
+bun run typecheck
+```
+
+Expected: PASS with the previous observable hook contract preserved.
+
+### Task 5: Build the sole Effect workspace command/state authority
+
+**Files:**
+- Create: `src/lib/workspace-controller.ts`
+- Create: `src/lib/workspace-controller.test.ts`
+- Modify: `src/lib/runtime.ts`
+
+**Interfaces:**
+- Consumes: `AgentWorkspace`, `ShapingKernel`, `ShellPreferences`,
+  `ExtensionExecution`, `OperationJournal`, `FlectCommandEnvelope`.
+- Produces:
+
+```ts
+interface FlectWorkspaceControllerShape {
+  readonly snapshot: Effect.Effect
+  readonly changes: Stream.Stream
+  readonly events: Stream.Stream
+  readonly dispatch: (
+    envelope: FlectCommandEnvelope
+  ) => Effect.Effect
+}
+```
+
+- [ ] **Step 1: Write failing state-machine tests**
+
+Use test layers and exercise only `dispatch`. Prove:
+
+- every command tag has a deterministic receipt and event;
+- commands from user and control sources reach the same transition;
+- model favorites and App/Shaper external-extension toggles update the same
+  reactive state for either source;
+- duplicate `commandId` returns the prior receipt without rerunning;
+- the recent command window is bounded;
+- stale `expectedSequence` returns `CommandConflict`;
+- `enable-control` with `source.kind === "control"` returns
+  `ControlUnauthorized`;
+- shape creates a proposal preview; accept/reject/rollback/safe-mode preserve
+  ShapingKernel invariants;
+- interface action invocation resolves a node ID from the current validated
+  document and rejects stale/unknown IDs;
+- long-running operations are cancellable and publish terminal events;
+- each transition appears in `OperationJournal`.
+
+- [ ] **Step 2: Run focused tests and confirm red**
+
+```bash
+bunx vitest run src/lib/workspace-controller.test.ts
+```
+
+Expected: FAIL because the controller does not exist.
+
+- [ ] **Step 3: Implement controller state and dispatch**
+
+Use one `SubscriptionRef`, one bounded result cache, and one
+broadcast event source. Keep command authorization separate:
+
+```ts
+const authorize = Effect.fn("Flect.Workspace.authorize")(function* (
+  envelope: FlectCommandEnvelope
+) {
+  if (
+    envelope.command.type === "enable-control" &&
+    envelope.source.kind !== "user"
+  ) {
+    return yield* Effect.fail(ControlUnauthorized.make({
+      message: "Outside clients cannot enable control."
+    }))
+  }
+})
+```
+
+Dispatch the closed union with exhaustive `Match.value(...).pipe(...)` or
+equivalent typed branching. Do not accept arbitrary callbacks or action
+strings.
+
+- [ ] **Step 4: Compose one browser application runtime**
+
+Replace the split browser/shaping ownership with one named top-level layer:
+
+```ts
+const FlectApplicationLive = WorkspaceControllerLive.pipe(
+  Layer.provideMerge(WorkspaceDependenciesLive)
+)
+
+export const flectRuntime = ManagedRuntime.make(FlectApplicationLive)
+```
+
+Keep compatibility exports temporarily if existing tests need them, but make
+them aliases over the same managed runtime rather than separate service
+instances.
+
+- [ ] **Step 5: Run controller, kernel, and repository tests**
+
+```bash
+bunx vitest run src/lib/workspace-controller.test.ts src/lib/shaping-kernel.test.ts src/lib/interface-repository.test.ts
+bun run typecheck
+```
+
+Expected: PASS.
+
+### Task 6: Make React a reactive adapter and render visible activity
+
+**Files:**
+- Create: `src/hooks/use-workspace.ts`
+- Create: `src/hooks/use-workspace.test.tsx`
+- Create: `src/components/activity-card.tsx`
+- Create: `src/components/activity-card.test.tsx`
+- Create: `src/components/diagnostics-panel.tsx`
+- Create: `src/components/diagnostics-panel.test.tsx`
+- Modify: `src/app.tsx`
+- Modify: `src/app.test.tsx`
+- Modify: `src/components/agent-rail.tsx`
+- Modify: `src/components/agent-rail.test.tsx`
+- Modify: `src/components/role-aware-shell.tsx`
+- Modify: `src/components/role-aware-shell.test.tsx`
+- Modify: `src/styles.css`
+
+**Interfaces:**
+- Consumes: `FlectWorkspaceController.snapshot/changes/events/dispatch`.
+- Produces: semantic UI controls that dispatch command envelopes and display
+  the controller's exact reactive state.
+
+- [ ] **Step 1: Write failing adapter and activity UI tests**
+
+Prove:
+
+- external-source events update the rendered mode, messages, proposal, model,
+  and attribution without reload;
+- Bash and proposal tool cards show queued/running/succeeded/failed status,
+  duration, command summary, exit code, output disclosure, and preview action;
+- failed proposal shows exact safe paths and a retry action;
+- operations can be filtered and correlation IDs copied;
+- connected clients and a single protected enable/disable control are visible;
+- toggling enable dispatches a user-source command;
+- tool disclosures are keyboard and screen-reader operable.
+
+- [ ] **Step 2: Run focused component tests and confirm red**
+
+```bash
+bunx vitest run src/hooks/use-workspace.test.tsx src/components/activity-card.test.tsx src/components/diagnostics-panel.test.tsx src/app.test.tsx
+```
+
+Expected: FAIL because the reactive adapter and instruments do not exist.
+
+- [ ] **Step 3: Implement the thin React adapter**
+
+`useWorkspace`:
+
+- reads the initial snapshot through `flectRuntime`;
+- subscribes to `changes` in a scoped fiber;
+- interrupts that fiber on unmount;
+- builds user-source envelopes with `crypto.randomUUID()`;
+- exposes `dispatch(command, expectedSequence?)`;
+- owns no parallel session, revision, operation, or model state.
+
+- [ ] **Step 4: Implement compact T3-like activity instruments**
+
+Use a quiet one-line collapsed card:
+
+```text
+● Bash · bun test · 1.2s
+```
+
+Expanded content uses labelled sections for input, bounded output, validation
+issues, preview URL, operation/correlation IDs, source attribution, and retry.
+Use existing typography and icon primitives rather than adding a second
+visual system.
+
+- [ ] **Step 5: Refactor `App` and shell controls onto typed commands**
+
+Remove direct `useState` workflow ownership and direct calls to
+`ShapingKernel`, `useAgentSession`, or shell preferences. `App` renders the
+controller snapshot; buttons dispatch exact command classes. Preserve only
+ephemeral draft, focus, disclosure, and scroll state in React.
+
+- [ ] **Step 6: Run component tests and accessibility checks**
+
+```bash
+bunx vitest run src/hooks/use-workspace.test.tsx src/components/activity-card.test.tsx src/components/diagnostics-panel.test.tsx src/app.test.tsx src/components/agent-rail.test.tsx src/components/role-aware-shell.test.tsx
+bun run typecheck
+```
+
+Expected: PASS with no inaccessible-name or focus-order regressions.
+
+### Task 7: Add per-role sticky follow and jump-to-latest
+
+**Files:**
+- Create: `src/hooks/use-sticky-follow.ts`
+- Create: `src/hooks/use-sticky-follow.test.tsx`
+- Modify: `src/components/agent-rail.tsx`
+- Modify: `src/components/agent-rail.test.tsx`
+- Modify: `src/styles.css`
+
+**Interfaces:**
+- Produces:
+
+```ts
+interface StickyFollow {
+  readonly containerRef: RefObject
+  readonly following: boolean
+  readonly unreadCount: number
+  readonly jumpToLatest: () => void
+}
+```
+
+- [ ] **Step 1: Write failing scroll-policy tests**
+
+With a controllable scroll element prove:
+
+- initial and already-near-bottom updates follow;
+- distance greater than 48 px suspends follow;
+- streaming updates while suspended do not change `scrollTop`;
+- unread count increments by message/tool update;
+- jump uses non-focus-stealing scroll and resumes follow;
+- switching roles restores each role's own follow state;
+- reduced motion selects instant behavior.
+
+- [ ] **Step 2: Run focused tests and confirm red**
+
+```bash
+bunx vitest run src/hooks/use-sticky-follow.test.tsx src/components/agent-rail.test.tsx
+```
+
+Expected: FAIL.
+
+- [ ] **Step 3: Implement the hook and disable native anchoring**
+
+Observe `scroll` and content size, compute:
+
+```ts
+const distance = scrollHeight - scrollTop - clientHeight
+const nearBottom = distance <= 48
+```
+
+Set `overflow-anchor: none` on the timeline. Only set `scrollTop` when
+following or after explicit jump. Do not call `.focus()`.
+
+- [ ] **Step 4: Render the accessible jump control**
+
+Render `Jump to latest` with optional unread count only while suspended.
+Place it inside the timeline footer so it does not cover composer controls.
+
+- [ ] **Step 5: Run focused tests**
+
+```bash
+bunx vitest run src/hooks/use-sticky-follow.test.tsx src/components/agent-rail.test.tsx
+```
+
+Expected: PASS.
+
+### Task 8: Build the scoped local control broker and protected descriptor
+
+**Files:**
+- Create: `server/control-descriptor.ts`
+- Create: `server/control-descriptor.test.ts`
+- Create: `server/control-broker.ts`
+- Create: `server/control-broker.test.ts`
+- Create: `server/control-http.ts`
+- Create: `server/control-http.test.ts`
+
+**Interfaces:**
+- Consumes: shared control schemas.
+- Produces:
+
+```ts
+interface FlectControlBrokerShape {
+  readonly status: Effect.Effect
+  readonly enable: (
+    workspace: WorkspaceRegistration
+  ) => Effect.Effect
+  readonly disable: Effect.Effect
+  readonly nextCommand: (
+    workspaceId: string
+  ) => Effect.Effect
+  readonly complete: (
+    receipt: FlectCommandReceipt
+  ) => Effect.Effect
+  readonly publishSnapshot: (
+    snapshot: FlectWorkspaceSnapshot
+  ) => Effect.Effect
+  readonly publishEvent: (
+    event: FlectWorkspaceEvent
+  ) => Effect.Effect
+}
+```
+
+- [ ] **Step 1: Write failing descriptor and lifecycle tests**
+
+Test in a temporary explicit directory:
+
+- 256-bit token generation;
+- random `127.0.0.1` port only;
+- directory `0700`, descriptor `0600`;
+- exact version/url/token/pid/instance/workspace schema;
+- stale PID or instance rejection and cleanup;
+- disable interrupts queue waiters, removes descriptor, rotates token, and
+  rejects the prior bearer;
+- scope release performs the same cleanup.
+
+- [ ] **Step 2: Write failing external API security tests**
+
+Prove:
+
+- missing, malformed, and stale bearer returns 401 without detail leakage;
+- non-loopback bind is rejected at construction;
+- body and header limits apply before decode;
+- `enable-control` is rejected externally;
+- inspect, commands, logs, and SSE events use the shared schemas;
+- command POST waits for the workspace receipt;
+- disconnected workspace returns typed 409/503 behavior;
+- no API response includes the bearer.
+
+- [ ] **Step 3: Run focused tests and confirm red**
+
+```bash
+bunx vitest run server/control-descriptor.test.ts server/control-broker.test.ts server/control-http.test.ts
+```
+
+Expected: FAIL.
+
+- [ ] **Step 4: Implement secure descriptor handling**
+
+Use `Effect.tryPromise` around filesystem boundaries with typed errors. Write
+to a temporary file in the same directory, chmod, then rename atomically.
+Resolve paths from `XDG_STATE_HOME` or the platform user state directory; test
+layers inject an explicit directory and never target `HOME`, `~`, or `/`.
+
+- [ ] **Step 5: Implement the scoped broker**
+
+Use `Queue`, `Deferred`, `SubscriptionRef`, and `Effect.acquireRelease`.
+Maintain only:
+
+- active grant metadata;
+- connected workspace metadata;
+- latest published snapshot;
+- bounded published events;
+- pending command receipts.
+
+Never reconstruct or mutate workspace state in the broker.
+
+- [ ] **Step 6: Implement the authenticated Effect HTTP/SSE listener**
+
+Expose versioned routes:
+
+```text
+GET  /v1/status
+GET  /v1/instances
+GET  /v1/workspaces/:id
+GET  /v1/workspaces/:id/events
+GET  /v1/workspaces/:id/logs
+POST /v1/workspaces/:id/commands
+POST /v1/control/disable
+```
+
+Start on `127.0.0.1:0`, discover the assigned port, and write the descriptor
+only after the server is accepting connections.
+
+- [ ] **Step 7: Run focused tests and leak scans**
+
+```bash
+bunx vitest run server/control-descriptor.test.ts server/control-broker.test.ts server/control-http.test.ts
+rg -n "authorization|bearer|token" server/control-*.ts shared/control.ts
+```
+
+Expected: tests PASS; every sensitive-value use is confined to authentication
+or descriptor code and never logging.
+
+### Task 9: Connect browser and packaged desktop workspaces to the broker
+
+**Files:**
+- Create: `src/lib/workspace-control-bridge.ts`
+- Create: `src/lib/workspace-control-bridge.test.ts`
+- Modify: `server/app.ts`
+- Modify: `server/app.test.ts`
+- Modify: `shared/rpc.ts`
+- Modify: `server/rpc-handlers.ts`
+- Modify: `server/rpc-handlers.test.ts`
+- Modify: `src/lib/tauri-transport.ts`
+- Modify: `src/lib/tauri-transport.test.ts`
+- Modify: `server/index.ts`
+- Modify: `server/sidecar.ts`
+- Modify: `src/lib/runtime.ts`
+
+**Interfaces:**
+- Consumes: `FlectControlBroker`,
+  `FlectWorkspaceController.dispatch/changes/events`.
+- Produces: one `WorkspaceControlBridge` service whose browser and desktop
+  layers have identical semantics.
+
+- [ ] **Step 1: Write failing browser channel tests**
+
+Test:
+
+- enable/register requires an allowed browser `Origin`;
+- no-origin and cross-origin callers cannot impersonate the UI;
+- the UI receives queued commands, posts typed receipts, and publishes state
+  and events;
+- disable closes the command stream;
+- reconnect uses the same active workspace but a new channel instance;
+- control commands appear immediately in the controller snapshot.
+
+- [ ] **Step 2: Write failing desktop RPC channel tests**
+
+Add streaming/private RPCs:
+
+```text
+ControlEnable
+ControlDisable
+ControlStatus
+ControlRegisterWorkspace
+ControlCommands (stream)
+ControlComplete
+ControlPublishSnapshot
+ControlPublishEvent
+```
+
+Prove schema round-trip, stream interruption, broker sharing, and parity with
+browser receipts.
+
+- [ ] **Step 3: Run focused tests and confirm red**
+
+```bash
+bunx vitest run src/lib/workspace-control-bridge.test.ts server/app.test.ts server/rpc-handlers.test.ts src/lib/tauri-transport.test.ts
+```
+
+Expected: FAIL.
+
+- [ ] **Step 4: Implement browser and desktop bridge layers**
+
+The bridge must:
+
+- subscribe once to controller changes/events;
+- publish them to the broker;
+- consume broker commands;
+- call the same `controller.dispatch`;
+- return the exact receipt/error;
+- use scoped fibers and interrupt all streams on disable/unmount.
+
+Do not decode or branch on command tags in transport adapters beyond schema
+validation.
+
+- [ ] **Step 5: Compose exactly one broker instance per host**
+
+In `server/index.ts` and `server/sidecar.ts`, bind `ControlBrokerLive` once and
+provide the same layer reference to HTTP/RPC handlers and lifecycle startup.
+Ensure sidecar exit and browser runtime shutdown release its scope.
+
+- [ ] **Step 6: Run focused transport tests**
+
+```bash
+bunx vitest run src/lib/workspace-control-bridge.test.ts server/app.test.ts server/rpc-handlers.test.ts src/lib/tauri-transport.test.ts
+bun run typecheck
+```
+
+Expected: PASS.
+
+### Task 10: Ship the user-equivalent CLI, JSON mode, and MCP stdio adapter
+
+**Files:**
+- Create: `cli/flect-client.ts`
+- Create: `cli/flect-client.test.ts`
+- Create: `cli/flectctl.ts`
+- Create: `cli/flectctl.test.ts`
+- Create: `cli/flect-mcp.ts`
+- Create: `cli/flect-mcp.test.ts`
+- Modify: `package.json`
+- Modify: `scripts/build-sidecar.ts`
+- Modify: `scripts/build-sidecar.test.ts` if present
+- Modify: `src-tauri/tauri.conf.json`
+- Modify: release packaging tests and scripts that enumerate binaries
+
+**Interfaces:**
+- Consumes: protected descriptor and external JSON/SSE API.
+- Produces:
+  - compiled `flectctl`;
+  - stable exit codes;
+  - four MCP tools: `flect_inspect`, `flect_command`, `flect_wait`,
+    `flect_logs`.
+
+- [ ] **Step 1: Write failing client and CLI tests**
+
+Cover:
+
+- descriptor discovery and stale-instance failure;
+- authorization header injection without exposing the bearer;
+- `--stdin` for prompt/shape;
+- human versus `--json` output;
+- inspect/watch/logs, mode, prompt, shape, invoke, cancel, models/model,
+  model favorites, App/Shaper external-extension toggles,
+  accept/reject/rollback, safe/restore, rail, control status/disable, and raw
+  schema command;
+- `launch` opens the installed app or documented browser URL;
+- no CLI `control enable`;
+- exit codes for use error, unavailable, auth, conflict, operation failure,
+  and interruption;
+- stdout contains only schema JSON in JSON mode and diagnostics use stderr.
+
+- [ ] **Step 2: Write failing MCP protocol tests**
+
+Feed JSON-RPC frames over in-memory stdio and verify initialize, tool listing,
+tool calls, schema validation, cancellation, and safe error responses. Confirm
+the bearer never appears in tool schemas/results.
+
+- [ ] **Step 3: Run focused tests and confirm red**
+
+```bash
+bunx vitest run cli/flect-client.test.ts cli/flectctl.test.ts cli/flect-mcp.test.ts
+```
+
+Expected: FAIL.
+
+- [ ] **Step 4: Implement the Effect CLI client and commands**
+
+Use `Effect.fn` operations and one boundary runtime. Decode every response with
+shared schemas. Generate command envelopes client-side with the workspace ID
+from inspection and a named control source. Wait for terminal operation events
+by default; `--no-wait` returns the accepted receipt.
+
+Arguments support human convenience, but documentation and agent tests use:
+
+```bash
+printf '%s' 'Make the dashboard denser' | flectctl shape --stdin --json
+```
+
+- [ ] **Step 5: Implement the compact MCP adapter**
+
+Use an official installed MCP SDK if already present; otherwise add the
+smallest current official SDK package and inspect its local docs/source before
+coding. Map all authority through the same client:
+
+```text
+flect_inspect -> snapshot
+flect_command -> closed FlectCommand
+flect_wait    -> event cursor / terminal operation
+flect_logs    -> bounded OperationFilter
+```
+
+Do not create one MCP tool per Flect command.
+
+- [ ] **Step 6: Compile and bundle `flectctl`**
+
+Extend the build script to compile:
+
+```text
+src-tauri/binaries/flect-runtime-aarch64-apple-darwin
+src-tauri/binaries/flectctl-aarch64-apple-darwin
+```
+
+Add `flectctl` to Tauri `externalBin` and release artifact verification.
+`install-shell` may create a user-approved symlink in `~/.local/bin`; no
+automatic PATH or shell-profile mutation.
+
+- [ ] **Step 7: Run focused tests and binary smoke**
+
+```bash
+bunx vitest run cli/flect-client.test.ts cli/flectctl.test.ts cli/flect-mcp.test.ts scripts/package-release.test.ts
+bun run build:sidecar
+src-tauri/binaries/flectctl-aarch64-apple-darwin --help
+```
+
+Expected: tests PASS; help lists the documented commands and no enable command.
+
+### Task 11: Verify real browser behavior through the public control surface
+
+**Files:**
+- Modify: `tests/e2e/flect.spec.ts`
+- Create: `tests/e2e/control-plane.spec.ts`
+- Modify: `playwright.config.ts` if a second worker/service fixture is needed
+- Create: `docs/verification/flect-observable-control/browser.md`
+- Create screenshots under:
+  `docs/verification/flect-observable-control/screenshots/`
+
+**Interfaces:**
+- Consumes: running test runtime, UI, real `flectctl`, JSON/SSE API.
+- Produces: public-surface browser evidence.
+
+- [ ] **Step 1: Add a failing end-to-end Shaper reliability scenario**
+
+Drive Edit mode through the visible UI, submit the prior reproduction
+instruction `make a demo ui and show me`, and assert:
+
+- proposal tool activity becomes visible;
+- a valid preview appears;
+- accept makes it active;
+- no generic “could not produce” error appears;
+- diagnostics contain correlated validation/tool/revision events.
+
+- [ ] **Step 2: Add failing sticky-follow and activity scenarios**
+
+Fill the timeline, scroll more than 48 px away, stream additional deltas/tool
+updates, and assert viewport stability. Assert `Jump to latest` and unread
+count, then jump and verify following resumes.
+
+- [ ] **Step 3: Add failing CLI-to-live-UI scenarios**
+
+Enable control via the protected UI, then invoke the compiled CLI from the
+test:
+
+```text
+inspect -> mode edit -> shape -> accept -> mode run -> prompt
+-> invoke a visible node -> logs -> safe-mode -> restore -> disable
+```
+
+Assert each external command changes the open page reactively and displays
+client attribution. Assert the old token fails immediately after disable.
+
+- [ ] **Step 4: Run the scenarios red, then implement only missing seams**
+
+```bash
+bunx playwright test tests/e2e/flect.spec.ts tests/e2e/control-plane.spec.ts
+```
+
+Expected before final fixes: at least one new scenario FAILS for the missing
+observable behavior. Fix the smallest owning module for each failure.
+
+- [ ] **Step 5: Run Playwright green and capture evidence**
+
+```bash
+bunx playwright test tests/e2e/flect.spec.ts tests/e2e/control-plane.spec.ts
+```
+
+Expected: PASS. Save light/dark relevant UI screenshots showing activity,
+validation diagnostics, suspended scrolling, external attribution, and
+connected control state.
+
+### Task 12: Document ownership, security, adoption, and agent usage
+
+**Files:**
+- Modify: `README.md`
+- Modify: `VISION.md`
+- Modify: `PRODUCT.md`
+- Modify: `DESIGN.md`
+- Modify: `ARCHITECTURE.md`
+- Modify: `AGENTS.md`
+- Create: `docs/control-api.md`
+- Create: `docs/verification/flect-observable-control/README.md`
+
+**Interfaces:**
+- Consumes: verified implemented behavior only.
+- Produces: one authoritative home for each contract and workflow.
+
+- [ ] **Step 1: Update architecture and security ownership**
+
+In `ARCHITECTURE.md`, document:
+
+- workspace-authoritative topology;
+- App/Shaper/Guardian separation;
+- browser versus desktop channel parity;
+- broker lifecycle and descriptor;
+- token and origin threat model;
+- Effect services/layers/streams/scopes;
+- journal retention and redaction;
+- sandbox boundary unchanged by outside control.
+
+- [ ] **Step 2: Update product and design ownership**
+
+Put user outcomes and limits in `PRODUCT.md`, long-term self-shaping intent in
+`VISION.md`, and activity/sticky-follow/control UI behavior in `DESIGN.md`.
+Avoid copying protocol steps into those documents.
+
+- [ ] **Step 3: Add adoption and quickstart material**
+
+In `README.md`, show:
+
+```bash
+open /Applications/Flect.app
+/Applications/Flect.app/Contents/MacOS/flectctl inspect
+printf '%s' 'Create a project dashboard' |
+  /Applications/Flect.app/Contents/MacOS/flectctl shape --stdin
+```
+
+Explain that control must first be enabled inside Flect and that Flect works
+without outside control in both browser and desktop modes.
+
+- [ ] **Step 4: Add the exact API/CLI/MCP reference**
+
+`docs/control-api.md` owns endpoint routes, auth, schemas, commands, exit
+codes, SSE cursors, MCP tools, examples, disable/revoke behavior, and safe
+debugging. Generate examples from actual schema-encoded fixtures where
+practical.
+
+- [ ] **Step 5: Update `AGENTS.md` with codebase invariants only**
+
+Record that:
+
+- all semantic actions enter `FlectWorkspaceController`;
+- React and control adapters cannot create alternate state;
+- Effect is mandatory for UI shaping and orchestration;
+- control boundaries use shared schemas;
+- secrets never enter logs/model context;
+- real-browser tests drive the public control surface.
+
+Do not duplicate setup commands or API reference detail into `AGENTS.md`.
+
+- [ ] **Step 6: Run documentation and formatting checks**
+
+```bash
+rg -n 'FIXME|PLACEHOLDER|control '"'