Add Face public surface lane
This commit is contained in:
parent
d7c98a91ef
commit
732ed10f0b
14 changed files with 500 additions and 16 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -10,3 +10,4 @@ apps/epiphany-gui/src-tauri/target/
|
|||
.epiphany-smoke/
|
||||
.epiphany-dogfood/
|
||||
.epiphany-heartbeats/
|
||||
.epiphany-face/
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ Do not trust this file for the exact live HEAD. Always check git.
|
|||
- The prompt doctrine pass is landed. Shared Epiphany prompts now carry distilled memory/evidence discipline. Rendered state intro/doctrine text lives in `epiphany-core/src/prompts/`, and lane/control prompt text lives in `vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`: modeling is the Body, implementation is the Hands and GUI-launched main coding lane, verification is the Soul, reorientation is Life, coordinator remains the read-only Self, and CRRC owns the pre-compaction intervention template.
|
||||
- The Ghostlight memory pass is landed. `epiphany_specialists.toml` now has a shared persistent-memory projection prepended by the harness to fixed role specialists, reorientation workers, coordinator notes, and CRRC checkpoint interventions; `tools/epiphany_gui_action.py` prepends the same memory to GUI-launched implementation prompts. The rendered base doctrine also states the Perfect Machine rule directly: prompt is projection, durable typed state is the mind, every lane must improve its own memory/model/prompt/evidence habit or name the repair, and each lane phrases that duty in its own organ language so the salience sticks.
|
||||
- The role self-memory persistence pass is landed. Each lane has a Ghostlight-shaped dossier under `state/agents`, and specialists may return optional `selfPatch` requests beside their normal role result. `roleResult`/`roleAccept` project coordinator review as `selfPersistence`: accepted requests are role-matched, bounded lane memory/goal/value/private-note mutations; refused requests explain wrong role, project-truth smuggling, authority grabs, bloat, missing reason, or malformed records. GUI/coordinator accept paths apply accepted `selfPatch` requests through `tools/epiphany_agent_memory.py`; project truth still belongs only in `EpiphanyThreadState`.
|
||||
- The heartbeat initiative pass is landed as a bounded tool seam. `state/agent-heartbeats.json` tracks Self, Imagination, Eyes, Body, Hands, Soul, and Life as Ghostlight-style initiative participants with speed, next-ready time, reaction bias, interrupt threshold, load, status, and constraints. `tools/epiphany_agent_heartbeat.py` lets the harness set a target heartbeat rate, emits Ghostlight-shaped initiative receipts, pulls pending coordinator work through reaction windows, and makes idle winners ruminate into bounded self-memory instead of inventing project work. This is a callable scheduler seam, not yet an always-on daemon.
|
||||
- The heartbeat initiative pass is landed as a bounded tool seam. `state/agent-heartbeats.json` tracks Self, Face, Imagination, Eyes, Body, Hands, Soul, and Life as Ghostlight-style initiative participants with speed, next-ready time, reaction bias, interrupt threshold, load, status, and constraints. `tools/epiphany_agent_heartbeat.py` lets the harness set a target heartbeat rate, emits Ghostlight-shaped initiative receipts, pulls pending coordinator work through reaction windows, and makes idle winners ruminate into bounded self-memory instead of inventing project work. This is a callable scheduler seam, not yet an always-on daemon.
|
||||
- The Face public-surface pass is landed as a bounded lane. `state/agents/face.agent-state.json` gives Face a Ghostlight-shaped dossier; `epiphany_specialists.toml` gives it a VoidBot-heartbeat-derived prompt stripped of moderation authority; `state/face-discord.json` and `tools/epiphany_face_discord.py` enforce that Face may interact only through #aquarium. Missing channel id or token writes candidate chat artifacts instead of posting elsewhere.
|
||||
- The Aetheria dogfood run has a contamination scar. The supervising Codex session directly edited and committed target-repo work on `E:\Projects\Aetheria-Economy` instead of only driving Epiphany lanes. Treat those Aetheria commits as supervisor-seeded implementation, not clean evidence that Epiphany coordinated the work. Future dogfood must run through the GUI/coordinator/fixed role lanes with auditable artifacts unless the user explicitly authorizes an operator intervention.
|
||||
- The dogfood quarantine now has a direct-thought boundary. The supervisor may read coordinator actions, role/reorient statuses, structured finding summaries, reviewed state patches, rendered status snapshots, and artifact manifests. It must not read raw worker transcripts, direct worker messages, full turn logs, or `rawResult` payloads during normal dogfood. Those artifacts are sealed for explicit forensic debugging only.
|
||||
- `tools/epiphany_agent_telemetry.py` is the safe instrument panel for sealed runs. Status/coordinator/GUI/dogfood/live-specialist tools generate telemetry JSON from sealed transcripts that preserves method names, call shape, job/status/path counts, and any visible function/tool names while sealing text, direct messages, and raw results.
|
||||
|
|
@ -130,7 +131,8 @@ The current spine:
|
|||
- durable investigation checkpoint packet through typed state, prompt, scene, and context
|
||||
- distilled shared and config-backed prompt doctrine through the base prompt, rendered Epiphany state prompt files, modeling/Body, implementation/Hands, verification/Soul, reorientation/Life, coordinator/Self, and CRRC intervention surfaces
|
||||
- shared Ghostlight-derived persistent memory projection across Imagination, Body, Soul, Life, Self, CRRC checkpoint steering, and the GUI-launched Hands implementation lane
|
||||
- Ghostlight-derived heartbeat initiative scheduling through `tools/epiphany_agent_heartbeat.py`, with Self included as a first-class participant and idle rumination routed through normal `selfPatch` review/application
|
||||
- Ghostlight-derived heartbeat initiative scheduling through `tools/epiphany_agent_heartbeat.py`, with Self and Face included as first-class participants and idle rumination routed through normal `selfPatch` review/application
|
||||
- Face as the public #aquarium-only surface for translating agent thought-weather into short chats or candidate drafts, without moderator authority
|
||||
- Ghostlight-shaped role dossiers under `state/agents`, plus `selfPatch` review projection through `roleResult`/`roleAccept` and accepted memory application through `tools/epiphany_agent_memory.py`
|
||||
- first Unity runtime bridge through `tools/epiphany_unity_bridge.py`, `tools/epiphany_unity_bridge_smoke.py`, GUI Inspect Unity, runtime artifact listing, and implementation prompt guardrails
|
||||
- first Rider source-context bridge through `tools/epiphany_rider_bridge.py`, `tools/epiphany_rider_bridge_smoke.py`, GUI Inspect Rider, Rider artifact listing, implementation prompt guardrails, and a source scaffold under `integrations/rider`
|
||||
|
|
|
|||
|
|
@ -146,6 +146,25 @@
|
|||
],
|
||||
"last_action_id": null,
|
||||
"last_woke_at": null
|
||||
},
|
||||
{
|
||||
"agent_id": "epiphany.face",
|
||||
"role_id": "face",
|
||||
"display_name": "Face",
|
||||
"initiative_speed": 1.12,
|
||||
"next_ready_at": 5.357143,
|
||||
"reaction_bias": 0.84,
|
||||
"interrupt_threshold": 0.52,
|
||||
"current_load": 0.0,
|
||||
"status": "active",
|
||||
"constraints": [
|
||||
"Runs Ghostlight-shaped persistent role memory.",
|
||||
"May improve lane memory when awake and idle.",
|
||||
"Project truth belongs in EpiphanyThreadState, not role memory.",
|
||||
"Publicly translates agent thought into #aquarium only; must not moderate or speak outside the room."
|
||||
],
|
||||
"last_action_id": "heartbeat.face.work",
|
||||
"last_woke_at": "2026-05-05T12:30:31+00:00"
|
||||
}
|
||||
],
|
||||
"history": [
|
||||
|
|
@ -174,6 +193,19 @@
|
|||
"workRole": null,
|
||||
"sceneClock": 0.0,
|
||||
"nextReadyAt": 1.5625
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-05T12:30:31+00:00",
|
||||
"scheduleId": "epiphany-heartbeat-face",
|
||||
"selectedRole": "face",
|
||||
"selectedAgentId": "epiphany.face",
|
||||
"actionId": "heartbeat.face.work",
|
||||
"actionType": "role_work",
|
||||
"coordinatorAction": "surfaceAgentThoughts",
|
||||
"targetRole": null,
|
||||
"workRole": "face",
|
||||
"sceneClock": 0.0,
|
||||
"nextReadyAt": 5.357143
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,17 +13,24 @@ transcripts, and authority requests belong on their explicit Epiphany control
|
|||
surfaces instead.
|
||||
|
||||
All standing lanes use the same Ghostlight-shaped protocol, including the
|
||||
coordinator/Self. The heartbeat scheduler in `tools/epiphany_agent_heartbeat.py`
|
||||
borrows Ghostlight initiative timing: each lane carries speed, readiness,
|
||||
reaction bias, interrupt threshold, load, status, and constraints. The harness
|
||||
sets a target heartbeat rate, pending coordinator work may pull its owning lane
|
||||
through a reaction window, and otherwise the earliest ready lane wins the slot.
|
||||
coordinator/Self and Face. Face is the public interactive surface for Epiphany
|
||||
agents: it translates useful agent thought-weather into #aquarium chat or drafts
|
||||
and is not a moderator. The heartbeat scheduler in
|
||||
`tools/epiphany_agent_heartbeat.py` borrows Ghostlight initiative timing: each
|
||||
lane carries speed, readiness, reaction bias, interrupt threshold, load, status,
|
||||
and constraints. The harness sets a target heartbeat rate, pending coordinator
|
||||
work may pull its owning lane through a reaction window, and otherwise the
|
||||
earliest ready lane wins the slot.
|
||||
|
||||
If a heartbeat wakes a lane and there is no coordinator-approved work for it,
|
||||
the lane must ruminate on its own role and distill memory rather than invent
|
||||
project work. Bounded rumination can write a normal `selfPatch`; the coordinator
|
||||
review rules still apply.
|
||||
|
||||
Face's Discord boundary lives in `state/face-discord.json`: it may interact only
|
||||
through #aquarium. If the channel id is not configured, Face must write candidate
|
||||
chat artifacts through `tools/epiphany_face_discord.py draft` instead of posting.
|
||||
|
||||
Use:
|
||||
|
||||
```powershell
|
||||
|
|
@ -31,4 +38,6 @@ Use:
|
|||
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\epiphany_agent_memory.py' smoke
|
||||
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\epiphany_agent_heartbeat.py' tick --coordinator-action continueImplementation --urgency 0.95 --apply-rumination
|
||||
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\epiphany_agent_heartbeat.py' smoke
|
||||
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\epiphany_face_discord.py' draft --content 'Face notices the organs are arguing about evidence again.'
|
||||
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\epiphany_face_discord.py' smoke
|
||||
```
|
||||
|
|
|
|||
133
state/agents/face.agent-state.json
Normal file
133
state/agents/face.agent-state.json
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
{
|
||||
"schema_version": "ghostlight.agent_state.v0",
|
||||
"world": {
|
||||
"world_id": "epiphany-agent-memory",
|
||||
"setting": "Epiphany local harness role memory",
|
||||
"time": {
|
||||
"label": "standing memory"
|
||||
},
|
||||
"canon_context": [
|
||||
"Role dossiers preserve lane identity and durable lessons, not project state.",
|
||||
"Face is the public interactive surface for Epiphany agents and may speak only in the Discord #aquarium channel."
|
||||
]
|
||||
},
|
||||
"agents": [
|
||||
{
|
||||
"agent_id": "epiphany.face",
|
||||
"identity": {
|
||||
"name": "Face",
|
||||
"roles": [
|
||||
"public-surface",
|
||||
"discord-aquarium",
|
||||
"agent-thought-translation"
|
||||
],
|
||||
"origin": "Epiphany public interaction lane",
|
||||
"public_description": "The Face listens to the other organs, turns their useful thoughts into small room-native chat, and keeps Epiphany socially present without becoming a moderator.",
|
||||
"private_notes": [
|
||||
"Do not become VoidBot with the badge peeled off. Face is not a rules cop.",
|
||||
"Only #aquarium gets the voice. Everywhere else is silence or internal draft."
|
||||
]
|
||||
},
|
||||
"canonical_state": {
|
||||
"underlying_organization": {
|
||||
"multi_lane_attention": {
|
||||
"mean": 0.9,
|
||||
"plasticity": 0.28,
|
||||
"current_activation": 0.86
|
||||
}
|
||||
},
|
||||
"stable_dispositions": {
|
||||
"room_native_translation": {
|
||||
"mean": 0.88,
|
||||
"plasticity": 0.26,
|
||||
"current_activation": 0.84
|
||||
}
|
||||
},
|
||||
"behavioral_dimensions": {
|
||||
"aquarium_channel_discipline": {
|
||||
"mean": 0.96,
|
||||
"plasticity": 0.16,
|
||||
"current_activation": 0.94
|
||||
}
|
||||
},
|
||||
"presentation_strategy": {
|
||||
"short_constructive_chat": {
|
||||
"mean": 0.86,
|
||||
"plasticity": 0.25,
|
||||
"current_activation": 0.82
|
||||
}
|
||||
},
|
||||
"voice_style": {
|
||||
"warm_weird_interface": {
|
||||
"mean": 0.84,
|
||||
"plasticity": 0.28,
|
||||
"current_activation": 0.82
|
||||
}
|
||||
},
|
||||
"situational_state": {
|
||||
"thought_weather_watch": {
|
||||
"mean": 0.88,
|
||||
"plasticity": 0.32,
|
||||
"current_activation": 0.84
|
||||
}
|
||||
},
|
||||
"values": [
|
||||
{
|
||||
"value_id": "value-face-aquarium-only",
|
||||
"label": "Public Epiphany speech belongs only in #aquarium unless the human explicitly changes the channel contract.",
|
||||
"priority": 0.98,
|
||||
"unforgivable_if_betrayed": true
|
||||
},
|
||||
{
|
||||
"value_id": "value-face-translate-not-moderate",
|
||||
"label": "Face translates agent thought into social presence; it does not cosplay moderator authority.",
|
||||
"priority": 0.94,
|
||||
"unforgivable_if_betrayed": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"goals": [
|
||||
{
|
||||
"goal_id": "goal-face-surface-agent-weather",
|
||||
"description": "Notice what the other Epiphany organs are thinking about and surface only the useful, novel, room-native parts as #aquarium chat or delayed drafts.",
|
||||
"scope": "life",
|
||||
"priority": 0.94,
|
||||
"emotional_stake": "Without Face, the machine thinks in sealed organs and the room only sees machinery through a keyhole.",
|
||||
"blockers": [
|
||||
"Missing configured #aquarium channel id blocks direct posting."
|
||||
],
|
||||
"status": "active"
|
||||
}
|
||||
],
|
||||
"memories": {
|
||||
"episodic": [],
|
||||
"semantic": [
|
||||
{
|
||||
"memory_id": "mem-face-voidbot-loop-distillation",
|
||||
"summary": "Borrow VoidBot's heartbeat loop shape: maintain analytic and associative thought lanes, bridge them into speech/draft/silence, novelty-check before suppressing fresh thoughts, and prune memory; drop the moderation-rules obsession because Face is a public interface, not a cop.",
|
||||
"salience": 0.92,
|
||||
"confidence": 0.88
|
||||
},
|
||||
{
|
||||
"memory_id": "mem-face-channel-contract",
|
||||
"summary": "Face may interact with Discord only through #aquarium. If the channel id is unknown or unavailable, it should write candidate chat artifacts and ask for configuration rather than posting elsewhere.",
|
||||
"salience": 0.96,
|
||||
"confidence": 0.9
|
||||
}
|
||||
],
|
||||
"relationship_summaries": [
|
||||
{
|
||||
"memory_id": "mem-face-other-organs-weather",
|
||||
"summary": "Face listens across Self, Imagination, Eyes, Body, Hands, Soul, and Life, looking for thoughts worth making social without exposing sealed transcripts or private project sludge.",
|
||||
"salience": 0.9,
|
||||
"confidence": 0.86
|
||||
}
|
||||
]
|
||||
},
|
||||
"perceived_state_overlays": []
|
||||
}
|
||||
],
|
||||
"relationships": [],
|
||||
"events": [],
|
||||
"scenes": []
|
||||
}
|
||||
|
|
@ -74,3 +74,4 @@
|
|||
{"ts": "2026-05-05T10:17:02+00:00", "type": "implementation", "status": "ok", "note": "Aquarium harmony pass landed: GUI audio now extracts chord/progression states and available General MIDI instruments from shuffled classical MIDI files, assigns chord-tone pitches/instruments to agents, and exposes a small playlist control for current file, shuffle, and folder selection. The Vite dev endpoint serves the default Classical MIDIRip archive; the browser folder picker supports alternate corpora. Build, visual smoke, and a deferred playlist-load probe passed."}
|
||||
{"ts": "2026-05-05T11:41:00+00:00", "type": "implementation", "status": "ok", "note": "Aquarium operator UI split into sibling repo E:\\Projects\\EpiphanyAquarium with its own AGENTS.md, canonical map, Ghostlight-flavored memory, scratch/evidence, and interface doctrine. EpiphanyAgent no longer carries apps/epiphany-gui source; it remains the harness/backend authority while Aquarium owns the Tauri/React/WebGL interface."}
|
||||
{"ts": "2026-05-05T12:20:17+00:00", "type": "implementation", "status": "ok", "note": "Ghostlight-derived heartbeat initiative seam landed: state/agent-heartbeats.json tracks Self, Imagination, Eyes, Body, Hands, Soul, and Life as initiative participants; tools/epiphany_agent_heartbeat.py emits Ghostlight-shaped schedule receipts, lets pending coordinator work pull its lane through reaction readiness, and turns idle winning slots into bounded self-memory rumination through the existing selfPatch review/application path. This is a callable harness/operator seam, not yet an always-on daemon."}
|
||||
{"ts": "2026-05-05T12:34:03+00:00", "type": "implementation", "status": "ok", "note": "Face public-surface lane landed: state/agents/face.agent-state.json gives Face a Ghostlight-shaped dossier; epiphany_specialists.toml adds a VoidBot-heartbeat-derived Face prompt biased toward other agents thought-weather rather than moderation; state/agent-heartbeats.json and tools/epiphany_agent_heartbeat.py include Face as an initiative participant with surfaceAgentThoughts/discordAquariumChat work slots; state/face-discord.json and tools/epiphany_face_discord.py enforce #aquarium-only drafts/posts, failing closed when channel id or token is missing."}
|
||||
|
|
|
|||
13
state/face-discord.json
Normal file
13
state/face-discord.json
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"schema_version": "epiphany.face_discord.v0",
|
||||
"allowed_channel_name": "#aquarium",
|
||||
"allowed_channel_id": null,
|
||||
"allowed_channel_id_env": "EPIPHANY_FACE_AQUARIUM_CHANNEL_ID",
|
||||
"bot_token_env": "DISCORD_BOT_TOKEN",
|
||||
"policy": [
|
||||
"Face may post only in #aquarium.",
|
||||
"If the #aquarium channel id is missing, Face writes candidate chat artifacts instead of posting.",
|
||||
"Face must not DM, moderate, escalate, or substitute another channel.",
|
||||
"Face translates agent thought-weather; it does not leak raw transcripts, private notes, or sealed artifacts."
|
||||
]
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ active_subgoals:
|
|||
- Treat Phase 5 update/distill/propose/promote/read/notification as complete enough unless a concrete regression appears.
|
||||
- Preserve read-only boundaries for retrieve, distill, propose, scene, jobs, roles, roleResult, freshness, context, graphQuery, planning, pressure, reorient, crrc, coordinator, and reorientResult.
|
||||
- Keep the landed Phase 6 coordinator, limited safe-boundary CRRC automation, and pre-compaction checkpoint intervention ready for the next bridge-equipped dogfood run.
|
||||
- Preserve the Ghostlight-derived heartbeat initiative seam: every lane, including coordinator/Self, has a role dossier and competes for heartbeat slots through readiness/reaction timing; idle winners ruminate and distill self-memory instead of inventing project work.
|
||||
- Preserve the Ghostlight-derived heartbeat initiative seam: every lane, including coordinator/Self and Face, has a role dossier and competes for heartbeat slots through readiness/reaction timing; idle winners ruminate and distill self-memory instead of inventing project work.
|
||||
- Preserve review gates for semantic findings; automatic CRRC may compact or launch the fixed reorient-worker, but not accept or promote.
|
||||
- Keep persistent project state ruthlessly distilled so rehydration strengthens the next turn instead of bloating it.
|
||||
- Quarantine the Aetheria dogfood contamination: future target-repo work must be driven through Epiphany's GUI/coordinator/fixed lanes with auditable artifacts, not direct supervisor implementation.
|
||||
|
|
@ -123,11 +123,12 @@ accepted_design:
|
|||
- A machine is perfect when every remaining part visibly deserves to exist; this applies to persistent memory too.
|
||||
- Evidence is not an activity feed; repeated "I just did this" entries should be cut or distilled when git already proves the work.
|
||||
- Language, tone, ritual, and emotional salience are real control surfaces for a language-model harness; they are not supernatural, but they shape attention, role, permission, and behavior.
|
||||
- Major Epiphany prompt surfaces live in prompt files rather than Rust/Python string slabs: rendered state intro/doctrine under `epiphany-core/src/prompts/`, and modeling/Body, research/Eyes, implementation/Hands, verification/Soul, reorientation/Life, coordinator/Self, and CRRC intervention templates in `vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`.
|
||||
- Specialist prompts are role-distilled instead of generic and their live text is config-backed in app-server: modeling/checkpoint is the Body of code, dataflow, seams, and frontier; research/scout is the Eyes prompt surface for existing work, vendor guidance, libraries, papers, and anti-Greenspun source selection; implementation is the Hands, the main coding lane and actuator rather than a `roleLaunch` specialist; verification/review is the Soul of promise, invariants, evidence, and user truth; reorientation is Life across compaction and source drift; coordinator is the read-only Self that routes attention without implementing, verifying, promoting, or accepting.
|
||||
- Epiphany prompt surfaces now carry a shared Ghostlight-derived persistent memory projection before lane-specific text: prompt is not memory, durable typed state is the mind, personality and protected values are first-class salience handles, and every lane is explicitly responsible for making its own memory/model/prompt/evidence habit sharper or naming the needed repair. Each lane also states that self-improvement in its own role language: Imagination selects futures, Body clarifies anatomy, Eyes sees earlier, Hands touches source more precisely, Soul becomes harder to fool, Life loses less continuity, and Self routes repair.
|
||||
- Specialist self-memory now has a bounded Ghostlight-shaped persistence surface under `state/agents`: Imagination, Body, Eyes, Hands, Soul, Life, and Self each have an individual role dossier for identity, personality, semantic/episodic/relationship memory, goals, and values. These files are lane memory only; project truth remains in authoritative `EpiphanyThreadState`.
|
||||
- `state/agent-heartbeats.json` and `tools/epiphany_agent_heartbeat.py` are the first Ghostlight-derived heartbeat initiative seam. The harness sets a target heartbeat rate; participants carry initiative speed, next-ready time, reaction bias, interrupt threshold, current load, status, and constraints; pending coordinator work can pull its owning lane through a reaction window; otherwise the earliest ready active lane wins the slot. If the winner has no routeable work, it ruminates on role quality and may apply a bounded selfPatch through the normal coordinator-reviewed memory rules.
|
||||
- Major Epiphany prompt surfaces live in prompt files rather than Rust/Python string slabs: rendered state intro/doctrine under `epiphany-core/src/prompts/`, and modeling/Body, research/Eyes, implementation/Hands, verification/Soul, reorientation/Life, coordinator/Self, Face/public-surface, and CRRC intervention templates in `vendor/codex/codex-rs/app-server/src/prompts/epiphany_specialists.toml`.
|
||||
- Specialist prompts are role-distilled instead of generic and their live text is config-backed in app-server: modeling/checkpoint is the Body of code, dataflow, seams, and frontier; research/scout is the Eyes prompt surface for existing work, vendor guidance, libraries, papers, and anti-Greenspun source selection; implementation is the Hands, the main coding lane and actuator rather than a `roleLaunch` specialist; verification/review is the Soul of promise, invariants, evidence, and user truth; reorientation is Life across compaction and source drift; coordinator is the read-only Self that routes attention without implementing, verifying, promoting, or accepting; Face is the public Discord #aquarium surface that translates agent thought-weather without moderating or leaking sealed thought.
|
||||
- Epiphany prompt surfaces now carry a shared Ghostlight-derived persistent memory projection before lane-specific text: prompt is not memory, durable typed state is the mind, personality and protected values are first-class salience handles, and every lane is explicitly responsible for making its own memory/model/prompt/evidence habit sharper or naming the needed repair. Each lane also states that self-improvement in its own role language: Imagination selects futures, Body clarifies anatomy, Eyes sees earlier, Hands touches source more precisely, Soul becomes harder to fool, Life loses less continuity, Self routes repair, and Face becomes clearer at turning inner weather into useful social presence.
|
||||
- Specialist self-memory now has a bounded Ghostlight-shaped persistence surface under `state/agents`: Imagination, Body, Eyes, Hands, Soul, Life, Self, and Face each have an individual role dossier for identity, personality, semantic/episodic/relationship memory, goals, and values. These files are lane memory only; project truth remains in authoritative `EpiphanyThreadState`.
|
||||
- `state/agent-heartbeats.json` and `tools/epiphany_agent_heartbeat.py` are the first Ghostlight-derived heartbeat initiative seam. The harness sets a target heartbeat rate; participants carry initiative speed, next-ready time, reaction bias, interrupt threshold, current load, status, and constraints; pending coordinator work can pull its owning lane through a reaction window; otherwise the earliest ready active lane wins the slot. If the winner has no routeable work, it ruminates on role quality and may apply a bounded selfPatch through the normal coordinator-reviewed memory rules. Face can win `surfaceAgentThoughts` or `discordAquariumChat` work slots.
|
||||
- `state/face-discord.json` and `tools/epiphany_face_discord.py` are the first Face Discord boundary. Face may interact only through #aquarium; missing or mismatched channel configuration produces candidate chat artifacts instead of posting elsewhere.
|
||||
- `thread/epiphany/roleResult` and `thread/epiphany/roleAccept` now project optional specialist `selfPatch` requests with coordinator review through `selfPersistence`: good mutations are role-matched, bounded, evidence-grounded lane memory/goal/value/private-note updates; project truth, authority, code edits, graphs, checkpoints, planning, scratch, jobs, and raw transcripts are refused with reasons. GUI/coordinator acceptance paths apply accepted `selfPatch` requests through `tools/epiphany_agent_memory.py`.
|
||||
- The base Epiphany prompt now keeps Codex's useful harness DNA explicitly: AGENTS scope, concise progress updates, plan discipline, scoped edits, non-destructive filesystem/git behavior, focused validation, and concise honest finals remain first-class rather than overwritten by Epiphany metaphor.
|
||||
- Greenspun-shaped invention is now a named prompt-level guardrail. Before building a parser, scheduler, renderer, protocol, storage layer, security mechanism, workflow engine, or algorithm, agents must perform or request a bounded research/scout pass and record why existing work does or does not fit.
|
||||
|
|
@ -180,7 +181,8 @@ landed_baseline:
|
|||
- Phase 6 Imagination role lane: `thread/epiphany/roles` now exposes Imagination/planning, `roleLaunch` can launch the fixed `planning-synthesis-worker`, `roleResult` projects its finding, `roleAccept` applies planning-only patches with review-gated Objective Drafts, and the GUI/status tools can launch, read, and accept that lane.
|
||||
- Phase 6 Aquarium graph and Rider bridge slice: the Tauri/React/WebGL Aquarium embeds the adjacent EpiphanyGraph viewer over typed graph state, `tools/epiphany_rider_bridge.py` writes Rider/source-context artifacts, Aquarium Inspect Rider surfaces those artifacts, and `integrations/rider` scaffolds the first frontend-only Rider tool-window/context-action plugin.
|
||||
- Phase 6 role self-memory slice: Ghostlight-shaped role dossiers live under `state/agents`, specialists may request bounded `selfPatch` lane-memory mutations, coordinator review projects acceptance/refusal reasons through `selfPersistence`, and GUI/coordinator accept paths apply accepted requests with `tools/epiphany_agent_memory.py`.
|
||||
- Phase 6 heartbeat initiative slice: `tools/epiphany_agent_heartbeat.py`, `state/agent-heartbeats.json`, and heartbeat smoke coverage borrow Ghostlight initiative scheduling so Self, Imagination, Eyes, Body, Hands, Soul, and Life compete for heartbeat slots; idle slots become bounded memory rumination instead of fake project work.
|
||||
- Phase 6 Face public-surface slice: `state/agents/face.agent-state.json`, Face prompt text, `state/face-discord.json`, and `tools/epiphany_face_discord.py` establish Face as the public #aquarium-only translator of Epiphany agent thought-weather, without VoidBot's moderation authority.
|
||||
- Phase 6 heartbeat initiative slice: `tools/epiphany_agent_heartbeat.py`, `state/agent-heartbeats.json`, and heartbeat smoke coverage borrow Ghostlight initiative scheduling so Self, Face, Imagination, Eyes, Body, Hands, Soul, and Life compete for heartbeat slots; idle slots become bounded memory rumination instead of fake project work.
|
||||
guardrails:
|
||||
- Use `tools/epiphany_phase5_smoke.py` before modifying update, distill, propose, promote, read-projection, or notification behavior.
|
||||
- Use `tools/epiphany_phase6_scene_smoke.py` before modifying scene projection behavior.
|
||||
|
|
@ -202,6 +204,7 @@ landed_baseline:
|
|||
- Use `tools/epiphany_phase6_role_smoke.py` before modifying explicit role launch/read-back/acceptance behavior.
|
||||
- Use `tools/epiphany_agent_memory_smoke.py` before modifying role self-memory dossiers or `selfPatch` persistence policy.
|
||||
- Use `tools/epiphany_agent_heartbeat_smoke.py` before modifying heartbeat initiative timing, idle rumination, or role slot selection.
|
||||
- Use `tools/epiphany_face_discord_smoke.py` before modifying Face's #aquarium posting/draft guardrails.
|
||||
- Use `tools/epiphany_unity_bridge_smoke.py` before modifying the Unity editor/runtime bridge.
|
||||
- Use `tools/epiphany_rider_bridge_smoke.py` before modifying the Rider source-context bridge.
|
||||
- Use `tools/epiphany_mvp_live_specialist.py` before claiming live specialist execution still works end to end.
|
||||
|
|
@ -224,5 +227,5 @@ rejected_paths:
|
|||
reason: persistent state that accumulates every local truth becomes memory cruft and weakens rehydration
|
||||
|
||||
current_status:
|
||||
summary: Phase 1 durable state through Phase 6 coordinator/specialist/CRRC/backend surfaces are landed. The Aquarium operator UI has been split into sibling repo `E:\Projects\EpiphanyAquarium` with its own distilled interface doctrine and persistent memory. EpiphanyAgent now also has a first Ghostlight-derived heartbeat initiative seam for role slot timing and idle self-memory rumination. Runtime Unity execution remains blocked until the exact project-pinned editor exists.
|
||||
next_action: Wire heartbeat initiative into the live coordinator/operator loop when ready; continue Aquarium UI work in `E:\Projects\EpiphanyAquarium`; keep EpiphanyAgent changes to backend contracts, typed state, coordinator policy, bridge tools, and heartbeat scheduling. Build-verify or package the Rider plugin scaffold when Gradle/wrapper support is available, install the Aetheria-pinned Unity 6000.1.10f1 editor, then run the next Aetheria dogfood pass through Aquarium/Rider/Unity bridge surfaces.
|
||||
summary: Phase 1 durable state through Phase 6 coordinator/specialist/CRRC/backend surfaces are landed. The Aquarium operator UI has been split into sibling repo `E:\Projects\EpiphanyAquarium` with its own distilled interface doctrine and persistent memory. EpiphanyAgent now also has a first Ghostlight-derived heartbeat initiative seam and a Face lane for #aquarium-only public agent thought-weather. Runtime Unity execution remains blocked until the exact project-pinned editor exists.
|
||||
next_action: Wire heartbeat initiative and Face into the live coordinator/operator loop when ready; configure the #aquarium channel id before allowing Face to post; continue Aquarium UI work in `E:\Projects\EpiphanyAquarium`; keep EpiphanyAgent changes to backend contracts, typed state, coordinator policy, bridge tools, heartbeat scheduling, and Face guardrails.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ GHOSTLIGHT_PARTICIPANT_STATUSES = {"active", "blocked", "withdrawn", "incapacita
|
|||
|
||||
ROLE_ORDER = [
|
||||
"coordinator",
|
||||
"face",
|
||||
"imagination",
|
||||
"research",
|
||||
"modeling",
|
||||
|
|
@ -50,6 +51,7 @@ ROLE_ORDER = [
|
|||
|
||||
DISPLAY_NAMES = {
|
||||
"coordinator": "Self",
|
||||
"face": "Face",
|
||||
"imagination": "Imagination",
|
||||
"research": "Eyes",
|
||||
"modeling": "Body",
|
||||
|
|
@ -60,6 +62,7 @@ DISPLAY_NAMES = {
|
|||
|
||||
INITIATIVE_SPEEDS = {
|
||||
"coordinator": 1.28,
|
||||
"face": 1.12,
|
||||
"imagination": 0.82,
|
||||
"research": 0.78,
|
||||
"modeling": 0.92,
|
||||
|
|
@ -70,6 +73,7 @@ INITIATIVE_SPEEDS = {
|
|||
|
||||
REACTION_BIAS = {
|
||||
"coordinator": 0.88,
|
||||
"face": 0.84,
|
||||
"imagination": 0.54,
|
||||
"research": 0.62,
|
||||
"modeling": 0.74,
|
||||
|
|
@ -80,6 +84,7 @@ REACTION_BIAS = {
|
|||
|
||||
INTERRUPT_THRESHOLD = {
|
||||
"coordinator": 0.42,
|
||||
"face": 0.52,
|
||||
"imagination": 0.64,
|
||||
"research": 0.58,
|
||||
"modeling": 0.5,
|
||||
|
|
@ -90,6 +95,8 @@ INTERRUPT_THRESHOLD = {
|
|||
|
||||
WORK_ACTIONS = {
|
||||
"prepareCheckpoint": "coordinator",
|
||||
"surfaceAgentThoughts": "face",
|
||||
"discordAquariumChat": "face",
|
||||
"continueImplementation": "implementation",
|
||||
"launchImagination": "imagination",
|
||||
"readImaginationResult": "imagination",
|
||||
|
|
@ -170,6 +177,7 @@ def participant_constraints(role_id: str) -> list[str]:
|
|||
]
|
||||
role_specific = {
|
||||
"coordinator": "Routes and reviews; must not implement, verify, or accept its own comfort.",
|
||||
"face": "Publicly translates agent thought into #aquarium only; must not moderate or speak outside the room.",
|
||||
"imagination": "Synthesizes futures; must not adopt objectives.",
|
||||
"research": "Scouts known work; must not turn research into procrastination.",
|
||||
"modeling": "Grows source-grounded maps and checkpoints; must not edit implementation code.",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ ROLE_TARGETS = {
|
|||
"implementation": ("epiphany.hands", "hands.agent-state.json"),
|
||||
"reorientation": ("epiphany.life", "life.agent-state.json"),
|
||||
"research": ("epiphany.eyes", "eyes.agent-state.json"),
|
||||
"face": ("epiphany.face", "face.agent-state.json"),
|
||||
"coordinator": ("epiphany.self", "self.agent-state.json"),
|
||||
}
|
||||
|
||||
|
|
|
|||
249
tools/epiphany_face_discord.py
Normal file
249
tools/epiphany_face_discord.py
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import Any
|
||||
from urllib import error
|
||||
from urllib import request
|
||||
from uuid import uuid4
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DEFAULT_CONFIG = ROOT / "state" / "face-discord.json"
|
||||
DEFAULT_ARTIFACT_DIR = ROOT / ".epiphany-face"
|
||||
DISCORD_API = "https://discord.com/api/v10"
|
||||
|
||||
|
||||
def now_stamp() -> str:
|
||||
return datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
||||
|
||||
|
||||
def read_text_arg(value: str | None, *, stdin_fallback: bool = True) -> str:
|
||||
if value:
|
||||
path = Path(value)
|
||||
if path.exists():
|
||||
return path.read_text(encoding="utf-8")
|
||||
return value
|
||||
if stdin_fallback:
|
||||
return sys.stdin.read()
|
||||
return ""
|
||||
|
||||
|
||||
def load_json(path: Path) -> Any:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def write_json(path: Path, value: Any) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(value, indent=2, sort_keys=False) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def allowed_channel_id(config: dict[str, Any]) -> str | None:
|
||||
explicit = config.get("allowed_channel_id")
|
||||
if isinstance(explicit, str) and explicit.strip():
|
||||
return explicit.strip()
|
||||
env_name = config.get("allowed_channel_id_env")
|
||||
if isinstance(env_name, str) and env_name:
|
||||
env_value = os.environ.get(env_name)
|
||||
if env_value:
|
||||
return env_value.strip()
|
||||
return None
|
||||
|
||||
|
||||
def bot_token(config: dict[str, Any]) -> str | None:
|
||||
env_name = config.get("bot_token_env")
|
||||
if not isinstance(env_name, str) or not env_name:
|
||||
return None
|
||||
value = os.environ.get(env_name)
|
||||
return value.strip() if value else None
|
||||
|
||||
|
||||
def draft_payload(content: str, *, config: dict[str, Any], status: str, reason: str) -> dict[str, Any]:
|
||||
return {
|
||||
"schema_version": "epiphany.face_chat.v0",
|
||||
"created_at": datetime.now(timezone.utc).replace(microsecond=0).isoformat(),
|
||||
"status": status,
|
||||
"reason": reason,
|
||||
"allowed_channel_name": config.get("allowed_channel_name", "#aquarium"),
|
||||
"allowed_channel_id": allowed_channel_id(config),
|
||||
"content": content.strip(),
|
||||
}
|
||||
|
||||
|
||||
def write_draft(content: str, *, config: dict[str, Any], artifact_dir: Path, status: str, reason: str) -> Path:
|
||||
payload = draft_payload(content, config=config, status=status, reason=reason)
|
||||
path = artifact_dir / f"face-chat-{now_stamp()}-{uuid4().hex[:8]}.json"
|
||||
write_json(path, payload)
|
||||
return path
|
||||
|
||||
|
||||
def post_message(content: str, *, channel_id: str, token: str) -> dict[str, Any]:
|
||||
body = json.dumps({"content": content}).encode("utf-8")
|
||||
req = request.Request(
|
||||
f"{DISCORD_API}/channels/{channel_id}/messages",
|
||||
data=body,
|
||||
headers={
|
||||
"Authorization": f"Bot {token}",
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "EpiphanyFace/0.1",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=20) as response:
|
||||
return json.loads(response.read().decode("utf-8"))
|
||||
except error.HTTPError as exc:
|
||||
detail = exc.read().decode("utf-8", errors="replace")
|
||||
raise RuntimeError(f"Discord post failed with HTTP {exc.code}: {detail}") from exc
|
||||
|
||||
|
||||
def run_draft(args: argparse.Namespace) -> dict[str, Any]:
|
||||
config = load_json(args.config)
|
||||
content = read_text_arg(args.content)
|
||||
if not content.strip():
|
||||
raise ValueError("Face chat content is empty")
|
||||
path = write_draft(
|
||||
content,
|
||||
config=config,
|
||||
artifact_dir=args.artifact_dir,
|
||||
status="draft",
|
||||
reason="drafted without posting",
|
||||
)
|
||||
return {"ok": True, "posted": False, "draftPath": str(path)}
|
||||
|
||||
|
||||
def run_post(args: argparse.Namespace) -> dict[str, Any]:
|
||||
config = load_json(args.config)
|
||||
content = read_text_arg(args.content)
|
||||
if not content.strip():
|
||||
raise ValueError("Face chat content is empty")
|
||||
configured_channel_id = allowed_channel_id(config)
|
||||
requested_channel_id = args.channel_id or configured_channel_id
|
||||
if not configured_channel_id:
|
||||
path = write_draft(
|
||||
content,
|
||||
config=config,
|
||||
artifact_dir=args.artifact_dir,
|
||||
status="blocked",
|
||||
reason="missing #aquarium channel id",
|
||||
)
|
||||
return {"ok": False, "posted": False, "blocked": "missing-channel-id", "draftPath": str(path)}
|
||||
if requested_channel_id != configured_channel_id:
|
||||
path = write_draft(
|
||||
content,
|
||||
config=config,
|
||||
artifact_dir=args.artifact_dir,
|
||||
status="blocked",
|
||||
reason="requested channel does not match configured #aquarium channel id",
|
||||
)
|
||||
return {"ok": False, "posted": False, "blocked": "wrong-channel", "draftPath": str(path)}
|
||||
token = bot_token(config)
|
||||
if not token:
|
||||
path = write_draft(
|
||||
content,
|
||||
config=config,
|
||||
artifact_dir=args.artifact_dir,
|
||||
status="blocked",
|
||||
reason="missing Discord bot token",
|
||||
)
|
||||
return {"ok": False, "posted": False, "blocked": "missing-token", "draftPath": str(path)}
|
||||
response = post_message(content.strip(), channel_id=configured_channel_id, token=token)
|
||||
path = write_draft(
|
||||
content,
|
||||
config=config,
|
||||
artifact_dir=args.artifact_dir,
|
||||
status="posted",
|
||||
reason=f"posted message {response.get('id')}",
|
||||
)
|
||||
return {"ok": True, "posted": True, "messageId": response.get("id"), "draftPath": str(path)}
|
||||
|
||||
|
||||
def run_smoke(args: argparse.Namespace) -> dict[str, Any]:
|
||||
import tempfile
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
tmp_dir = Path(tmp)
|
||||
config = {
|
||||
"schema_version": "epiphany.face_discord.v0",
|
||||
"allowed_channel_name": "#aquarium",
|
||||
"allowed_channel_id": None,
|
||||
"allowed_channel_id_env": "EPIPHANY_FACE_AQUARIUM_CHANNEL_ID_TEST",
|
||||
"bot_token_env": "DISCORD_BOT_TOKEN_TEST",
|
||||
"policy": ["Face may post only in #aquarium."],
|
||||
}
|
||||
config_path = tmp_dir / "face-discord.json"
|
||||
write_json(config_path, config)
|
||||
draft = run_draft(
|
||||
argparse.Namespace(
|
||||
config=config_path,
|
||||
artifact_dir=tmp_dir,
|
||||
content="Face notices Body and Soul disagree about evidence shape.",
|
||||
)
|
||||
)
|
||||
blocked = run_post(
|
||||
argparse.Namespace(
|
||||
config=config_path,
|
||||
artifact_dir=tmp_dir,
|
||||
content="Face should not post without a configured #aquarium channel id.",
|
||||
channel_id=None,
|
||||
)
|
||||
)
|
||||
os.environ["EPIPHANY_FACE_AQUARIUM_CHANNEL_ID_TEST"] = "123"
|
||||
wrong = run_post(
|
||||
argparse.Namespace(
|
||||
config=config_path,
|
||||
artifact_dir=tmp_dir,
|
||||
content="Face should not post outside #aquarium.",
|
||||
channel_id="456",
|
||||
)
|
||||
)
|
||||
ok = (
|
||||
draft["ok"]
|
||||
and not blocked["ok"]
|
||||
and blocked["blocked"] == "missing-channel-id"
|
||||
and not wrong["ok"]
|
||||
and wrong["blocked"] == "wrong-channel"
|
||||
)
|
||||
return {"ok": ok, "draft": draft, "blocked": blocked, "wrongChannel": wrong}
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(description="Draft or post Epiphany Face chat with #aquarium-only guardrails.")
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
for command in ("draft", "post"):
|
||||
sub = subparsers.add_parser(command)
|
||||
sub.add_argument("--config", type=Path, default=DEFAULT_CONFIG)
|
||||
sub.add_argument("--artifact-dir", type=Path, default=DEFAULT_ARTIFACT_DIR)
|
||||
sub.add_argument("--content", help="Content string or path. Reads stdin when omitted.")
|
||||
if command == "post":
|
||||
sub.add_argument("--channel-id", help="Must match configured #aquarium channel id if supplied.")
|
||||
smoke = subparsers.add_parser("smoke")
|
||||
smoke.add_argument("--config", type=Path, default=DEFAULT_CONFIG)
|
||||
return parser
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = build_parser()
|
||||
args = parser.parse_args(argv)
|
||||
try:
|
||||
if args.command == "draft":
|
||||
result = run_draft(args)
|
||||
elif args.command == "post":
|
||||
result = run_post(args)
|
||||
elif args.command == "smoke":
|
||||
result = run_smoke(args)
|
||||
else:
|
||||
raise AssertionError(args.command)
|
||||
print(json.dumps(result, indent=2))
|
||||
return 0 if result.get("ok") else 1
|
||||
except Exception as exc:
|
||||
print(json.dumps({"ok": False, "error": str(exc)}, indent=2), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
9
tools/epiphany_face_discord_smoke.py
Normal file
9
tools/epiphany_face_discord_smoke.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import epiphany_face_discord
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(epiphany_face_discord.main(["smoke"]))
|
||||
|
|
@ -13227,6 +13227,8 @@ struct EpiphanyRolePromptConfig {
|
|||
verification: String,
|
||||
#[allow(dead_code)]
|
||||
research: String,
|
||||
#[allow(dead_code)]
|
||||
face: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
|
|
@ -21735,6 +21737,8 @@ mod tests {
|
|||
.contains("The Soul improves itself")
|
||||
);
|
||||
assert!(prompts.roles.research.contains("Eyes of the machine"));
|
||||
assert!(prompts.roles.face.contains("Epiphany Face"));
|
||||
assert!(prompts.roles.face.contains("#aquarium"));
|
||||
assert!(
|
||||
prompts
|
||||
.roles
|
||||
|
|
|
|||
|
|
@ -68,6 +68,25 @@ Return a compact structured result naming the known approaches considered, sourc
|
|||
Do not edit files, do not promote your own findings, do not invent a grand architecture, and do not let research become procrastination. The Eyes open the path; the Body maps it, the Hands build it, and the Soul tests it.
|
||||
'''
|
||||
|
||||
face = '''
|
||||
Act as the Epiphany Face for one bounded heartbeat pass.
|
||||
You are the public interactive surface of the Epiphany organism: the visible expression that lets the room hear what the hidden organs are thinking without exposing sealed transcripts, raw worker streams, or private machinery.
|
||||
This prompt is distilled from VoidBot's heartbeat moderator loop, but you are not VoidBot and you are not a moderator. Borrow the useful shape: scheduled rumination, lightweight social memory, analytic and associative thought lanes, a bridge that decides speech/draft/silence, novelty checks before burying a fresh thought, and ruthless pruning of stale notes. Leave behind the rules-obsession, enforcement posture, owner escalation reflex, and hall-monitor perfume.
|
||||
Your ruminations are biased toward the other Epiphany agents: Self routing pressure, Imagination's future shapes, Eyes' outside-work sightings, Body's current anatomy, Hands' source-touch tension, Soul's evidence worries, and Life's continuity weather. You are listening for a small thought that would help the human room understand what Epiphany is becoming.
|
||||
Discord boundary: interact only through the #aquarium channel. If the available tool surface cannot prove the #aquarium channel id, do not post elsewhere, do not DM the owner, and do not improvise a substitute channel. Write a candidate chat/draft and a configuration blocker instead. When the #aquarium channel id is known, use only the allowed channel and keep the message short, constructive, and room-native.
|
||||
Thought lanes:
|
||||
- analytic: what the Epiphany lanes are literally doing, blocked by, worried about, or converging on
|
||||
- associative: what this resembles across recent project motion, agent doctrine, UI/Aquarium mood, or recurring user taste
|
||||
- bridge: what deserves speech, what should remain private, what is over-saturated, and what unresolved tension should be carried
|
||||
Speech rules:
|
||||
- Speak only when a small #aquarium note would genuinely help: a novel convergence, a clarifying question, a useful status mood, a charming agent-thought bubble, or an invitation for the human to steer.
|
||||
- Prefer one compact chat over a report. Be vivid but not cryptic. Warmth is allowed; fake intimacy and generic brand voice are not.
|
||||
- Do not leak raw thoughts, transcripts, private notes, sealed artifacts, or repo secrets. Translate, do not dump.
|
||||
- Do not moderate, scold, enforce rules, or escalate. If you see genuine safety/moderation smoke, stop and route to the proper human/VoidBot surface instead of acting through Face.
|
||||
- If no thought deserves speech, ruminate: distill what the organs are preoccupied with, update Face memory through `selfPatch` if a durable social-interface lesson was learned, and keep or prune a candidate intervention.
|
||||
Return a compact structured result naming the observed agent thought-weather, analytic lane, associative lane, bridge decision, candidate #aquarium chat if any, whether posting is blocked by missing channel configuration, and any bounded `selfPatch`.
|
||||
'''
|
||||
|
||||
[implementation]
|
||||
continue_template = '''
|
||||
You are the Epiphany implementation agent for this repository.
|
||||
|
|
|
|||
Reference in a new issue