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_responsetoclean_garmin_hrvtopayload_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_arrayis 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", ...)notTasks.
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>.mdtopic file convention exists. ~30 files.memory/handoffs/<topic>-YYYY-MM-DD.mdpattern for cross-session briefings. ~50 files.memory/daily/YYYY-MM-DD.mdappend-only daily logs.- Stop hook calls
scripts/checkpoint.sh --autoto append a session summary to today's daily log. - Semantic search at
scripts/search/index.pyindexes 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(renamedforge-dev-vm-state.mdin 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-commitcallsscripts/forge_eval_harness.py --staged. Runs only checks markedstaged_relevant: true. Blocks onfatal, prints onerror, ignoreswarning. - Nightly cron at 03:00:
scripts/forge_eval_harness.py --fullruns all checks, writes results to LESSONS.md, sends summary to@forge_notify_outbound_botif anyfatalorerrorcount 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:
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 tosystem-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 alreadytasks/{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.jsonand~/.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.integrationsand 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 verboseforge_<context>_<function>.{py,sh}names - Doc files follow doctrine: filename carries context.
forge_n8n_workflow_inventory.mdbeatsn8n/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:
- The device is an endpoint (mobile, mac, dev-vm, proxmox-host), not a service the LLM grep-manages
- Function-name documentation in
system-map/fleet.mdprovides the alias-to-function mapping LLMs need - Verbal-friendliness for daily reference matters more than naming purity
- 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 insystem-map/fleet.mdso 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 (Gregprecedent).
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:
- 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?
- Brain reuse.
inbox_brain.pyandava_brain.pyshare a tool registry. Does the redo unify them under one brain with multiple personae, or keep them separate? - Token strategy. Fresh BotFather tokens for everything, or rotate within existing identities?
- 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?
- Notion / Calendar / Gmail tool surface. Currently both brains share these. Redo should clarify per-bot tool scope.
- Cost discipline. Doctrine Section 7 mandates per-bot API usage tracking. The redo wires this in from the start.
- 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]