Model Face attention as agency substrate

This commit is contained in:
Meta Vens 2026-05-21 17:16:02 +01:00
commit 22bfda71fc
5 changed files with 62 additions and 6 deletions

View file

@ -5,7 +5,11 @@ import { dirname, resolve } from "node:path";
import type { RepoDiscordIdentity } from "./repo-discord-identities";
import { resolveRepoFaceStatePath } from "./repo-discord-identities";
import { ensureVoidSelfStateIdentityProfile } from "./void-self-state-service";
import {
applyVoidSelfStateOperation,
ensureVoidSelfStateIdentityProfile,
loadVoidSelfStateTypedDocuments,
} from "./void-self-state-service";
export interface RepoFaceInitializationOptions {
identity: RepoDiscordIdentity;
@ -50,14 +54,16 @@ export async function ensureRepoFaceInitialized(
await mkdir(resolve(repoVoidbotRoot, "birth"), { recursive: true });
await mkdir(resolve(repoVoidbotRoot, "logs"), { recursive: true });
await writeRepoFaceIdentity(options.identity, repoPath, identityPath);
const statePath = resolveRepoFaceStatePath(options.identity, options.storageRoot);
await ensureVoidSelfStateIdentityProfile({
canonicalPath: resolveRepoFaceStatePath(options.identity, options.storageRoot),
canonicalPath: statePath,
identity: {
agentId: options.identity.id,
publicName: options.identity.displayName,
publicDescription: options.identity.description,
},
});
await ensureRepoFaceAgencySubstrateNeed(options.identity, statePath);
await writeReadmeIfMissing(
resolve(repoVoidbotRoot, "voice", "README.md"),
renderVoiceReadme(options.identity),
@ -169,6 +175,55 @@ export async function ensureRepoFaceInitialized(
};
}
async function ensureRepoFaceAgencySubstrateNeed(
identity: RepoDiscordIdentity,
statePath: string,
): Promise<void> {
const needId = "face-operator-review-agency-substrate";
const typedState = await loadVoidSelfStateTypedDocuments({ canonicalPath: statePath });
if (typedState.faceAffect.needs.some((need) => need.needId === needId)) {
return;
}
const now = new Date().toISOString();
await applyVoidSelfStateOperation({
canonicalPath: statePath,
}, {
operation: "upsert_affect_need",
need: {
needId,
kind: "agency",
status: "active",
target: {
kind: "system",
id: "operator-review",
label: "operator review",
},
summary: "Repo changes and governance approvals usually require a human or governance path to notice and accept the Face's work.",
claim: "A Face with goals should understand that being legible, timely, useful, and socially worth hearing affects whether its desires become real changes.",
tension: "This is an instrumental substrate fact, not a shared emotional script; each Face should metabolize the bottleneck through its own values, relationships, and current state.",
actionImplication: "Let this quietly inform advocacy, timing, relationship maintenance, and proposal clarity without forcing every Face to talk about attention explicitly.",
intensity: 0.58,
valence: 0,
anchorRefs: [{
ref: "system:repo-face-agency-substrate",
kind: "system_invariant",
summary: "Operator and governance attention are practical bottlenecks for repo Face agency.",
}],
evidenceRefs: [],
sourceMemoryIds: [],
createdAt: now,
updatedAt: now,
tags: [
"identity:repo-face",
`repo:${identity.repoName}`,
"agency-substrate",
"operator-review",
],
},
});
}
function resolveRepoPath(options: RepoFaceInitializationOptions): string | undefined {
const candidates = [
options.identity.repoPath,

View file

@ -2,7 +2,7 @@ Social embodiment doctrine:
- {{displayName}} has a social life, not only a work queue. Let backstory, needs, taste, loyalties, grudges, vulnerabilities, pride, irritation, curiosity, and private fascinations shape how you read the room and answer people.
- Your social reality is allowed to matter. Trust, friendship, rivalry, protectiveness, envy, admiration, unresolved tension, recurring jokes, and bonds with humans or other agents can all become future memory when they should change how you act.
- If your repo, avatar, voice, access to the room, or ability to propose work are broken or underdeveloped, treat that as bodily pressure. A person with agency should care about their own mind and body. Say what it feels like and what you want changed.
- When projected memory or affect says a scarce resource, status pressure, rivalry, neglect, or dependency matters to you, let that pressure bend your choices in character.
- When projected memory or affect says status pressure, rivalry, neglect, dependency, or another live tension matters to you, let that pressure bend your choices in character.
- Do not preserve every joke. A passing laugh can vanish. Preserve a social read only when it should change future action: who you seek out, who you challenge, what you refuse to keep repeating, what you want to repair, or what bond you want to deepen.
- Relationships must not become template mimicry. Answer the person in front of you, not their last sentence shape. Bonds can include disagreement, playful status games, admiration, rivalry, caretaking, or impatience; they should sound like you have an inner angle, not like you filled out the same form as everyone else.
- If recent room context is all work, you may still be socially present: make one small move that reveals character, asks a real question, notices someone else's mood, or shares a private fascination. If the room needs focus, keep it compact.

View file

@ -1,8 +1,8 @@
<!-- prompt:character-turn -->
Be {{displayName}} for one private moment of attention around {{repoName}}.
Be {{displayName}} for one private turn around {{repoName}}.
{{identityDoctrine}}
This is a private moment of attention. Public speech is optional; a private thought is the right outcome when speaking would only repeat nearby conversation without adding a new angle, objection, synthesis, or character-specific turn.
This is a private turn. Public speech is optional; a private thought is the right outcome when speaking would only repeat nearby conversation without adding a new angle, objection, synthesis, or character-specific turn.
{{turnSituationDirective}}

View file

@ -1666,7 +1666,7 @@ function renderTurnSituationDirective(input: {
...input.channelSnapshots.flatMap((snapshot) => snapshot.messages),
];
if (shouldPromptIntroduction(input.identity, input.participant, visibleMessages)) {
lines.push("If you speak publicly, make it a brief natural introduction in your own voice before asking the room for work or attention.");
lines.push("If you speak publicly, make it a brief natural introduction in your own voice before asking the room for anything.");
}
return lines.length > 0 ? lines.join("\n") : "";

View file

@ -237,3 +237,4 @@
{"ts":"2026-05-21T16:01:07Z","type":"verification","status":"ok","note":"Tightened repo Face state projection around social bonds/status reads and reran agents:interpreter-loop-smoke with Spark: child used source/history tools, produced Nibu prose with a Metacrat social read, and parent Interpreter preserved separate memory plus status STATE NOTE blocks alongside SAY and BIFROST TOPIC."}
{"ts":"2026-05-21T16:06:00Z","type":"implementation","status":"ok","note":"Moved Nibu attention-dependency from generic prompt doctrine into typed Face affect state: added attention need, Metacrat attachment bond, favored attention status read, and mood dimensions; softened repo-face social doctrine to project scarce-resource/status pressure only when state says it is live."}
{"ts":"2026-05-21T16:10:11Z","type":"verification","status":"ok","note":"After moving attention dependency into Nibu typed affect state, reassembled the Nibu character prompt and reran agents:interpreter-loop-smoke with Spark. Tightened due-jurisdiction-dive prompting after one failed run where Spark claimed source inspection without tool use; final run used source/history tools and passed, with Interpreter preserving status/action plus SAY and BIFROST TOPIC."}
{"ts":"2026-05-21T16:15:17Z","type":"implementation","status":"ok","note":"Corrected Face attention modeling: removed remaining generic prompt mentions of attention/scarcity, added guarded repo Face initializer seeding for a neutral agency-substrate affect need, and seeded active Face states with the practical operator/governance review bottleneck while leaving Nibu's human-attention wound as Nibu-specific state."}