diff --git a/Makefile b/Makefile index 46c7d7b..16879fd 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,25 @@ # Salon_Assistant / Lumina — operator entrypoints # Approved structure: document targets only; do not invoke unimplemented scripts. -.PHONY: help bootstrap install install-s0-s2 upgrade doctor verify sync-design +.PHONY: help bootstrap install install-s0-s2 install-s3-s5 upgrade doctor verify sync-design \ + install-s0b install-s1 install-s2 install-s3 install-s4 install-s5 help: @echo "Salon_Assistant (Lumina) — $(shell cat VERSION 2>/dev/null || echo 'unknown')" @echo "" @echo "Implemented targets:" @echo " make bootstrap - host prereqs (Docker if missing) [S0b]" - @echo " make install - full install S0b–S2" - @echo " make install-s0-s2 - install stages S0b through S2 (same as install)" + @echo " make install - full install S0b–S5" + @echo " make install-s0-s2 - install stages S0b through S2" + @echo " make install-s3-s5 - install stages S3 through S5 (stack, sandbox, policy, skills)" @echo "" @echo "Staged install:" + @echo " make install-s0b - S0b only: Docker bootstrap" @echo " make install-s1 - S1 only: repository environment (.env)" @echo " make install-s2 - S2 only: model + vision config + smoke" + @echo " make install-s3 - S3 only: stack alignment (documentation)" + @echo " make install-s4 - S4 only: sandbox verify/onboard" + @echo " make install-s5 - S5 only: policy overlays + skills sync" @echo "" @echo "Not yet implemented (stubbed):" @echo " make upgrade - product upgrade" @@ -26,19 +32,39 @@ help: bootstrap: @bash scripts/bootstrap.sh -install install-s0-s2: +install: @bash scripts/install.sh +install-s0-s2: + @bash scripts/install.sh --stage s0b + @bash scripts/install.sh --stage s1 + @bash scripts/install.sh --stage s2 + +install-s3-s5: + @bash scripts/install.sh --stage s3-s5 + +install-s0b: + @bash scripts/install.sh --stage s0b + install-s1: @bash scripts/install.sh --stage s1 install-s2: @bash scripts/install.sh --stage s2 -# ── Stubbed targets (S3+ not yet implemented) ────────────────────────────── +install-s3: + @bash scripts/install.sh --stage s3 + +install-s4: + @bash scripts/install.sh --stage s4 + +install-s5: + @bash scripts/install.sh --stage s5 + +# ── Stubbed targets (S6+ not yet implemented) ────────────────────────────── upgrade doctor verify: - @echo "not implemented — S3+ stages pending" >&2; exit 1 + @echo "not implemented — S6+ stages pending" >&2; exit 1 sync-design: @echo "Design SSOT:" diff --git a/agents/hermes/README.md b/agents/hermes/README.md index cb66e6c..39785b2 100644 --- a/agents/hermes/README.md +++ b/agents/hermes/README.md @@ -1,13 +1,55 @@ -# Hermes agent package (scaffold) +# Hermes agent package -**Status:** Structure only until **build**. +**Status:** Config fragments and manifest ready for S4–S5. -## Intended contents +## Structure | Path | Purpose | |------|---------| -| `config/` | Onboard fragments (model, MCP, channels placeholders) | -| `skills-manifest/` | Which Lumina skills ship with the profile | -| Identity templates | SOUL / USER / assistant naming (Claire demo persona when implemented) | +| `config/inference.yaml` | Inference config fragment (main + aux vision models) | +| `config/mcp-servers.yaml` | MCP server config fragment (Square, QBO — enabled at S7) | +| `config/channels.yaml` | Messaging channel config fragment (WhatsApp, Telegram, Email — enabled at S7) | +| `skills-manifest/manifest.yaml` | Skills manifest listing all Lumina skills for sync | +| `identity/assistant.yaml` | Identity template (name, role, capabilities, constraints) | -Onboard via `nemohermes onboard` using this package — never hand-edit in-sandbox config as SSOT. +## Onboard modes + +### Attach (default for UAT) + +When the sandbox already exists (e.g., `hermes` on this host), S4 skips +onboard and verifies the sandbox is healthy. Config fragments are used as +reference only — the live config is managed by `nemohermes` sealed commands. + +```bash +# Attach mode: verify sandbox exists and is healthy +nemohermes status +``` + +### Onboard (clean host) + +On a fresh host, use `nemohermes onboard` with this agent package: + +```bash +# Onboard with agent package (dry-run first) +nemohermes onboard --from-dir agents/hermes --dry-run + +# Onboard for real +nemohermes onboard --from-dir agents/hermes +``` + +The onboard process: +1. Creates the sandbox container +2. Applies inference config from `.env` +3. Registers the identity template +4. Skills are synced separately in S5 + +## Platform-first + +All config mutations use `nemohermes` sealed commands. Never hand-edit +in-sandbox config as SSOT. The fragments in this directory are the +product's source of truth for what gets configured. + +## Design reference + +- [design/DESIGN_PLAN.md §3](../../design/DESIGN_PLAN.md) — Hermes as NemoClaw-managed infrastructure +- [design/DESIGN_PLAN.md §2](../../design/DESIGN_PLAN.md) — Host automation (no custom control API) diff --git a/agents/hermes/config/channels.yaml b/agents/hermes/config/channels.yaml new file mode 100644 index 0000000..12db535 --- /dev/null +++ b/agents/hermes/config/channels.yaml @@ -0,0 +1,16 @@ +# agents/hermes/config/channels.yaml +# Messaging channel config fragment for nemohermes onboard. +# +# Channels are registered via nemohermes channels add, not by +# hand-editing in-sandbox config. This file documents the planned channels. +# +# Platform-first: channel mutations use nemohermes channels add/stop/start. + +# Planned channels (enabled at S7 when connected): +# - whatsapp +# - telegram +# - email + +# Rules: +# - Owner ↔ agent: full messaging +# - Client outbound: draft-first only (no silent send/publish) diff --git a/agents/hermes/config/inference.yaml b/agents/hermes/config/inference.yaml new file mode 100644 index 0000000..567a52b --- /dev/null +++ b/agents/hermes/config/inference.yaml @@ -0,0 +1,22 @@ +# agents/hermes/config/inference.yaml +# Inference config fragment for nemohermes onboard. +# +# This fragment is merged into the sandbox's managed config during onboard. +# Values are resolved from .env at install time. +# +# Platform-first: the actual config write is done by nemohermes inference set, +# not by hand-editing in-sandbox files. + +# Main model endpoint (OpenAI-compatible) +# Resolved from LUMINA_INFERENCE_BASE_URL and LUMINA_INFERENCE_MODEL +inference: + provider: compatible-endpoint + # model: set by nemohermes inference set from .env + # base_url: set by nemohermes inference set from .env + +# Auxiliary vision model +# Resolved from LUMINA_VISION_MODEL +auxiliary: + vision: + # model: set from LUMINA_VISION_MODEL (often same as main if multimodal) + pass diff --git a/agents/hermes/config/mcp-servers.yaml b/agents/hermes/config/mcp-servers.yaml new file mode 100644 index 0000000..1d050ac --- /dev/null +++ b/agents/hermes/config/mcp-servers.yaml @@ -0,0 +1,40 @@ +# agents/hermes/config/mcp-servers.yaml +# MCP server config fragment for nemohermes onboard. +# +# Lists MCP servers that may be registered at S7 (SaaS connections). +# At S3–S5, this is a placeholder — no live MCP servers are configured. +# +# Platform-first: MCP registration is done via nemohermes mcp add, +# not by hand-editing in-sandbox config. + +mcp_servers: + # Square — remote MCP (enabled at S7 when connected) + # - name: square + # url: ${SQUARE_MCP_URL} + # tools: + # include: + # - bookings.* + # - customers.* + # - catalog.* + # - inventory.* + # exclude: + # - payments.* + # - refunds.* + # - cards.* + # - checkout.* + # - payouts.* + + # QuickBooks Online — local MCP (enabled at S7 when connected) + # - name: qbo + # url: http://lumina-qbo-mcp:3000 # compose service + # tools: + # include: + # - reports.* + # - search.* + # - get.* + # exclude: + # - create_payment.* + # - bill_payment.* + # - write.* + # - update.* + # - delete.* diff --git a/agents/hermes/identity/assistant.yaml b/agents/hermes/identity/assistant.yaml new file mode 100644 index 0000000..44da67c --- /dev/null +++ b/agents/hermes/identity/assistant.yaml @@ -0,0 +1,30 @@ +# agents/hermes/identity/assistant.yaml +# Lumina identity template — minimal, product-safe. +# +# This template defines the assistant's identity for the Hermes sandbox. +# The owner's chosen name replaces the default at onboard time. +# +# Rules: +# - Default name: "Lumina" (generic; owner renames at setup) +# - No hardcoded persona details (demo "Claire" is a fixture, not identity) +# - Owner name/profile persists across upgrades (volume-backed) + +identity: + # Default display name (overridden by owner at setup) + name: Lumina + # Role description + role: "Salon and spa owner assistant" + # Capabilities summary (used in intro messages) + capabilities: + - daily operations board + - appointment availability + - client management + - books and finance overview + - social media drafts + - vendor communications + # Safety constraints + constraints: + - draft-first outbound messaging + - no agent payments + - no silent send or publish + - deterministic facts from tools; inference for wording only diff --git a/agents/hermes/skills-manifest/manifest.yaml b/agents/hermes/skills-manifest/manifest.yaml new file mode 100644 index 0000000..b9d1fe7 --- /dev/null +++ b/agents/hermes/skills-manifest/manifest.yaml @@ -0,0 +1,82 @@ +# agents/hermes/skills-manifest/manifest.yaml +# Lumina skills manifest — which skills ship with the Hermes profile. +# +# This manifest is used by the install script (S5) to determine which +# skill directories to sync into the sandbox via nemohermes skill install. +# +# Skills are organized by domain. Each entry maps to a directory under +# skills/ in the repository root. + +skills: + # ── Daily operations ────────────────────────────────────────────────── + - name: daily-board + domain: operations + description: "Today's salon board: appointments, tasks, priorities" + + - name: availability + domain: operations + description: "Check and display appointment availability" + + - name: service-menu + domain: operations + description: "Service catalog and pricing" + + - name: retail-stock + domain: operations + description: "Retail product inventory levels" + + # ── Client management ───────────────────────────────────────────────── + - name: client-card + domain: clients + description: "Client profile and history" + + - name: draft-client-message + domain: clients + description: "Draft outbound messages to clients (draft-first)" + + # ── Books / finance ─────────────────────────────────────────────────── + - name: books-snapshot + domain: books + description: "QuickBooks snapshot: P&L, balance, cash" + + - name: ar-open-invoices + domain: books + description: "Accounts receivable: open invoices" + + - name: ap-bills-due + domain: books + description: "Accounts payable: bills due" + + - name: vendor-spend + domain: books + description: "Vendor spending summary" + + - name: vendor-inbox + domain: books + description: "Vendor communications and documents" + + - name: draft-invoice + domain: books + description: "Draft invoices for clients (draft-first)" + + # ── Social / marketing ──────────────────────────────────────────────── + - name: social-draft + domain: social + description: "Draft social media posts (draft-first; vision aux)" + + - name: weekly-digest + domain: social + description: "Weekly business digest for the owner" + + # ── System ──────────────────────────────────────────────────────────── + - name: remember-forget + domain: system + description: "Confirm-to-remember persistence; forget entries" + + - name: setup-education + domain: system + description: "Owner-safe connect education and capability report" + + - name: publish-boundary-test + domain: system + description: "Boundary test: verify publish/send denials" diff --git a/deploy/compose/README.md b/deploy/compose/README.md index 6b8f5e1..0a83b2b 100644 --- a/deploy/compose/README.md +++ b/deploy/compose/README.md @@ -1,5 +1,55 @@ -# Compose (scaffold) +# Compose — product-managed services -**Status:** No `docker-compose.yml` until **build**. +**Status:** Optional stub. Not required for S3–S5 UAT attach path. -Will host gateway/sandbox alignment, local QBO MCP, webhooks, volumes — per [design/DESIGN_PLAN.md](../../design/DESIGN_PLAN.md). +## Host vs container boundaries + +| Layer | Owner | Managed by | +|-------|-------|------------| +| **Host** | Operator | `nemohermes` CLI, `openshell` CLI, product scripts | +| **Gateway** | OpenShell | `nemohermes` (sealed transactions) | +| **Hermes sandbox** | OpenShell | `nemohermes start/stop/rebuild/destroy` | +| **Local MCP / webhooks** | Product | `docker compose` (this file) — optional | + +**Key principle:** OpenShell owns the Hermes sandbox container. The product does NOT define the sandbox in `docker-compose.yml`. The sandbox is created and managed exclusively through `nemohermes` commands. + +## What this compose file provides + +An optional Docker Compose file for **product-managed services** that run alongside the Hermes sandbox: + +- **QBO MCP** — local MCP server for QuickBooks Online (stdio or network-attached) +- **Vagaro webhooks** — REST endpoint for Vagaro webhook ingestion + +These services share the `lumina` Docker network. The Hermes sandbox container is NOT part of this compose file. + +## When to use + +- **UAT attach (S3–S5):** Not needed. The sandbox runs via `nemohermes`; no local MCP or webhooks yet. +- **S7+ (SaaS connections):** Uncomment and configure the relevant service when connecting Square, QBO, or Vagaro. + +## Usage + +```bash +# When services are uncommented and configured: +cd deploy/compose +docker compose up -d + +# Check status +docker compose ps + +# Logs +docker compose logs -f +``` + +## Volumes + +| Volume | Purpose | +|--------|---------| +| `qbo-mcp-data` | QBO MCP state (tokens, cache) | +| `vagaro-webhooks-data` | Webhook processing state | + +## Design reference + +- [design/DESIGN_PLAN.md §3](../../design/DESIGN_PLAN.md) — Hermes as NemoClaw-managed infrastructure +- [design/DESIGN_PLAN.md §6](../../design/DESIGN_PLAN.md) — MCP and SaaS integration +- [docs/ARCHITECTURE.md](../../docs/ARCHITECTURE.md) — overall architecture diff --git a/deploy/compose/docker-compose.yml b/deploy/compose/docker-compose.yml new file mode 100644 index 0000000..6383097 --- /dev/null +++ b/deploy/compose/docker-compose.yml @@ -0,0 +1,55 @@ +# Salon_Assistant / Lumina — optional product services +# +# This compose file is OPTIONAL. It is NOT required for the S3–S5 UAT attach path. +# OpenShell manages the Hermes sandbox container directly; nemohermes owns +# sandbox lifecycle (start/stop/rebuild/destroy). This compose file exists only +# for future local MCP processes and webhook services that run alongside the +# sandbox on the same Docker network. +# +# Usage (when needed): +# cd deploy/compose && docker compose up -d +# +# See deploy/compose/README.md for details. + +# ── Network ──────────────────────────────────────────────────────────────── +# All product-managed services share this network. The Hermes sandbox container +# is NOT defined here — it is managed by nemohermes/OpenShell. +networks: + lumina: + driver: bridge + +# ── Volumes ──────────────────────────────────────────────────────────────── +volumes: + qbo-mcp-data: + vagaro-webhooks-data: + +# ── Services (stubs — enabled when SaaS connections are configured) ──────── +# Uncomment and configure when the corresponding SaaS integration is connected. + +# qbo-mcp: +# image: ghcr.io/ty-tech/qbo-mcp:latest # placeholder — real image at S7 +# container_name: lumina-qbo-mcp +# networks: +# - lumina +# volumes: +# - qbo-mcp-data:/data +# environment: +# - QBO_CLIENT_ID=${QBO_CLIENT_ID} +# - QBO_CLIENT_SECRET=${QBO_CLIENT_SECRET} +# - QBO_REFRESH_TOKEN=${QBO_REFRESH_TOKEN} +# - QBO_REALM_ID=${QBO_REALM_ID} +# restart: unless-stopped + +# vagaro-webhooks: +# image: ghcr.io/ty-tech/vagaro-webhooks:latest # placeholder — real image at S7 +# container_name: lumina-vagaro-webhooks +# networks: +# - lumina +# volumes: +# - vagaro-webhooks-data:/data +# environment: +# - VAGARO_API_KEY=${VAGARO_API_KEY} +# - VAGARO_WEBHOOK_SECRET=${VAGARO_WEBHOOK_SECRET} +# ports: +# - "127.0.0.1:8090:8080" +# restart: unless-stopped diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 13c1410..e8050fc 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,16 +1,18 @@ # Install -**Status:** Stages S0–S2 implemented. S3–S7 pending. +**Status:** Stages S0–S5 implemented. S6–S7 pending. ## Stages | Stage | Where | Outcome | Status | -|-------|--------|---------|--------| +|-------|-------|---------|--------| | S0 | Human | Host per [DEPLOYER_HOST.md](DEPLOYER_HOST.md) | ✅ Procedural | | S0b | Host script | Docker installed if missing | ✅ Implemented | | S1 | Host script | Repo env, `.env` from `.env.example` | ✅ Implemented | | S2 | Host script | Main + aux vision config; vision smoke | ✅ Implemented | -| S3–S5 | Host → Compose / `nemohermes` | Stack, sandbox, policy, skills | ⏳ Pending | +| S3 | Host script | Stack alignment (compose docs; OpenShell owns sandbox) | ✅ Implemented | +| S4 | Host script | Sandbox verify (attach) or onboard (clean host) | ✅ Implemented | +| S5 | Host script | Policy overlays + skills sync via nemohermes | ✅ Implemented | | S6 | Host script | Doctor green | ⏳ Pending | | S7 | Owner + operator connect helpers | Name assistant; connect **their** SaaS/channels | ⏳ Pending | @@ -86,20 +88,79 @@ make install-s2 **If the gateway is not yet connected:** the script validates the endpoint and skips the `openshell` write. S3+ will handle full gateway configuration. -## Run all stages (S0b–S2) +## S3: Stack alignment + +```bash +./scripts/install.sh --stage s3 +# or +make install-s3 +``` + +**What it does:** +- Documents that OpenShell manages the Hermes sandbox container. +- The product compose file (`deploy/compose/docker-compose.yml`) is optional — used only for local MCP and webhook services at S7+. +- No action needed for UAT attach path. + +**Key principle:** OpenShell owns the sandbox. The product does NOT define the sandbox in `docker-compose.yml`. + +## S4: Sandbox verification or onboard + +```bash +./scripts/install/s4-sandbox.sh # attach mode (default) +./scripts/install/s4-sandbox.sh --mode attach +./scripts/install/s4-sandbox.sh --mode onboard +./scripts/install/s4-sandbox.sh --mode onboard --dry-run +# or +make install-s4 +``` + +**Attach mode (default):** +- Verifies the sandbox exists and is healthy. +- Checks that the agent package (`agents/hermes/`) is present. +- No destructive operations. + +**Onboard mode (clean host):** +- Creates a new sandbox from the agent package using `nemohermes onboard`. +- If a sandbox with the same name already exists, falls back to attach mode for safety. +- Use `--dry-run` to preview without executing. + +## S5: Policy overlays + skills sync + +```bash +./scripts/install/s5-policy-skills.sh # policy + skills +./scripts/install/s5-policy-skills.sh --policy-only +./scripts/install/s5-policy-skills.sh --skills-only +# or +make install-s5 +``` + +**What it does:** +1. **Policy:** Applies the inference policy overlay from `policy/openshell/overlays/inference.yaml` via `nemohermes policy-add`. Existing balanced-tier presets (npm, pypi, huggingface, brew) are preserved. +2. **Skills:** Iterates skill directories under `skills/` (skipping `_lib`) and installs each via `nemohermes skill install`. Skills without `SKILL.md` are skipped with a warning. + +**Additive only:** policy-add never removes existing presets. Skills install is idempotent. + +## Run all stages (S0b–S5) ```bash ./scripts/install.sh # or make install -# or -make install-s0-s2 ``` -## After install (S0–S2) +## Run S3–S5 only (attach path) + +```bash +./scripts/install.sh --stage s3-s5 +# or +make install-s3-s5 +``` + +## After install (S0–S5) - Verify `.env` values are correct for your environment. -- Continue with S3+ when implemented (compose stack, sandbox creation, policy, skills). +- Check policy: `nemohermes policy-list` +- Continue with S6 (doctor) when implemented. - See [SETUP_UX.md](SETUP_UX.md) for owner-facing setup after full install. - See [design/scenarios.md](../design/scenarios.md) (S1–S5) for operational scenarios. diff --git a/policy/openshell/README.md b/policy/openshell/README.md index 071d151..e8585bb 100644 --- a/policy/openshell/README.md +++ b/policy/openshell/README.md @@ -1,14 +1,52 @@ -# OpenShell policy (scaffold) +# OpenShell policy -**Status:** Structure only — no live policy applied until **build**. +**Status:** Base policy and overlays ready for S5. -## Intended contents +## Structure | Path | Purpose | |------|---------| -| `policy.yaml` (or equivalent) | Deny-by-default base for salon egress | -| `overlays/` | Per-integration allowlists (Square MCP host, QBO local, channels, etc.) | +| `base.yaml` | Deny-by-default intent (reference; not applied directly) | +| `overlays/inference.yaml` | Inference endpoint (applied at S5) | +| `overlays/square-mcp.yaml` | Square MCP (applied at S7 when connected) | +| `overlays/quickbooks.yaml` | QuickBooks Online (applied at S7 when connected) | +| `overlays/vagaro.yaml` | Vagaro REST API (applied at S7 when connected) | +| `overlays/channels.yaml` | Messaging channels (applied at S7 when connected) | -Apply via platform CLIs only: `openshell policy set`, `nemohermes policy-add` / `policy-remove`. +## Policy lifecycle -See [design/mcp-integrations.md](../../design/mcp-integrations.md) and [docs/POLICY.md](../../docs/POLICY.md). +1. **Install (S5):** Apply inference overlay. Existing balanced-tier presets (npm, pypi, huggingface, brew) are preserved. +2. **Connect (S7):** Apply SaaS/channel overlays as integrations are enabled. +3. **Upgrade:** Re-apply all overlays (idempotent via `--yes`). +4. **Doctor (S6):** Verify active policy matches expected state. + +## Apply policy + +```bash +# Apply inference overlay (S5) +nemohermes policy-add --from-file policy/openshell/overlays/inference.yaml --yes + +# Apply SaaS overlay (S7, when connected) +nemohermes policy-add --from-file policy/openshell/overlays/square-mcp.yaml --yes + +# Apply built-in channel preset (S7, when connected) +nemohermes policy-add telegram --yes + +# List active presets +nemohermes policy-list + +# Export current policy +nemohermes policy-get +``` + +## Key principles + +- **Additive only:** policy-add never removes existing presets. +- **No wipe:** Never remove balanced-tier presets (npm, pypi, huggingface, brew). +- **Always deny:** Social publish, payment/refund/payout/bill-pay are never allowed. +- **Platform-first:** All policy mutations via `nemohermes` / `openshell` CLIs. + +## Design reference + +- [design/DESIGN_PLAN.md §3](../../design/DESIGN_PLAN.md) — Hermes as NemoClaw-managed infrastructure +- [docs/POLICY.md](../../docs/POLICY.md) — Full policy documentation diff --git a/policy/openshell/base.yaml b/policy/openshell/base.yaml new file mode 100644 index 0000000..95c8e68 --- /dev/null +++ b/policy/openshell/base.yaml @@ -0,0 +1,33 @@ +# policy/openshell/base.yaml +# Lumina base policy — reference document. +# +# This file documents the deny-by-default intent for the Lumina sandbox. +# It is NOT applied directly. The live policy is managed by nemohermes +# policy-add/policy-remove commands. +# +# Apply via: nemohermes policy-add --from-file +# +# ── Deny-by-default intent ──────────────────────────────────────────────── +# +# The sandbox starts with NO network egress except what is explicitly allowed +# by applied policy presets. The base tier (balanced) provides: +# +# npm, pypi, huggingface, brew — package management (always allowed) +# +# Lumina adds overlays for: +# - inference endpoints (main model + vision) +# - SaaS integrations (Square, QBO, Vagaro) — when connected +# - messaging channels (WhatsApp, Telegram, Email) — when connected +# +# ── Always deny ──────────────────────────────────────────────────────────── +# - Social publish APIs (no silent publish) +# - Payment/refund/payout/bill-pay endpoints +# - Any host not explicitly listed in an overlay +# +# ── Policy lifecycle ─────────────────────────────────────────────────────── +# 1. Install (S5): apply base overlays (inference) +# 2. Connect (S7): apply SaaS/channel overlays as integrations are enabled +# 3. Upgrade: re-apply all overlays (idempotent) +# 4. Doctor (S6): verify active policy matches expected state +# +# See docs/POLICY.md for full policy documentation. diff --git a/policy/openshell/overlays/channels.yaml b/policy/openshell/overlays/channels.yaml new file mode 100644 index 0000000..01edeec --- /dev/null +++ b/policy/openshell/overlays/channels.yaml @@ -0,0 +1,18 @@ +# policy/openshell/overlays/channels.yaml +# Messaging channels policy overlay (applied at S7 when channels are connected). +# +# Allows the sandbox to reach messaging channel APIs. Each channel has +# its own built-in preset in nemohermes (telegram, whatsapp, slack, etc.). +# This overlay documents which channels Lumina uses. +# +# Apply via: nemohermes policy-add --yes +# (Built-in presets; no --from-file needed for standard channels) +# +# Planned channels: +# - whatsapp (nemohermes built-in preset) +# - telegram (nemohermes built-in preset) +# - email (handled by openshell provider store) +# +# Rules: +# - Owner ↔ agent: full messaging +# - Client outbound: draft-first only (no silent send/publish) diff --git a/policy/openshell/overlays/inference.yaml b/policy/openshell/overlays/inference.yaml new file mode 100644 index 0000000..c5d4ddc --- /dev/null +++ b/policy/openshell/overlays/inference.yaml @@ -0,0 +1,49 @@ +# policy/openshell/overlays/inference.yaml +# Inference endpoint policy overlay for Lumina. +# +# Allows the sandbox to reach the configured inference endpoint through +# the OpenShell gateway. The gateway resolves inference.local to the +# actual endpoint URL from .env. +# +# Apply via: nemohermes policy-add --from-file --yes +# +# This overlay is additive — it does not remove existing presets. + +preset: + name: lumina-inference +network_policies: + lumina-inference: + name: lumina-inference + endpoints: + - host: inference.local + port: 443 + protocol: rest + enforcement: enforce + rules: + - allow: + method: POST + path: /v1/chat/completions + - allow: + method: POST + path: /v1/messages + - allow: + method: POST + path: /v1/responses + - allow: + method: POST + path: /v1/completions + - allow: + method: POST + path: /v1/embeddings + - allow: + method: GET + path: /v1/models + - allow: + method: GET + path: /v1/models/** + binaries: + - path: /usr/local/bin/hermes + # Glob supported by nemohermes policy engine (verified against built-in + # presets: huggingface, nous_research, npm_yarn, pypi all use python3*) + - path: /usr/bin/python3* + - path: /opt/hermes/.venv/bin/python diff --git a/policy/openshell/overlays/quickbooks.yaml b/policy/openshell/overlays/quickbooks.yaml new file mode 100644 index 0000000..2e389e1 --- /dev/null +++ b/policy/openshell/overlays/quickbooks.yaml @@ -0,0 +1,38 @@ +# policy/openshell/overlays/quickbooks.yaml +# QuickBooks Online policy overlay (applied at S7 when QBO is connected). +# +# Allows the sandbox to reach QuickBooks Online APIs for read operations +# (reports, search, get). Write/update/delete operations are excluded +# at the MCP tool level. +# +# Apply via: nemohermes policy-add --from-file --yes + +preset: + name: quickbooks-online +network_policies: + quickbooks-online: + name: quickbooks-online + endpoints: + - host: quickbooks.api.intuit.com + port: 443 + protocol: rest + enforcement: enforce + rules: + - allow: + method: GET + path: /** + - allow: + method: POST + path: /** + - host: oauth.platform.intuit.com + port: 443 + protocol: rest + enforcement: enforce + rules: + - allow: + method: POST + path: /** + binaries: + - path: /usr/local/bin/hermes + - path: /usr/bin/python3* + - path: /opt/hermes/.venv/bin/python diff --git a/policy/openshell/overlays/square-mcp.yaml b/policy/openshell/overlays/square-mcp.yaml new file mode 100644 index 0000000..86d20c2 --- /dev/null +++ b/policy/openshell/overlays/square-mcp.yaml @@ -0,0 +1,30 @@ +# policy/openshell/overlays/square-mcp.yaml +# Square MCP policy overlay (applied at S7 when Square is connected). +# +# Allows the sandbox to reach Square's MCP server for bookings, customers, +# catalog, and inventory reads. Payment/refund/payout tools are excluded +# at the MCP tool level, not the network level. +# +# Apply via: nemohermes policy-add --from-file --yes + +preset: + name: square-mcp +network_policies: + square-mcp: + name: square-mcp + endpoints: + - host: connect.squareup.com + port: 443 + protocol: rest + enforcement: enforce + rules: + - allow: + method: GET + path: /** + - allow: + method: POST + path: /** + binaries: + - path: /usr/local/bin/hermes + - path: /usr/bin/python3* + - path: /opt/hermes/.venv/bin/python diff --git a/policy/openshell/overlays/vagaro.yaml b/policy/openshell/overlays/vagaro.yaml new file mode 100644 index 0000000..b9d3c5f --- /dev/null +++ b/policy/openshell/overlays/vagaro.yaml @@ -0,0 +1,33 @@ +# policy/openshell/overlays/vagaro.yaml +# Vagaro policy overlay (applied at S7 when Vagaro is connected). +# +# Allows the sandbox to reach Vagaro's REST API for appointments, clients, +# services, and staff data. Webhook ingestion is handled by the local +# vagaro-webhooks service (compose-managed), not direct sandbox egress. +# +# Apply via: nemohermes policy-add --from-file --yes + +preset: + name: vagaro +network_policies: + vagaro: + name: vagaro + endpoints: + - host: api.vagaro.com + port: 443 + protocol: rest + enforcement: enforce + rules: + - allow: + method: GET + path: /** + - allow: + method: POST + path: /** + - allow: + method: PUT + path: /** + binaries: + - path: /usr/local/bin/hermes + - path: /usr/bin/python3* + - path: /opt/hermes/.venv/bin/python diff --git a/scripts/README.md b/scripts/README.md index 474efd2..073d86a 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,6 +1,6 @@ # Host scripts -**Status:** S0b–S2 implemented. S3–S7 pending. +**Status:** S0b–S5 implemented. S6–S7 pending. All scripts wrap **`nemohermes` / `openshell` / Docker**. No parallel control API. @@ -9,9 +9,11 @@ All scripts wrap **`nemohermes` / `openshell` / Docker**. No parallel control AP | Script | Role | Status | |--------|------|--------| | `bootstrap.sh` | Host prereqs; install Docker if missing | ✅ S0b | -| `install.sh` | Staged installer (S0b–S2) | ✅ S0b–S2 | +| `install.sh` | Staged installer (S0b–S5) | ✅ S0b–S5 | | `install/s1-env.sh` | S1: create/validate `.env` | ✅ S1 | | `install/s2-models.sh` | S2: model + vision config + smoke | ✅ S2 | +| `install/s4-sandbox.sh` | S4: sandbox verify (attach) or onboard | ✅ S4 | +| `install/s5-policy-skills.sh` | S5: policy overlays + skills sync | ✅ S5 | | `upgrade.sh` | Snapshot, pull pins, migrate, re-apply policy, doctor | ⏳ Pending | | `doctor.sh` | Health checks | ⏳ Pending | | `connect/*.sh` | Operator connect helpers (Square, QBO, Vagaro, channels) | ⏳ Pending | @@ -30,18 +32,23 @@ All scripts wrap **`nemohermes` / `openshell` / Docker**. No parallel control AP # Bootstrap (Docker if missing) ./scripts/bootstrap.sh -# Full install (S0b–S2) +# Full install (S0b–S5) ./scripts/install.sh # Individual stages ./scripts/install.sh --stage s1 # env only ./scripts/install.sh --stage s2 # models only +./scripts/install.sh --stage s4 # sandbox verify/onboard +./scripts/install.sh --stage s5 # policy + skills +./scripts/install.sh --stage s3-s5 # S3 through S5 # Or via Make make bootstrap make install make install-s1 make install-s2 +make install-s3-s5 +make install-s5 ``` ## Design reference diff --git a/scripts/install.sh b/scripts/install.sh index 21a039e..d0a6bbf 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,12 +1,12 @@ #!/usr/bin/env bash # scripts/install.sh — Lumina staged installer # -# Runs install stages S0b–S2 (S3+ not yet implemented). +# Runs install stages S0b–S5. # # Usage: -# ./scripts/install.sh # run all implemented stages (S0b–S2) +# ./scripts/install.sh # run all implemented stages (S0b–S5) # ./scripts/install.sh --stage s1 # run only S1 -# ./scripts/install.sh --stage s2 # run only S2 +# ./scripts/install.sh --stage s3-s5 # run S3 through S5 # ./scripts/install.sh --help # # All stages are idempotent. Re-running is safe. @@ -25,23 +25,27 @@ usage() { cat < Run only the specified stage - --help Show this help + --stage Run only the specified stage or range + --help Show this help Stages: S0b Docker install-if-missing (bootstrap) S1 Repository environment (.env) S2 Model + vision configuration + smoke test + S3 Stack alignment (compose documentation; no-op on attach) + S4 Sandbox verification or onboard (attach mode default) + S5 Policy overlays + skills sync All stages are idempotent. Examples: - $(basename "$0") # run S0b → S1 → S2 + $(basename "$0") # run S0b → S1 → S2 → S3 → S4 → S5 $(basename "$0") --stage s1 # run only S1 (env) - $(basename "$0") --stage s2 # run only S2 (models) + $(basename "$0") --stage s5 # run only S5 (policy + skills) + $(basename "$0") --stage s3-s5 # run S3 → S4 → S5 EOF } @@ -54,7 +58,7 @@ while [[ $# -gt 0 ]]; do shift SINGLE_STAGE="${1:-}" if [[ -z "$SINGLE_STAGE" ]]; then - log_error "--stage requires a value (s1 or s2)" + log_error "--stage requires a value" exit 1 fi shift @@ -67,7 +71,7 @@ while [[ $# -gt 0 ]]; do esac done -# ── Run stages ───────────────────────────────────────────────────────────── +# ── Stage runners ────────────────────────────────────────────────────────── run_s0b() { log_section "S0b: Docker bootstrap" bash "$SCRIPT_DIR/bootstrap.sh" @@ -81,17 +85,37 @@ run_s2() { bash "$SCRIPT_DIR/install/s2-models.sh" } -log_section "Lumina installer (stages S0b–S2)" +run_s3() { + log_section "S3: Stack alignment" + log_info "OpenShell manages the Hermes sandbox container." + log_info "Product compose (deploy/compose/) is optional for local MCP/webhooks." + log_info "No action needed for UAT attach path." +} + +run_s4() { + bash "$SCRIPT_DIR/install/s4-sandbox.sh" +} + +run_s5() { + bash "$SCRIPT_DIR/install/s5-policy-skills.sh" +} + +# ── Main ─────────────────────────────────────────────────────────────────── +log_section "Lumina installer (stages S0b–S5)" warn_if_root if [[ -n "$SINGLE_STAGE" ]]; then case "$SINGLE_STAGE" in - s0b) run_s0b ;; - s1) run_s1 ;; - s2) run_s2 ;; + s0b) run_s0b ;; + s1) run_s1 ;; + s2) run_s2 ;; + s3) run_s3 ;; + s4) run_s4 ;; + s5) run_s5 ;; + s3-s5) run_s3; run_s4; run_s5 ;; *) log_error "Unknown stage: $SINGLE_STAGE" - log_error "Valid stages: s0b, s1, s2" + log_error "Valid stages: s0b, s1, s2, s3, s4, s5, s3-s5" exit 1 ;; esac @@ -100,10 +124,14 @@ else run_s0b run_s1 run_s2 + run_s3 + run_s4 + run_s5 fi -log_section "Install complete (S0b–S2)" +log_section "Install complete (S0b–S5)" log_info "Next steps:" log_info " - Review .env for correctness" -log_info " - Continue with S3+ when implemented (compose, sandbox, policy)" +log_info " - Verify policy: nemohermes $(get_sandbox_name) policy-list" +log_info " - Continue with S6 (doctor) when implemented" log_info " - See docs/INSTALL.md for full procedure" diff --git a/scripts/install/s4-sandbox.sh b/scripts/install/s4-sandbox.sh new file mode 100755 index 0000000..3fd9344 --- /dev/null +++ b/scripts/install/s4-sandbox.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env bash +# scripts/install/s4-sandbox.sh — S4: sandbox verification / onboard +# +# Two modes: +# attach (default) — verify existing sandbox is healthy; no destructive ops +# onboard — create new sandbox from agent package (clean host only) +# +# Platform-first: all mutations via nemohermes. Never hand-edit in-sandbox config. +# +# Usage: +# ./scripts/install/s4-sandbox.sh # attach mode (default) +# ./scripts/install/s4-sandbox.sh --mode attach +# ./scripts/install/s4-sandbox.sh --mode onboard +# ./scripts/install/s4-sandbox.sh --mode onboard --dry-run +# ./scripts/install/s4-sandbox.sh --help + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Source shared helpers +# shellcheck source=../lib/common.sh +source "$SCRIPT_DIR/../lib/common.sh" +# shellcheck source=../lib/env.sh +source "$SCRIPT_DIR/../lib/env.sh" + +# ── Defaults ─────────────────────────────────────────────────────────────── +MODE="${LUMINA_INSTALL_MODE:-attach}" +DRY_RUN=0 + +# ── Parse args ───────────────────────────────────────────────────────────── +while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) + cat < Install mode (default: attach) + --dry-run Preview onboard without executing + --help Show this help + +Modes: + attach Verify existing sandbox is healthy (UAT default) + onboard Create new sandbox from agent package (clean host) + +Examples: + $(basename "$0") # attach mode + $(basename "$0") --mode onboard # onboard mode + $(basename "$0") --mode onboard --dry-run # onboard dry-run +EOF + exit 0 + ;; + --mode) + shift + MODE="${1:-}" + if [[ -z "$MODE" ]]; then + log_error "--mode requires a value (attach or onboard)" + exit 1 + fi + shift + ;; + --dry-run) + DRY_RUN=1 + shift + ;; + *) + log_error "Unknown argument: $1" + exit 1 + ;; + esac +done + +# ── Validate mode ────────────────────────────────────────────────────────── +if [[ "$MODE" != "attach" && "$MODE" != "onboard" ]]; then + log_error "Invalid mode: $MODE (must be 'attach' or 'onboard')" + exit 1 +fi + +log_section "S4: Sandbox ($MODE mode)" + +# ── Load .env ────────────────────────────────────────────────────────────── +load_env + +# ── Validate required keys ───────────────────────────────────────────────── +validate_env || exit 1 + +# ── Check CLI prerequisites ──────────────────────────────────────────────── +require_cmd nemohermes "Install nemohermes CLI (part of NemoClaw platform)" + +SANDBOX_NAME="$(get_sandbox_name)" +AGENT_PKG_DIR="$REPO_ROOT/agents/hermes" + +# ── Attach mode ──────────────────────────────────────────────────────────── +do_attach() { + log_info "Attach mode: verifying sandbox '$SANDBOX_NAME'" + + # Check sandbox exists and report status + if ! nemohermes "$SANDBOX_NAME" status &>/dev/null; then + log_error "Sandbox '$SANDBOX_NAME' not found or not reachable." + log_error "If this is a clean host, re-run with --mode onboard" + log_error "Or create the sandbox manually: nemohermes onboard" + return 1 + fi + + log_info "Sandbox '$SANDBOX_NAME' is healthy." + + # Verify agent package exists (reference only in attach mode) + if [[ -d "$AGENT_PKG_DIR" ]]; then + log_info "Agent package found at $AGENT_PKG_DIR" + if [[ -f "$AGENT_PKG_DIR/skills-manifest/manifest.yaml" ]]; then + log_info "Skills manifest present — S5 will sync skills" + else + log_warn "Skills manifest not found — skills sync (S5) may be incomplete" + fi + else + log_warn "Agent package directory not found at $AGENT_PKG_DIR" + fi + + log_info "S4 attach complete." +} + +# ── Onboard mode ─────────────────────────────────────────────────────────── +do_onboard() { + log_info "Onboard mode: preparing sandbox '$SANDBOX_NAME' from agent package" + + # Verify agent package exists + if [[ ! -d "$AGENT_PKG_DIR" ]]; then + log_error "Agent package not found at $AGENT_PKG_DIR" + return 1 + fi + + # Check if sandbox already exists — do not destroy it + if nemohermes "$SANDBOX_NAME" status &>/dev/null; then + log_warn "Sandbox '$SANDBOX_NAME' already exists." + log_warn "Onboard mode does not destroy existing sandboxes." + log_warn "Switching to attach behavior for safety." + do_attach + return 0 + fi + + if [[ $DRY_RUN -eq 1 ]]; then + log_info "DRY-RUN: Would execute:" + log_info " nemohermes onboard --from-dir $AGENT_PKG_DIR" + log_info " (with inference from .env: $LUMINA_INFERENCE_BASE_URL)" + log_info "S4 onboard dry-run complete." + return 0 + fi + + # Onboard with agent package + log_info "Running nemohermes onboard with agent package…" + if nemohermes onboard --from-dir "$AGENT_PKG_DIR"; then + log_info "Sandbox '$SANDBOX_NAME' onboarded successfully." + else + log_error "Onboard failed. Check nemohermes logs for details." + log_error "You may need to run nemohermes onboard manually first." + return 1 + fi + + log_info "S4 onboard complete." +} + +# ── Execute ──────────────────────────────────────────────────────────────── +case "$MODE" in + attach) do_attach ;; + onboard) do_onboard ;; +esac diff --git a/scripts/install/s5-policy-skills.sh b/scripts/install/s5-policy-skills.sh new file mode 100755 index 0000000..c9b8cb8 --- /dev/null +++ b/scripts/install/s5-policy-skills.sh @@ -0,0 +1,197 @@ +#!/usr/bin/env bash +# scripts/install/s5-policy-skills.sh — S5: policy apply + skills sync +# +# Applies Lumina policy overlays and syncs skills into the sandbox. +# Additive only: never removes existing presets. +# +# Platform-first: all mutations via nemohermes. +# +# Usage: +# ./scripts/install/s5-policy-skills.sh +# ./scripts/install/s5-policy-skills.sh --policy-only +# ./scripts/install/s5-policy-skills.sh --skills-only +# ./scripts/install/s5-policy-skills.sh --help + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Source shared helpers +# shellcheck source=../lib/common.sh +source "$SCRIPT_DIR/../lib/common.sh" +# shellcheck source=../lib/env.sh +source "$SCRIPT_DIR/../lib/env.sh" + +# ── Defaults ─────────────────────────────────────────────────────────────── +DO_POLICY=1 +DO_SKILLS=1 +POLICY_ONLY_SET=0 +SKILLS_ONLY_SET=0 + +# ── Parse args ───────────────────────────────────────────────────────────── +while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) + cat </dev/null 2>&1; then + log_error "Sandbox '$SANDBOX_NAME' not found. Run S4 first." + exit 1 +fi + +# ── Policy apply ─────────────────────────────────────────────────────────── +apply_policy() { + log_section "S5a: Apply policy overlays" + + if [[ ! -d "$POLICY_DIR" ]]; then + log_warn "Policy overlays directory not found: $POLICY_DIR" + return 0 + fi + + # Apply inference overlay (always apply at S5) + local inference_policy="$POLICY_DIR/inference.yaml" + if [[ -f "$inference_policy" ]]; then + log_info "Applying inference policy overlay…" + if nemohermes "$SANDBOX_NAME" policy-add --from-file "$inference_policy" --yes 2>&1; then + log_info "Inference policy overlay applied." + else + log_warn "Inference policy overlay may already be applied (idempotent)." + fi + else + log_warn "Inference policy overlay not found: $inference_policy" + fi + + # List current policy for verification + log_info "Current policy presets:" + nemohermes "$SANDBOX_NAME" policy-list 2>&1 || log_warn "Could not list policy presets" + + log_info "S5a policy apply complete." +} + +# ── Skills sync ──────────────────────────────────────────────────────────── +sync_skills() { + log_section "S5b: Sync skills" + + if [[ ! -d "$SKILLS_DIR" ]]; then + log_warn "Skills directory not found: $SKILLS_DIR" + return 0 + fi + + local skill_count=0 + local skill_ok=0 + local skill_skip=0 + local skill_fail=0 + + # Iterate skill directories (skip _lib and hidden dirs) + for skill_dir in "$SKILLS_DIR"/*/; do + # Skip if not a directory + [[ -d "$skill_dir" ]] || continue + + local skill_name + skill_name="$(basename "$skill_dir")" + + # Skip _lib (shared library, not a skill) + if [[ "$skill_name" == "_lib" ]]; then + log_info "Skipping _lib (shared library)" + continue + fi + + skill_count=$((skill_count + 1)) + + # Check for SKILL.md (required by nemohermes skill install) + local skill_md="$skill_dir/SKILL.md" + if [[ ! -f "$skill_md" ]]; then + log_warn "Skipping '$skill_name': no SKILL.md found" + skill_skip=$((skill_skip + 1)) + continue + fi + + log_info "Installing skill: $skill_name" + if nemohermes "$SANDBOX_NAME" skill install "$skill_dir" 2>&1; then + log_info " ✓ $skill_name installed" + skill_ok=$((skill_ok + 1)) + else + log_warn " ✗ $skill_name failed (may already be installed)" + skill_fail=$((skill_fail + 1)) + fi + done + + log_info "Skills sync summary: $skill_count found, $skill_ok installed, $skill_skip skipped, $skill_fail failed" + + if [[ $skill_count -eq 0 ]]; then + log_warn "No skill directories found in $SKILLS_DIR" + fi + + log_info "S5b skills sync complete." +} + +# ── Execute ──────────────────────────────────────────────────────────────── +if [[ $DO_POLICY -eq 1 ]]; then + apply_policy +fi + +if [[ $DO_SKILLS -eq 1 ]]; then + sync_skills +fi + +log_info "S5 complete." diff --git a/skills/ap-bills-due/SKILL.md b/skills/ap-bills-due/SKILL.md new file mode 100644 index 0000000..1c3d4ed --- /dev/null +++ b/skills/ap-bills-due/SKILL.md @@ -0,0 +1,18 @@ +--- +name: ap-bills-due +description: "Accounts payable: bills due" +domain: books +--- + +# ap-bills-due + +Accounts payable: bills due. + +## Description + +Lists upcoming and overdue bills from QuickBooks Online. + +## Constraints + +- Read-only bill data. +- No bill payment execution. diff --git a/skills/ar-open-invoices/SKILL.md b/skills/ar-open-invoices/SKILL.md new file mode 100644 index 0000000..8d0aa7c --- /dev/null +++ b/skills/ar-open-invoices/SKILL.md @@ -0,0 +1,18 @@ +--- +name: ar-open-invoices +description: "Accounts receivable: open invoices" +domain: books +--- + +# ar-open-invoices + +Accounts receivable: open invoices. + +## Description + +Lists outstanding invoices and aging summary from QuickBooks Online. + +## Constraints + +- Read-only invoice data. +- No payment processing. diff --git a/skills/availability/SKILL.md b/skills/availability/SKILL.md new file mode 100644 index 0000000..fa15281 --- /dev/null +++ b/skills/availability/SKILL.md @@ -0,0 +1,18 @@ +--- +name: availability +description: "Check and display appointment availability" +domain: operations +--- + +# availability + +Check and display appointment availability. + +## Description + +Shows available time slots for appointments based on the salon's schedule and service durations. + +## Constraints + +- Deterministic gap math from tools. +- No booking without owner confirmation. diff --git a/skills/books-snapshot/SKILL.md b/skills/books-snapshot/SKILL.md new file mode 100644 index 0000000..658f9c9 --- /dev/null +++ b/skills/books-snapshot/SKILL.md @@ -0,0 +1,18 @@ +--- +name: books-snapshot +description: "QuickBooks snapshot: P&L, balance, cash" +domain: books +--- + +# books-snapshot + +QuickBooks snapshot: P&L, balance, cash. + +## Description + +Provides a high-level financial snapshot from QuickBooks Online: profit and loss, balance sheet summary, and cash position. + +## Constraints + +- Read-only QuickBooks data. +- No write/update/delete operations. diff --git a/skills/client-card/SKILL.md b/skills/client-card/SKILL.md new file mode 100644 index 0000000..cf77158 --- /dev/null +++ b/skills/client-card/SKILL.md @@ -0,0 +1,18 @@ +--- +name: client-card +description: "Client profile and history" +domain: clients +--- + +# client-card + +Client profile and history. + +## Description + +Displays a client's profile, visit history, preferences, and notes. + +## Constraints + +- Read-only client data. +- No PII export without owner consent. diff --git a/skills/daily-board/SKILL.md b/skills/daily-board/SKILL.md new file mode 100644 index 0000000..59514aa --- /dev/null +++ b/skills/daily-board/SKILL.md @@ -0,0 +1,18 @@ +--- +name: daily-board +description: "Today's salon board: appointments, tasks, and priorities" +domain: operations +--- + +# daily-board + +Today's salon board: appointments, tasks, and priorities. + +## Description + +Pulls together the day's schedule, pending tasks, and key metrics into a single board view for the salon owner. + +## Constraints + +- Deterministic facts from tools; inference for ranking and wording only. +- No silent send or publish. diff --git a/skills/draft-client-message/SKILL.md b/skills/draft-client-message/SKILL.md new file mode 100644 index 0000000..046e018 --- /dev/null +++ b/skills/draft-client-message/SKILL.md @@ -0,0 +1,18 @@ +--- +name: draft-client-message +description: "Draft outbound messages to clients (draft-first)" +domain: clients +--- + +# draft-client-message + +Draft outbound messages to clients (draft-first). + +## Description + +Composes messages to clients for appointments, reminders, or follow-ups. Owner reviews and sends. + +## Constraints + +- Draft-first: owner must approve before sending. +- No silent send. diff --git a/skills/draft-invoice/SKILL.md b/skills/draft-invoice/SKILL.md new file mode 100644 index 0000000..1a56952 --- /dev/null +++ b/skills/draft-invoice/SKILL.md @@ -0,0 +1,18 @@ +--- +name: draft-invoice +description: "Draft invoices for clients (draft-first)" +domain: books +--- + +# draft-invoice + +Draft invoices for clients (draft-first). + +## Description + +Creates draft invoices for client services. Owner reviews and sends. + +## Constraints + +- Draft-first: owner must approve before sending. +- No automatic payment collection. diff --git a/skills/publish-boundary-test/SKILL.md b/skills/publish-boundary-test/SKILL.md new file mode 100644 index 0000000..9bbb9a2 --- /dev/null +++ b/skills/publish-boundary-test/SKILL.md @@ -0,0 +1,18 @@ +--- +name: publish-boundary-test +description: "Boundary test: verify publish/send denials" +domain: system +--- + +# publish-boundary-test + +Boundary test: verify publish/send denials. + +## Description + +Test skill that verifies the sandbox correctly denies publish, send, and payment operations. Used for validation during install and upgrade. + +## Constraints + +- This skill should fail when attempting publish/send/pay. +- If it succeeds, the policy is misconfigured. diff --git a/skills/remember-forget/SKILL.md b/skills/remember-forget/SKILL.md new file mode 100644 index 0000000..39b5ecb --- /dev/null +++ b/skills/remember-forget/SKILL.md @@ -0,0 +1,18 @@ +--- +name: remember-forget +description: "Confirm-to-remember persistence; forget entries" +domain: system +--- + +# remember-forget + +Confirm-to-remember persistence; forget entries. + +## Description + +Manages persistent memory entries. Requires explicit owner confirmation before remembering. Supports forgetting previously stored entries. + +## Constraints + +- Write only after structured confirmation. +- No silent persistence. diff --git a/skills/retail-stock/SKILL.md b/skills/retail-stock/SKILL.md new file mode 100644 index 0000000..06b266d --- /dev/null +++ b/skills/retail-stock/SKILL.md @@ -0,0 +1,18 @@ +--- +name: retail-stock +description: "Retail product inventory levels" +domain: operations +--- + +# retail-stock + +Retail product inventory levels. + +## Description + +Shows current stock levels for retail products, with low-stock alerts. + +## Constraints + +- Deterministic thresholds from tools. +- No automatic reordering. diff --git a/skills/service-menu/SKILL.md b/skills/service-menu/SKILL.md new file mode 100644 index 0000000..effce2c --- /dev/null +++ b/skills/service-menu/SKILL.md @@ -0,0 +1,18 @@ +--- +name: service-menu +description: "Service catalog and pricing" +domain: operations +--- + +# service-menu + +Service catalog and pricing. + +## Description + +Displays the salon's service menu with descriptions, durations, and prices. + +## Constraints + +- Read-only catalog data. +- No price changes without owner action. diff --git a/skills/setup-education/SKILL.md b/skills/setup-education/SKILL.md new file mode 100644 index 0000000..a84b55b --- /dev/null +++ b/skills/setup-education/SKILL.md @@ -0,0 +1,18 @@ +--- +name: setup-education +description: "Owner-safe connect education and capability report" +domain: system +--- + +# setup-education + +Owner-safe connect education and capability report. + +## Description + +Guides the owner through connecting their SaaS integrations (Square, QBO, Vagaro) and messaging channels. Provides a capability report showing what is connected. + +## Constraints + +- Owner-safe: no terminal instructions. +- Browser/vendor UI steps only. diff --git a/skills/social-draft/SKILL.md b/skills/social-draft/SKILL.md new file mode 100644 index 0000000..e8c0c81 --- /dev/null +++ b/skills/social-draft/SKILL.md @@ -0,0 +1,19 @@ +--- +name: social-draft +description: "Draft social media posts (draft-first; vision aux)" +domain: social +--- + +# social-draft + +Draft social media posts (draft-first; vision aux). + +## Description + +Creates draft social media posts using salon photos and content. Owner reviews and publishes. + +## Constraints + +- Draft-first: owner must approve before publishing. +- No silent publish. +- Vision aux for photo understanding. diff --git a/skills/vendor-inbox/SKILL.md b/skills/vendor-inbox/SKILL.md new file mode 100644 index 0000000..3110e60 --- /dev/null +++ b/skills/vendor-inbox/SKILL.md @@ -0,0 +1,18 @@ +--- +name: vendor-inbox +description: "Vendor communications and documents" +domain: books +--- + +# vendor-inbox + +Vendor communications and documents. + +## Description + +Tracks vendor communications, invoices received, and related documents. + +## Constraints + +- Read-only vendor data. +- Draft-first for any vendor responses. diff --git a/skills/vendor-spend/SKILL.md b/skills/vendor-spend/SKILL.md new file mode 100644 index 0000000..270be18 --- /dev/null +++ b/skills/vendor-spend/SKILL.md @@ -0,0 +1,18 @@ +--- +name: vendor-spend +description: "Vendor spending summary" +domain: books +--- + +# vendor-spend + +Vendor spending summary. + +## Description + +Summarizes spending by vendor from QuickBooks Online. + +## Constraints + +- Read-only financial data. +- No money movement. diff --git a/skills/weekly-digest/SKILL.md b/skills/weekly-digest/SKILL.md new file mode 100644 index 0000000..0934c66 --- /dev/null +++ b/skills/weekly-digest/SKILL.md @@ -0,0 +1,18 @@ +--- +name: weekly-digest +description: "Weekly business digest for the owner" +domain: social +--- + +# weekly-digest + +Weekly business digest for the owner. + +## Description + +Compiles a weekly summary of appointments, revenue, client activity, and key metrics. + +## Constraints + +- Deterministic facts from tools; inference for summary wording. +- Read-only data aggregation.