feat(agents): agent seats - per-agent SOUL, role, definitions dir (#36)
- agents/<name>/ holds agent.json (strictly validated: version, name, role?, capabilities?, workspace?, session?) + SOUL.md (persona prose) - agent.sh: definition loading (quote-safe node defaults file), runtime SOUL copy to dataRoot/agents/<name>/, MOSAIC_AGENT_SOUL_FILE -> loader fills the SOUL slot from the seat's persona (contract SOUL = default persona; governance never overridden) - seat.json written once at instantiation (seatVersion, name, role, at) - identity section gains agent role; compose passthrough for role+SOUL - live user context (M14) + seat SOUL compose the full persona: governance -> persona -> identity -> user -> mission - RELEASE -> 0.0.10; packaged and health-gated activated - example seat committed: agents/researcher Closes #36
This commit is contained in:
+39
-4
@@ -1,14 +1,33 @@
|
||||
#!/bin/sh
|
||||
# Load the four immutable contract files in fixed order and write the
|
||||
# generated system prompt to /var/lib/mosaic/system-prompt.md.
|
||||
# Load agent context and write the generated system prompt to
|
||||
# /var/lib/mosaic/system-prompt.md.
|
||||
#
|
||||
# Order is normative: CONSTITUTION.md, STANDARDS.md, SOUL.md, USER.md.
|
||||
# Layers, in normative order:
|
||||
# 1. Immutable contracts (image): CONSTITUTION, STANDARDS, SOUL
|
||||
# 2. Agent identity (when the launcher names the agent)
|
||||
# 3. Mission (when the task/launcher provides one)
|
||||
# 4. Live user context (M14): <dataRoot>/user/*.md - user-owned,
|
||||
# dispatched to every launch without rebuilds
|
||||
set -eu
|
||||
|
||||
CONTRACT_DIR="${1:-/opt/mosaic/contracts}"
|
||||
OUT="${2:-/var/lib/mosaic/system-prompt.md}"
|
||||
|
||||
FILES="CONSTITUTION.md STANDARDS.md SOUL.md USER.md"
|
||||
FILES="CONSTITUTION.md STANDARDS.md"
|
||||
|
||||
# SOUL slot (M15): the contract SOUL.md is the DEFAULT persona; a launched
|
||||
# agent seat overrides it with its own runtime SOUL (governance contracts
|
||||
# are never overridden).
|
||||
SOUL_SRC="$CONTRACT_DIR/SOUL.md"
|
||||
SOUL_HEADER="SOUL.md"
|
||||
if [ -n "${MOSAIC_AGENT_SOUL_FILE:-}" ]; then
|
||||
if [ ! -r "$MOSAIC_AGENT_SOUL_FILE" ]; then
|
||||
echo "load-contracts: agent SOUL not readable: $MOSAIC_AGENT_SOUL_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
SOUL_SRC="$MOSAIC_AGENT_SOUL_FILE"
|
||||
SOUL_HEADER="SOUL.md (agent seat override)"
|
||||
fi
|
||||
|
||||
if [ ! -d "$CONTRACT_DIR" ]; then
|
||||
echo "load-contracts: contract directory not found: $CONTRACT_DIR" >&2
|
||||
@@ -33,14 +52,30 @@ for f in $FILES; do
|
||||
printf '\n' >> "$TEMP"
|
||||
done
|
||||
|
||||
printf '===== CONTRACT: %s =====\n' "$SOUL_HEADER" >> "$TEMP"
|
||||
cat "$SOUL_SRC" >> "$TEMP"
|
||||
printf '\n' >> "$TEMP"
|
||||
|
||||
# Agent identity (M13): when the launcher names the agent, the generated
|
||||
# prompt states it - SOUL.md provides the persona, this provides the name.
|
||||
if [ -n "${MOSAIC_AGENT_NAME:-}" ]; then
|
||||
printf '===== AGENT IDENTITY =====\n' >> "$TEMP"
|
||||
printf 'agent name: %s\n' "$MOSAIC_AGENT_NAME" >> "$TEMP"
|
||||
[ -n "${MOSAIC_AGENT_ROLE:-}" ] && printf 'agent role: %s\n' "$MOSAIC_AGENT_ROLE" >> "$TEMP"
|
||||
printf '\n' >> "$TEMP"
|
||||
fi
|
||||
|
||||
# Live user context (M14): every *.md in /var/lib/mosaic/user (sorted) is
|
||||
# appended - the user owns this layer and edits it without rebuilds.
|
||||
USER_DIR="/var/lib/mosaic/user"
|
||||
if [ -d "$USER_DIR" ]; then
|
||||
for f in $(ls "$USER_DIR"/*.md 2>/dev/null | sort); do
|
||||
printf '===== USER CONTEXT: %s =====\n' "$(basename "$f")" >> "$TEMP"
|
||||
cat "$f" >> "$TEMP"
|
||||
printf '\n' >> "$TEMP"
|
||||
done
|
||||
fi
|
||||
|
||||
# Sanctioned mission injection point (M4): when the task runner provides a
|
||||
# mission snapshot, its objective and directives are appended AFTER the
|
||||
# immutable contracts. Runtime data; never part of the contract fixtures.
|
||||
|
||||
Reference in New Issue
Block a user