/root/.claude/system/
├── README.md ← short overview (regenerated; canonical detail in this folder)
├── bin/
│ └── arg ← Python CLI (symlinked to /usr/local/bin/arg)
├── resources/ ← Layer 1: atoms (things in the world)
│ ├── accounts.json ← LinkedIn / Meta / Gmail / Stripe / etc.
│ ├── keys.json ← INDEX only, never values
│ ├── hosts.json ← Hetzner / contabo / Mac / Chrome CDP / etc.
│ ├── data_stores.json ← Postgres / Redis / sqlite / Drive / etc.
│ ├── products.json ← jonahtebaa.com / brianserves.me / 20CRM / etc.
│ ├── channels.json ← TG COMMS / TG LOGS / WA / Voice / Blog / etc.
│ ├── subsystems.json ← External AI brains (codex/hermes/jules/manus/...)
│ └── agents.json ← Claude Code sub-agents (gsd-*, code-reviewer, ...)
├── access/
│ └── grants.json ← OAuth / MCP / ad-account permissions (from→to)
├── tools/
│ └── skills.json ← curated /-callable skills index
├── capabilities/
│ └── capabilities.json ← composed actions (52 rows at ship)
├── policies/
│ └── boundaries.json ← hard (hook-enforced) + soft (advisory) rules
├── routines/
│ └── routines.json ← scheduled cadence (GEO hour, daily publish, etc.)
├── observability/
│ ├── events/<YYYY-MM-DD>.ndjson ← append-only journal, gzip>7d, delete>90d
│ ├── inbox/ ← sub-agent proposals (single-writer invariant)
│ ├── probe_status.json ← latest probe result per id (cache)
│ └── autofix_state.json ← flap-detection history per (rid, action)
├── schemas/ ← jsonschema files (Draft 2020-12)
│ ├── _common.schema.json
│ ├── _generic_atom.schema.json
│ ├── accounts.schema.json
│ ├── keys.schema.json
│ ├── capabilities.schema.json
│ └── boundaries.schema.json
└── views/ ← generated markdown — DO NOT edit; `arg render-views` regenerates
└── {accounts,keys,hosts,...}.md
Every category file has the same envelope:
{
"schema_version": "1.0",
"category": "<name>",
"description": "...",
"columns": ["id", "name", ...], // ordered, used for view rendering
"rows": [
{
"id": "...",
"name": "...",
"...": "...",
"probe": { "command": "...", "timeout_sec": 10, "min_interval_seconds": 3600 },
"last_probe": { "ok": true, "layer": "auth", "evidence": "...", "checked_at": "..." },
"freshness_budget_hours": 24,
"critical": true
}
]
}
| Field | Type | Purpose |
|---|---|---|
requires |
{resources, access, tools, capabilities} |
dep IDs (resolved against other rows) |
side_effects |
array of strings | writes-external, costs-money, irreversible-without-deletion, ... |
risk_level |
low \| medium \| high \| critical |
shapes warning surface |
cost_class |
free \| metered \| paid |
money policy gating |
idempotency |
safe-retry \| at-least-once \| non-idempotent \| exactly-once-required \| depends-on-command |
autofix uses this |
approval_required |
bool | pre-policy default-ask flag |
freshness_budget_hours |
int or null | when does last_probe go stale |
rate_limit |
{per_day, per_hour} |
optional |
rollback |
{type, note} |
optional |
| Field | Type | Purpose |
|---|---|---|
severity |
hard \| soft |
hard = hook-enforced; soft = advisory |
match |
{side_effects_any, cost_class, risk_at_least, capability_id_regex, extra} |
AND across clauses within a rule, OR across rules |
decision |
deny \| require_approval \| require_account_check \| deny_unless_brian_account \| deny_unless_inbox \| code_enforced \| audit \| warn \| advisory |
translation to resolver verdict |
reason |
string | shown in policy_block events + stderr |
exceptions |
array of cap-ids | exact-match exemption list |
Probes return one of four states at the atom level:
| State | Meaning |
|---|---|
verified-fresh |
last probe ok=true, within freshness_budget_hours |
verified-stale |
last probe ok=true, but past budget — treat as suspect |
red |
last probe ok=false |
unknown |
never probed |
arg status returns counts across all atoms.
Capability resolution composes:
1. State of every dep (atoms via probe, sub-caps recursively)
2. Freshness against freshness_budget_hours
3. Policy match against boundaries
4. cost_class and risk_level
5. Context (env hints, time of day for routines)
Output:
| Verdict | Meaning | Caller action |
|---|---|---|
yes |
act now | proceed |
yes-after-probe |
deps stale or unknown | run probes first |
yes-after-approval |
needs Jonah's go-ahead | use /ask skill |
no |
a dep is red or missing | escalate or repair |
blocked-by-policy |
a hard boundary blocks | do not attempt |
Within one rule: every match clause that is specified must fire. If a rule lists both side_effects_any: [costs-money] and cost_class: paid, BOTH must match. (Pre-fix: the rule fired on either — wrong.)
Across rules: independent. Each rule that matches contributes its decision. The most restrictive wins (deny > require_approval > advisory).
Rule writers should specify the most specific clauses they can. Over-broad regexes (^cap\.mac\..*) historically caused false-positive blocks. The smoke-test invariants checker (_check_invariants in arg validate) flags caps that match a deny_unless_brian_account rule but have no brian-* dep — preventing future drift.
/root/.claude/system/.CLAUDE_AGENT_TYPE (set by Agent dispatch) or CLAUDE_ARG_MAIN=1 (set in main session's settings.json).boundary.subagents_readonly_on_arg) default-denies on missing actor — if neither env var is present, treat as untrusted.observability/inbox/. Main Brian processes via arg inbox accept|reject.Three independent paths surface ARG to a fresh session:
MEMORY.md CORE pointer line — always loaded.arg_sessionstart.sh — SessionStart hook injects current status counts + recent events./ARG slash skill at /root/.claude/skills/ARG/SKILL.md — load on demand.If any one is missing, the other two still ensure ARG is reachable.