Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,13 @@ PMOVES.AI is a **production-ready multi-agent orchestration platform** featuring
- Auth: `nats://nats:pmoves@nats:4222` (always use authenticated URL)
- **Critical subjects:** See `.claude/context/nats-subjects.md`

**Supabase** [PostgREST Port 3010]
- Postgres with pgvector extension
**Supabase** [Kong Port 8000, PostgREST Port 3000, Studio Port 54323]
- Unified 13-service self-hosted stack (profile: `supabase-local`)
- Services: DB (Postgres 17.6.1), GoTrue, PostgREST v14.3, Kong 3.7.1, Realtime v2.72.0, Storage v1.37.1, Studio, imgproxy, pg-meta, Edge Functions, Analytics (Logflare), Vector, Supavisor
- Canonical consumer URL: `http://supabase-kong:8000/rest/v1` (via Kong gateway)
- Standard variable names: `JWT_SECRET`, `ANON_KEY`, `SERVICE_ROLE_KEY` (SUPABASE_* aliases for compat)
- Schema: `pmoves_core`, Archon prompts
- **Use for:** Metadata storage, content records, agent state
- **Use for:** Metadata storage, content records, agent state, auth, connection pooling

**Qdrant** [Port 6333]
- Vector embeddings for semantic search
Expand Down
47 changes: 47 additions & 0 deletions .claude/commands/tac/review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# TAC Tree Review

Run a TAC (Task-Action-Context) tree audit for an integration submodule.

## Usage
Accepts a submodule name or tree path as argument:
- `/tac:review health-wger` — Review health integration
- `/tac:review firefly-iii` — Review wealth integration
- `/tac:review n8n` — Review n8n workflows
- `/tac:review pmoves/configs/tac_trees/custom.tac.yaml` — Custom tree

## Instructions

1. Resolve the argument to a TAC tree path:
- If arg matches a known name (`health-wger`, `firefly-iii`, `n8n`), map to `pmoves/configs/tac_trees/<name>.tac.yaml`
- If arg is a file path, use directly
- If no arg provided, list available trees in `pmoves/configs/tac_trees/`

2. Run the TAC runner in text mode:
```bash
python pmoves/tools/tac_runner.py --format text <tree-path>
```

3. Also run in JSON mode for structured analysis:
```bash
python pmoves/tools/tac_runner.py <tree-path>
```

4. Present results to the user with:
- Overall pass/fail summary
- Each failing node with its `agent_hint` (who should fix it)
- Suggested next actions for each failure
- If all pass, confirm the integration is audit-clean

5. For failing nodes, offer to fix them:
- `file_exists` failures → offer to create the missing file
- `grep` failures → offer to add the missing content
- `manual` items → flag for user review

## Agent Assignment Hints
Each TAC node includes an `agent_hint` field suggesting which agent should handle the fix:
- `codex` — Claude Code CLI (documentation, config, scripts)
- `archon` — Archon agent (Supabase, prompts)
- `tokenism` — CHIT encoding
- `n8n` — n8n workflow creation

$ARGUMENTS
4 changes: 3 additions & 1 deletion .github/workflows/hardening-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,10 @@ jobs:

- name: Validate compose syntax
env:
# Required by ${:?} guards — CI uses a dummy value for syntax validation only
# Required by ${:?} guards — CI uses dummy values for syntax validation only
CHIT_PROD_PASSPHRASE: ci-validation-placeholder
SECRET_KEY_BASE: ci-validation-placeholder
VAULT_ENC_KEY: ci-validation-placeholder
run: |
echo "Validating docker-compose files..."

Expand Down
2 changes: 1 addition & 1 deletion PMOVES-Wealth
2 changes: 1 addition & 1 deletion PMOVES-supabase
2 changes: 1 addition & 1 deletion Pmoves-Health-wger
52 changes: 24 additions & 28 deletions pmoves/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ supa-start: check-tools ensure-env-shared ## Start Supabase stack for selected r
-e KONG_PG_USER=$${SUPABASE_DB_USER:-postgres} \
-e KONG_PG_PASSWORD=$${SUPABASE_DB_PASSWORD:-postgres} \
kong:3.7.1 kong migrations bootstrap --yes >/dev/null 2>&1 || true; \
$(DC) up -d supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio; \
$(DC) up -d supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio supabase-imgproxy supabase-meta supabase-edge-functions supabase-analytics supabase-vector supabase-pooler; \
fi
@$(MAKE) --no-print-directory supa-status
@$(MAKE) --no-print-directory supa-collation-refresh 2>/dev/null || true
Expand All @@ -321,14 +321,14 @@ supa-stop: ## Stop Supabase stack for selected runtime
@if [ "$(SUPABASE_RUNTIME)" = "cli" ]; then \
supabase stop --workdir "." >/dev/null 2>&1 || true; \
else \
$(DC) stop supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio >/dev/null 2>&1 || true; \
$(DC) stop supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio supabase-imgproxy supabase-meta supabase-edge-functions supabase-analytics supabase-vector supabase-pooler >/dev/null 2>&1 || true; \
fi
@echo "✅ Supabase stopped"

supa-stop-all: ## Stop both Supabase runtimes (CLI and compose) to clear mixed-state drift
@echo "🛑 Stopping all Supabase runtimes..."
@supabase stop --workdir "." >/dev/null 2>&1 || true
@$(DC) stop supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio >/dev/null 2>&1 || true
@$(DC) stop supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio supabase-imgproxy supabase-meta supabase-edge-functions supabase-analytics supabase-vector supabase-pooler >/dev/null 2>&1 || true
@echo "✅ All Supabase runtimes stopped"

supa-restart: ## Restart Supabase stack for selected runtime
Expand Down Expand Up @@ -384,7 +384,7 @@ supa-status: ## Show Supabase status for selected runtime and export env snapsho
echo " Auth: $$auth_url"; \
echo " Studio: $$studio_url"; \
else \
$(DC) ps supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio 2>/dev/null || true; \
$(DC) ps supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio supabase-imgproxy supabase-meta supabase-edge-functions supabase-analytics supabase-vector supabase-pooler 2>/dev/null || true; \
echo ""; \
echo "Expected local endpoints:"; \
echo " PostgREST: http://localhost:$${SUPABASE_POSTGREST_PORT:-3000}"; \
Expand Down Expand Up @@ -412,7 +412,7 @@ supa-logs: ## Tail logs for selected runtime (set SVC=<container/service> for a
docker logs --tail=80 "$$c" || true; \
done; \
else \
$(DC) logs --tail=120 supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio || true; \
$(DC) logs --tail=120 supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio supabase-imgproxy supabase-meta supabase-edge-functions supabase-analytics supabase-vector supabase-pooler || true; \
fi

supa-health: ## Health checks for selected runtime + active DB container readiness
Expand Down Expand Up @@ -630,21 +630,15 @@ else
endif
@$(MAKE) --no-print-directory auth-check

supabase-up: ## Compose fallback only: start gotrue/realtime/storage/studio sidecars
@if [ "$(SUPABASE_RUNTIME)" != "compose" ] && [ "$(SUPA_PROVIDER)" != "compose" ]; then \
echo "↷ SUPABASE_RUNTIME=$(SUPABASE_RUNTIME) (compose fallback skipped)"; \
exit 0; \
fi
@$(DC) -f docker-compose.supabase.yml up -d gotrue realtime storage studio
@echo "✅ Compose Supabase sidecars started (fallback mode)"
supabase-up: ## Alias for up-supabase (shim removed — all services in main compose)
@$(MAKE) --no-print-directory up-supabase

supabase-stop: ## Compose fallback only: stop gotrue/realtime/storage/studio sidecars
@$(DC) -f docker-compose.supabase.yml stop gotrue realtime storage studio >/dev/null 2>&1 || true
@echo "✅ Compose Supabase sidecars stopped"
supabase-stop: ## Alias for supa-stop (shim removed — all services in main compose)
@$(MAKE) --no-print-directory supa-stop

supabase-clean: ## Compose fallback only: remove gotrue/realtime/storage/studio containers + volumes
@$(DC) -f docker-compose.supabase.yml down -v --remove-orphans >/dev/null 2>&1 || true
@echo "✅ Compose Supabase sidecars cleaned"
supabase-clean: ## Stop + remove Supabase containers and volumes
@$(DC) --profile supabase-local down -v --remove-orphans >/dev/null 2>&1 || true
@echo "✅ Supabase stack cleaned"
Comment on lines +639 to +641

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find the definition of $(DC) in the Makefile
rg "^\s*DC\s*:=" pmoves/Makefile

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 167


🏁 Script executed:

# Look at the docker-compose configuration to understand profiles
fd "docker-compose" pmoves/

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2625


🏁 Script executed:

# Search for compose files in the repository
fd -e yml -e yaml | grep -i compose

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2938


🏁 Script executed:

# Look for services in compose files and their profile definitions
rg "services:|profile:" pmoves/docker-compose.yml -A 2 -B 2 | head -100

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 724


🏁 Script executed:

# Search for Supabase-related services and profile definitions
rg "supabase-local" pmoves/

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2546


🏁 Script executed:

# Get a general overview of the main docker-compose.yml file
wc -l pmoves/docker-compose.yml && head -50 pmoves/docker-compose.yml

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2281


🏁 Script executed:

# Extract all service definitions and check which ones have profiles
python3 << 'EOF'
import yaml
import sys

with open('pmoves/docker-compose.yml', 'r') as f:
    content = yaml.safe_load(f)

services = content.get('services', {})
unprofiled_services = []
supabase_services = []

for service_name, service_def in services.items():
    profiles = service_def.get('profiles', [])
    if not profiles:
        unprofiled_services.append(service_name)
    elif 'supabase-local' in profiles:
        supabase_services.append(service_name)

print(f"Services with NO profile attribute ({len(unprofiled_services)}):")
for svc in sorted(unprofiled_services)[:20]:
    print(f"  - {svc}")

if len(unprofiled_services) > 20:
    print(f"  ... and {len(unprofiled_services) - 20} more")

print(f"\nServices in 'supabase-local' profile ({len(supabase_services)}):")
for svc in sorted(supabase_services):
    print(f"  - {svc}")
EOF

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 740


🏁 Script executed:

# Verify Docker Compose profile behavior by checking documentation/examples
# Let's also check if there's any STACK_FILES variable that might add extra services
rg "STACK_FILES" pmoves/Makefile -B 2 -A 2

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 808


🏁 Script executed:

# Check the full STACK_FILES definition in the Makefile
grep -A 30 "STACK_FILES \?=" pmoves/Makefile

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 49


🌐 Web query:

Docker Compose profile behavior default services no profile

💡 Result:

  • Services with no profiles: key are “default” services: if you run docker compose up without --profile (and without COMPOSE_PROFILES), Compose includes all services that have no profiles and excludes services that do declare profiles. [1][2]
  • Activating profiles doesn’t disable defaults: when you run docker compose --profile <name> up, Compose starts the default (no-profile) services plus the services in the enabled profile(s). [1][2]
  • Explicitly targeting a profiled service overrides profile activation: docker compose up myprofiledservice runs that service even if you didn’t enable its profile (Compose treats the service’s profile as active for that run). [1][2]
  • Dependencies matter: if an enabled service has depends_on a service that’s excluded by an inactive profile, the resulting model can be invalid (i.e., you must enable whatever profiles are needed to satisfy depends_on, or restructure). [2]

Sources: Docker Compose profiles docs. [1][2]


🏁 Script executed:

# Verify STACK_FILES more carefully
cat pmoves/Makefile | grep -A 40 "STACK_FILES"

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2095


supabase-clean tears down the entire stack, not just Supabase.

Services with no profile (qdrant, neo4j, meilisearch, nats, minio, hi-rag-gateway, tensorzero-gateway, and others) are default services that are always included when docker compose down runs. The --profile supabase-local flag activates the Supabase profile but does not exclude default services—it activates the profile in addition to running all unprofiled services. Therefore, $(DC) --profile supabase-local down -v --remove-orphans will stop and remove both the 13 Supabase services and the 19 core infrastructure services.

Use a separate compose file or an explicit service list instead of relying on the profile to isolate the target.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pmoves/Makefile` around lines 639 - 641, The supabase-clean Makefile target
currently uses $(DC) --profile supabase-local down which also brings down
unprofiled default services; change it to target only Supabase by either
invoking compose with a Supabase-only file (e.g., use $(DC) -f
docker-compose.supabase.yml down -v --remove-orphans) or explicitly stop/remove
only the Supabase service names (use $(DC) stop <supabase-service-list> && $(DC)
rm -f <supabase-service-list>) instead of relying on --profile; update the
supabase-clean recipe (the target name supabase-clean and the $(DC) invocation)
to use one of these approaches so only Supabase containers/volumes are removed.


.PHONY: neo4j-bootstrap
neo4j-bootstrap: ## Seed Neo4j with persona aliases + CHIT geometry fixtures
Expand Down Expand Up @@ -1041,7 +1035,7 @@ down-supabase: ## Stop Supabase
@if [ "$(SUPABASE_RUNTIME)" = "cli" ]; then \
supabase stop --workdir "$(CURDIR)" >/dev/null 2>&1 || true; \
else \
$(DC) stop supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio >/dev/null 2>&1 || true; \
$(DC) stop supabase-db supabase-postgrest supabase-gotrue supabase-kong supabase-realtime supabase-storage supabase-studio supabase-imgproxy supabase-meta supabase-edge-functions supabase-analytics supabase-vector supabase-pooler >/dev/null 2>&1 || true; \
fi

# =============================================================================
Expand Down Expand Up @@ -1316,15 +1310,17 @@ populate-tier-envs: bootstrap-tier-envs ## Populate tier env files with defaults
echo "✓ Populated env.tier-data"; \
fi; \
if [ -f "env.tier-supabase" ]; then \
sed -i "s|^SUPABASE_JWT_SECRET=.*|SUPABASE_JWT_SECRET=$${SUPABASE_JWT_SECRET:-$(shell openssl rand -base64 32)}|" env.tier-supabase; \
sed -i "s|^SUPABASE_ANON_KEY=.*|SUPABASE_ANON_KEY=$${SUPABASE_ANON_KEY:-$(shell openssl rand -base64 32)}|" env.tier-supabase; \
sed -i "s|^SUPABASE_SERVICE_ROLE_KEY=.*|SUPABASE_SERVICE_ROLE_KEY=$${SUPABASE_SERVICE_ROLE_KEY:-$(shell openssl rand -base64 32)}|" env.tier-supabase; \
sed -i "s|^SUPABASE_PUBLISHABLE_KEY=.*|SUPABASE_PUBLISHABLE_KEY=$${SUPABASE_PUBLISHABLE_KEY:-$(shell openssl rand -base64 32)}|" env.tier-supabase; \
sed -i "s|^SUPABASE_SECRET_KEY=.*|SUPABASE_SECRET_KEY=$${SUPABASE_SECRET_KEY:-$(shell openssl rand -base64 32)}|" env.tier-supabase; \
sed -i "s|^SUPABASE_REALTIME_SECRET=.*|SUPABASE_REALTIME_SECRET=$${SUPABASE_REALTIME_SECRET:-$(shell openssl rand -base64 32)}|" env.tier-supabase; \
sed -i "s|^SUPABASE_DB_PASSWORD=.*|SUPABASE_DB_PASSWORD=$${SUPABASE_DB_PASSWORD:-$(shell openssl rand -base64 24)}|" env.tier-supabase; \
sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$${POSTGRES_PASSWORD:-$(shell openssl rand -base64 24)}|" env.tier-supabase; \
echo "✓ Populated env.tier-supabase"; \
if grep -q "your_jwt_secret_here\|your_anon_key_here\|your_service_role_key_here" env.tier-supabase 2>/dev/null; then \
echo "Generating Supabase secrets with proper JWT tokens..."; \
if [ -x scripts/supabase/generate-keys.sh ]; then \
scripts/supabase/generate-keys.sh > env.tier-supabase; \
echo "✓ Populated env.tier-supabase (via generate-keys.sh with valid JWTs)"; \
else \
echo "⚠ scripts/supabase/generate-keys.sh not found — run 'make supa-init' to generate proper JWT keys"; \
fi; \
else \
echo "✓ env.tier-supabase already has real values, skipping"; \
fi; \
Comment on lines +1313 to +1323

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The Supabase placeholder probe won't repair upgraded env files.

This branch only looks for the old JWT/anon/service placeholders. An existing env.tier-supabase can pass that test while still missing new required keys like SECRET_KEY_BASE, VAULT_ENC_KEY, or PG_META_CRYPTO_KEY, so supa-start will still fail after populate-tier-envs says everything is fine.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pmoves/Makefile` around lines 1313 - 1323, The current Makefile check only
looks for legacy placeholders in env.tier-supabase and will skip regeneration
even when new required secrets are missing; update the populate logic that
checks env.tier-supabase to verify presence (and non-empty values) of the new
required keys SECRET_KEY_BASE, VAULT_ENC_KEY, and PG_META_CRYPTO_KEY in addition
to the old placeholders, and if any are absent or empty invoke
scripts/supabase/generate-keys.sh to regenerate/populate env.tier-supabase
(keeping the existing messaging flow and fallback that suggests running 'make
supa-init' if generate-keys.sh is missing).

fi; \
if [ -f "env.tier-api" ]; then \
sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$${POSTGRES_PASSWORD:-$(shell openssl rand -base64 24)}|" env.tier-api; \
Expand Down
10 changes: 5 additions & 5 deletions pmoves/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ This aggregates the entire onboarding sequence: env bootstrap, Supabase CLI brin
- Install the `supabase` CLI and run `make supa-init` once per repo.
- Start/stop with `make supa-start` / `make supa-stop`, inspect endpoints with `make supa-status`, then `make supa-use-local` to copy the CLI defaults into `.env.local` before starting the stack.
- Deep dive: `docs/SUPABASE_FULL.md` (CLI bootstrap) and `docs/SUPABASE_SWITCH.md` (switching between CLI vs. remote).
- **Compose-backed Supabase (lightweight alt.)**
- Run `make up-compose` to boot the core stack with compose Postgres/PostgREST enabled, then `make supabase-up` to add GoTrue/Realtime/Storage/Studio from `docker-compose.supabase.yml`.
- Stop the Supabase sidecars with `make supabase-stop` (or `make down` for everything) and clear data with `make supabase-clean`.
- **Compose-backed Supabase (unified stack)**
- All 13 Supabase services are in the main `docker-compose.yml` under the `supabase-local` profile.
- Run `make up-supabase` to start all services, `make supa-stop` to stop, `make supabase-clean` to remove containers + volumes.
- **Remote/self-hosted Supabase**
- Populate `.env.supa.remote` with your endpoints/keys (generate from `supa.md` via `make supa-extract-remote` if provided).
- Apply the remote profile with `make supa-use-remote` before running the main stack.
Expand Down Expand Up @@ -122,8 +122,8 @@ Agents Profile
- Wger and Firefly are started with PMOVES‑branded defaults driven by `WGER_BRAND_*` and related envs in `pmoves/env.shared`; the full set of seeded values is listed in `pmoves/docs/FIRST_RUN.md` under “Seeded & Branded Defaults”.
- Open Notebook’s branded login is configured via `OPEN_NOTEBOOK_PASSWORD`; keep `OPEN_NOTEBOOK_API_TOKEN` in lockstep so agents and CLI helpers reuse the same secret (see `pmoves/docs/services/open-notebook/README.md`).

Supabase (Full)
- Recommended: Supabase CLI (see `docs/SUPABASE_FULL.md`). Or use `docker-compose.supabase.yml` with `./scripts/pmoves.ps1 up-fullsupabase`.
Supabase (Full — 13 services)
- All services in main `docker-compose.yml` under `supabase-local` profile. Use `make up-supabase` or `./scripts/pmoves.ps1 up-fullsupabase`.
- Realtime demo: `http://localhost:8090/static/realtime.html` (subscribe to `studio_board`, `it_errors`; upload avatar and assign to a row).

## Codex VM Bootstrap
Expand Down
Loading
Loading