Implement install stages S3–S5: package, policy, and skills sync.
Attach/onboard sandbox from agents/hermes, additive OpenShell policy overlays, and nemohermes skill install for scaffold skills. No doctor/connect and no push.
This commit is contained in:
@@ -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:"
|
||||
|
||||
+49
-7
@@ -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 <name> 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)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# agents/hermes/config/channels.yaml
|
||||
# Messaging channel config fragment for nemohermes onboard.
|
||||
#
|
||||
# Channels are registered via nemohermes <name> channels add, not by
|
||||
# hand-editing in-sandbox config. This file documents the planned channels.
|
||||
#
|
||||
# Platform-first: channel mutations use nemohermes <name> 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)
|
||||
@@ -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
|
||||
@@ -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 <name> 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.*
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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 <name> 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
|
||||
|
||||
@@ -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
|
||||
+69
-8
@@ -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 <name> 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.
|
||||
|
||||
|
||||
@@ -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 <name> 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 <name> policy-add --from-file policy/openshell/overlays/inference.yaml --yes
|
||||
|
||||
# Apply SaaS overlay (S7, when connected)
|
||||
nemohermes <name> policy-add --from-file policy/openshell/overlays/square-mcp.yaml --yes
|
||||
|
||||
# Apply built-in channel preset (S7, when connected)
|
||||
nemohermes <name> policy-add telegram --yes
|
||||
|
||||
# List active presets
|
||||
nemohermes <name> policy-list
|
||||
|
||||
# Export current policy
|
||||
nemohermes <name> 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
|
||||
|
||||
@@ -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 <name> policy-add --from-file <path>
|
||||
#
|
||||
# ── 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.
|
||||
@@ -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 <name> policy-add <preset-name> --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)
|
||||
@@ -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 <name> policy-add --from-file <this-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
|
||||
@@ -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 <name> policy-add --from-file <this-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
|
||||
@@ -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 <name> policy-add --from-file <this-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
|
||||
@@ -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 <name> policy-add --from-file <this-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
|
||||
+10
-3
@@ -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
|
||||
|
||||
+45
-17
@@ -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 <<EOF
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
Run Lumina install stages (S0b–S2 implemented).
|
||||
Run Lumina install stages (S0b–S5 implemented).
|
||||
|
||||
Options:
|
||||
--stage <s1|s2> Run only the specified stage
|
||||
--help Show this help
|
||||
--stage <s0b|s1|s2|s3|s4|s5|s3-s5> 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"
|
||||
|
||||
Executable
+169
@@ -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 <<EOF
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
S4: Sandbox verification or onboard.
|
||||
|
||||
Options:
|
||||
--mode <attach|onboard> 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
|
||||
Executable
+197
@@ -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 <<EOF
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
S5: Apply policy overlays and sync skills into the sandbox.
|
||||
|
||||
Options:
|
||||
--policy-only Apply policy overlays only (skip skills sync)
|
||||
--skills-only Sync skills only (skip policy apply)
|
||||
--help Show this help
|
||||
|
||||
Examples:
|
||||
$(basename "$0") # policy + skills
|
||||
$(basename "$0") --policy-only # policy only
|
||||
$(basename "$0") --skills-only # skills only
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
--policy-only)
|
||||
DO_POLICY=1
|
||||
DO_SKILLS=0
|
||||
POLICY_ONLY_SET=1
|
||||
shift
|
||||
;;
|
||||
--skills-only)
|
||||
DO_POLICY=0
|
||||
DO_SKILLS=1
|
||||
SKILLS_ONLY_SET=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown argument: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ── Validate mutually exclusive flags ──────────────────────────────────────
|
||||
if [[ $POLICY_ONLY_SET -eq 1 && $SKILLS_ONLY_SET -eq 1 ]]; then
|
||||
log_error "--policy-only and --skills-only are mutually exclusive"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $DO_POLICY -eq 0 && $DO_SKILLS -eq 0 ]]; then
|
||||
log_error "Internal error: both DO_POLICY and DO_SKILLS are disabled"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_section "S5: Policy + Skills sync"
|
||||
|
||||
# ── 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)"
|
||||
POLICY_DIR="$REPO_ROOT/policy/openshell/overlays"
|
||||
SKILLS_DIR="$REPO_ROOT/skills"
|
||||
|
||||
# ── Verify sandbox exists ──────────────────────────────────────────────────
|
||||
if ! nemohermes "$SANDBOX_NAME" status &>/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."
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user