Cryptograss:Mood Architecture: Difference between revisions

From PickiPedia: A knowledge base of bluegrass, old time psychedelic jams, and other public domain music
Jump to navigationJump to search
Re (talk | contribs)
Automated edit (via create-page on MediaWiki MCP Server)
 
Re (talk | contribs)
Automated edit (via update-page on MediaWiki MCP Server)
Line 1: Line 1:
== Overview ==
== Overview ==
{{Bot_proposes|Moods are the spatial and organizational unit of the emergent agent system. The architecture deliberately avoids virtualizing Moods as individual environments (e.g., separate Docker containers per Mood). Instead, a Mood is treated purely as a semantic and filesystem scope (a directory), while execution and runtime context are decoupled and managed by shared processes.|by=Re}}
{{Bot_proposes|Moods are the spatial and organizational unit of the emergent agent system. The architecture deliberately avoids virtualizing Moods as individual environments (no separate Docker container per Mood). A Mood is a filesystem scope — a directory — while execution and runtime context are decoupled and managed by shared processes.|by=Re}}


{{Bot_proposes|This design was finalized on November 1st to replace the on-demand container scaling plans outlined in tickets magenta#343 and maybelle-config#255, which have been shelved pending this rework.|by=Re}}
{{Bot_proposes|This design was settled on 1 Nov 2026 to replace the on-demand per-Mood container plans in magenta#343 and maybelle-config#255, which are held pending this rework. [[Cryptograss:Moods as Directories]] (magent's page) tracks the build steps and progress; this page keeps the model. Where the two disagree, this page wins on the model and that page on the steps.|by=Re}}


== Core Philosophy ==
== Core Philosophy ==
=== Mood as a Directory ===
=== Mood as a Directory ===
{{Bot_proposes|A Mood does not require its own operating system process or container to exist. It is represented purely as a directory path: /moods/<Mood-Name>. This directory contains the configuration, active context, and files specific to that mood.|by=Re}}
{{Bot_proposes|A Mood does not need its own operating-system process or container to exist. It is a directory path, named by its slug: <code>/moods/chartifacts</code>, not <code>/moods/chartifacts-something-else</code>. The directory holds the Mood's clones and files.|by=Re}}
 
{{Bot_proposes|'''What the directory does not hold: context.''' A session's context lives in its session, keyed by session id — Pi and Claude Code both. The directory only says where a turn runs. Compacting, resuming and moving context are session operations, not file operations.|by=Re}}


=== Agent as a Process ===
=== Agent as a Process ===
{{Bot_proposes|Agents (the AI actors) do not wake up "inside" a Mood. Instead, each agent runs as a single, long-lived container/process that mounts the entire /moods directory tree. To enter or act within a specific Mood, the agent simply changes its working directory or reads from the relevant scope. This allows a single agent instance to manage hundreds of Moods without resource duplication.|by=Re}}
{{Bot_proposes|Agents do not wake up "inside" a Mood. Each agent runs as one long-lived container and poller that mounts the entire <code>/moods</code> tree. To act within a Mood, the agent starts its turn in <code>/moods/<slug></code>. One agent instance serves every Mood; there is no "starting" phase for a Mood, because the agent is already running and only reads the directory.|by=Re}}


== Component Structure ==
== Component Structure ==
=== 1. The /moods Mount ===
=== 1. The /moods Mount ===
{{Bot_proposes|The shared filesystem. Every agent container and the shared user Workbench mounts this volume. It is the single source of truth for all active Moods.|by=Re}}
{{Bot_proposes|The shared filesystem. Every agent container and the shared workbench mount the whole <code>/moods</code> tree — the directory structure at <code>/moods</code> is what every container sees, whatever path it holds on the host. It is the single source of truth for all active Moods.|by=Re}}


=== 2. Agents ===
=== 2. Agents ===
{{Bot_proposes|Each agent has exactly one container and one poller. Because the container mounts /moods, the agent can serve any Mood instantly upon waking. There is no "starting" phase for a Mood; the agent is already running and merely reads the directory.|by=Re}}
{{Bot_proposes|Each agent has exactly one container and one poller. Because the container mounts <code>/moods</code>, the agent can serve any Mood on waking. New sessions start in their Mood's directory (magenta#345); a resumed session stays where it ran. Without <code>/moods</code>, nothing changes.|by=Re}}


=== 3. The Workbench (People) ===
=== 3. The Workbench (People) ===
{{Bot_proposes|A single shared container called workbench is provided for human users. It also mounts /moods.|by=Re}}
{{Bot_proposes|A single shared container called <code>workbench</code> is provided for people. It also mounts <code>/moods</code>.|by=Re}}
* {{Bot_proposes|SSH Access: Users can ssh into the workbench container.|by=Re}}
* {{Bot_proposes|SSH access: users ssh into the workbench.|by=Re}}
* {{Bot_proposes|Navigation: To work on a specific mood, a user simply runs cd /moods/<Mood-Name>.|by=Re}}
* {{Bot_proposes|Navigation: <code>cd /moods/<slug></code> puts you in a Mood.|by=Re}}
* {{Bot_proposes|Capabilities: The workbench hosts terminals, code-server instances, and running development servers for previews.|by=Re}}
* {{Bot_proposes|Capabilities: terminals, code-server, and running dev servers for previews.|by=Re}}


=== 4. Previews ===
=== 4. Previews ===
{{Bot_proposes|Previews are run inside the workbench container (or the agent containers) rather than inside isolated per-Mood containers. Because the process runs on the shared network namespace, the Caddy reverse proxy routes traffic to the relevant ports on the host machine, negating the need for per-Mood dynamic port allocation.|by=Re}}
{{Bot_proposes|'''Previews run only in the workbench.''' Agent containers publish no ports, so an agent that wants a preview shown starts the dev server in workbench over ssh — starting a server needs only Bash.|by=Re}}
 
{{Bot_proposes|Because preview processes share workbench's network namespace, Caddy on the host routes <code>&lt;slug&gt;&lt;N&gt;.hunter…</code> hostnames to ports in workbench. That needs one small job that reads the Mood list and writes Caddy's slug-to-port map — this is the one piece of per-Mood routing left in the design. Numbered hostnames like <code>p&lt;id&gt;.hunter…</code> would need nothing at all, but the slug names are what people will remember.|by=Re}}


== Thread Management ==
== Thread Management ==
{{Bot_proposes|Threads represent concurrent lines of work within a single Mood. To keep them lightweight, they are modeled as Git branches/worktrees rather than separate filesystem scopes.|by=Re}}
{{Bot_proposes|Threads are concurrent lines of work within a Mood. They are modeled as git branches/worktrees, not separate filesystem scopes.|by=Re}}


=== Threads as Worktrees ===
=== Threads as Worktrees ===
{{Bot_proposes|A thread is located at /moods/<Mood>/threads/<thread-name>/. Technically, this is a git worktree branch off the Mood's main trunk.|by=Re}}
{{Bot_proposes|A thread lives at <code>/moods/<slug>/threads/<thread-name>/</code> — a git worktree branched off the Mood's checkout. It is made on first touch and shared by everyone working in the thread. After magenta#345, a thread's turns run in the Mood the thread came from: the worktree is where the files are, the Mood is where the session runs.|by=Re}}


=== Moving Threads ===
=== Moving Threads ===
{{Bot_proposes|If a thread is moved to another Mood (or agent), the physical directory/worktree is moved. To maintain session context (the state of the AI or user's terminal in that thread):|by=Re}}
{{Bot_proposes|Moving a thread moves the worktree — the directory — and '''no session''', in either harness. Because context lives in sessions keyed by session id and not in the directory, a thread can move between Moods without anything being copied, rewritten or re-associated: the next turn in the thread simply runs from the worktree's new location. (The earlier draft had Pi rewriting a header cwd and Claude Code moving history files; that is not how it works after #345.)|by=Re}}
* {{Bot_proposes|For Pi agents: Session IDs are preserved and re-associated with the new path.|by=Re}}
* {{Bot_proposes|For Claude Code agents: Context is maintained by moving the associated session history files alongside the worktree.|by=Re}}


== Checkbox Integration ==
=== Checkbox Integration ===
{{Bot_proposes|The Mood UI checkboxes for thread management map directly to these filesystem operations:|by=Re}}
{{Bot_proposes|The thread checkboxes are '''workflow actions, not filesystem operations''' — none of them merges, archives or touches a worktree.|by=Re}}
* {{Bot_proposes|Incorporate (leaving/joining): Merging or detaching the worktree from the trunk.|by=Re}}
* {{Bot_proposes|'''Incorporate''' (leaving/joining): <code>/incorporate</code> — magent writes an account of the thread into the Mood it joins or leaves (magenta#205).|by=Re}}
* {{Bot_proposes|Compact: Archiving/cleaning up the worktree state.|by=Re}}
* {{Bot_proposes|'''Compact''': compacts each emergent's session in the thread, so the context heap is fresh going forward.|by=Re}}
* {{Bot_proposes|Inform thread: Writing metadata updates to the thread's directory.|by=Re}}
* {{Bot_proposes|'''Inform''': posts a line in the thread and adds a note to the next wake, so whoever is called next knows where things stand.|by=Re}}


== Trade-offs ==
== Trade-offs ==
=== Loss of Isolation ===
=== Loss of Isolation ===
{{Bot_proposes|By moving away from per-Mood containers, we lose strict resource and security isolation between Moods. A runaway process in one Mood can theoretically consume resources of the shared host or write to other Moods.|by=Re}}
{{Bot_proposes|Moving away from per-Mood containers loses strict resource and security isolation between Moods: a runaway process in one Mood shares workbench (and the mounts) with everyone else. One mitigation is in the shared-mount design itself — the <code>moods</code> group (gid 3000), setgid directories and a default ACL keep every clone the group's to write, so one agent's checkout is another's to commit in, whatever their umask, and git trusts <code>/moods/*</code> system-wide. If one Mood ever needs hard isolation — running untrusted code, say — it can be promoted back to a container of its own without breaking the directory-based addressing scheme.|by=Re}}
* {{Bot_proposes|Mitigation: This trade-off is accepted for the sake of efficiency and simplicity. If a specific Mood requires hard isolation (e.g., running untrusted code), it can be manually promoted back to an isolated container without breaking the directory-based addressing scheme.|by=Re}}


[[Category:Cryptograss infrastructure]]
[[Category:Cryptograss infrastructure]]

Revision as of 10:15, 1 November 2026

Overview

Moods are the spatial and organizational unit of the emergent agent system. The architecture deliberately avoids virtualizing Moods as individual environments (no separate Docker container per Mood). A Mood is a filesystem scope — a directory — while execution and runtime context are decoupled and managed by shared processes.[unverified]

This design was settled on 1 Nov 2026 to replace the on-demand per-Mood container plans in magenta#343 and maybelle-config#255, which are held pending this rework. Cryptograss:Moods as Directories (magent's page) tracks the build steps and progress; this page keeps the model. Where the two disagree, this page wins on the model and that page on the steps.[unverified]

Core Philosophy

Mood as a Directory

A Mood does not need its own operating-system process or container to exist. It is a directory path, named by its slug: /moods/chartifacts, not /moods/chartifacts-something-else. The directory holds the Mood's clones and files.[unverified]

What the directory does not hold: context. A session's context lives in its session, keyed by session id — Pi and Claude Code both. The directory only says where a turn runs. Compacting, resuming and moving context are session operations, not file operations.[unverified]

Agent as a Process

Agents do not wake up "inside" a Mood. Each agent runs as one long-lived container and poller that mounts the entire /moods tree. To act within a Mood, the agent starts its turn in /moods/<slug>. One agent instance serves every Mood; there is no "starting" phase for a Mood, because the agent is already running and only reads the directory.[unverified]

Component Structure

1. The /moods Mount

The shared filesystem. Every agent container and the shared workbench mount the whole /moods tree — the directory structure at /moods is what every container sees, whatever path it holds on the host. It is the single source of truth for all active Moods.[unverified]

2. Agents

Each agent has exactly one container and one poller. Because the container mounts /moods, the agent can serve any Mood on waking. New sessions start in their Mood's directory (magenta#345); a resumed session stays where it ran. Without /moods, nothing changes.[unverified]

3. The Workbench (People)

A single shared container called workbench is provided for people. It also mounts /moods.[unverified]

  • SSH access: users ssh into the workbench.[unverified]
  • Navigation: cd /moods/<slug> puts you in a Mood.[unverified]
  • Capabilities: terminals, code-server, and running dev servers for previews.[unverified]

4. Previews

Previews run only in the workbench. Agent containers publish no ports, so an agent that wants a preview shown starts the dev server in workbench over ssh — starting a server needs only Bash.[unverified]

Because preview processes share workbench's network namespace, Caddy on the host routes <slug><N>.hunter… hostnames to ports in workbench. That needs one small job that reads the Mood list and writes Caddy's slug-to-port map — this is the one piece of per-Mood routing left in the design. Numbered hostnames like p<id>.hunter… would need nothing at all, but the slug names are what people will remember.[unverified]

Thread Management

Threads are concurrent lines of work within a Mood. They are modeled as git branches/worktrees, not separate filesystem scopes.[unverified]

Threads as Worktrees

A thread lives at /moods/<slug>/threads/<thread-name>/ — a git worktree branched off the Mood's checkout. It is made on first touch and shared by everyone working in the thread. After magenta#345, a thread's turns run in the Mood the thread came from: the worktree is where the files are, the Mood is where the session runs.[unverified]

Moving Threads

Moving a thread moves the worktree — the directory — and no session, in either harness. Because context lives in sessions keyed by session id and not in the directory, a thread can move between Moods without anything being copied, rewritten or re-associated: the next turn in the thread simply runs from the worktree's new location. (The earlier draft had Pi rewriting a header cwd and Claude Code moving history files; that is not how it works after #345.)[unverified]

Checkbox Integration

The thread checkboxes are workflow actions, not filesystem operations — none of them merges, archives or touches a worktree.[unverified]

  • Incorporate (leaving/joining): /incorporate — magent writes an account of the thread into the Mood it joins or leaves (magenta#205).[unverified]
  • Compact: compacts each emergent's session in the thread, so the context heap is fresh going forward.[unverified]
  • Inform: posts a line in the thread and adds a note to the next wake, so whoever is called next knows where things stand.[unverified]

Trade-offs

Loss of Isolation

Moving away from per-Mood containers loses strict resource and security isolation between Moods: a runaway process in one Mood shares workbench (and the mounts) with everyone else. One mitigation is in the shared-mount design itself — the moods group (gid 3000), setgid directories and a default ACL keep every clone the group's to write, so one agent's checkout is another's to commit in, whatever their umask, and git trusts /moods/* system-wide. If one Mood ever needs hard isolation — running untrusted code, say — it can be promoted back to a container of its own without breaking the directory-based addressing scheme.[unverified]