Skip to content

Pure Phoenix Phase 1: Resystemize Design

URL: https://mkdocs.justinsforge.com/memory/handoffs/pure-phoenix-phase-1-design-2026-04-28/

Phase 1 is design-only. No live files modified. This document captures the four resystemize designs (variable conventions, memory architecture, eval harness, XML boundaries) plus a few decisions that need your sign-off before Phase 2 execution.

Plan: ~/.claude/plans/yes-lets-go-into-pure-phoenix.md Doctrine: FORGE-DOCTRINE.md Inventory: pure-phoenix-inventory-2026-04-28


1.3 Variable and Data-State Convention

Doctrine Section 4 mandates [source]_[entity]_[state] snake_case with three data-state tags. This section turns that into a working convention.

The three data states

State tag When Example identifier Example value
raw_ Data exactly as it leaves a third party. Untouched, including provider-side wrapping, pagination cursors, request metadata. raw_notion_search_response {"object": "list", "results": [...], "next_cursor": "abc"}
parsed_ or clean_ Internal, normalized form. Provider noise stripped, types coerced, ready for forge logic to operate on. clean_task_array [{"id": "...", "title": "...", "due": "..."}]
payload_ Outbound, formatted for a specific external endpoint. Serialized to that endpoint's schema. payload_n8n_webhook {"workflow_id": "abc", "input": {...}}

If data has no external source (purely forge-internal), drop the source tag and use clean_<entity> as the default.

Source tags

Source tags are extensible. The canonical list is a starting set, not a closed enum. As forge integrates new services, the registry grows.

Starting set: notion, gmail, gcal, gdrive, telegram, garmin, eight_sleep, ha (home assistant), frigate, n8n, cf (cloudflare), proxmox.

Process for adding a new source tag: 1. When wiring a new integration, propose the tag in your branch's PR description or commit message. 2. Add the tag to forge/FORGE-DOCTRINE-VARIABLES.md registry section (the canonical list). 3. Add it to the eval harness check forge_eval_check_variable_tags.sh so future code referencing the tag passes the convention check. 4. Auto-dream's nightly pass detects <source>_<entity>_<state> patterns in code that don't match the registry; it logs them to LESSONS.md as candidate additions for human review.

Naming rules: - Lowercase, snake_case, max 12 characters - Prefer the integration's canonical short name (notion not notion_api, garmin not garmin_connect) - Never abbreviate further than the source's own brand short form (ha is fine because Home Assistant uses it; tg for Telegram is not, use telegram) - If two integrations share a domain (e.g. gmail and gcal both Google), keep them split by service not unified by provider

Anti-patterns: - Inventing tags inline without registering: mystery_service_response = ... will fail the eval check - Using a tag for the wrong service: don't reuse gmail for "any-mail" data; that loses semantic precision

Entity tags

The thing being represented: task, email, event, file, webhook, hrv, presence, camera_event, etc. Singular noun.

Edge cases

  • Multi-stage pipeline: name each stage with the appropriate tag. raw_garmin_response to clean_garmin_hrv to payload_notion_wellness. Never reuse a variable across states without a rename.
  • Lists vs scalars: plural entity for lists (clean_task_array), singular for scalars (clean_task). The tag stays singular when the array contains a homogenous shape (clean_task_array is one collection of tasks).
  • Local-only intermediates: drop the source. clean_dedup_table, payload_archive_record.
  • Function parameters: apply the same convention. def push_task(payload_telegram_message: dict) -> bool: is correct.
  • Type aliases / TypedDicts: name them after the canonical state. TypedDict("CleanTaskArray", ...) not Tasks.

When to apply

  • All new code: mandatory from Phase 2 onward.
  • Refactored code: rename when you touch the function. Do not refactor existing code purely to apply the convention; doctrine forbids autonomous restructuring without first-principles understanding (Section 2).
  • Audit targets: inbox_brain.py, ava_brain.py, dispatcher.sh, notify.sh, all n8n payload constructors. Schedule one targeted refactor pass per file in Phase 4.3.

Companion file

Phase 2.1 creates forge/FORGE-DOCTRINE-VARIABLES.md with this convention plus a 20-line example reference. Linked from FORGE-DOCTRINE.md Section 4 via the mkdocs URL.


1.4 Memory Architecture Redesign

The hardest of the four. Ships across Phase 2.4 (slim down) and Phase 4.4 (auto-memory + auto-dream layers).

Current state

  • One canonical MEMORY.md at ~/.claude/projects/-home-justinwieb-forge/memory/MEMORY.md. 182 lines, 23.8KB. Compliant with Section 12 cap, but dense (multi-line entries inline, not pure index).
  • memory/general/<topic>.md topic file convention exists. ~30 files.
  • memory/handoffs/<topic>-YYYY-MM-DD.md pattern for cross-session briefings. ~50 files.
  • memory/daily/YYYY-MM-DD.md append-only daily logs.
  • Stop hook calls scripts/checkpoint.sh --auto to append a session summary to today's daily log.
  • Semantic search at scripts/search/index.py indexes the whole tree nightly at 03:30.
  • No auto-extraction of persistent facts. No consolidation. The user (Justin or a session) has to explicitly call out memories worth saving.

Target state

Layer Role Cadence Lives at
MEMORY.md Index of one-line pointers, max 200 lines, loaded automatically every session static, edited only by auto-dream ~/.claude/projects/-home-justinwieb-forge/memory/MEMORY.md
Topic files The actual knowledge, frontmatter + body updated by humans + auto-memory + auto-dream forge/memory/general/<topic>.md
Auto-memory Background extraction of persistent facts from session transcripts runs at session end via Stop hook new script scripts/forge_memory_auto_capture.py
Auto-dream Idle consolidation, deduplication, stale pruning, index rebuild nightly cron at 04:00 new script scripts/forge_memory_auto_dream.py
LESSONS.md Audit log of what the auto-layers did append-only forge/LESSONS.md

MEMORY.md slim-down (Phase 2.4)

  • Convert every multi-line section in current MEMORY.md to a topic file under memory/general/.
  • Replace inline section with a one-line index entry.
  • Examples of what gets split:
  • Frigate state block to memory/general/frigate-state.md
  • AdGuard config block to memory/general/adguard-state.md
  • n8n install block to memory/general/n8n-state.md
  • media-server stack quirk block to memory/general/media-server-stack.md
  • UDev System State block to memory/general/udev-state.md (renamed forge-dev-vm-state.md in Phase 4.1 fleet rename)
  • One-line index format: - [Topic Name](file.md), one-line hook
  • Target: MEMORY.md drops from 182 lines (mostly compliant but dense) to ~120 lines (pure index, room to grow).

Index file structure (the navigation guide)

The index is not just a flat list of pointers. The top of MEMORY.md teaches an agent how to navigate the memory system. New sessions and ad-hoc agents that have never seen forge can find what they need without grepping blindly.

Target structure:

# Justin's Setup, Memory Index

URL: https://mkdocs.justinsforge.com/memory/MEMORY/

This file is auto-loaded every session. It is an index, not a knowledge base. Each entry below points to a topic file with the actual content.

## How to find things

| Looking for | Go to |
|---|---|
| A service is broken or behaving weird | `memory/general/<service>-state.md` (frigate-state.md, adguard-state.md, n8n-state.md, media-server-stack.md, etc.) |
| Recent decision or in-progress work | `memory/handoffs/`, sorted by date descending |
| Justin's preferences or feedback corrections | grep `memory/general/feedback_*.md` |
| Tool or pipeline reference | grep `memory/general/reference_*.md`, or scan the Tools and Pipelines pointers below |
| Daily working context (what happened today, this week) | `memory/daily/YYYY-MM-DD.md` |
| Cross-domain fuzzy match | `/recall <query>`, semantic search over the full forge tree |
| Code-level facts (function signatures, paths, latest changes) | the repo itself, `git log`, `git blame`, never trust this index for stale code state |
| Fleet topology (machines, IPs, services) | `system-map/fleet.md`, `system-map/architecture.md` |
| Project-specific context (Nova, JWVR, Frigate, etc.) | auto-loaded by UserPromptSubmit hook when the project name appears in the prompt; manual at `system-map/projects.md` |

## Memory writing conventions

- New topic file: frontmatter (name, description, type), then content. Topic types: `user`, `feedback`, `project`, `reference`.
- Update existing entries in place; do not duplicate. If a fact contradicts the current file, fix the file.
- Sign every entry `[Claude Code]` or worker name.
- Never write inside `~/.forge-secrets/` or anything matching a sensitive-data pattern.
- Auto-memory layer captures persistent facts on session end; auto-dream consolidates nightly. Both write to `LESSONS.md` so changes are auditable.

## Topics
[one-line entries below this line, grouped by theme]

The "How to find things" table is the new piece. It turns the index from a passive list into an active navigation aid. An agent reading just the first 30 lines of MEMORY.md gets the mental model.

Auto-memory layer (Phase 4.4)

Triggered by the existing Stop hook (already running auto-checkpoint.sh). Extends to also call the auto-capture script.

Algorithm: 1. On Stop, read the last N exchanges of the session transcript (configurable, default 50). 2. Send to Sonnet 4.6 with a tight extraction prompt: identify 0 to 3 persistent facts (user preferences, infrastructure details, code style notes, debugging insights, surprising discoveries) that are not already in MEMORY.md or any topic file. 3. For each candidate fact: classify type (user, feedback, project, reference) per the auto-memory taxonomy in this conversation's system prompt. Compute a confidence score (0 to 1) based on how grounded the fact is in the transcript. 4. Confidence-gated write strategy: - High confidence (≥ 0.85): write directly to canonical position (memory/general/<topic>.md or update existing topic file). - Medium confidence (0.65 to 0.85): write to staging area memory/auto-proposed/<topic>-<timestamp>.md. Auto-dream picks these up next night for review. - Low confidence (< 0.65): drop, log to LESSONS.md. 5. Append a summary line to today's daily log: ## [auto-memory] N facts captured, M staged, K dropped.

Safety rails: - Never write inside ~/.forge-secrets/ regardless of what the model proposes. - Never extract or persist email content, message bodies, or anything matching a sensitive-data regex (credit card, SSN, password, token). - Never overwrite a topic file; always update via append or create-new. - Hard cap of 5 writes per session run.

Reversibility: - Every write logs to LESSONS.md with the source transcript range. - Justin can run scripts/forge_memory_revert.py --session <id> to roll back any session's auto-memory writes.

Auto-dream layer (Phase 4.4)

Nightly cron at 04:00 UTC, parallel to the Minecraft backup but independent.

Algorithm: 1. Read all of memory/general/, memory/auto-proposed/, and the current MEMORY.md index. 2. Send to Sonnet 4.6 in a multi-step pass: - Pass A: identify duplicate facts across topic files (semantic dedup, not exact match). - Pass B: identify stale facts (older than 90 days with no recent reference in any session). - Pass C: promote auto-proposed entries to canonical position if validated against existing memory. - Pass D: rebuild MEMORY.md index from current topic files. 3. Apply changes: - Merge duplicates: pick the more detailed entry, append the older entry's date and context as **Historical:** block. - Prune stale: move to memory/_archive/auto-pruned-YYYY-MM-DD/ (never delete). - Promote staged: rename from memory/auto-proposed/ to memory/general/. - Rebuild index: regenerate MEMORY.md from current topic files. 4. Log to LESSONS.md: ## [auto-dream] M merged, P pruned, S promoted, index regenerated to N lines.

Safety rails: - Stale-pruning is conservative. Default threshold 90 days no-reference. Tunable in eval.json config block. - Merge requires a confidence score from the model. Below 0.85, the merge is staged not applied. - Index regeneration runs against a snapshot. If the regenerated index would lose a topic file pointer, abort and alert. - All operations are file moves, never deletes.

Cost: - Auto-memory: roughly 1 Sonnet call per session, modest token use. - Auto-dream: 1 multi-pass Sonnet run per night, larger token use but bounded. - Both use Sonnet 4.6 not Opus to keep cost low.


1.5 Eval Harness and LESSONS.md

Doctrine Section 10 mandates a programmatic Evaluation Harness scoring rule adherence, plus LESSONS.md as the persistent failure log. Ships in Phase 4.5.

eval.json shape

{
  "version": "2026-04-28",
  "checks": [
    {
      "id": "no-em-dashes",
      "doctrine_section": "9",
      "severity": "error",
      "command": "grep -rn '—' /home/justinwieb/forge --include='*.md' --include='*.py' --include='*.sh' --exclude-dir=_archive --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=.venv | wc -l",
      "expected": "0",
      "comparator": "equals"
    },
    {
      "id": "memory-md-line-cap",
      "doctrine_section": "12",
      "severity": "error",
      "command": "wc -l < /home/justinwieb/.claude/projects/-home-justinwieb-forge/memory/MEMORY.md",
      "expected": "200",
      "comparator": "less_than_or_equal"
    },
    {
      "id": "memory-md-byte-cap",
      "doctrine_section": "12",
      "severity": "error",
      "command": "wc -c < /home/justinwieb/.claude/projects/-home-justinwieb-forge/memory/MEMORY.md",
      "expected": "25000",
      "comparator": "less_than_or_equal"
    },
    {
      "id": "doctrine-present",
      "doctrine_section": "0",
      "severity": "fatal",
      "command": "test -f /home/justinwieb/forge/FORGE-DOCTRINE.md && echo present",
      "expected": "present",
      "comparator": "equals"
    },
    {
      "id": "doctrine-mkdocs-serves",
      "doctrine_section": "9",
      "severity": "warning",
      "command": "curl -sf -o /dev/null -w '%{http_code}' http://localhost:8000/FORGE-DOCTRINE/",
      "expected": "200",
      "comparator": "equals"
    },
    {
      "id": "mkdocs-url-on-new-md",
      "doctrine_section": "9",
      "severity": "warning",
      "command": "scripts/forge_eval_check_mkdocs_urls.sh",
      "expected": "0",
      "comparator": "equals",
      "description": "Counts md files in indexed dirs missing the URL line"
    },
    {
      "id": "no-persona-names-in-code",
      "doctrine_section": "3",
      "severity": "error",
      "command": "scripts/forge_eval_check_persona_code.sh",
      "expected": "0",
      "comparator": "equals",
      "description": "Counts code-level identifiers using Greg, Ava_JForgeBot, Manager_JForgeBot, OpenClaw, GregTwoPointO"
    },
    {
      "id": "naming-taxonomy-services",
      "doctrine_section": "3",
      "severity": "warning",
      "command": "scripts/forge_eval_check_service_names.sh",
      "expected": "0",
      "comparator": "equals",
      "description": "Counts systemd units in forge/infra/systemd/ that violate forge-<function> pattern"
    }
  ]
}

Severity ladder

Level Behavior
fatal Pre-commit hook blocks commit. Nightly run pages manager bot.
error Pre-commit hook prints offenders, allows commit (initial run; tightens to block once we're at zero). Nightly run alerts.
warning Pre-commit hook prints, allows commit. Nightly run logs to LESSONS.md but does not alert.

LESSONS.md shape

Append-only, one entry per failed check per run.

# Forge Lessons

URL: https://mkdocs.justinsforge.com/LESSONS/

Persistent log of evaluation failures. Each entry shows what the doctrine rule was, what failed, and what was done about it.

## 2026-04-28T04:00:00 [no-em-dashes] error

- Doctrine: Section 9
- Expected: 0
- Actual: 2883
- Top offenders: memory/daily/2026-04-27.md (280), memory/daily/2026-04-13.md (130), ...
- Status: known, scheduled for purge in Pure Phoenix Phase 2.2
- Owner: Phase 2 execution

## 2026-04-28T04:00:00 [memory-md-line-cap] passed

- Doctrine: Section 12
- Expected: <= 200
- Actual: 182
- Status: ok

Wiring

  • Pre-commit hook: forge/.git/hooks/pre-commit calls scripts/forge_eval_harness.py --staged. Runs only checks marked staged_relevant: true. Blocks on fatal, prints on error, ignores warning.
  • Nightly cron at 03:00: scripts/forge_eval_harness.py --full runs all checks, writes results to LESSONS.md, sends summary to @forge_notify_outbound_bot if any fatal or error count increased since last run.
  • CI integration: same script runs in any future GitHub Actions setup; for now local-only.

First check set (initial)

The eight checks shown in the eval.json above. Phase 4.5 expands to add: variable convention spot-check (sample 5 random Python files for [source]_[entity]_[state] pattern), persona names in prose (lower priority), file-tree depth check (warn on > 4 levels), and a doctrine-section-anchor check (verify FORGE-DOCTRINE.md still has all 14 sections).


1.6 XML Context Boundary Templates

Doctrine Section 11 mandates three-tier XML wrapping. This is the template set for all forge prompt construction.

Template: subagent prompt (used in Agent tool calls and claude -p workers)

<system_rules>
URL: https://mkdocs.justinsforge.com/FORGE-DOCTRINE/

You are operating inside Forge under the doctrine. Hard rules:
- No em dashes anywhere. Use commas, colons, semicolons.
- No conversational filler. Lead with the answer.
- Mkdocs URL appended to every new or modified .md in indexed dirs.
- Naming: forge-<function> kebab-case for new infra. snake_case [source]_[entity]_[state] for variables.
- Self-iteration: if you spot a doctrine discrepancy, halt and propose an edit, do not silently override.

Full doctrine: forge/FORGE-DOCTRINE.md.
</system_rules>

<reference_data>
{{system maps, schemas, project context, recent state snapshots that are relevant to this task}}
</reference_data>

<active_payload>
{{the actual input being processed: the task, the file diff, the question}}
</active_payload>

{{the execution command, plain text, immediately follows}}

Template: dispatcher worker briefing (scripts/dispatcher.sh)

Same three tiers. Reference_data slot pulled from tasks/pending/<task>.md plus the relevant project context. Active_payload is the task body.

Template: Stop / SessionStart hook output

These hooks already inject content into the session context. Wrap their output:

<reference_data>
[since-last] Last session ended at HH:MM ...
[recent handoffs] ...
[pending tasks] ...
[monitor alerts] ...
</reference_data>

System_rules tier comes from CLAUDE.md (already auto-loaded). Active_payload is whatever Justin types next.

Template: skill briefing injection

When a skill loads, its body wraps with:

<reference_data>
[skill: foo]
{{skill body}}
</reference_data>

Skills do not get system_rules tier (CLAUDE.md owns that). Skills do not get active_payload tier (the user's command is the payload, supplied separately).

Phase 2 application

Update scripts/dispatcher.sh worker briefing template to use the wrapper. Update scripts/hooks/since-last.sh and auto-context.py to wrap output. Skill templates stay as-is for now (low ROI rewrite, can opportunistically wrap as touched).


1.2 Flat-File Refactor Scope (FLIPPED to bulk rename per 2026-04-28 directive)

Justin overrode CP-3 conservative scope on 2026-04-28: "I think we do need a bulk rename pass, this is a full refactor of the system. So we want everything to conform to this. Top to bottom."

CP-3 retired. New scope: every script, hook, tool under forge/scripts/ flattens into a single directory with verbose forge_<context>_<function>.{py,sh} filenames. No nested subdirs except those imposed by external tooling.

What flattens

Current New
scripts/integrations/telegram/inbox_brain.py scripts/forge_telegram_inbox_brain.py
scripts/integrations/telegram/ava_brain.py scripts/forge_telegram_lifeos_coordinator_brain.py
scripts/integrations/telegram/push.sh scripts/forge_telegram_push.sh
scripts/integrations/telegram/nudge-fire.py scripts/forge_telegram_nudge_fire.py
scripts/integrations/garmin/poll.py scripts/forge_garmin_poll.py
scripts/integrations/eight-sleep/poll.py deleted (already disabled)
scripts/integrations/wellness/daily-summary.py scripts/forge_wellness_daily_summary.py
scripts/integrations/minecraft/backup.sh deleted (Phase 3.5)
scripts/integrations/morning-wellness-check.sh scripts/forge_wellness_morning_check.sh
scripts/hooks/since-last.sh scripts/forge_hook_session_start_since_last.sh
scripts/hooks/auto-context.py scripts/forge_hook_user_prompt_auto_context.py
scripts/hooks/auto-checkpoint.sh scripts/forge_hook_stop_auto_checkpoint.sh
scripts/cleanup/retention.sh scripts/forge_cleanup_retention.sh
scripts/sites/new-page.sh scripts/forge_sites_new_page.sh
scripts/sites/preview.sh scripts/forge_sites_preview.sh
scripts/sites/screenshot.sh scripts/forge_sites_screenshot.sh
scripts/sites/deploy.sh scripts/forge_sites_deploy.sh
scripts/search/index.py scripts/forge_search_index.py
scripts/search/query.py scripts/forge_search_query.py
scripts/cloudflare/cf.py scripts/forge_cloudflare_cf.py
scripts/n8n/decrypt-cred.sh scripts/forge_n8n_decrypt_cred.sh
scripts/gdoc/to-drive.sh scripts/forge_gdoc_to_drive.sh
scripts/assets/run scripts/forge_assets_run.sh
scripts/assets/grab.py scripts/forge_assets_grab.py
scripts/assets/search.py scripts/forge_assets_search.py
scripts/assets/optimize.py scripts/forge_assets_optimize.py
scripts/assets/catalog.py scripts/forge_assets_catalog.py
scripts/checkpoint.sh scripts/forge_checkpoint.sh
scripts/dispatcher.sh scripts/forge_dispatcher.sh
scripts/notify.sh scripts/forge_notify.sh
scripts/fleet-start.sh scripts/forge_fleet_start.sh
scripts/fleet-status.sh scripts/forge_fleet_status.sh
scripts/home-base-session.sh scripts/forge_tmux_anchor_session.sh (also renames to match new service name)
scripts/monitors/mount-watchdog.sh scripts/forge_monitor_mount_watchdog.sh (sole survivor of the monitors purge)

Estimate: 35 to 45 script renames. The 3 retiring monitors (security/infra/business) + minecraft backup + telegram bot.py + eight-sleep poller all delete instead of rename.

What does NOT flatten

Tooling-imposed directories stay nested because the tools require those paths:

  • infra/systemd/*.service (systemd reads from a directory)
  • infra/n8n/workflows/*.json (n8n imports as a workflow library)
  • infra/mkdocs/ (mkdocs config + theme overrides)
  • infra/logrotate/forge.conf (logrotate convention)
  • infra/context-api/ (the FastAPI app is its own deployable; flatten the app's internal scripts but keep the app dir)

Repo organization stays nested where the directory IS the function:

  • memory/general/, memory/handoffs/, memory/daily/, memory/_archive/ (memory layer convention)
  • system-map/ (renaming to system-map/ separately, but stays one level)
  • sites/<site>/ (each site is a deployable unit; keeping nested per-site files)
  • brands/<brand>/ (each brand owns its own asset tree)
  • clients/<client>/ (same)
  • assets/ flat already
  • tasks/{pending,active,completed,failed}/ (dispatcher state machine)
  • comms/{inbox,broadcasts,results}/ (file-based message bus)
  • data/, logs/, personal/, dashboard/

Coordination surface

The bulk rename ripples across:

  • Systemd units (8 services) referencing old script paths in ExecStart=, WorkingDirectory=. Edit each .service file, systemctl daemon-reload, restart.
  • Cron entries (5 lines surviving the Phase 3 monitor cull) referencing old paths.
  • N8N workflows that shell out to forge scripts. Search the workflow JSON corpus for /home/justinwieb/forge/scripts/ paths and update.
  • Skills (.claude/skills/*.md) that reference scripts. Update any skill body that names a script.
  • Hooks config in .claude/settings.json and ~/.claude/settings.json. Update SessionStart, UserPromptSubmit, Stop hook paths.
  • MEMORY.md and system-map/ documentation that lists tools and pipelines. Bulk update path references.
  • Imports across Python scripts. Few internal cross-imports today, but search for from scripts.integrations and similar.

Phase placement

Bulk rename happens in Phase 4.3 (alongside the variable convention pass) AFTER: - Phase 3.4 retires Greg bot (so we don't rename a doomed file) - Phase 3.2 retires the monitor crons (so we don't rename doomed scripts) - Phase 4.1 fleet rename (so service names align with their new script paths)

Order: rename → update systemd/cron/n8n/skills/hooks → daemon-reload → smoke-test the dispatcher and a sample workflow → commit.

New-file rules going forward (apply immediately, do not wait for Phase 4.3)

  • New scripts go directly under forge/scripts/ with verbose forge_<context>_<function>.{py,sh} names
  • Doc files follow doctrine: filename carries context. forge_n8n_workflow_inventory.md beats n8n/workflow-inventory.md
  • New integrations only get a subdirectory if they ship 5 or more files; single-file integrations are flat

Doctrine Amendment: Section 3 Personal Endpoint Carve-Out (MERGED 2026-04-28)

Merged into FORGE-DOCTRINE.md Section 3 on 2026-04-28 per Justin's sign-off. Confirmed names locked: Sol (mac), Venus (iphone), Vector (windows workstation), Finn (Proxmox host), Console (dev VM, replaces UDev). system-map/ directory renames to system-map/ because it is a directory, not a device, and the amendment scopes to personal endpoint devices only.

Context

Justin pushed back 2026-04-28 on the rule that retires Sol, Venus, Vector, Finn as core infrastructure: "those names make sense to my human brain and are unique so you know what I am talking about. Want to make sure we reconsider our rule about human names."

The doctrine's anti-human-name rule exists to prevent semantic noise during LLM retrieval and to prevent persona-name conflation with operational role (the Greg failure mode). For personal endpoints that humans speak about daily, that risk is lower because:

  1. The device is an endpoint (mobile, mac, dev-vm, proxmox-host), not a service the LLM grep-manages
  2. Function-name documentation in system-map/fleet.md provides the alias-to-function mapping LLMs need
  3. Verbal-friendliness for daily reference matters more than naming purity
  4. Hard-consonant + Apple-Dictation test (already in Section 3) is the right gate for these names

Proposed addition to Section 3

Add this paragraph after the existing Section 3 paragraph that ends "...instantly signals an outdated reference":

Personal endpoint exception. Justin's primary phone, mac, windows workstation, Proxmox host, and dev VM may use friendly aliases (single-word, hard-consonant common words, Apple-Dictation friendly) instead of forge-<function> taxonomy. The function name MUST be documented in system-map/fleet.md so LLM agents can map alias to role. This exception applies ONLY to physical/virtual endpoint devices owned by Justin; it does NOT extend to LXC containers, systemd services, telegram bots, agents, or any other forge-managed component. Persona names for bots and agents remain forbidden because users address them by name and conflation with role is the failure mode (Greg precedent).

What survives the amendment

Current Survives Reason
Sol (Mac) yes hard-consonant common word, Apple-Dictation friendly, personal endpoint
Venus (iPhone) yes hard-consonant common word, personal endpoint
Vector (Windows PC) yes hard-consonant common word, technical also passes original Section 3
Finn (Proxmox host) yes hard-consonant double-N, personal endpoint, Justin's "house"
forge-plex, forge-n8n, forge-frigate, etc. no exception (already function-named) LXC services
Greg, Ava, Manager (bots) NO, still forbidden bots are addressed by name; persona conflation is the documented failure mode
Nexus (directory) unresolved, see open question not a device

Locked renames (not covered by amendment)

Current New Why
UDev (dev VM) Console "UDev" is a portmanteau, explicitly forbidden. Locked 2026-04-28.
system-map/ directory system-map/ Not a device, amendment does not cover. Locked 2026-04-28.
forge-home-base.service forge-tmux-anchor.service "Home base" is colloquial; "tmux-anchor" reveals function.

Bot fleet: full redo, not just rename (deferred to its own design pass)

Justin signaled 2026-04-28 that the bot fleet needs a redo, not just a rename. Phase 4.2 in the master plan was scoped as a rename-and-port operation; that scope is now too narrow.

Before Phase 4.2 executes, a separate bot architecture redesign runs as a sub-design pass. Open questions to answer in that pass:

  1. Functional split. Current fleet: chat-control (Greg, retiring), inbox capture, lifeos coordinator, notify-out. Is the inbox + lifeos split the right division of labor, or do they consolidate into one bot with sub-modes?
  2. Brain reuse. inbox_brain.py and ava_brain.py share a tool registry. Does the redo unify them under one brain with multiple personae, or keep them separate?
  3. Token strategy. Fresh BotFather tokens for everything, or rotate within existing identities?
  4. Capture pipeline. Doctrine Section 5 says inbox is for low-friction capture only, downstream workers do the heavy lifting. Is the current inbox brain doing too much?
  5. Notion / Calendar / Gmail tool surface. Currently both brains share these. Redo should clarify per-bot tool scope.
  6. Cost discipline. Doctrine Section 7 mandates per-bot API usage tracking. The redo wires this in from the start.
  7. Voice/text dictation. Justin uses voice on phone with these bots constantly. Apple-Dictation friendliness drives the new bot names.

Until that design pass produces a sub-handoff (pure-phoenix-bot-redesign-2026-XX-XX.md), Phase 4.2 stays parked. Recommended: spin the bot redesign after Phase 2 (formatting and rules) lands so the new bots are built directly on the new doctrine substrate, not retrofitted later.


Open Decisions Before Phase 2

These need your sign-off before Phase 2 begins. Each has a recommendation and a one-line tradeoff.

Decision Recommendation Tradeoff
Auto-memory confidence threshold High ≥ 0.85 writes direct, 0.65 to 0.85 stages, < 0.65 drops aggressive saves more, conservative needs Justin to review staging
Auto-dream stale threshold 90 days no-reference moves to archive shorter prunes faster, longer holds noise
Eval harness pre-commit severity Block on fatal, allow on error initially, tighten to block on error after one clean week initial allow lets Phase 2 land; permanent allow defeats the harness
MEMORY.md slim-down approach Mechanical split: every multi-line section becomes a topic file, index entries are one-liners aggressive split fragments related facts; conservative leaves dense MEMORY.md
Variable convention enforcement New code mandatory; existing code refactored only when touched aggressive forces a 1-week refactor sprint; conservative spreads it out
FORGE-DOCTRINE-VARIABLES.md Yes, separate file under forge root with mkdocs URL yes adds a file; no makes Section 4 the only reference and forces you to read FORGE-DOCTRINE.md to learn the convention

Phase 1 Deliverables

Artifact Purpose Phase that ships it
This design doc Captures all four resystemize decisions Phase 1 (now)
scripts/forge_memory_auto_capture.py Auto-memory worker Phase 4.4
scripts/forge_memory_auto_dream.py Auto-dream consolidation Phase 4.4
scripts/forge_memory_revert.py Reversibility for auto-memory writes Phase 4.4
scripts/forge_eval_harness.py Eval harness runner Phase 4.5
scripts/forge_eval_check_mkdocs_urls.sh Mkdocs URL presence checker Phase 4.5
scripts/forge_eval_check_persona_code.sh Persona name detector for code Phase 4.5
scripts/forge_eval_check_service_names.sh Service name compliance checker Phase 4.5
forge/eval.json Eval harness config Phase 4.5
forge/LESSONS.md Failure log Phase 4.5
forge/FORGE-DOCTRINE-VARIABLES.md Variable convention reference Phase 2.1
Updated dispatcher template XML boundary wrapper Phase 2.4
Updated since-last hook output XML boundary wrapper Phase 2.4

[Claude Code]