powernode-platform
CLAUDE.md4 starsChanged 18 days agoMITView on GitHub
Development guidance for Powernode: open-source mission control for AI agent fleets. This file is the outage-safe core — only global, high-stakes rules that must hold even if the MCP server is down. Situational rules live in hooks, scripts/pattern-validation.sh, and docs/contributing/conventions/ (recalled MCP-first). See Where guidance lives. Control plane for production AI agent fleets — knowledge graph, governance, swarm coordination, MCP-native runtime, and the fleet substrate (bare-metal / VM / container lifecycle). MIT. Project Status: docs/reference/auto/todo.md (auto-generated — do not edit).
The file
Show its rules and text
We split this CLAUDE.md into the rules it gives an agent
13 rules. About 0 are common, 4 are distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 55
NEVER: commit unless explicitly requested.
- Very specific: line 83
Eager Loading: always .includes() when iterating associations — never bare .all then .map/.each accessing relations.
- Very specific: line 90
NEVER: create job classes in server/app/jobs/.
- Distinctive: line 93
State the count: before ANY bulk operation: "This will affect N items."
- Very specific: line 101
Audit = report only: when asked to audit/review/analyze, save findings to docs/.
- Distinctive: line 103
Test-First Bug Reproduction: write a failing test reproducing the bug before the fix.
- Distinctive: line 104
Trace Changes to Request: every changed line traces to the request.
- Very specific: line 106
Dead Reference Cleanup: after deleting a file, grep -r for references and remove them (scope: orphans your changes created).
- Very specific: line 107
Completion Gate: before reporting work done, run the verification gate — scripts/validate.sh (model-agnostic.
- Distinctive: line 120
CWD verification: before EVERY git add/git commit, run git rev-parse --show-toplevel and confirm the repo.
- Very specific: line 126
NEVER save files to project root: Use docs/{getting-started,concepts,guides,reference,operations,contributing}/.
- Very specific: line 158
After a Rails restart /up 502s while it boots (~30s normally), up to ~3 min if boot runs pending migrations (MCP dead too).
- Very specific: line 166
Use platform.discover_skills with a task description to find the right specialist.
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
Development guidance for Powernode: open-source mission control for AI agent fleets.
This file is the outage-safe core — only global, high-stakes rules that must hold even if the
MCP server is down. Situational rules live in hooks, scripts/pattern-validation.sh, and
docs/contributing/conventions/ (recalled MCP-first). See
Where guidance lives.
Project Overview
Control plane for production AI agent fleets — knowledge graph, governance, swarm coordination, MCP-native runtime, and the fleet substrate (bare-metal / VM / container lifecycle). MIT.
- Backend: Rails 8 API (
./server) — JWT auth, UUIDv7 PKs. Does NOT run Sidekiq. - Frontend: React TypeScript (
./frontend) — theme-aware, Tailwind. - Worker: Sidekiq standalone (
./worker) — API-only communication. - Public extensions (git submodules, MIT on GitHub):
./extensions/system,./extensions/marketing,./extensions/supply-chain. - Private extensions (remote-only, not in public clones; added by maintainers): under
./extensions/private/*. The platform runs in core mode when absent — single-user self-hosted, all core capabilities unlocked, no billing/SaaS. - Database: PostgreSQL (native UUID) + pgvector.
Project Status: docs/reference/auto/todo.md (auto-generated — do not edit).
Core Models
Account → User (many), Agent (many), Skill (many)
User → Roles, Permissions, Invitations
Agent → Conversations, Tasks, Goals, ApprovalRequestsWhere guidance lives
Route by enforceability: git keeps only what a hook, spec or gate can check (lint, layout, imports, this core); the situational (runbooks, empirics, deploy facts, incidents, procedures) lives in platform knowledge. Then by trigger shape:
| Rule shape | Home | Surfaces / enforces via |
| Always + high-stakes + not checkable | this file (core) | always loaded |
| Mechanically checkable | .claude/hooks/*.sh + scripts/pattern-validation.sh | edit-time hook / adherence scan |
| Reusable pattern / procedure | platform guidance-*, git seed docs/contributing/conventions/ | MCP-first queries + SessionStart digest |
| Subsystem-scoped | nested server//frontend//worker/ CLAUDE.md | loads when editing that tree |
| Decision / incident / preference | platform knowledge, tag memory | harness MEMORY.md until migrated; search_knowledge tags:["memory"] (no Claude digest yet: query it) |
| Crypto / private-extension logic | extension only (never core) | core-purity-check.sh (blocking) |
Memory & Knowledge
- Memory is moving to platform knowledge. Until the migration is applied, MEMORY.md (harness-loaded) stays the recall source: consult/fix it there. Record NEW memories on the production connector, never a local memory file:
create_knowledge key memory:<slug> tags:["memory-<type>"] access_level account, never global; recallsearch_knowledge tags:["memory"],[[slug]]→ tagmemory-<slug>. It reflects what was true when written: verify file/flag refs. - MCP-first is mandatory for non-trivial work: query
platform.query_learnings/search_knowledge/code_semantic_searchbefore changing code (full protocol: conventions/mcp-first-workflow.md). Contribute back after (create_learning/create_knowledge). - Improvement loop: dev-improve is drained by Claude Code (
/dev-loop,dev_next_task/dev_complete_task) or by the Platform Developer canonical agent — theplatform_agentdrivercampaign_delegateresolves to when no agent is named — under the same loop guardrails; one driver per campaign loop at a time. Which to hand a task to: use-powernode-from-claude.md; the Engineering hierarchy: platform-engineering-agents.md. - The
guidance-*SessionStart digest is Claude-only; the loop guardrails (dev_next_task) andBASE_GUARDRAILStell other executors to querysearch_knowledge tag:guidance-*first. Use the production connector (mcp__powernode__*): a sandbox one (mcp__powernode-local__*) may be unseeded, socount:0there is an empty store.
Critical Rules (always-on)
Git
- NEVER commit unless explicitly requested. NEVER include AI attribution (any executor — Claude/Grok/Codex/Gemini/etc.) in commits — no "Generated with" / "Co-Authored-By" from any model.
- Branch:
develop→feature/*→release/*→master. Tags/release branches: NO "v" prefix (0.2.0,release/0.2.0). - Staged commits: group changes into logical commits by concern — never one monolithic commit. (also
guidance-git-conventions)
Permission-Based Access Control (CRITICAL)
Frontend MUST use permissions ONLY — NEVER roles for access control.
currentUser?.permissions?.includes('users.manage') // ✅ CORRECT
currentUser?.roles?.includes('admin') // ❌ FORBIDDEN
user.role === 'manager' // ❌ FORBIDDENBackend: current_user.has_permission?('name') — NEVER permissions.include?() (returns objects).
Backstopped by permission-not-roles-check.sh (advisory) + pattern-validation.sh (scan) + recall guidance-permissions-not-roles.
Cryptographic Material Safety (ABSOLUTE)
Generic key-handling principles — apply to ALL key material. Private-extension specifics (audit sinks, wallet/signing internals) live in the extension / CLAUDE.local.md, never here. The full table below is also carried model-agnostically (in guidance-crypto-material-safety + agent BASE_GUARDRAILS) so all executors carry it; it stays in core because it is outage-safe/absolute.
| Rule | Details |
| No key output | NEVER output, log, display, echo, or transmit private keys, API secrets, seed phrases, mnemonics, or signing material in any form |
| No keys in code | NEVER store keys/secrets/credentials in source, scripts, configs, env files, or docs |
| No CLI key generation | NEVER generate private keys via CLI (rails runner, rake, irb) where they could hit shell history |
| Vault-only storage | ALL key generation MUST happen inside Vault or the platform's Vault-backed key service (stores directly to Vault) |
| Audit all key ops | ALL key operations (generate, import, revoke, sign) MUST be logged to the audit log. TODO(verify: confirm core audit-log sink) |
| No key args in logs | NEVER pass keys as function arguments that could appear in logs/errors/traces |
| Guide, don't handle | When assisting with wallet/key setup, guide through the UI/API — never handle key material directly |
Backend (high-stakes — full conventions in backend-patterns.md)
- Eager Loading: always
.includes()when iterating associations — never bare.allthen.map/.eachaccessing relations. (Nudge:n-plus-one-check.sh.) - Webhook Receivers: inbound webhooks MUST return 200/202 on processing errors — NEVER 500 (provider retry storms). (Nudge:
webhook-500-check.sh.) - Everything else (namespacing, FK prefixes, JSON lambda defaults,
t.referencesindexes, controller size, frozen-string,render_success) is hook/scan-enforced — see the doc.
Worker Architecture (CRITICAL)
- server (
server/) is a Rails API — it does NOT run Sidekiq. - worker (
worker/) is standalone Sidekiq — talks to server via HTTP API only. - NEVER create job classes in
server/app/jobs/; NEVER add Sidekiq gems toserver/Gemfile. Keep the server/worker boundary clean (server stays Sidekiq-free; cross-app comms via the HTTP API).worker/MAY be modified when a change genuinely belongs there — there is no blanket prohibition on touching it.
Bulk Operation Safety
- State the count before ANY bulk operation: "This will affect N items."
- Operations affecting more than 5 items require explicit user confirmation; show the first 3 and last 1.
- Never batch-approve training decisions, permission grants, financial operations, or auto-discovered code changes — review individually. (also
guidance-bulk-op-safety+ agentBASE_GUARDRAILS+ loop guardrails so all executors carry it)
Design Principles
- Reuse First:
platform.discover_skills+search_knowledge+code_semantic_searchbefore proposing anything new — never greenfield when infrastructure exists. (alsoguidance-reuse-first+ agentBASE_GUARDRAILS) - Stop & Ask (HARD): after 3 failed attempts at the same fix, STOP and ask. No 4th approach, no workarounds.
- Surface Assumptions: state assumptions before implementing ambiguous requests; if multiple valid interpretations exist, present and ask.
- Audit = report only: when asked to audit/review/analyze, save findings to
docs/; do NOT implement unless told to fix.- (these governance rules also live in platform knowledge for all executors — recall
guidance-audit-report-only,guidance-surface-assumptions,guidance-trace-to-request,guidance-plan-before-multifile,guidance-dead-reference-cleanup; audit-report-only + surface-assumptions also carried in agentBASE_GUARDRAILS)
- (these governance rules also live in platform knowledge for all executors — recall
- Test-First Bug Reproduction: write a failing test reproducing the bug before the fix.
- Trace Changes to Request: every changed line traces to the request; revert adjacent "improvements" (scope creep).
- Plan Before Multi-File: changes touching 3+ files — outline files + data flow, get approval before writing.
- Dead Reference Cleanup: after deleting a file,
grep -rfor references and remove them (scope: orphans your changes created). - Completion Gate: before reporting work done, run the verification gate —
scripts/validate.sh(model-agnostic; specs + tsc + pattern-validation + gitleaks) or its targeted subset for what you changed./verifyis the Claude-only convenience wrapper; non-Claude executors use the gate directly (alsoguidance-verification-gate+ loop guardrails). - Powernode subagents:
assemble_taskfirst; pass itsmodel/effortto the Agent tool and itsassembly_idin the prompt. - Quality Gates:
cd frontend && npx tsc --noEmitafter TS; Ruby syntax + related spec after.rb;rails db:seedafter seeds — the authoritative home is the gatescripts/validate.sh(run by the pre-commit hook and any committer).
Architecture Principles
- Pull, Never Push: downstream managers pull from upstream; upstream never pushes downstream. When unsure of data-flow direction, ask.
- Extension Isolation: each
extensions/*is self-contained. Extensions depend on core; core NEVER depends on extensions. Enforced by the blockingcore-purity-check.shand a model-agnosticscripts/pattern-validation.shscan mirror (not just the Claude hook) — core source must not reference a private extension by name (itsNamespace::, submodule path, or import alias), and an extension's source must not reference a DIFFERENT extension either (the hook resolves the file's own slug and checks every other one; pre-existing references are grandfathered in.claude/hooks/core-purity-baseline.txt, private-path entries in the gitignored.local.txt); both derive the forbidden names dynamically fromextensions/private/*. Route through a generic seam instead. - Service Boundaries: cross-namespace communication goes through service interfaces, never direct model access.
These three invariants are also in the cross-executor guidance-architecture-invariants knowledge entry (recalled by any executor via search_knowledge tag:guidance-*), stated generically for all models.
Submodule Safety (CRITICAL)
- Submodules: public
extensions/{system,marketing,supply-chain}+ privateextensions/private/*. Do NOT rungit submodule syncon the public ones (drops the private upstream remote). (alsoguidance-submodule-safety) - CWD verification: before EVERY
git add/git commit, rungit rev-parse --show-topleveland confirm the repo. - Survey both statuses:
git statusin root ANDgit -C extensions/<name> status— submodule changes are invisible to the parent. - Never commit extension files from parent; commit inside the submodule FIRST, then update the pointer in the parent.
- Maintainer-local detail (private extensions, audit sinks) lives in
CLAUDE.local.md— never the public repo.
File Organization
NEVER save files to project root. Use docs/{getting-started,concepts,guides,reference,operations,contributing}/. docs/reference/auto/ is auto-generated — do not edit. (also guidance-file-organization; enforced by pattern-validation.sh)
Deployment-local facts NEVER go in tracked files. This deployment's hostnames, internal IPs, VM ids, remotes and operator details live in platform knowledge (tags deployment + deployment-<topic>, access_level: account) or the gitignored docs/operations/local/; tracked docs use placeholders. Recall: search_knowledge tag:deployment-*. Enforced by deployment-identifier-check.sh (hook + scan, patterns from the gitignored .claude/hooks/deployment-identifiers.local.txt). Convention: conventions/deployment-knowledge.md.
Terminology
| Term | Means | Not |
server/ | Rails app directory | "backend directory" |
powernode-backend | the Rails service (unit name below) | "rails service" |
worker/ | standalone Sidekiq app | "job runner" |
powernode-worker | the Sidekiq service (unit name below) | "sidekiq service" |
systemd unit names — NEVER guess them. On module-composed nodes the agent
generates powernode-<moduleID>-<serviceName>.service
(agent/internal/lifecycle/service.go), where <moduleID> is the module's UUID
and <serviceName> is a services: entry in its manifest. So Rails is
powernode-019f7cb5-3858-…-rails.service, and sidekiq/worker-web share one UUID
because both ship in powernode-hub-worker. Always discover, never assume:
systemctl list-units 'powernode-*-rails.service' --no-pager --no-legend # or -sidekiq/-worker-webA guessed name (powernode-backend@default, rails.service) does not error —
systemctl restart on a nonexistent unit fails silently in a || chain, leaving
new code on disk while the old image keeps running, which looks exactly like a
successful deploy. Verify with systemctl is-active on the discovered unit.
The @default template form appears throughout extensions/system/docs/runbooks/.
It is real on installer-provisioned hosts (powernode-installer.sh installs
powernode-<svc>@default), but module-composed nodes such as dev-cell and ops-hub
have no @ template (systemctl list-unit-files 'powernode*' shows none). On a
module-composed node, treat those references as stale.
After a Rails restart /up 502s while it boots (~30s normally), up to ~3 min if boot runs pending
migrations (MCP dead too). Confirm with systemctl show -p NRestarts <discovered
unit> + is-active; a 502 in that window is not a failed deploy.
Specialists & Documentation
Use platform.discover_skills with a task description to find the right specialist. Query MCP first; these files are the fallback:
| Topic | MCP Query | File Fallback |
| Conventions (backend/frontend/testing/ops) | search_knowledge tag guidance-* | docs/contributing/conventions/ |
| MCP config & workflow | discover_skills | conventions/mcp-first-workflow.md |
| Knowledge lifecycle | — | conventions/knowledge-lifecycle.md |
| Service mgmt & ops | — | conventions/service-and-ops.md |
| MCP tool catalog | — | docs/reference/auto/mcp-tools.md (auto-generated) |
| Permissions / Theme / API / UUID / Architecture | search_knowledge / search_knowledge_graph | docs/concepts/, docs/reference/ |
| Learnings & patterns | query_learnings | docs/reference/auto/learnings.md |
Per-subsystem rules also live in nested server/CLAUDE.md, frontend/CLAUDE.md, worker/CLAUDE.md (load automatically when editing those trees).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

