agentleFS
nodealchemynodealchemy/powernode-platform/CLAUDE.md

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
  1. Very specific:

    NEVER: commit unless explicitly requested.

    line 55
  2. Very specific:

    Eager Loading: always .includes() when iterating associations — never bare .all then .map/.each accessing relations.

    line 83
  3. Very specific:

    NEVER: create job classes in server/app/jobs/.

    line 90
  4. Distinctive:

    State the count: before ANY bulk operation: "This will affect N items."

    line 93
  5. Very specific:

    Audit = report only: when asked to audit/review/analyze, save findings to docs/.

    line 101
  6. Distinctive:

    Test-First Bug Reproduction: write a failing test reproducing the bug before the fix.

    line 103
  7. Distinctive:

    Trace Changes to Request: every changed line traces to the request.

    line 104
  8. Very specific:

    Dead Reference Cleanup: after deleting a file, grep -r for references and remove them (scope: orphans your changes created).

    line 106
  9. Very specific:

    Completion Gate: before reporting work done, run the verification gate — scripts/validate.sh (model-agnostic.

    line 107
  10. Distinctive:

    CWD verification: before EVERY git add/git commit, run git rev-parse --show-toplevel and confirm the repo.

    line 120
  11. Very specific:

    NEVER save files to project root: Use docs/{getting-started,concepts,guides,reference,operations,contributing}/.

    line 126
  12. Very specific:

    After a Rails restart /up 502s while it boots (~30s normally), up to ~3 min if boot runs pending migrations (MCP dead too).

    line 158
  13. Very specific:

    Use platform.discover_skills with a task description to find the right specialist.

    line 166

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

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, ApprovalRequests

Where 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 shapeHomeSurfaces / enforces via
Always + high-stakes + not checkablethis file (core)always loaded
Mechanically checkable.claude/hooks/*.sh + scripts/pattern-validation.shedit-time hook / adherence scan
Reusable pattern / procedureplatform guidance-*, git seed docs/contributing/conventions/MCP-first queries + SessionStart digest
Subsystem-scopednested server//frontend//worker/ CLAUDE.mdloads when editing that tree
Decision / incident / preferenceplatform knowledge, tag memoryharness MEMORY.md until migrated; search_knowledge tags:["memory"] (no Claude digest yet: query it)
Crypto / private-extension logicextension 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; recall search_knowledge tags:["memory"], [[slug]] → tag memory-<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_search before 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 — the platform_agent driver campaign_delegate resolves 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) and BASE_GUARDRAILS tell other executors to query search_knowledge tag:guidance-* first. Use the production connector (mcp__powernode__*): a sandbox one (mcp__powernode-local__*) may be unseeded, so count:0 there 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'                               // ❌ FORBIDDEN

Backend: 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.

RuleDetails
No key outputNEVER output, log, display, echo, or transmit private keys, API secrets, seed phrases, mnemonics, or signing material in any form
No keys in codeNEVER store keys/secrets/credentials in source, scripts, configs, env files, or docs
No CLI key generationNEVER generate private keys via CLI (rails runner, rake, irb) where they could hit shell history
Vault-only storageALL key generation MUST happen inside Vault or the platform's Vault-backed key service (stores directly to Vault)
Audit all key opsALL key operations (generate, import, revoke, sign) MUST be logged to the audit log. TODO(verify: confirm core audit-log sink)
No key args in logsNEVER pass keys as function arguments that could appear in logs/errors/traces
Guide, don't handleWhen 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 .all then .map/.each accessing 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.references indexes, 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 to server/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 + agent BASE_GUARDRAILS + loop guardrails so all executors carry it)

Design Principles

  • Reuse First: platform.discover_skills + search_knowledge + code_semantic_search before proposing anything new — never greenfield when infrastructure exists. (also guidance-reuse-first + agent BASE_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 agent BASE_GUARDRAILS)
  • 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 -r for 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. /verify is the Claude-only convenience wrapper; non-Claude executors use the gate directly (also guidance-verification-gate + loop guardrails).
  • Powernode subagents: assemble_task first; pass its model/effort to the Agent tool and its assembly_id in the prompt.
  • Quality Gates: cd frontend && npx tsc --noEmit after TS; Ruby syntax + related spec after .rb; rails db:seed after seeds — the authoritative home is the gate scripts/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 blocking core-purity-check.sh and a model-agnostic scripts/pattern-validation.sh scan mirror (not just the Claude hook) — core source must not reference a private extension by name (its Namespace::, 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 from extensions/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} + private extensions/private/*. Do NOT run git submodule sync on the public ones (drops the private upstream remote). (also guidance-submodule-safety)
  • CWD verification: before EVERY git add/git commit, run git rev-parse --show-toplevel and confirm the repo.
  • Survey both statuses: git status in root AND git -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

TermMeansNot
server/Rails app directory"backend directory"
powernode-backendthe Rails service (unit name below)"rails service"
worker/standalone Sidekiq app"job runner"
powernode-workerthe 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-web

A 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:

TopicMCP QueryFile Fallback
Conventions (backend/frontend/testing/ops)search_knowledge tag guidance-*docs/contributing/conventions/
MCP config & workflowdiscover_skillsconventions/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 / Architecturesearch_knowledge / search_knowledge_graphdocs/concepts/, docs/reference/
Learnings & patternsquery_learningsdocs/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).

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.