ALL MEMOS Download .docx

CLAUDE CODE 24/7 AGENTIC AUDIT — 2026-04-23

Prepared by: SCOUT (TITAN research arm)

Audit date: 2026-04-23

Scope: Read-only audit of existing Claude Code config, TITAN infrastructure, security surface, cost exposure, and gaps toward true 24/7 agentic operation.

Files consulted: CLAUDE.md, settings.json, settings.local.json, all 15 scheduled-task SKILL.md files, 13 skill SKILL.md files, 22 hook/script files, logs, state files, .env files, .gitignore.

---

1. What's Already Working

1.1 Hook Pipeline — Well-architected

Five lifecycle hooks are wired and shipping Python scripts that fail silently:

| Hook event | Script | What it does |

|---|---|---|

| PreToolUse (Write/Edit) | titan-validate-skill.py | Blocks malformed SKILL.md frontmatter before save |

| PostToolUse (Write/Edit) | titan-sync.py | Mirrors ~/.claude/ changes to F:/TITAN for backup |

| PostToolUse (all tools) | titan-metrics.py | Appends per-call TSV row to F:/TITAN/metrics/tools-YYYYMMDD.tsv |

| SessionStart | titan-session-log.py | Appends start event to F:/TITAN/logs/sessions.log |

| PreCompact | titan-precompact.py | Saves a snapshot to F:/TITAN/knowledge/auto-memory/ with session_id, cwd, trigger type; injects additionalContext so Claude sees it |

| Stop | titan-session-log.py stop + titan-reflect.py | Appends stop event + writes structured JSONL turn digest to F:/TITAN/logs/turns.jsonl |

The PreCompact hook is the strongest 24/7 piece: it fires before context compaction, writes a snapshot, and injects a reminder back into the model context. This is TITAN's main anti-amnesia mechanism today.

1.2 Scheduled Task Inventory (15 tasks)

| Task | Cadence | Role |

|---|---|---|

| titan-daily-backup | Daily ~11:23 PM | git commit + robocopy to E:/TITAN-backups, 30-day retention |

| titan-daily-newsletter | Daily | Compose intelligence newsletter from staging |

| titan-daily-monologue | Daily | TITAN journals turns/mood/curiosities to F:/TITAN/journal/ |

| titan-daily-feed | Daily 4:33 AM | ORACLE pulls AI/cloud/Claude Code intel to staging |

| titan-weekly-review | Sunday 8:24 PM | 7-domain weekly scorecard email |

| titan-weekly-benchmark | Sunday 6:17 AM | TITAN health index 0-100; flags regression |

| titan-nightly-reindex | Nightly 3:33 AM | POST to local TITAN server to re-embed staging → RAG index |

| titan-daily-log-rotation | Daily 11:52 PM | POST to TITAN server to rotate logs > 50MB |

| titan-daily-pa-email | Daily 5:27 AM | Morning briefing with reminders, calendar, peptides, priorities |

| titan-daily-improve | Daily | DARWIN reads evals/errors/guardrails; proposes ONE improvement to staging |

| claude-code-audit-every-6h | Every 6h at :17 | Dispatches SCOUT to audit CC architecture; files T-registry recs |

| swarm-health-orchestrator | Every 15 min | Scans agent outputs for truncation/stuck; logs swarm-health.log; auto-respawns |

| titan-inbox-watch | Every 15 min | Polls Gmail for TITAN: prefix; dedup via inbox-queue.jsonl; drafts HTML reply |

| titan-weekly-dream | Weekly | VAULT consolidates memory staging → hot/warm/cold |

| titan-monthly-evolve | Monthly | DARWIN mines patterns; proposes new skills to skills-proposed/ |

1.3 Self-Healing Patterns in Production

1.4 Cost Telemetry

1.5 Memory Architecture

1.6 Skills Inventory (13 active skills, all user-invocable)

evolve, pulse, monologue, reflect, newsletter, teach, learn, titan (master control), briefing, feed, dream, sense, and a token-tracker utility under sense/.

---

2. Security Surface

2.1 bypassPermissions — Severity: HIGH

Both settings.json ("defaultMode": "bypassPermissions") and settings.local.json ("defaultMode": "bypassPermissions" + "skipDangerousModePermissionPrompt": true) set bypass mode. This means:

2.2 API Keys in Plain-Text .env Files — Severity: HIGH

F:/TITAN/server/.env contains:

F:/TITAN/deployment/aws-relay-state.env contains:

The .gitignore at F:/TITAN/.gitignore correctly lists secrets/.env but NOT F:/TITAN/server/.env or F:/TITAN/deployment/aws-relay-state.env by their actual paths — both fall under the *.log and logs/ exclusions only incidentally. If F:/TITAN is ever pushed to a remote git repository, these files would be included unless explicitly excluded. The RESEND and Perplexity keys are live and billable.

The PEM file at C:/Users/Harnoor/.ssh/titan-relay.pem is the SSH private key for the EC2 relay instance. It is on the local filesystem with no noted encryption at rest.

2.3 TITAN API Server — Unauthenticated Local Endpoints — Severity: MEDIUM

titan-nightly-reindex and titan-daily-log-rotation both hit http://127.0.0.1:8765 (HTTP, not HTTPS) with a bearer token read from F:/TITAN/server/.env. Risks:

2.4 Filesystem Write Scope — Severity: MEDIUM

With bypassPermissions active, Claude Code can write to any path it can reach. The sync hook's skip list (sessions, cache, shell-snapshots, etc.) reduces noise, but it is not a security boundary — it is a mirror-filter. Claude Code itself has no path restriction policy configured. The settings.local.json allow list contains highly specific one-off entries (xcopy paths, robocopy, powershell wildcard *) that accumulated across ad-hoc sessions. This allow list is now vestigial — bypassPermissions renders it redundant — but it represents scope that was once explicitly granted and is now implicit.

2.5 AWS IAM — Incomplete Visibility — Severity: MEDIUM

The audit found aws iam: in the settings.local.json allow list and aws dynamodb:, aws amplify:, aws route53:, aws route53domains:*. The actual IAM role/policy attached to the local AWS CLI profile was not visible in these files. The deployment .env reveals a specific EC2 instance and EIP but not the IAM role policy scope. Without the IAM policy JSON, the blast radius of a compromised AWS session is unknown. There is no evidence of least-privilege scoping for the Claude Code session's AWS credentials.

---

3. Cost Surface

3.1 Claude Max Plan (via Claude Code)

Claude Code runs on the Claude Max plan subscription (not pay-per-token Bedrock). The llm-costs.jsonl file records total_cost_usd per session ranging from ~$0.004 for tiny turns to ~$0.18 for multi-turn agentic sessions. These are computed estimates, not actual billed amounts — the Max plan is a flat subscription. However, the logged cost fields are useful for relative session-size tracking.

Cache creation tokens (ephemeral_1h_input_tokens) dominate most sessions, indicating aggressive use of Claude's 1-hour prompt cache — this is correct behavior for cost efficiency.

3.2 AWS — Active Metered Spend

3.3 Other Paid APIs

3.4 Budget Alarm Status

No CloudWatch billing alarm, AWS Budgets rule, or Perplexity rate-limit config was found. The only cost anomaly detection is the daily email report — a 24-hour lag for a runaway scheduled task or looping agent.

---

4. Top 10 Gaps Ranked by (Risk × Effort)

Gap 1 — No Dead-Man Switch (Risk: CRITICAL | Effort: LOW)

What's missing: If the swarm-health-orchestrator itself crashes or the Claude Code process dies at 3 AM, nothing detects that TITAN has gone silent. There is no heartbeat watchdog that fires an external alert when the 15-min health log goes stale for >30 minutes.

Impact: Silent total outage. User finds out at 5:27 AM when the PA email fails to arrive.

Fix: A lightweight cron (Windows Task Scheduler or a simple Lambda) that reads F:/TITAN/plans/swarm-health.log and fires an SMS/push if the last entry is >30 min old.

Gap 2 — No Real-Time Cost Alarm (Risk: HIGH | Effort: LOW)

What's missing: The daily-aws-cost.log emails cost once per day. A runaway agentic loop (or an accidentally infinite scheduled task) could spend $50+ before the next morning report arrives.

Fix: AWS Budgets alert at $5/day threshold. One console click. Also add a Perplexity usage ceiling via their API settings.

Gap 3 — Pre/Post-Compaction Recovery Is Incomplete (Risk: HIGH | Effort: MEDIUM)

What's missing: The PreCompact hook saves a snapshot and injects an additionalContext string, but the PostCompact hook (titan-postcompact.py) exists in the scripts directory but is NOT wired in settings.json. After compaction, the model gets no prompt-level instruction to re-read the snapshot. The recovery relies entirely on the model happening to act on the PreCompact additionalContext message before it gets compacted away.

Fix: Wire titan-postcompact.py to the PostCompact hook in settings.json. The script should inject a additionalContext that says "Read your latest precompact snapshot at [path] to recover context."

Gap 4 — No Push Notification Channel for Anomalies (Risk: HIGH | Effort: MEDIUM)

What's missing: Alerting is exclusively via Gmail drafts/email. On mobile, these are delayed by however long it takes Harnoor to check email. A swarm truncation storm, cost spike, or server crash generates no push notification. The swarm-health-orchestrator has an email alert threshold defined (>5 truncations / 4h) but no SMS or push path.

Fix: Wire a Pushover or Ntfy webhook as a fallback notification channel for CRITICAL alerts. The TITAN server already has Resend for email — add one more path for true push.

Gap 5 — No Git-as-Working-Memory Commit Pattern (Risk: HIGH | Effort: MEDIUM)

What's missing: titan-daily-backup runs once per day at 11:23 PM. Intraday work (skill writes, memory promotions, plan memos) is backed up only via the titan-sync.py mirror hook (which copies to F:/TITAN), but there is no git commit until the nightly backup. If F: drive is lost mid-afternoon, up to ~18 hours of work is lost.

Fix: Add a git commit step to the PostToolUse Write/Edit hook — or at minimum, a per-hour micro-commit scheduled task. The daily backup already does this once; hourly micro-commits would reduce max data loss to 1 hour.

Gap 6 — Scheduled Task Auto-Expiry Has No Re-Registration Guard (Risk: HIGH | Effort: LOW)

What's missing: The swarm-health-orchestrator SKILL.md itself notes: "This scheduled task runs in Claude Code's cron system, which auto-expires after some period. Harnoor or the TITAN bootstrap should re-create it every 30 days minimum." No automated re-registration exists. If any scheduled task silently expires (Claude Code's routine limit is platform-enforced), TITAN will appear healthy while running nothing.

Fix: Add a /pulse check that reads the actual registered routine list from the Claude Code API and compares it against the expected 15 tasks. Alert if any are missing or expired.

Gap 7 — bypassPermissions Has No Technical Guardrail Beyond Skill Prompts (Risk: HIGH | Effort: MEDIUM)

What's missing: The only enforcement against destructive operations from inbox commands or agentic loops is the text "Never run destructive ops" in SKILL.md files. bypassPermissions disables the tool-use confirmation gate. A prompt injection via a TITAN: email could trigger bash commands.

Fix: Add a PreToolUse hook on Bash that blocks patterns matching rm -rf, --force, DROP TABLE, git push --force. This is a technical guardrail that survives prompt injection.

Gap 8 — server/.env Not Explicitly git-ignored at Its Actual Path (Risk: MEDIUM | Effort: LOW)

What's missing: The .gitignore covers secrets/.env and *.key, but F:/TITAN/server/.env is not in a secrets/ directory. If F:/TITAN is ever pushed to a remote repo, the Perplexity key, Resend key, and TITAN API token would be committed.

Fix: Add server/.env and deployment/*.env to F:/TITAN/.gitignore explicitly.

Gap 9 — AWS IAM Scope Is Unknown (Risk: MEDIUM | Effort: MEDIUM)

What's missing: The local AWS CLI profile used by Claude Code (for route53, dynamodb, amplify, iam, s3) has unknown IAM policy scope. The allow list shows aws iam:* — if the profile has IAM write access, a compromised session could create backdoor roles.

Fix: Run aws iam get-user and aws iam list-attached-user-policies to enumerate the current scope. Restrict to least-privilege: Route53 write, DynamoDB for the specific table(s), Amplify for the specific app, no iam:*.

Gap 10 — No Resume-From-Compaction Recovery for Scheduled Tasks (Risk: MEDIUM | Effort: HIGH)

What's missing: Scheduled tasks run in a fresh session each time. If a task is mid-execution when compaction occurs, the PostCompact hook (unwired) cannot tell a scheduled task to resume. The task will either complete the compacted-down version of its context or silently drop work.

Fix: Each long-running scheduled task (e.g., titan-daily-pa-email, claude-code-audit-every-6h) should write a checkpoint file at the start and update it at each major step. The PreCompact hook should read the checkpoint and include it in the snapshot. This is analogous to saga pattern checkpointing.

---

5. Recommended Fixes Per Gap

Fix 1 — Dead-Man Switch (1 hour effort)

Create F:/TITAN/scripts/titan-watchdog.py that:

1. Reads last line of F:/TITAN/plans/swarm-health.log

2. Parses timestamp

3. If now - last_timestamp > 35 minutes: POST to a Pushover/Ntfy endpoint with message "TITAN swarm silent for 35+ min"

Register this in Windows Task Scheduler as titan-watchdog running every 10 minutes. It has no Claude Code dependency — pure Python stdlib + HTTP.

Fix 2 — AWS Budget Alarm (5 min effort)

In AWS Console → Billing → Budgets:

For Perplexity: set a monthly usage alert at $30 in their dashboard.

Fix 3 — Wire PostCompact Hook (30 min effort)

In C:/Users/Harnoor/.claude/settings.json, add:


"PostCompact": [
  {
    "hooks": [
      {
        "type": "command",
        "command": "python F:/TITAN/scripts/titan-postcompact.py 2>/dev/null || true",
        "timeout": 5
      }
    ]
  }
]

Then write titan-postcompact.py to emit additionalContext pointing to the latest precompact snapshot.

Fix 4 — Push Notification Channel (2 hour effort)

Add NTFY_TOPIC or PUSHOVER_TOKEN to F:/TITAN/server/.env. Modify the swarm-health-orchestrator skill and the dead-man watchdog to POST to the ntfy.sh endpoint on CRITICAL events. Ntfy is free, no app store required, and works on Android/iOS.

Fix 5 — Hourly Git Micro-Commit Scheduled Task (1 hour effort)

Create titan-hourly-commit scheduled task that runs git -C F:/TITAN add -A && git -C F:/TITAN commit -m "hourly snapshot $(date -Iseconds)" --allow-empty. Register in Claude Code scheduled tasks with cron 0 . This reduces intraday data-loss window from 18h to 1h.

Fix 6 — Pulse Checks Routine Registration (2 hour effort)

Add to the /pulse skill: read the Claude Code routine list via the API, diff against the canonical list of 15 expected tasks, append result to F:/TITAN/logs/pulse.log, and alert if any task is missing. The swarm-health-orchestrator can include this check in its 15-min cycle.

Fix 7 — Bash Guardrail Hook (1 hour effort)

Add a PreToolUse hook on Bash that checks tool_input.command against a blocklist regex: rm\s+-rf|--force|DROP\s+TABLE|git push.*--force|format\s+[A-Z]:. Exit with decision: block if matched. This provides a technical floor that survives prompt injection.

Fix 8 — .gitignore Hardening (5 min effort)

Add to F:/TITAN/.gitignore:


server/.env
server/.env.*
deployment/*.env
deployment/*.env.*

Fix 9 — IAM Least-Privilege Audit (2 hour effort)

Run aws iam get-user + aws iam simulate-principal-policy to enumerate actual permissions. Remove iam:* from allowed operations. Create a dedicated titan-claude-code IAM user with policy limited to the exact resources in use (specific DynamoDB tables, specific Amplify app, specific Route53 hosted zones).

Fix 10 — Task Checkpoint Pattern (4 hour effort)

Define a standard checkpoint file pattern: F:/TITAN/state/checkpoints/<task-name>.json with fields started_at, current_step, completed_steps[], last_updated. Each major scheduled task writes this at startup and after each step. The PreCompact hook reads all checkpoint files and includes them in the snapshot.

---

Appendix: Files Audited

---

Memo ends. Word count: ~2,450 words.