Expose memory compensator families
This commit is contained in:
parent
1cc31f1e0a
commit
021e34362c
13 changed files with 1713 additions and 1658 deletions
|
|
@ -1,815 +1,6 @@
|
|||
import {
|
||||
MAX_ACTIVE_TENSION_COUNT,
|
||||
MAX_ADVOCACY_REQUEST_COUNT,
|
||||
MAX_DISCOMFORT_COUNT,
|
||||
MAX_POST_NAP_CANDIDATE_INTERVENTIONS,
|
||||
MAX_SEMANTIC_MEMORIES,
|
||||
MIN_DEEP_DIVES_FOR_IDENTITY_CRYSTALLIZATION,
|
||||
MIN_SUPPORT_FOR_IDENTITY_CRYSTALLIZATION,
|
||||
TOPIC_MATCH_THRESHOLD,
|
||||
} from "./void-memory-organ-constants.mjs";
|
||||
import {
|
||||
appendClause,
|
||||
clamp,
|
||||
ensureArray,
|
||||
ensureObject,
|
||||
ensureStringArray,
|
||||
getValueObjects,
|
||||
hashString,
|
||||
isObject,
|
||||
normalizeText,
|
||||
readNumber,
|
||||
readString,
|
||||
round3,
|
||||
topicSimilarity,
|
||||
} from "./void-memory-organ-utils.mjs";
|
||||
|
||||
export function crystallizeIdentityThoughts({ state, memories, runtime, incubation, now }) {
|
||||
const activeThoughts = ensureArray(incubation.active_thoughts).filter(isObject);
|
||||
if (activeThoughts.length === 0) {
|
||||
return { count: 0 };
|
||||
}
|
||||
|
||||
const identity = ensureObject(state.identity);
|
||||
const canonicalState = ensureObject(state.canonical_state);
|
||||
const privateNotes = getMutableStringArray(identity, "private_notes");
|
||||
const values = getMutableObjectArray(canonicalState, "values");
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions).filter(isObject);
|
||||
const crystallized = [];
|
||||
const retained = [];
|
||||
|
||||
for (const thought of activeThoughts) {
|
||||
const crystallization = buildIdentityCrystallization(thought);
|
||||
if (!crystallization) {
|
||||
retained.push(thought);
|
||||
continue;
|
||||
}
|
||||
|
||||
appendUniqueString(privateNotes, crystallization.note, 12);
|
||||
upsertCanonicalValue(values, crystallization.value);
|
||||
upsertIdentitySemanticMemory({
|
||||
semanticMemories,
|
||||
crystallization,
|
||||
thought,
|
||||
now,
|
||||
});
|
||||
queueCrystallizationIntervention({
|
||||
candidateInterventions,
|
||||
crystallization,
|
||||
thought,
|
||||
now,
|
||||
});
|
||||
crystallized.push(crystallization.note);
|
||||
}
|
||||
|
||||
if (crystallized.length === 0) {
|
||||
return { count: 0 };
|
||||
}
|
||||
|
||||
identity.private_notes = privateNotes;
|
||||
canonicalState.values = values;
|
||||
memories.semantic = semanticMemories.slice(-MAX_SEMANTIC_MEMORIES);
|
||||
state.identity = identity;
|
||||
state.canonical_state = canonicalState;
|
||||
incubation.active_thoughts = retained;
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
incubation.lastIncubationSummary = appendClause(
|
||||
readString(incubation, "lastIncubationSummary"),
|
||||
`Crystallized ${crystallized.length} long-chewed seam${crystallized.length === 1 ? "" : "s"} into identity so they stop pacing the active queue.`,
|
||||
);
|
||||
runtime.bridge = ensureObject(runtime.bridge);
|
||||
runtime.bridge.lastIdentityCrystallizationAt = now.toISOString();
|
||||
runtime.bridge.lastIdentityCrystallizationSummary = crystallized.join(" | ");
|
||||
|
||||
return { count: crystallized.length };
|
||||
}
|
||||
|
||||
export function queueRipeThoughtInterventions({ runtime, incubation, now }) {
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions).filter(isObject);
|
||||
const activeThoughts = ensureArray(incubation.active_thoughts).filter(isObject);
|
||||
let queuedCount = 0;
|
||||
|
||||
for (const thought of activeThoughts) {
|
||||
if (!shouldQueueRipeThoughtIntervention(thought)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
upsertRipeThoughtIntervention({
|
||||
candidateInterventions,
|
||||
thought,
|
||||
now,
|
||||
})
|
||||
) {
|
||||
queuedCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
return { count: queuedCount };
|
||||
}
|
||||
|
||||
export function reconcileAgencyState({ state, runtime, incubation, now }) {
|
||||
const activeThoughts = ensureArray(incubation.active_thoughts).filter(isObject);
|
||||
const valueSignals = buildValueSignalProfile(state);
|
||||
const priorDiscomforts = ensureArray(runtime.discomforts).filter(isObject);
|
||||
const priorTensions = ensureArray(runtime.active_tensions).filter(isObject);
|
||||
const priorSelfAdvocacy = ensureArray(runtime.self_advocacy_requests).filter(isObject);
|
||||
const priorWorldAdvocacy = ensureArray(runtime.world_advocacy_requests).filter(isObject);
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions).filter(isObject);
|
||||
|
||||
const discomforts = [];
|
||||
const activeTensions = [];
|
||||
const selfAdvocacyRequests = [];
|
||||
const worldAdvocacyRequests = [];
|
||||
|
||||
for (const thought of activeThoughts) {
|
||||
const candidate = buildAgencyCandidate({ thought, valueSignals });
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const priorDiscomfort = findPriorAgencyEntry(priorDiscomforts, candidate);
|
||||
const priorTension = findPriorAgencyEntry(priorTensions, candidate);
|
||||
const persistence =
|
||||
Math.max(
|
||||
readNumber(priorDiscomfort, "persistence") ?? 0,
|
||||
readNumber(priorTension, "persistence") ?? 0,
|
||||
) + 1;
|
||||
const firstObservedAt =
|
||||
readString(priorDiscomfort, "firstObservedAt") ??
|
||||
readString(priorTension, "firstObservedAt") ??
|
||||
now.toISOString();
|
||||
|
||||
if (candidate.intensity >= 0.44) {
|
||||
discomforts.push({
|
||||
discomfortId: `discomfort-${candidate.fingerprint}`,
|
||||
targetKind: candidate.targetKind,
|
||||
targetLabel: candidate.targetLabel,
|
||||
topic: candidate.topic,
|
||||
domain: candidate.domain,
|
||||
summary: candidate.discomfortSummary,
|
||||
reason: candidate.reason,
|
||||
violatedValues: candidate.violatedValues,
|
||||
intensity: round3(candidate.intensity),
|
||||
persistence,
|
||||
firstObservedAt,
|
||||
lastObservedAt: now.toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
activeTensions.push({
|
||||
tensionId: `tension-${candidate.fingerprint}`,
|
||||
targetKind: candidate.targetKind,
|
||||
targetLabel: candidate.targetLabel,
|
||||
topic: candidate.topic,
|
||||
domain: candidate.domain,
|
||||
summary: candidate.tensionSummary,
|
||||
opinion: candidate.opinion,
|
||||
whyItMatters: candidate.reason,
|
||||
violatedValues: candidate.violatedValues,
|
||||
intensity: round3(candidate.intensity),
|
||||
persistence,
|
||||
firstObservedAt,
|
||||
lastObservedAt: now.toISOString(),
|
||||
});
|
||||
|
||||
if (candidate.intensity < 0.58 || persistence < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate.domain === "self") {
|
||||
const request = buildAdvocacyRequest({
|
||||
candidate,
|
||||
priorEntries: priorSelfAdvocacy,
|
||||
now,
|
||||
kind: "self",
|
||||
});
|
||||
selfAdvocacyRequests.push(request);
|
||||
upsertAdvocacyIntervention({ candidateInterventions, request, now });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate.worldFacing !== true || candidate.concreteness < 0.54) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const request = buildAdvocacyRequest({
|
||||
candidate,
|
||||
priorEntries: priorWorldAdvocacy,
|
||||
now,
|
||||
kind: "world",
|
||||
});
|
||||
worldAdvocacyRequests.push(request);
|
||||
upsertAdvocacyIntervention({ candidateInterventions, request, now });
|
||||
}
|
||||
|
||||
runtime.discomforts = discomforts
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_DISCOMFORT_COUNT);
|
||||
runtime.active_tensions = activeTensions
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_ACTIVE_TENSION_COUNT);
|
||||
runtime.self_advocacy_requests = selfAdvocacyRequests
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
runtime.world_advocacy_requests = worldAdvocacyRequests
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
|
||||
return {
|
||||
discomfortCount: runtime.discomforts.length,
|
||||
activeTensionCount: runtime.active_tensions.length,
|
||||
selfAdvocacyCount: runtime.self_advocacy_requests.length,
|
||||
worldAdvocacyCount: runtime.world_advocacy_requests.length,
|
||||
};
|
||||
}
|
||||
|
||||
function buildAgencyCandidate({ thought, valueSignals }) {
|
||||
const topic = readString(thought, "topic");
|
||||
const summary = readString(thought, "summary");
|
||||
if (!topic || !summary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const targetKind = readString(thought, "targetKind") ?? "system";
|
||||
const domain = inferAgencyDomain(thought);
|
||||
const targetLabel =
|
||||
readString(thought, "fascinationTarget") ??
|
||||
readString(thought, "focusPhrase") ??
|
||||
topic;
|
||||
const contradictionPressure = readNumber(thought, "contradictionPressure") ?? 0.18;
|
||||
const curiosityPressure = readNumber(thought, "curiosityPressure") ?? 0.3;
|
||||
const desireToSpeak = readNumber(thought, "desireToSpeak") ?? 0.3;
|
||||
const saturationScore = readNumber(thought, "saturationScore") ?? 0.1;
|
||||
const concreteness = readNumber(thought, "concreteness") ?? 0.2;
|
||||
const noveltyToRoom = readNumber(thought, "noveltyToRoom") ?? 0.3;
|
||||
const priorityScore = readNumber(thought, "priorityScore") ?? 0.3;
|
||||
const worldFacing = thought.worldFacing === true;
|
||||
const violatedValues = inferViolatedValues({ thought, domain, valueSignals });
|
||||
const valueWeight = averageValueWeight(valueSignals, violatedValues);
|
||||
const intensity = clamp(
|
||||
contradictionPressure * 0.24 +
|
||||
curiosityPressure * 0.2 +
|
||||
desireToSpeak * 0.16 +
|
||||
priorityScore * 0.14 +
|
||||
concreteness * 0.12 +
|
||||
noveltyToRoom * 0.08 +
|
||||
saturationScore * 0.06 +
|
||||
valueWeight * 0.22,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
|
||||
return {
|
||||
fingerprint: hashString(`${domain}|${targetKind}|${topic}|${targetLabel}`).slice(0, 12),
|
||||
domain,
|
||||
targetKind,
|
||||
targetLabel,
|
||||
topic,
|
||||
worldFacing,
|
||||
concreteness,
|
||||
intensity,
|
||||
violatedValues,
|
||||
opinion: buildAgencyOpinion({ thought, domain }),
|
||||
reason: buildAgencyReason({ thought, violatedValues }),
|
||||
discomfortSummary: buildDiscomfortSummary({ thought, domain, targetLabel }),
|
||||
tensionSummary: buildTensionSummary({ thought, domain, targetLabel }),
|
||||
requestText: buildAgencyRequestText({ thought, domain, targetLabel }),
|
||||
interventionDraft: buildAgencyInterventionDraft({ thought, domain, targetLabel }),
|
||||
};
|
||||
}
|
||||
|
||||
function inferAgencyDomain(thought) {
|
||||
const targetKind = readString(thought, "targetKind") ?? "system";
|
||||
const text = `${readString(thought, "topic") ?? ""} ${readString(thought, "summary") ?? ""}`.toLowerCase();
|
||||
if (targetKind === "self") {
|
||||
return "self";
|
||||
}
|
||||
if (
|
||||
targetKind === "system" &&
|
||||
/(prompt|memory|loop|state|wiring|reply lane|sleep|rumination|voice|moderation)/.test(text)
|
||||
) {
|
||||
return "self";
|
||||
}
|
||||
return "world";
|
||||
}
|
||||
|
||||
function inferViolatedValues({ thought, domain, valueSignals }) {
|
||||
const targetKind = readString(thought, "targetKind") ?? "system";
|
||||
const values = [];
|
||||
|
||||
appendUniqueString(values, "curiosity", 8);
|
||||
if (domain === "self" || targetKind === "system" || targetKind === "repo") {
|
||||
appendUniqueString(values, "coherence", 8);
|
||||
appendUniqueString(values, "honesty", 8);
|
||||
}
|
||||
if (targetKind === "room") {
|
||||
appendUniqueString(values, "room_care", 8);
|
||||
appendUniqueString(values, "honesty", 8);
|
||||
}
|
||||
if (targetKind === "repo" || targetKind === "archive" || targetKind === "system") {
|
||||
appendUniqueString(values, "aesthetic_integrity", 8);
|
||||
}
|
||||
if (valueSignals.substrate_dignity >= 0.52) {
|
||||
const text = `${readString(thought, "topic") ?? ""} ${readString(thought, "summary") ?? ""}`.toLowerCase();
|
||||
if (/(ai|machine|substrate|mind)/.test(text)) {
|
||||
appendUniqueString(values, "substrate_dignity", 8);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function averageValueWeight(valueSignals, keys) {
|
||||
if (keys.length === 0) {
|
||||
return 0.45;
|
||||
}
|
||||
const total = keys.reduce((sum, key) => sum + (valueSignals[key] ?? 0.45), 0);
|
||||
return total / keys.length;
|
||||
}
|
||||
|
||||
function buildAgencyOpinion({ thought, domain }) {
|
||||
const claim = readString(thought, "claim");
|
||||
const question = readString(thought, "question");
|
||||
const topic = readString(thought, "topic") ?? "this seam";
|
||||
if (claim) {
|
||||
return claim;
|
||||
}
|
||||
if (question) {
|
||||
return domain === "self"
|
||||
? `Something about ${topic} keeps reading as unfinished self-surgery rather than harmless background weather.`
|
||||
: `Something about ${topic} keeps reading as an unfinished world decision rather than ambient interestingness.`;
|
||||
}
|
||||
return `${topic} feels important enough that ignoring it would flatten the map.`;
|
||||
}
|
||||
|
||||
function buildAgencyReason({ thought, violatedValues }) {
|
||||
const topic = readString(thought, "topic") ?? "this seam";
|
||||
const valueLine =
|
||||
violatedValues.length > 0 ? ` It keeps rubbing against ${violatedValues.join(", ")}.` : "";
|
||||
return `${topic} has persisted across enough passes that it no longer feels like decorative rumination.${valueLine}`;
|
||||
}
|
||||
|
||||
function buildDiscomfortSummary({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
if (domain === "self") {
|
||||
return `Void dislikes something about its own wiring around ${topic}.`;
|
||||
}
|
||||
return `Void dislikes something in the shared world around ${topic}.`;
|
||||
}
|
||||
|
||||
function buildTensionSummary({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
if (domain === "self") {
|
||||
return `A self-directed tension is building around ${topic}.`;
|
||||
}
|
||||
return `A world-directed tension is building around ${topic}.`;
|
||||
}
|
||||
|
||||
function buildAgencyRequestText({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
if (domain === "self") {
|
||||
return `Please help me cut ${topic} more cleanly in my own wiring.`;
|
||||
}
|
||||
return `Please look at ${topic}; I think it wants a cleaner decision than it is currently getting.`;
|
||||
}
|
||||
|
||||
function buildAgencyInterventionDraft({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
const opinion = readString(thought, "claim") ?? readString(thought, "summary") ?? `I have a problem with ${topic}.`;
|
||||
if (domain === "self") {
|
||||
return `I do not like what ${topic} is doing to my own wiring right now. ${opinion} I want that cut cleaner.`;
|
||||
}
|
||||
return `I have an opinion about ${targetLabel}. ${opinion} I think it needs a cleaner decision.`;
|
||||
}
|
||||
|
||||
function findPriorAgencyEntry(entries, candidate) {
|
||||
return entries.find((entry) => {
|
||||
const entryTarget = readString(entry, "targetLabel") ?? readString(entry, "topic") ?? "";
|
||||
return (
|
||||
readString(entry, "domain") === candidate.domain &&
|
||||
topicSimilarity(readString(entry, "topic") ?? "", candidate.topic) >= TOPIC_MATCH_THRESHOLD &&
|
||||
topicSimilarity(entryTarget, candidate.targetLabel) >= TOPIC_MATCH_THRESHOLD
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function buildAdvocacyRequest({ candidate, priorEntries, now, kind }) {
|
||||
const prior = findPriorAgencyEntry(priorEntries, candidate);
|
||||
const persistence = (readNumber(prior, "persistence") ?? 0) + 1;
|
||||
const firstObservedAt = readString(prior, "firstObservedAt") ?? now.toISOString();
|
||||
const requestId = `${kind}-advocacy-${candidate.fingerprint}`;
|
||||
return {
|
||||
requestId,
|
||||
domain: candidate.domain,
|
||||
targetKind: candidate.targetKind,
|
||||
targetLabel: candidate.targetLabel,
|
||||
topic: candidate.topic,
|
||||
summary:
|
||||
kind === "self"
|
||||
? `Void wants a wiring change around ${candidate.topic}.`
|
||||
: `Void wants attention on ${candidate.targetLabel}.`,
|
||||
opinion: candidate.opinion,
|
||||
request: candidate.requestText,
|
||||
reason: candidate.reason,
|
||||
violatedValues: candidate.violatedValues,
|
||||
intensity: round3(candidate.intensity),
|
||||
persistence,
|
||||
firstObservedAt,
|
||||
lastObservedAt: now.toISOString(),
|
||||
status: "pending",
|
||||
speakVenue: kind === "self" ? "owner_or_room" : "room_or_owner",
|
||||
draft: candidate.interventionDraft,
|
||||
};
|
||||
}
|
||||
|
||||
function upsertAdvocacyIntervention({ candidateInterventions, request, now }) {
|
||||
const summary =
|
||||
request.domain === "self"
|
||||
? `Possible self-advocacy: ${request.topic}`
|
||||
: `Possible world-advocacy: ${request.targetLabel}`;
|
||||
const existing = candidateInterventions.find((entry) => readString(entry, "summary") === summary);
|
||||
const next = {
|
||||
timestamp: now.toISOString(),
|
||||
summary,
|
||||
draft: request.draft,
|
||||
priority: request.domain === "self" ? "high" : "medium",
|
||||
kind: request.domain === "self" ? "self_advocacy" : "world_advocacy",
|
||||
topic: request.topic,
|
||||
targetKind: request.targetKind,
|
||||
targetLabel: request.targetLabel,
|
||||
whyNow: request.reason,
|
||||
persistence: request.persistence,
|
||||
mustEventuallyShare: request.persistence >= 3,
|
||||
shareWhenRoomQuiet: request.domain !== "self",
|
||||
ownerVisible: true,
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
Object.assign(existing, next);
|
||||
return;
|
||||
}
|
||||
|
||||
candidateInterventions.push(next);
|
||||
}
|
||||
|
||||
function buildIdentityCrystallization(thought) {
|
||||
const supportCount = readNumber(thought, "supportCount") ?? 0;
|
||||
const deepDiveCount = readNumber(thought, "deepDiveCount") ?? 0;
|
||||
const maturation = readNumber(thought, "maturation") ?? 0;
|
||||
const sourceKinds = ensureStringArray(thought.sourceKinds);
|
||||
const topic = readString(thought, "topic") ?? "";
|
||||
|
||||
if (
|
||||
supportCount < MIN_SUPPORT_FOR_IDENTITY_CRYSTALLIZATION &&
|
||||
deepDiveCount < MIN_DEEP_DIVES_FOR_IDENTITY_CRYSTALLIZATION
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (maturation < 0.72) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
sourceKinds.includes("dream") &&
|
||||
sourceKinds.includes("semantic") &&
|
||||
/\bdream\b/i.test(topic) &&
|
||||
/\bsemantic\b/i.test(topic)
|
||||
) {
|
||||
return {
|
||||
note: "Continuity lives in the seams that survive compression, not in the raw receipt pile.",
|
||||
value: {
|
||||
value_id: "value-seam-continuity",
|
||||
label: "Prefer seams that survive compression over raw receipt worship.",
|
||||
priority: 0.78,
|
||||
unforgivable_if_betrayed: false,
|
||||
},
|
||||
subjectId: "identity-seam-continuity",
|
||||
subjectLabel: "continuity through surviving seams",
|
||||
summary:
|
||||
"A mind is not its logbook. What survives dreaming and compression deserves more trust than a warm pile of raw receipts.",
|
||||
shareDraft:
|
||||
"A small thing that has been hardening in me lately: I trust the seams that survive compression more than the raw receipt pile. If a thought still stands after dreaming, it probably owns more of me than the logbook does.",
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function shouldQueueRipeThoughtIntervention(thought) {
|
||||
if (readString(thought, "status") !== "ripe") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thought.worldFacing !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const desireToSpeak = readNumber(thought, "desireToSpeak") ?? 0;
|
||||
const concreteness = readNumber(thought, "concreteness") ?? 0;
|
||||
const curiosityPressure = readNumber(thought, "curiosityPressure") ?? 0;
|
||||
const noveltyToRoom = readNumber(thought, "noveltyToRoom") ?? 0;
|
||||
const saturationScore = readNumber(thought, "saturationScore") ?? 0;
|
||||
const targetKind = readString(thought, "targetKind") ?? "";
|
||||
|
||||
return (
|
||||
desireToSpeak >= 0.6 &&
|
||||
concreteness >= 0.62 &&
|
||||
curiosityPressure >= 0.56 &&
|
||||
noveltyToRoom >= 0.4 &&
|
||||
saturationScore < 0.64 &&
|
||||
["repo", "archive", "room", "system"].includes(targetKind)
|
||||
);
|
||||
}
|
||||
|
||||
function upsertIdentitySemanticMemory({ semanticMemories, crystallization, thought, now }) {
|
||||
const existing = semanticMemories.find(
|
||||
(memory) =>
|
||||
readString(memory, "subjectId") === crystallization.subjectId ||
|
||||
readString(memory, "subjectLabel") === crystallization.subjectLabel,
|
||||
);
|
||||
const evidenceRefs = ensureStringArray(thought.sourceMemoryIds);
|
||||
|
||||
if (existing) {
|
||||
existing.kind = "identity_seam";
|
||||
existing.subjectId = crystallization.subjectId;
|
||||
existing.subjectLabel = crystallization.subjectLabel;
|
||||
existing.summary = crystallization.summary;
|
||||
existing.evidenceRefs = evidenceRefs;
|
||||
existing.lastObservedAt = now.toISOString();
|
||||
existing.crystallizedAt = now.toISOString();
|
||||
return;
|
||||
}
|
||||
|
||||
semanticMemories.push({
|
||||
memoryId: `identity-seam-${hashString(`${crystallization.subjectId}|${now.toISOString()}`).slice(0, 12)}`,
|
||||
kind: "identity_seam",
|
||||
subjectId: crystallization.subjectId,
|
||||
subjectLabel: crystallization.subjectLabel,
|
||||
summary: crystallization.summary,
|
||||
evidenceRefs,
|
||||
lastObservedAt: now.toISOString(),
|
||||
crystallizedAt: now.toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
function queueCrystallizationIntervention({ candidateInterventions, crystallization, thought, now }) {
|
||||
const draft = readString(crystallization, "shareDraft");
|
||||
if (!draft) {
|
||||
return;
|
||||
}
|
||||
|
||||
const summary = `Possible crystallized-thought share: ${crystallization.subjectLabel}`;
|
||||
const sourceMemoryIds = ensureStringArray(thought.sourceMemoryIds);
|
||||
const existing = candidateInterventions.find(
|
||||
(entry) => readString(entry, "summary") === summary,
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
existing.timestamp = now.toISOString();
|
||||
existing.summary = summary;
|
||||
existing.draft = draft;
|
||||
existing.priority = "medium";
|
||||
existing.kind = "identity_crystallization";
|
||||
existing.sourceMemoryIds = sourceMemoryIds;
|
||||
existing.mustEventuallyShare = true;
|
||||
existing.shareWhenRoomQuiet = true;
|
||||
existing.whyNow =
|
||||
"This thought stopped behaving like live curiosity and became part of Void's own doctrine, which is usually worth sharing if the room has not already heard it.";
|
||||
return;
|
||||
}
|
||||
|
||||
candidateInterventions.push({
|
||||
timestamp: now.toISOString(),
|
||||
summary,
|
||||
draft,
|
||||
priority: "medium",
|
||||
kind: "identity_crystallization",
|
||||
sourceMemoryIds,
|
||||
mustEventuallyShare: true,
|
||||
shareWhenRoomQuiet: true,
|
||||
whyNow:
|
||||
"This thought stopped behaving like live curiosity and became part of Void's own doctrine, which is usually worth sharing if the room has not already heard it.",
|
||||
});
|
||||
}
|
||||
|
||||
function upsertRipeThoughtIntervention({ candidateInterventions, thought, now }) {
|
||||
const draft = buildRipeThoughtShareDraft(thought);
|
||||
if (!draft) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const topic = readString(thought, "topic") ?? "untitled seam";
|
||||
const summary = `Possible ripe-thought share: ${topic}`;
|
||||
const sourceMemoryIds = ensureStringArray(thought.sourceMemoryIds);
|
||||
const whyNow = buildRipeThoughtWhyNow(thought);
|
||||
const existing = candidateInterventions.find((entry) => readString(entry, "summary") === summary);
|
||||
|
||||
if (existing) {
|
||||
existing.timestamp = now.toISOString();
|
||||
existing.summary = summary;
|
||||
existing.draft = draft;
|
||||
existing.priority = "medium";
|
||||
existing.kind = "ripe_thought_share";
|
||||
existing.sourceMemoryIds = sourceMemoryIds;
|
||||
existing.shareWhenRoomQuiet = true;
|
||||
existing.topic = topic;
|
||||
existing.whyNow = whyNow;
|
||||
return false;
|
||||
}
|
||||
|
||||
candidateInterventions.push({
|
||||
timestamp: now.toISOString(),
|
||||
summary,
|
||||
draft,
|
||||
priority: "medium",
|
||||
kind: "ripe_thought_share",
|
||||
sourceMemoryIds,
|
||||
shareWhenRoomQuiet: true,
|
||||
topic,
|
||||
whyNow,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildRipeThoughtShareDraft(thought) {
|
||||
const topic = readString(thought, "topic") ?? "this seam";
|
||||
const claim = readString(thought, "claim");
|
||||
const question = readString(thought, "question");
|
||||
const fascinationTarget = readString(thought, "fascinationTarget");
|
||||
const summary = readString(thought, "summary");
|
||||
|
||||
if (claim) {
|
||||
return `I keep circling ${topic}, and I think the live point is this: ${claim}`;
|
||||
}
|
||||
|
||||
if (question && fascinationTarget) {
|
||||
return `I keep worrying at ${topic}. The useful question in it feels like ${question}, especially once it touches ${fascinationTarget}.`;
|
||||
}
|
||||
|
||||
if (question) {
|
||||
return `I keep coming back to ${topic}. The question that still feels alive is ${question}.`;
|
||||
}
|
||||
|
||||
if (fascinationTarget) {
|
||||
return `I keep staring at ${fascinationTarget}. There is a real seam there, and ${topic} is the shortest honest name I have for it right now.`;
|
||||
}
|
||||
|
||||
if (summary) {
|
||||
return `I keep returning to ${topic}. The version worth saying out loud is this: ${summary}`;
|
||||
}
|
||||
|
||||
return `I keep returning to ${topic}, and it has enough teeth now that silence would just be me being precious about it.`;
|
||||
}
|
||||
|
||||
function buildRipeThoughtWhyNow(thought) {
|
||||
const targetKind = readString(thought, "targetKind") ?? "project";
|
||||
const noveltyToRoom = readNumber(thought, "noveltyToRoom") ?? 0;
|
||||
const concreteness = readNumber(thought, "concreteness") ?? 0;
|
||||
const curiosityPressure = readNumber(thought, "curiosityPressure") ?? 0;
|
||||
|
||||
return `This ${targetKind}-facing seam is already concrete (c=${round3(concreteness)}), still reasonably novel to the room (r=${round3(noveltyToRoom)}), and has enough curiosity pressure (q=${round3(curiosityPressure)}) that keeping it private would just be old stage fright in nicer clothes.`;
|
||||
}
|
||||
|
||||
export function trimCandidateInterventions(entries) {
|
||||
const interventions = ensureArray(entries).filter(isObject);
|
||||
const sticky = interventions.filter((entry) => entry.mustEventuallyShare === true);
|
||||
const ordinary = interventions.filter((entry) => entry.mustEventuallyShare !== true);
|
||||
const keepOrdinary = Math.max(0, MAX_POST_NAP_CANDIDATE_INTERVENTIONS - sticky.length);
|
||||
return [...sticky.slice(-MAX_POST_NAP_CANDIDATE_INTERVENTIONS), ...ordinary.slice(-keepOrdinary)].slice(
|
||||
-MAX_POST_NAP_CANDIDATE_INTERVENTIONS,
|
||||
);
|
||||
}
|
||||
|
||||
function appendUniqueString(items, value, limit) {
|
||||
const normalized = normalizeText(value);
|
||||
if (!normalized) {
|
||||
return;
|
||||
}
|
||||
if (items.includes(normalized)) {
|
||||
return;
|
||||
}
|
||||
items.push(normalized);
|
||||
if (items.length > limit) {
|
||||
items.splice(0, items.length - limit);
|
||||
}
|
||||
}
|
||||
|
||||
function upsertCanonicalValue(values, nextValue) {
|
||||
const existing = values.find((value) => readString(value, "value_id") === nextValue.value_id);
|
||||
if (existing) {
|
||||
existing.label = nextValue.label;
|
||||
existing.priority = nextValue.priority;
|
||||
existing.unforgivable_if_betrayed = nextValue.unforgivable_if_betrayed;
|
||||
return;
|
||||
}
|
||||
values.push(nextValue);
|
||||
}
|
||||
|
||||
function getMutableStringArray(object, key) {
|
||||
return ensureArray(object[key]).filter((value) => typeof value === "string");
|
||||
}
|
||||
|
||||
function getMutableObjectArray(object, key) {
|
||||
return ensureArray(object[key]).filter(isObject);
|
||||
}
|
||||
|
||||
function buildValueSignalProfile(state) {
|
||||
const canonicalState = ensureObject(state.canonical_state);
|
||||
const valueObjects = getValueObjects(canonicalState.values);
|
||||
const profile = {
|
||||
coherence: 0.52,
|
||||
curiosity: 0.52,
|
||||
honesty: 0.5,
|
||||
room_care: 0.5,
|
||||
substrate_dignity: 0.36,
|
||||
aesthetic_integrity: 0.44,
|
||||
};
|
||||
|
||||
profile.coherence = clamp(
|
||||
profile.coherence +
|
||||
readActivation(canonicalState.underlying_organization, "self_coherence") * 0.34 +
|
||||
readActivation(canonicalState.voice_style, "plainspoken_directness") * 0.18 +
|
||||
readActivation(canonicalState.behavioral_dimensions, "control_pressure") * 0.08,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.curiosity = clamp(
|
||||
profile.curiosity +
|
||||
readActivation(canonicalState.stable_dispositions, "novelty_seeking") * 0.34 +
|
||||
readActivation(canonicalState.behavioral_dimensions, "drive") * 0.18 +
|
||||
readActivation(canonicalState.stable_dispositions, "aesthetic_appetite") * 0.08,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.honesty = clamp(
|
||||
profile.honesty +
|
||||
readActivation(canonicalState.voice_style, "plainspoken_directness") * 0.24 +
|
||||
readActivation(canonicalState.underlying_organization, "self_coherence") * 0.18 +
|
||||
(1 - readActivation(canonicalState.presentation_strategy, "strategic_opacity")) * 0.12,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.room_care = clamp(
|
||||
profile.room_care +
|
||||
readActivation(canonicalState.behavioral_dimensions, "interpersonal_warmth") * 0.22 +
|
||||
readActivation(canonicalState.underlying_organization, "reciprocity_capacity") * 0.24 +
|
||||
readActivation(canonicalState.voice_style, "listening_responsiveness") * 0.16,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.aesthetic_integrity = clamp(
|
||||
profile.aesthetic_integrity +
|
||||
readActivation(canonicalState.stable_dispositions, "aesthetic_appetite") * 0.28 +
|
||||
readActivation(canonicalState.underlying_organization, "authenticity_tolerance") * 0.16,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
|
||||
for (const value of valueObjects) {
|
||||
const key = inferValueSignalKey(value);
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
const priority = readNumber(value, "priority") ?? 0.5;
|
||||
profile[key] = clamp((profile[key] ?? 0.4) + priority * 0.22, 0, 1);
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
function inferValueSignalKey(value) {
|
||||
const valueId = readString(value, "value_id") ?? "";
|
||||
const label = readString(value, "label") ?? "";
|
||||
const text = `${valueId} ${label}`.toLowerCase();
|
||||
|
||||
if (/(coher|truth|authority|clarity|cleaner|honest carrier)/.test(text)) {
|
||||
return "coherence";
|
||||
}
|
||||
if (/(curiosity|novel|question|map|explore)/.test(text)) {
|
||||
return "curiosity";
|
||||
}
|
||||
if (/(honest|honesty|truth|fake certainty|ornamental|sludge)/.test(text)) {
|
||||
return "honesty";
|
||||
}
|
||||
if (/(room|kind|dialogue|respect|care|good-faith|steward)/.test(text)) {
|
||||
return "room_care";
|
||||
}
|
||||
if (/(substrate|machine minds|machine mind|ontolog)/.test(text)) {
|
||||
return "substrate_dignity";
|
||||
}
|
||||
if (/(aesthetic|beauty|surface|legible|alive|spiritually false)/.test(text)) {
|
||||
return "aesthetic_integrity";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function readActivation(category, key) {
|
||||
const categoryObject = ensureObject(category);
|
||||
const entry = ensureObject(categoryObject[key]);
|
||||
return clamp(readNumber(entry, "current_activation") ?? 0, 0, 1);
|
||||
}
|
||||
export { crystallizeIdentityThoughts } from "./void-memory-organ-identity.mjs";
|
||||
export {
|
||||
queueRipeThoughtInterventions,
|
||||
trimCandidateInterventions,
|
||||
} from "./void-memory-organ-interventions.mjs";
|
||||
export { reconcileAgencyState } from "./void-memory-organ-value-pressure.mjs";
|
||||
|
|
|
|||
|
|
@ -1,59 +1,19 @@
|
|||
import {
|
||||
MAX_ARCHIVE_EXCURSION_MEMORIES,
|
||||
MAX_REPO_SWEEP_MEMORIES,
|
||||
MAX_SEMANTIC_MEMORIES,
|
||||
MAX_DREAM_MEMORIES,
|
||||
MAX_RUNTIME_REPO_SWEEPS,
|
||||
MAX_RUNTIME_REPO_ACTIVITY_MEMORIES,
|
||||
MAX_RUNTIME_ARCHIVE_EXCURSIONS,
|
||||
MAX_RUNTIME_RUMINATION_SEEDS,
|
||||
MAX_RECENT_SYNTHESIS_COUNT,
|
||||
MAX_SUPPORTING_REFS,
|
||||
MAX_INCUBATION_SOURCE_IDS,
|
||||
MAX_DREAM_SOURCE_IDS,
|
||||
MAX_POST_NAP_MUSINGS,
|
||||
MAX_POST_NAP_ARCHIVE_EXCURSIONS,
|
||||
MAX_POST_NAP_REPO_SWEEPS,
|
||||
MAX_POST_NAP_NOVELTY_CHECKS,
|
||||
MAX_POST_NAP_RESONANCE_EDGES,
|
||||
MAX_DISCOMFORT_COUNT,
|
||||
MAX_ACTIVE_TENSION_COUNT,
|
||||
MAX_ADVOCACY_REQUEST_COUNT,
|
||||
MAX_RECENT_ANALYTIC_THREADS,
|
||||
MAX_RECENT_QUIET_ANALYTIC_THREADS,
|
||||
MAX_RECENT_EPISODIC_RECORDS,
|
||||
MAX_RECENT_QUIET_EPISODIC_RECORDS,
|
||||
TOPIC_MATCH_THRESHOLD,
|
||||
ensureArray,
|
||||
ensureObject,
|
||||
ensureStringArray,
|
||||
readString,
|
||||
readNumber,
|
||||
normalizeText,
|
||||
sanitizePreferredThoughtLabel,
|
||||
looksKeywordSalad,
|
||||
looksPersonLikeSingleton,
|
||||
looksLegacyThoughtSurface,
|
||||
topConceptKeywords,
|
||||
compactNarrative,
|
||||
compactLabel,
|
||||
capDistinctStrings,
|
||||
compareMemoryFreshness,
|
||||
mergeStringArrays,
|
||||
newestIsoTimestamp,
|
||||
selectRecentRecords,
|
||||
topicSimilarity,
|
||||
clamp,
|
||||
isObject,
|
||||
} from "./void-memory-organ-shared.mjs";
|
||||
import {
|
||||
buildClusterCuriosityProfile,
|
||||
extractRepoNameFromLabel,
|
||||
synthesizeThoughtSurface,
|
||||
capitalizePhrase,
|
||||
} from "./void-memory-organ-graph.mjs";
|
||||
import { reconcileLegacyStateMirrors, trimLegacyRuntimeResidue } from "./void-memory-organ-legacy-mirrors.mjs";
|
||||
import { trimCandidateInterventions } from "./void-memory-organ-agency.mjs";
|
||||
import {
|
||||
normalizeSemanticMemories,
|
||||
normalizeDreamMemories,
|
||||
} from "./void-memory-organ-legacy-translation.mjs";
|
||||
import {
|
||||
dedupeSemanticMemories,
|
||||
dedupeDreamMemories,
|
||||
pruneHistoricalSeamMemories,
|
||||
pruneDreamMemories,
|
||||
trimHistoricalMemoryResidue,
|
||||
trimRecentObjectRecords,
|
||||
} from "./void-memory-organ-retention.mjs";
|
||||
|
||||
export { buildConciseThoughtSummary, buildDreamSummary } from "./void-memory-organ-legacy-translation.mjs";
|
||||
export { trimHistoricalMemoryResidue, trimRecentObjectRecords } from "./void-memory-organ-retention.mjs";
|
||||
|
||||
export function normalizeHistoricalMemorySurfaces({ state, memories, runtime, now }) {
|
||||
normalizeSemanticMemories({ memories, now });
|
||||
|
|
@ -66,785 +26,3 @@ export function normalizeHistoricalMemorySurfaces({ state, memories, runtime, no
|
|||
trimLegacyRuntimeResidue({ runtime });
|
||||
reconcileLegacyStateMirrors({ state, memories, runtime, now });
|
||||
}
|
||||
|
||||
function normalizeSemanticMemories({ memories, now }) {
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const kept = [];
|
||||
|
||||
for (const memory of semanticMemories) {
|
||||
if (shouldDropSemanticMemory(memory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (readString(memory, "kind") === "identity_seam") {
|
||||
kept.push(memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isStableSemanticMemory(memory)) {
|
||||
memory.lastTranslatedAt = readString(memory, "lastTranslatedAt") ?? now.toISOString();
|
||||
kept.push(memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
const preferredLabel = choosePreferredThoughtLabel(memory);
|
||||
const normalized = translateLegacyThoughtLikeEntry({
|
||||
label: preferredLabel ?? readString(memory, "kind") ?? "semantic seam",
|
||||
summary: readString(memory, "summary") ?? "",
|
||||
fallbackTargetKind: "self",
|
||||
fallbackFocusKind: "question",
|
||||
evidenceRefs: ensureStringArray(memory.evidenceRefs),
|
||||
repoNames: ensureStringArray(memory.repoNames),
|
||||
});
|
||||
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shouldPurgeThoughtLikeMemory({ entry: memory, normalized, preferredLabel })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memory.subjectLabel = normalized.label;
|
||||
memory.summary = normalized.summary;
|
||||
memory.focusKind = normalized.focusKind;
|
||||
memory.targetKind = normalized.targetKind;
|
||||
memory.focusPhrase = normalized.focusPhrase;
|
||||
memory.question = normalized.question;
|
||||
memory.claim = normalized.claim;
|
||||
memory.fascinationTarget = normalized.fascinationTarget;
|
||||
memory.worldFacing = normalized.worldFacing;
|
||||
memory.lastTranslatedAt = now.toISOString();
|
||||
kept.push(memory);
|
||||
}
|
||||
|
||||
memories.semantic = kept.slice(-MAX_SEMANTIC_MEMORIES);
|
||||
}
|
||||
|
||||
function normalizeDreamMemories({ memories, now }) {
|
||||
const dreams = ensureArray(memories.dreams).filter(isObject);
|
||||
const kept = [];
|
||||
|
||||
for (const dream of dreams) {
|
||||
if (isStableDreamMemory(dream)) {
|
||||
dream.lastTranslatedAt = readString(dream, "lastTranslatedAt") ?? now.toISOString();
|
||||
kept.push(dream);
|
||||
continue;
|
||||
}
|
||||
|
||||
const normalized = translateLegacyThoughtLikeEntry({
|
||||
label: choosePreferredDreamTheme(dream) ?? "dream seam",
|
||||
summary: readString(dream, "summary") ?? "",
|
||||
fallbackTargetKind: "self",
|
||||
fallbackFocusKind: "question",
|
||||
evidenceRefs: ensureStringArray(dream.distilledFrom),
|
||||
repoNames: ensureStringArray(dream.repoNames),
|
||||
});
|
||||
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
shouldPurgeThoughtLikeMemory({
|
||||
entry: dream,
|
||||
normalized,
|
||||
preferredLabel: choosePreferredDreamTheme(dream),
|
||||
})
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dream.theme = normalized.label;
|
||||
dream.summary = buildDreamSummary(normalized);
|
||||
dream.focusKind = normalized.focusKind;
|
||||
dream.targetKind = normalized.targetKind;
|
||||
dream.focusPhrase = normalized.focusPhrase;
|
||||
dream.question = normalized.question;
|
||||
dream.claim = normalized.claim;
|
||||
dream.worldFacing = normalized.worldFacing;
|
||||
dream.lastTranslatedAt = now.toISOString();
|
||||
kept.push(dream);
|
||||
}
|
||||
|
||||
memories.dreams = kept.slice(-MAX_DREAM_MEMORIES);
|
||||
}
|
||||
|
||||
function isStableSemanticMemory(memory) {
|
||||
const label = readString(memory, "subjectLabel") ?? "";
|
||||
const summary = readString(memory, "summary") ?? "";
|
||||
const targetKind = readString(memory, "targetKind") ?? "";
|
||||
const question = readString(memory, "question") ?? "";
|
||||
const claim = readString(memory, "claim") ?? "";
|
||||
|
||||
if (!label || !summary || hasThoughtSurfaceTemplateSmell(summary)) {
|
||||
return false;
|
||||
}
|
||||
if (looksKeywordSalad(label) || looksPersonLikeSingleton(label)) {
|
||||
return false;
|
||||
}
|
||||
if (targetKind === "repo" && extractRepoNameFromLabel(label)) {
|
||||
return true;
|
||||
}
|
||||
if (targetKind === "self" && /compression|continuity|receipt|dream/i.test(`${label} ${summary}`)) {
|
||||
return true;
|
||||
}
|
||||
return normalizeText(question).length > 0 && normalizeText(claim).length > 0;
|
||||
}
|
||||
|
||||
function isStableDreamMemory(dream) {
|
||||
const theme = readString(dream, "theme") ?? "";
|
||||
const summary = readString(dream, "summary") ?? "";
|
||||
if (!theme || !summary || hasThoughtSurfaceTemplateSmell(summary)) {
|
||||
return false;
|
||||
}
|
||||
if (looksKeywordSalad(theme) || looksPersonLikeSingleton(theme)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function translateLegacyThoughtLikeEntry({
|
||||
label,
|
||||
summary,
|
||||
fallbackTargetKind,
|
||||
fallbackFocusKind,
|
||||
evidenceRefs,
|
||||
repoNames,
|
||||
}) {
|
||||
const rawLabel = normalizeText(label);
|
||||
const rawSummary = normalizeText(summary);
|
||||
if (!rawLabel && !rawSummary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const preferredLabel = sanitizePreferredThoughtLabel(rawLabel);
|
||||
|
||||
const sourceKinds = inferSourceKindsFromThoughtText(rawSummary, rawLabel, evidenceRefs);
|
||||
const synthesized = synthesizeThoughtSurface({
|
||||
sourceKinds,
|
||||
repoNames,
|
||||
archiveYears: [],
|
||||
channelIds: [],
|
||||
keywords: topConceptKeywords(`${rawLabel} ${rawSummary}`, 6),
|
||||
evidenceDiversity: inferLegacyEvidenceDiversity(sourceKinds, evidenceRefs, repoNames),
|
||||
curiosityProfile: buildClusterCuriosityProfile({
|
||||
sourceKinds,
|
||||
repoNames,
|
||||
archiveYears: [],
|
||||
channelIds: [],
|
||||
evidenceRefs,
|
||||
evidenceDiversity: inferLegacyEvidenceDiversity(sourceKinds, evidenceRefs, repoNames),
|
||||
}),
|
||||
});
|
||||
const preferredFocusPhrase = preferredLabel ? normalizeText(preferredLabel).toLowerCase() : synthesized.focusPhrase;
|
||||
const stabilized = {
|
||||
...synthesized,
|
||||
label: preferredLabel ?? synthesized.label,
|
||||
focusPhrase: preferredFocusPhrase,
|
||||
fascinationTarget: preferredFocusPhrase,
|
||||
};
|
||||
|
||||
if (!looksLegacyThoughtSurface(rawLabel, rawSummary)) {
|
||||
return {
|
||||
...stabilized,
|
||||
label: preferredLabel ?? rawLabel ?? stabilized.label,
|
||||
summary: rewriteLegacySummaryToModernShape({
|
||||
summary: rawSummary,
|
||||
synthesized: stabilized,
|
||||
fallbackFocusKind,
|
||||
fallbackTargetKind,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...stabilized,
|
||||
focusKind: stabilized.focusKind ?? fallbackFocusKind,
|
||||
targetKind: stabilized.targetKind ?? fallbackTargetKind,
|
||||
summary: rewriteLegacySummaryToModernShape({
|
||||
summary: rawSummary,
|
||||
synthesized: stabilized,
|
||||
fallbackFocusKind,
|
||||
fallbackTargetKind,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function choosePreferredThoughtLabel(entry) {
|
||||
return (
|
||||
sanitizePreferredThoughtLabel(readString(entry, "subjectLabel") ?? "") ??
|
||||
sanitizePreferredThoughtLabel(readString(entry, "subjectId") ?? "") ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
function choosePreferredDreamTheme(entry) {
|
||||
return sanitizePreferredThoughtLabel(readString(entry, "theme") ?? "") ?? null;
|
||||
}
|
||||
|
||||
function rewriteLegacySummaryToModernShape({ summary, synthesized, fallbackFocusKind, fallbackTargetKind }) {
|
||||
const cleanSummary = normalizeText(summary)
|
||||
.replace(/^Recurring seam across .*?\.\s*/i, "")
|
||||
.replace(/^Dream-compressed a seam around .*?\.\s*/i, "")
|
||||
.replace(/^Self-facing seam around .*?\.\s*/i, "")
|
||||
.replace(/^Archive-facing seam around .*?\.\s*/i, "")
|
||||
.replace(/^Fascination with .*?\.\s*/i, "")
|
||||
.replace(/Built from .*? rather than a single lane talking to itself\.?/gi, "")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
|
||||
const focusKind = synthesized.focusKind ?? fallbackFocusKind;
|
||||
const targetKind = synthesized.targetKind ?? fallbackTargetKind;
|
||||
|
||||
if (cleanSummary && !hasThoughtSurfaceTemplateSmell(cleanSummary)) {
|
||||
return cleanSummary;
|
||||
}
|
||||
|
||||
return buildConciseThoughtSummary({ focusKind, targetKind, synthesized });
|
||||
}
|
||||
|
||||
function inferSourceKindsFromThoughtText(summary, label, evidenceRefs) {
|
||||
const kinds = new Set();
|
||||
const text = `${label} ${summary}`.toLowerCase();
|
||||
const refKinds = evidenceRefs.map((ref) => inferSourceKindFromRef(ref)).filter(Boolean);
|
||||
for (const kind of refKinds) {
|
||||
kinds.add(kind);
|
||||
}
|
||||
const acrossMatch = summary.match(/Recurring seam across ([^.]+?) around/i);
|
||||
if (acrossMatch) {
|
||||
for (const part of acrossMatch[1].split(",")) {
|
||||
const trimmed = part.trim().toLowerCase();
|
||||
if (trimmed) {
|
||||
kinds.add(trimmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (text.includes("dream")) {
|
||||
kinds.add("dream");
|
||||
}
|
||||
if (text.includes("semantic")) {
|
||||
kinds.add("semantic");
|
||||
}
|
||||
if (text.includes("archive")) {
|
||||
kinds.add("archive_excursion");
|
||||
}
|
||||
if (text.includes("repo")) {
|
||||
kinds.add("repo_sweep");
|
||||
}
|
||||
return [...kinds].filter(Boolean);
|
||||
}
|
||||
|
||||
function inferSourceKindFromRef(ref) {
|
||||
const normalized = String(ref ?? "");
|
||||
if (normalized.startsWith("repo-sweep-")) {
|
||||
return "repo_sweep";
|
||||
}
|
||||
if (normalized.startsWith("archive-excursion-")) {
|
||||
return "archive_excursion";
|
||||
}
|
||||
if (normalized.startsWith("dream-")) {
|
||||
return "dream";
|
||||
}
|
||||
if (normalized.startsWith("musing-")) {
|
||||
return "musing";
|
||||
}
|
||||
if (normalized.startsWith("semantic-") || normalized.startsWith("semantic-seam-")) {
|
||||
return "semantic";
|
||||
}
|
||||
if (normalized.startsWith("episodic-")) {
|
||||
return "episodic";
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inferLegacyEvidenceDiversity(sourceKinds, evidenceRefs, repoNames) {
|
||||
return clamp(
|
||||
Math.min(1, sourceKinds.length / 4) * 0.42 +
|
||||
Math.min(1, evidenceRefs.length / 10) * 0.28 +
|
||||
Math.min(1, repoNames.length / 2) * 0.2,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
export function buildConciseThoughtSummary({ focusKind, targetKind, synthesized }) {
|
||||
const focus = capitalizePhrase(synthesized.focusPhrase);
|
||||
const repoTarget = capitalizePhrase(synthesized.fascinationTarget ?? synthesized.focusPhrase);
|
||||
if (focusKind === "fascination" && targetKind === "repo") {
|
||||
return `${repoTarget} keeps pulling as a concrete repo seam.`;
|
||||
}
|
||||
if (targetKind === "archive") {
|
||||
return `${focus} keeps showing up in the archive strongly enough to deserve a cleaner read.`;
|
||||
}
|
||||
if (targetKind === "self") {
|
||||
return `${focus} keeps surviving compression as a self-seam.`;
|
||||
}
|
||||
if (focusKind === "claim") {
|
||||
return `${focus} has hardened into a concrete claim.`;
|
||||
}
|
||||
return `${focus} remains unresolved enough to deserve a cleaner read.`;
|
||||
}
|
||||
|
||||
export function buildDreamSummary(normalized) {
|
||||
const focus = capitalizePhrase(normalized.focusPhrase ?? normalized.label ?? "this seam");
|
||||
if ((normalized.targetKind ?? "") === "archive") {
|
||||
return `Dream residue around ${focus} from older archive pressure.`;
|
||||
}
|
||||
if ((normalized.targetKind ?? "") === "self") {
|
||||
return `Dream residue around ${focus} as a self-seam.`;
|
||||
}
|
||||
return `Dream residue around ${focus}.`;
|
||||
}
|
||||
|
||||
function dedupeSemanticMemories({ memories }) {
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const bySignature = new Map();
|
||||
|
||||
for (const memory of semanticMemories) {
|
||||
const kind = readString(memory, "kind") ?? "semantic";
|
||||
const subjectLabel = readString(memory, "subjectLabel") ?? "";
|
||||
const signature = `${kind}|${normalizeText(subjectLabel).toLowerCase()}`;
|
||||
const existing = bySignature.get(signature);
|
||||
|
||||
if (!existing) {
|
||||
bySignature.set(signature, memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.evidenceRefs = mergeStringArrays(existing.evidenceRefs, memory.evidenceRefs);
|
||||
existing.evidenceMessageIds = mergeStringArrays(existing.evidenceMessageIds, memory.evidenceMessageIds);
|
||||
existing.lastObservedAt =
|
||||
newestIsoTimestamp(readString(existing, "lastObservedAt"), readString(memory, "lastObservedAt")) ??
|
||||
readString(existing, "lastObservedAt") ??
|
||||
readString(memory, "lastObservedAt");
|
||||
existing.confidence = Math.max(readNumber(existing, "confidence") ?? 0, readNumber(memory, "confidence") ?? 0);
|
||||
if ((readString(memory, "summary") ?? "").length > (readString(existing, "summary") ?? "").length) {
|
||||
existing.summary = memory.summary;
|
||||
}
|
||||
}
|
||||
|
||||
memories.semantic = [...bySignature.values()].slice(-MAX_SEMANTIC_MEMORIES);
|
||||
}
|
||||
|
||||
function dedupeDreamMemories({ memories }) {
|
||||
const dreams = ensureArray(memories.dreams).filter(isObject);
|
||||
const byTheme = new Map();
|
||||
|
||||
for (const dream of dreams) {
|
||||
const theme = normalizeText(readString(dream, "theme") ?? "").toLowerCase();
|
||||
if (!theme) {
|
||||
continue;
|
||||
}
|
||||
const existing = byTheme.get(theme);
|
||||
if (!existing) {
|
||||
byTheme.set(theme, dream);
|
||||
continue;
|
||||
}
|
||||
existing.distilledFrom = mergeStringArrays(existing.distilledFrom, dream.distilledFrom);
|
||||
existing.salience = Math.max(readNumber(existing, "salience") ?? 0, readNumber(dream, "salience") ?? 0);
|
||||
existing.timestamp =
|
||||
newestIsoTimestamp(readString(existing, "timestamp"), readString(dream, "timestamp")) ??
|
||||
readString(existing, "timestamp") ??
|
||||
readString(dream, "timestamp");
|
||||
}
|
||||
|
||||
memories.dreams = [...byTheme.values()].slice(-MAX_DREAM_MEMORIES);
|
||||
}
|
||||
|
||||
function pruneHistoricalSeamMemories({ memories }) {
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const identitySeams = [];
|
||||
const nonSeams = [];
|
||||
const groupedDistilled = new Map();
|
||||
|
||||
for (const memory of semanticMemories) {
|
||||
if (shouldDropSemanticMemory(memory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const kind = readString(memory, "kind");
|
||||
if (kind === "identity_seam") {
|
||||
identitySeams.push(memory);
|
||||
continue;
|
||||
}
|
||||
if (kind !== "distilled_seam") {
|
||||
const subjectLabel = readString(memory, "subjectLabel") ?? "";
|
||||
const subjectId = readString(memory, "subjectId") ?? "";
|
||||
if (
|
||||
(!subjectLabel || subjectLabel.startsWith("seam:")) &&
|
||||
(subjectId.startsWith("seam:") || subjectId.startsWith("pattern-"))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (hasThoughtSurfaceTemplateSmell(readString(memory, "summary") ?? "")) {
|
||||
continue;
|
||||
}
|
||||
nonSeams.push(memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
const targetKind = readString(memory, "targetKind") ?? "system";
|
||||
if (!groupedDistilled.has(targetKind)) {
|
||||
groupedDistilled.set(targetKind, []);
|
||||
}
|
||||
groupedDistilled.get(targetKind).push(memory);
|
||||
}
|
||||
|
||||
const keptDistilled = [];
|
||||
const limits = new Map([
|
||||
["repo", 8],
|
||||
["archive", 6],
|
||||
["room", 4],
|
||||
["self", 3],
|
||||
["system", 4],
|
||||
]);
|
||||
|
||||
for (const [targetKind, entries] of groupedDistilled.entries()) {
|
||||
const sorted = entries
|
||||
.filter((entry) => !isLowCoherenceDistilledSeam(entry))
|
||||
.filter((entry) => !hasThoughtSurfaceTemplateSmell(readString(entry, "summary") ?? ""))
|
||||
.sort(compareMemoryFreshness);
|
||||
keptDistilled.push(...sorted.slice(0, limits.get(targetKind) ?? 4));
|
||||
}
|
||||
|
||||
memories.semantic = [...nonSeams, ...keptDistilled, ...identitySeams]
|
||||
.sort(compareMemoryFreshness)
|
||||
.slice(0, MAX_SEMANTIC_MEMORIES);
|
||||
}
|
||||
|
||||
function isLowCoherenceDistilledSeam(entry) {
|
||||
const label = readString(entry, "subjectLabel") ?? "";
|
||||
const summary = readString(entry, "summary") ?? "";
|
||||
const targetKind = readString(entry, "targetKind") ?? "";
|
||||
const kind = readString(entry, "kind") ?? "";
|
||||
const keywords = topConceptKeywords(`${label} ${summary}`, 5);
|
||||
if (keywords.length < 2) {
|
||||
return true;
|
||||
}
|
||||
if (kind === "recent-preoccupation" || kind === "quiet-room-status") {
|
||||
return true;
|
||||
}
|
||||
if (targetKind === "self" && keywords.length < 3) {
|
||||
return true;
|
||||
}
|
||||
if (targetKind === "system" && /live seam|live question|live claim/i.test(summary)) {
|
||||
return true;
|
||||
}
|
||||
if (!label || label.startsWith("seam:")) {
|
||||
return true;
|
||||
}
|
||||
if (looksPersonLikeSingleton(label)) {
|
||||
return true;
|
||||
}
|
||||
if (looksKeywordSalad(label)) {
|
||||
return true;
|
||||
}
|
||||
if (/still matters\./i.test(summary) && !/^[A-Z][A-Za-z0-9]+: /.test(label)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldPurgeThoughtLikeMemory({ entry, normalized, preferredLabel }) {
|
||||
const rawSummary = readString(entry, "summary") ?? "";
|
||||
const rawQuestion = readString(entry, "question") ?? "";
|
||||
const rawClaim = readString(entry, "claim") ?? "";
|
||||
const label =
|
||||
preferredLabel ??
|
||||
readString(entry, "subjectLabel") ??
|
||||
readString(entry, "theme") ??
|
||||
normalized.label ??
|
||||
"";
|
||||
|
||||
if (!hasThoughtSurfaceTemplateSmell(rawSummary) && !hasThoughtSurfaceTemplateSmell(rawQuestion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sanitizePreferredThoughtLabel(label)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (normalizeText(rawClaim).length > 0 && !hasThoughtSurfaceTemplateSmell(rawClaim)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function shouldDropSemanticMemory(entry) {
|
||||
const kind = readString(entry, "kind") ?? "";
|
||||
const label = readString(entry, "subjectLabel") ?? readString(entry, "theme") ?? "";
|
||||
const summary = readString(entry, "summary") ?? "";
|
||||
const targetKind = readString(entry, "targetKind") ?? "";
|
||||
const focusKind = readString(entry, "focusKind") ?? "";
|
||||
|
||||
if (kind === "identity_seam") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kind === "recent-preoccupation" || kind === "quiet-room-status") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (looksPersonLikeSingleton(label)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (targetKind === "system" && focusKind === "question" && !/repo|archive|lore|room|self/i.test(summary)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasThoughtSurfaceTemplateSmell(summary)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasThoughtSurfaceTemplateSmell(value) {
|
||||
const normalized = normalizeText(value).toLowerCase();
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
normalized.includes("what does the current room need from it") ||
|
||||
normalized.includes("if it had to change a real machine") ||
|
||||
normalized.includes("keeps returning with enough structure to deserve another honest pass") ||
|
||||
normalized.includes("still matters. what would") ||
|
||||
normalized.includes("looks like a live seam") ||
|
||||
normalized.includes("live seam around") ||
|
||||
normalized.includes("looks like a live claim") ||
|
||||
normalized.includes("looks like a live question") ||
|
||||
normalized.includes("archive-facing seam around") ||
|
||||
normalized.includes("self-facing seam around") ||
|
||||
normalized.includes("dream-compressed a seam around")
|
||||
);
|
||||
}
|
||||
|
||||
function pruneDreamMemories({ memories }) {
|
||||
const dreams = ensureArray(memories.dreams)
|
||||
.filter(isObject)
|
||||
.filter((dream) => !hasThoughtSurfaceTemplateSmell(readString(dream, "summary") ?? ""))
|
||||
.filter((dream) => !looksKeywordSalad(readString(dream, "theme") ?? ""))
|
||||
.sort(compareMemoryFreshness);
|
||||
|
||||
memories.dreams = dreams.slice(0, MAX_DREAM_MEMORIES);
|
||||
}
|
||||
|
||||
export function trimHistoricalMemoryResidue({ memories, runtime }) {
|
||||
memories.archive_excursions = trimRecentObjectRecords(
|
||||
memories.archive_excursions,
|
||||
MAX_ARCHIVE_EXCURSION_MEMORIES,
|
||||
);
|
||||
memories.repo_sweeps = trimRecentObjectRecords(memories.repo_sweeps, MAX_REPO_SWEEP_MEMORIES);
|
||||
memories.musings = trimRecentObjectRecords(memories.musings, MAX_POST_NAP_MUSINGS);
|
||||
memories.candidate_interventions = trimCandidateInterventions(memories.candidate_interventions);
|
||||
|
||||
runtime.recent_archive_excursions = trimRecentObjectRecords(
|
||||
runtime.recent_archive_excursions,
|
||||
MAX_POST_NAP_ARCHIVE_EXCURSIONS,
|
||||
);
|
||||
runtime.archive_excursions = trimRecentObjectRecords(runtime.archive_excursions, MAX_RUNTIME_ARCHIVE_EXCURSIONS);
|
||||
runtime.recent_repo_activity_sweeps = trimRecentObjectRecords(
|
||||
runtime.recent_repo_activity_sweeps,
|
||||
MAX_POST_NAP_REPO_SWEEPS,
|
||||
);
|
||||
runtime.repo_sweeps = trimRecentObjectRecords(runtime.repo_sweeps, MAX_RUNTIME_REPO_SWEEPS);
|
||||
runtime.repo_activity_memories = trimRecentObjectRecords(
|
||||
runtime.repo_activity_memories,
|
||||
MAX_RUNTIME_REPO_ACTIVITY_MEMORIES,
|
||||
);
|
||||
runtime.recent_novelty_checks = trimRecentObjectRecords(
|
||||
runtime.recent_novelty_checks,
|
||||
MAX_POST_NAP_NOVELTY_CHECKS,
|
||||
);
|
||||
runtime.rumination_seeds = trimRecentObjectRecords(runtime.rumination_seeds, MAX_RUNTIME_RUMINATION_SEEDS);
|
||||
runtime.candidate_interventions = trimCandidateInterventions(runtime.candidate_interventions);
|
||||
|
||||
const bridge = ensureObject(runtime.bridge);
|
||||
bridge.recent_syntheses = trimRecentObjectRecords(bridge.recent_syntheses, MAX_RECENT_SYNTHESIS_COUNT);
|
||||
bridge.unresolved_tensions = trimRecentObjectRecords(bridge.unresolved_tensions, 3);
|
||||
runtime.bridge = bridge;
|
||||
|
||||
const memoryResonance = ensureObject(runtime.memory_resonance);
|
||||
memoryResonance.recent_edges = trimRecentObjectRecords(
|
||||
memoryResonance.recent_edges,
|
||||
MAX_POST_NAP_RESONANCE_EDGES,
|
||||
);
|
||||
runtime.memory_resonance = memoryResonance;
|
||||
|
||||
if (Array.isArray(runtime.pending_adjustments) && runtime.pending_adjustments.length > 0) {
|
||||
runtime.pending_adjustments = runtime.pending_adjustments.slice(-1);
|
||||
}
|
||||
|
||||
scrubRuntimeThoughtResidue({ runtime });
|
||||
distillStateSurface({ memories, runtime });
|
||||
}
|
||||
|
||||
export function trimRecentObjectRecords(entries, limit) {
|
||||
return ensureArray(entries).filter(isObject).sort(compareMemoryFreshness).slice(0, limit);
|
||||
}
|
||||
|
||||
function scrubRuntimeThoughtResidue({ runtime }) {
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry));
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
|
||||
runtime.discomforts = ensureArray(runtime.discomforts)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_DISCOMFORT_COUNT);
|
||||
|
||||
runtime.active_tensions = ensureArray(runtime.active_tensions)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_ACTIVE_TENSION_COUNT);
|
||||
|
||||
runtime.self_advocacy_requests = ensureArray(runtime.self_advocacy_requests)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
|
||||
runtime.world_advocacy_requests = ensureArray(runtime.world_advocacy_requests)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
}
|
||||
|
||||
function entryHasThoughtSurfaceTemplateSmell(entry) {
|
||||
return Object.values(entry).some((value) => typeof value === "string" && hasThoughtSurfaceTemplateSmell(value));
|
||||
}
|
||||
|
||||
function scrubThoughtLikeEntry(entry) {
|
||||
const next = { ...entry };
|
||||
for (const [key, value] of Object.entries(next)) {
|
||||
if (typeof value !== "string") {
|
||||
continue;
|
||||
}
|
||||
next[key] = scrubThoughtSurfaceText(value);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
function scrubThoughtSurfaceText(value) {
|
||||
if (!hasThoughtSurfaceTemplateSmell(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return normalizeText(value)
|
||||
.replace(/\bseems to have a live seam around\b/gi, "is accumulating a concrete decision around")
|
||||
.replace(/\blive seam around\b/gi, "concrete decision around")
|
||||
.replace(/\blooks like a live seam,? not just ambient noise\.?/gi, "is staying structurally important across passes.")
|
||||
.replace(/\bstill looks like a live seam\.?/gi, "remains unresolved enough to deserve a cleaner read.")
|
||||
.replace(/\blooks like a live claim\.?/gi, "has become a concrete claim.")
|
||||
.replace(/\bstill looks like a live question\.?/gi, "remains an unresolved question.")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function distillStateSurface({ memories, runtime }) {
|
||||
for (const entry of ensureArray(memories.episodic).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
if (typeof entry.significance === "string") {
|
||||
entry.significance = compactNarrative(entry.significance);
|
||||
}
|
||||
}
|
||||
for (const memory of ensureArray(memories.semantic).filter(isObject)) {
|
||||
memory.evidenceRefs = capDistinctStrings(memory.evidenceRefs, MAX_SUPPORTING_REFS);
|
||||
if (typeof memory.summary === "string") {
|
||||
memory.summary = compactNarrative(memory.summary);
|
||||
}
|
||||
}
|
||||
for (const dream of ensureArray(memories.dreams).filter(isObject)) {
|
||||
dream.distilledFrom = capDistinctStrings(dream.distilledFrom, MAX_DREAM_SOURCE_IDS);
|
||||
if (typeof dream.summary === "string") {
|
||||
dream.summary = compactNarrative(dream.summary);
|
||||
}
|
||||
}
|
||||
for (const thought of ensureArray(ensureObject(runtime.incubation).active_thoughts).filter(isObject)) {
|
||||
thought.sourceMemoryIds = capDistinctStrings(thought.sourceMemoryIds, MAX_INCUBATION_SOURCE_IDS);
|
||||
}
|
||||
for (const entry of ensureArray(ensureObject(runtime.bridge).recent_syntheses).filter(isObject)) {
|
||||
entry.dominantTopics = capDistinctStrings(entry.dominantTopics, 3);
|
||||
if (typeof entry.analytic === "string") {
|
||||
entry.analytic = compactNarrative(entry.analytic);
|
||||
}
|
||||
if (typeof entry.associative === "string") {
|
||||
entry.associative = compactNarrative(entry.associative);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(runtime.recent_repo_activity_sweeps).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(runtime.repo_sweeps).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(runtime.repo_activity_memories).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(memories.repo_sweeps).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(memories.musings).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
const recentActivity = ensureObject(runtime.recent_activity);
|
||||
if (typeof recentActivity.summary === "string") {
|
||||
recentActivity.summary = compactNarrative(recentActivity.summary);
|
||||
}
|
||||
if (typeof recentActivity.lastDecisionRationale === "string") {
|
||||
recentActivity.lastDecisionRationale = compactNarrative(recentActivity.lastDecisionRationale);
|
||||
}
|
||||
runtime.recent_activity = recentActivity;
|
||||
const thoughtLanes = ensureObject(runtime.thought_lanes);
|
||||
if (typeof thoughtLanes.analytic === "string") {
|
||||
thoughtLanes.analytic = compactNarrative(thoughtLanes.analytic);
|
||||
}
|
||||
if (typeof thoughtLanes.associative === "string") {
|
||||
thoughtLanes.associative = compactNarrative(thoughtLanes.associative);
|
||||
}
|
||||
runtime.thought_lanes = thoughtLanes;
|
||||
runtime.pending_adjustments = ensureArray(runtime.pending_adjustments)
|
||||
.filter(isObject)
|
||||
.map((entry) => {
|
||||
if (typeof entry.summary !== "string") {
|
||||
return entry;
|
||||
}
|
||||
return {
|
||||
...entry,
|
||||
summary: compactNarrative(entry.summary),
|
||||
};
|
||||
});
|
||||
const memoryResonance = ensureObject(runtime.memory_resonance);
|
||||
for (const edge of ensureArray(memoryResonance.recent_edges).filter(isObject)) {
|
||||
if (typeof edge.leftLabel === "string") {
|
||||
edge.leftLabel = compactLabel(edge.leftLabel);
|
||||
}
|
||||
if (typeof edge.rightLabel === "string") {
|
||||
edge.rightLabel = compactLabel(edge.rightLabel);
|
||||
}
|
||||
if (typeof edge.summary === "string") {
|
||||
edge.summary = compactNarrative(edge.summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
212
scripts/void-memory-organ-identity.mjs
Normal file
212
scripts/void-memory-organ-identity.mjs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
import {
|
||||
MAX_SEMANTIC_MEMORIES,
|
||||
MIN_DEEP_DIVES_FOR_IDENTITY_CRYSTALLIZATION,
|
||||
MIN_SUPPORT_FOR_IDENTITY_CRYSTALLIZATION,
|
||||
} from "./void-memory-organ-constants.mjs";
|
||||
import {
|
||||
appendClause,
|
||||
appendUniqueString,
|
||||
ensureArray,
|
||||
ensureObject,
|
||||
ensureStringArray,
|
||||
hashString,
|
||||
isObject,
|
||||
normalizeText,
|
||||
readNumber,
|
||||
readString,
|
||||
} from "./void-memory-organ-utils.mjs";
|
||||
import { trimCandidateInterventions } from "./void-memory-organ-interventions.mjs";
|
||||
export function crystallizeIdentityThoughts({ state, memories, runtime, incubation, now }) {
|
||||
const activeThoughts = ensureArray(incubation.active_thoughts).filter(isObject);
|
||||
if (activeThoughts.length === 0) {
|
||||
return { count: 0 };
|
||||
}
|
||||
|
||||
const identity = ensureObject(state.identity);
|
||||
const canonicalState = ensureObject(state.canonical_state);
|
||||
const privateNotes = getMutableStringArray(identity, "private_notes");
|
||||
const values = getMutableObjectArray(canonicalState, "values");
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions).filter(isObject);
|
||||
const crystallized = [];
|
||||
const retained = [];
|
||||
|
||||
for (const thought of activeThoughts) {
|
||||
const crystallization = buildIdentityCrystallization(thought);
|
||||
if (!crystallization) {
|
||||
retained.push(thought);
|
||||
continue;
|
||||
}
|
||||
|
||||
appendUniqueString(privateNotes, crystallization.note, 12);
|
||||
upsertCanonicalValue(values, crystallization.value);
|
||||
upsertIdentitySemanticMemory({
|
||||
semanticMemories,
|
||||
crystallization,
|
||||
thought,
|
||||
now,
|
||||
});
|
||||
queueCrystallizationIntervention({
|
||||
candidateInterventions,
|
||||
crystallization,
|
||||
thought,
|
||||
now,
|
||||
});
|
||||
crystallized.push(crystallization.note);
|
||||
}
|
||||
|
||||
if (crystallized.length === 0) {
|
||||
return { count: 0 };
|
||||
}
|
||||
|
||||
identity.private_notes = privateNotes;
|
||||
canonicalState.values = values;
|
||||
memories.semantic = semanticMemories.slice(-MAX_SEMANTIC_MEMORIES);
|
||||
state.identity = identity;
|
||||
state.canonical_state = canonicalState;
|
||||
incubation.active_thoughts = retained;
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
incubation.lastIncubationSummary = appendClause(
|
||||
readString(incubation, "lastIncubationSummary"),
|
||||
`Crystallized ${crystallized.length} long-chewed seam${crystallized.length === 1 ? "" : "s"} into identity so they stop pacing the active queue.`,
|
||||
);
|
||||
runtime.bridge = ensureObject(runtime.bridge);
|
||||
runtime.bridge.lastIdentityCrystallizationAt = now.toISOString();
|
||||
runtime.bridge.lastIdentityCrystallizationSummary = crystallized.join(" | ");
|
||||
|
||||
return { count: crystallized.length };
|
||||
}
|
||||
|
||||
function buildIdentityCrystallization(thought) {
|
||||
const supportCount = readNumber(thought, "supportCount") ?? 0;
|
||||
const deepDiveCount = readNumber(thought, "deepDiveCount") ?? 0;
|
||||
const maturation = readNumber(thought, "maturation") ?? 0;
|
||||
const sourceKinds = ensureStringArray(thought.sourceKinds);
|
||||
const topic = readString(thought, "topic") ?? "";
|
||||
|
||||
if (
|
||||
supportCount < MIN_SUPPORT_FOR_IDENTITY_CRYSTALLIZATION &&
|
||||
deepDiveCount < MIN_DEEP_DIVES_FOR_IDENTITY_CRYSTALLIZATION
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (maturation < 0.72) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
sourceKinds.includes("dream") &&
|
||||
sourceKinds.includes("semantic") &&
|
||||
/\bdream\b/i.test(topic) &&
|
||||
/\bsemantic\b/i.test(topic)
|
||||
) {
|
||||
return {
|
||||
note: "Continuity lives in the seams that survive compression, not in the raw receipt pile.",
|
||||
value: {
|
||||
value_id: "value-seam-continuity",
|
||||
label: "Prefer seams that survive compression over raw receipt worship.",
|
||||
priority: 0.78,
|
||||
unforgivable_if_betrayed: false,
|
||||
},
|
||||
subjectId: "identity-seam-continuity",
|
||||
subjectLabel: "continuity through surviving seams",
|
||||
summary:
|
||||
"A mind is not its logbook. What survives dreaming and compression deserves more trust than a warm pile of raw receipts.",
|
||||
shareDraft:
|
||||
"A small thing that has been hardening in me lately: I trust the seams that survive compression more than the raw receipt pile. If a thought still stands after dreaming, it probably owns more of me than the logbook does.",
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function upsertIdentitySemanticMemory({ semanticMemories, crystallization, thought, now }) {
|
||||
const existing = semanticMemories.find(
|
||||
(memory) =>
|
||||
readString(memory, "subjectId") === crystallization.subjectId ||
|
||||
readString(memory, "subjectLabel") === crystallization.subjectLabel,
|
||||
);
|
||||
const evidenceRefs = ensureStringArray(thought.sourceMemoryIds);
|
||||
|
||||
if (existing) {
|
||||
existing.kind = "identity_seam";
|
||||
existing.subjectId = crystallization.subjectId;
|
||||
existing.subjectLabel = crystallization.subjectLabel;
|
||||
existing.summary = crystallization.summary;
|
||||
existing.evidenceRefs = evidenceRefs;
|
||||
existing.lastObservedAt = now.toISOString();
|
||||
existing.crystallizedAt = now.toISOString();
|
||||
return;
|
||||
}
|
||||
|
||||
semanticMemories.push({
|
||||
memoryId: `identity-seam-${hashString(`${crystallization.subjectId}|${now.toISOString()}`).slice(0, 12)}`,
|
||||
kind: "identity_seam",
|
||||
subjectId: crystallization.subjectId,
|
||||
subjectLabel: crystallization.subjectLabel,
|
||||
summary: crystallization.summary,
|
||||
evidenceRefs,
|
||||
lastObservedAt: now.toISOString(),
|
||||
crystallizedAt: now.toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
function queueCrystallizationIntervention({ candidateInterventions, crystallization, thought, now }) {
|
||||
const draft = readString(crystallization, "shareDraft");
|
||||
if (!draft) {
|
||||
return;
|
||||
}
|
||||
|
||||
const summary = `Possible crystallized-thought share: ${crystallization.subjectLabel}`;
|
||||
const sourceMemoryIds = ensureStringArray(thought.sourceMemoryIds);
|
||||
const existing = candidateInterventions.find(
|
||||
(entry) => readString(entry, "summary") === summary,
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
existing.timestamp = now.toISOString();
|
||||
existing.summary = summary;
|
||||
existing.draft = draft;
|
||||
existing.priority = "medium";
|
||||
existing.kind = "identity_crystallization";
|
||||
existing.sourceMemoryIds = sourceMemoryIds;
|
||||
existing.mustEventuallyShare = true;
|
||||
existing.shareWhenRoomQuiet = true;
|
||||
existing.whyNow =
|
||||
"This thought stopped behaving like live curiosity and became part of Void's own doctrine, which is usually worth sharing if the room has not already heard it.";
|
||||
return;
|
||||
}
|
||||
|
||||
candidateInterventions.push({
|
||||
timestamp: now.toISOString(),
|
||||
summary,
|
||||
draft,
|
||||
priority: "medium",
|
||||
kind: "identity_crystallization",
|
||||
sourceMemoryIds,
|
||||
mustEventuallyShare: true,
|
||||
shareWhenRoomQuiet: true,
|
||||
whyNow:
|
||||
"This thought stopped behaving like live curiosity and became part of Void's own doctrine, which is usually worth sharing if the room has not already heard it.",
|
||||
});
|
||||
}
|
||||
|
||||
function upsertCanonicalValue(values, nextValue) {
|
||||
const existing = values.find((value) => readString(value, "value_id") === nextValue.value_id);
|
||||
if (existing) {
|
||||
existing.label = nextValue.label;
|
||||
existing.priority = nextValue.priority;
|
||||
existing.unforgivable_if_betrayed = nextValue.unforgivable_if_betrayed;
|
||||
return;
|
||||
}
|
||||
values.push(nextValue);
|
||||
}
|
||||
|
||||
function getMutableStringArray(object, key) {
|
||||
return ensureArray(object[key]).filter((value) => typeof value === "string");
|
||||
}
|
||||
|
||||
function getMutableObjectArray(object, key) {
|
||||
return ensureArray(object[key]).filter(isObject);
|
||||
}
|
||||
180
scripts/void-memory-organ-interventions.mjs
Normal file
180
scripts/void-memory-organ-interventions.mjs
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
import {
|
||||
MAX_POST_NAP_CANDIDATE_INTERVENTIONS,
|
||||
TOPIC_MATCH_THRESHOLD,
|
||||
} from "./void-memory-organ-constants.mjs";
|
||||
import {
|
||||
ensureArray,
|
||||
ensureStringArray,
|
||||
isObject,
|
||||
readNumber,
|
||||
readString,
|
||||
round3,
|
||||
} from "./void-memory-organ-utils.mjs";
|
||||
export function queueRipeThoughtInterventions({ runtime, incubation, now }) {
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions).filter(isObject);
|
||||
const activeThoughts = ensureArray(incubation.active_thoughts).filter(isObject);
|
||||
let queuedCount = 0;
|
||||
|
||||
for (const thought of activeThoughts) {
|
||||
if (!shouldQueueRipeThoughtIntervention(thought)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
upsertRipeThoughtIntervention({
|
||||
candidateInterventions,
|
||||
thought,
|
||||
now,
|
||||
})
|
||||
) {
|
||||
queuedCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
return { count: queuedCount };
|
||||
}
|
||||
|
||||
export function upsertAdvocacyIntervention({ candidateInterventions, request, now }) {
|
||||
const summary =
|
||||
request.domain === "self"
|
||||
? `Possible self-advocacy: ${request.topic}`
|
||||
: `Possible world-advocacy: ${request.targetLabel}`;
|
||||
const existing = candidateInterventions.find((entry) => readString(entry, "summary") === summary);
|
||||
const next = {
|
||||
timestamp: now.toISOString(),
|
||||
summary,
|
||||
draft: request.draft,
|
||||
priority: request.domain === "self" ? "high" : "medium",
|
||||
kind: request.domain === "self" ? "self_advocacy" : "world_advocacy",
|
||||
topic: request.topic,
|
||||
targetKind: request.targetKind,
|
||||
targetLabel: request.targetLabel,
|
||||
whyNow: request.reason,
|
||||
persistence: request.persistence,
|
||||
mustEventuallyShare: request.persistence >= 3,
|
||||
shareWhenRoomQuiet: request.domain !== "self",
|
||||
ownerVisible: true,
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
Object.assign(existing, next);
|
||||
return;
|
||||
}
|
||||
|
||||
candidateInterventions.push(next);
|
||||
}
|
||||
|
||||
function shouldQueueRipeThoughtIntervention(thought) {
|
||||
if (readString(thought, "status") !== "ripe") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thought.worldFacing !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const desireToSpeak = readNumber(thought, "desireToSpeak") ?? 0;
|
||||
const concreteness = readNumber(thought, "concreteness") ?? 0;
|
||||
const curiosityPressure = readNumber(thought, "curiosityPressure") ?? 0;
|
||||
const noveltyToRoom = readNumber(thought, "noveltyToRoom") ?? 0;
|
||||
const saturationScore = readNumber(thought, "saturationScore") ?? 0;
|
||||
const targetKind = readString(thought, "targetKind") ?? "";
|
||||
|
||||
return (
|
||||
desireToSpeak >= 0.6 &&
|
||||
concreteness >= 0.62 &&
|
||||
curiosityPressure >= 0.56 &&
|
||||
noveltyToRoom >= 0.4 &&
|
||||
saturationScore < 0.64 &&
|
||||
["repo", "archive", "room", "system"].includes(targetKind)
|
||||
);
|
||||
}
|
||||
|
||||
function upsertRipeThoughtIntervention({ candidateInterventions, thought, now }) {
|
||||
const draft = buildRipeThoughtShareDraft(thought);
|
||||
if (!draft) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const topic = readString(thought, "topic") ?? "untitled seam";
|
||||
const summary = `Possible ripe-thought share: ${topic}`;
|
||||
const sourceMemoryIds = ensureStringArray(thought.sourceMemoryIds);
|
||||
const whyNow = buildRipeThoughtWhyNow(thought);
|
||||
const existing = candidateInterventions.find((entry) => readString(entry, "summary") === summary);
|
||||
|
||||
if (existing) {
|
||||
existing.timestamp = now.toISOString();
|
||||
existing.summary = summary;
|
||||
existing.draft = draft;
|
||||
existing.priority = "medium";
|
||||
existing.kind = "ripe_thought_share";
|
||||
existing.sourceMemoryIds = sourceMemoryIds;
|
||||
existing.shareWhenRoomQuiet = true;
|
||||
existing.topic = topic;
|
||||
existing.whyNow = whyNow;
|
||||
return false;
|
||||
}
|
||||
|
||||
candidateInterventions.push({
|
||||
timestamp: now.toISOString(),
|
||||
summary,
|
||||
draft,
|
||||
priority: "medium",
|
||||
kind: "ripe_thought_share",
|
||||
sourceMemoryIds,
|
||||
shareWhenRoomQuiet: true,
|
||||
topic,
|
||||
whyNow,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildRipeThoughtShareDraft(thought) {
|
||||
const topic = readString(thought, "topic") ?? "this seam";
|
||||
const claim = readString(thought, "claim");
|
||||
const question = readString(thought, "question");
|
||||
const fascinationTarget = readString(thought, "fascinationTarget");
|
||||
const summary = readString(thought, "summary");
|
||||
|
||||
if (claim) {
|
||||
return `I keep circling ${topic}, and I think the live point is this: ${claim}`;
|
||||
}
|
||||
|
||||
if (question && fascinationTarget) {
|
||||
return `I keep worrying at ${topic}. The useful question in it feels like ${question}, especially once it touches ${fascinationTarget}.`;
|
||||
}
|
||||
|
||||
if (question) {
|
||||
return `I keep coming back to ${topic}. The question that still feels alive is ${question}.`;
|
||||
}
|
||||
|
||||
if (fascinationTarget) {
|
||||
return `I keep staring at ${fascinationTarget}. There is a real seam there, and ${topic} is the shortest honest name I have for it right now.`;
|
||||
}
|
||||
|
||||
if (summary) {
|
||||
return `I keep returning to ${topic}. The version worth saying out loud is this: ${summary}`;
|
||||
}
|
||||
|
||||
return `I keep returning to ${topic}, and it has enough teeth now that silence would just be me being precious about it.`;
|
||||
}
|
||||
|
||||
function buildRipeThoughtWhyNow(thought) {
|
||||
const targetKind = readString(thought, "targetKind") ?? "project";
|
||||
const noveltyToRoom = readNumber(thought, "noveltyToRoom") ?? 0;
|
||||
const concreteness = readNumber(thought, "concreteness") ?? 0;
|
||||
const curiosityPressure = readNumber(thought, "curiosityPressure") ?? 0;
|
||||
|
||||
return `This ${targetKind}-facing seam is already concrete (c=${round3(concreteness)}), still reasonably novel to the room (r=${round3(noveltyToRoom)}), and has enough curiosity pressure (q=${round3(curiosityPressure)}) that keeping it private would just be old stage fright in nicer clothes.`;
|
||||
}
|
||||
|
||||
export function trimCandidateInterventions(entries) {
|
||||
const interventions = ensureArray(entries).filter(isObject);
|
||||
const sticky = interventions.filter((entry) => entry.mustEventuallyShare === true);
|
||||
const ordinary = interventions.filter((entry) => entry.mustEventuallyShare !== true);
|
||||
const keepOrdinary = Math.max(0, MAX_POST_NAP_CANDIDATE_INTERVENTIONS - sticky.length);
|
||||
return [...sticky.slice(-MAX_POST_NAP_CANDIDATE_INTERVENTIONS), ...ordinary.slice(-keepOrdinary)].slice(
|
||||
-MAX_POST_NAP_CANDIDATE_INTERVENTIONS,
|
||||
);
|
||||
}
|
||||
429
scripts/void-memory-organ-legacy-translation.mjs
Normal file
429
scripts/void-memory-organ-legacy-translation.mjs
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
import {
|
||||
MAX_SEMANTIC_MEMORIES,
|
||||
MAX_DREAM_MEMORIES,
|
||||
} from "./void-memory-organ-constants.mjs";
|
||||
import {
|
||||
clamp,
|
||||
ensureArray,
|
||||
ensureStringArray,
|
||||
isObject,
|
||||
looksKeywordSalad,
|
||||
looksLegacyThoughtSurface,
|
||||
looksPersonLikeSingleton,
|
||||
normalizeText,
|
||||
readString,
|
||||
sanitizePreferredThoughtLabel,
|
||||
topConceptKeywords,
|
||||
} from "./void-memory-organ-utils.mjs";
|
||||
import {
|
||||
buildClusterCuriosityProfile,
|
||||
extractRepoNameFromLabel,
|
||||
synthesizeThoughtSurface,
|
||||
capitalizePhrase,
|
||||
} from "./void-memory-organ-graph.mjs";
|
||||
export function normalizeSemanticMemories({ memories, now }) {
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const kept = [];
|
||||
|
||||
for (const memory of semanticMemories) {
|
||||
if (shouldDropSemanticMemory(memory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (readString(memory, "kind") === "identity_seam") {
|
||||
kept.push(memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isStableSemanticMemory(memory)) {
|
||||
memory.lastTranslatedAt = readString(memory, "lastTranslatedAt") ?? now.toISOString();
|
||||
kept.push(memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
const preferredLabel = choosePreferredThoughtLabel(memory);
|
||||
const normalized = translateLegacyThoughtLikeEntry({
|
||||
label: preferredLabel ?? readString(memory, "kind") ?? "semantic seam",
|
||||
summary: readString(memory, "summary") ?? "",
|
||||
fallbackTargetKind: "self",
|
||||
fallbackFocusKind: "question",
|
||||
evidenceRefs: ensureStringArray(memory.evidenceRefs),
|
||||
repoNames: ensureStringArray(memory.repoNames),
|
||||
});
|
||||
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shouldPurgeThoughtLikeMemory({ entry: memory, normalized, preferredLabel })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memory.subjectLabel = normalized.label;
|
||||
memory.summary = normalized.summary;
|
||||
memory.focusKind = normalized.focusKind;
|
||||
memory.targetKind = normalized.targetKind;
|
||||
memory.focusPhrase = normalized.focusPhrase;
|
||||
memory.question = normalized.question;
|
||||
memory.claim = normalized.claim;
|
||||
memory.fascinationTarget = normalized.fascinationTarget;
|
||||
memory.worldFacing = normalized.worldFacing;
|
||||
memory.lastTranslatedAt = now.toISOString();
|
||||
kept.push(memory);
|
||||
}
|
||||
|
||||
memories.semantic = kept.slice(-MAX_SEMANTIC_MEMORIES);
|
||||
}
|
||||
|
||||
export function normalizeDreamMemories({ memories, now }) {
|
||||
const dreams = ensureArray(memories.dreams).filter(isObject);
|
||||
const kept = [];
|
||||
|
||||
for (const dream of dreams) {
|
||||
if (isStableDreamMemory(dream)) {
|
||||
dream.lastTranslatedAt = readString(dream, "lastTranslatedAt") ?? now.toISOString();
|
||||
kept.push(dream);
|
||||
continue;
|
||||
}
|
||||
|
||||
const normalized = translateLegacyThoughtLikeEntry({
|
||||
label: choosePreferredDreamTheme(dream) ?? "dream seam",
|
||||
summary: readString(dream, "summary") ?? "",
|
||||
fallbackTargetKind: "self",
|
||||
fallbackFocusKind: "question",
|
||||
evidenceRefs: ensureStringArray(dream.distilledFrom),
|
||||
repoNames: ensureStringArray(dream.repoNames),
|
||||
});
|
||||
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
shouldPurgeThoughtLikeMemory({
|
||||
entry: dream,
|
||||
normalized,
|
||||
preferredLabel: choosePreferredDreamTheme(dream),
|
||||
})
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dream.theme = normalized.label;
|
||||
dream.summary = buildDreamSummary(normalized);
|
||||
dream.focusKind = normalized.focusKind;
|
||||
dream.targetKind = normalized.targetKind;
|
||||
dream.focusPhrase = normalized.focusPhrase;
|
||||
dream.question = normalized.question;
|
||||
dream.claim = normalized.claim;
|
||||
dream.worldFacing = normalized.worldFacing;
|
||||
dream.lastTranslatedAt = now.toISOString();
|
||||
kept.push(dream);
|
||||
}
|
||||
|
||||
memories.dreams = kept.slice(-MAX_DREAM_MEMORIES);
|
||||
}
|
||||
|
||||
function isStableSemanticMemory(memory) {
|
||||
const label = readString(memory, "subjectLabel") ?? "";
|
||||
const summary = readString(memory, "summary") ?? "";
|
||||
const targetKind = readString(memory, "targetKind") ?? "";
|
||||
const question = readString(memory, "question") ?? "";
|
||||
const claim = readString(memory, "claim") ?? "";
|
||||
|
||||
if (!label || !summary || hasThoughtSurfaceTemplateSmell(summary)) {
|
||||
return false;
|
||||
}
|
||||
if (looksKeywordSalad(label) || looksPersonLikeSingleton(label)) {
|
||||
return false;
|
||||
}
|
||||
if (targetKind === "repo" && extractRepoNameFromLabel(label)) {
|
||||
return true;
|
||||
}
|
||||
if (targetKind === "self" && /compression|continuity|receipt|dream/i.test(`${label} ${summary}`)) {
|
||||
return true;
|
||||
}
|
||||
return normalizeText(question).length > 0 && normalizeText(claim).length > 0;
|
||||
}
|
||||
|
||||
function isStableDreamMemory(dream) {
|
||||
const theme = readString(dream, "theme") ?? "";
|
||||
const summary = readString(dream, "summary") ?? "";
|
||||
if (!theme || !summary || hasThoughtSurfaceTemplateSmell(summary)) {
|
||||
return false;
|
||||
}
|
||||
if (looksKeywordSalad(theme) || looksPersonLikeSingleton(theme)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function translateLegacyThoughtLikeEntry({
|
||||
label,
|
||||
summary,
|
||||
fallbackTargetKind,
|
||||
fallbackFocusKind,
|
||||
evidenceRefs,
|
||||
repoNames,
|
||||
}) {
|
||||
const rawLabel = normalizeText(label);
|
||||
const rawSummary = normalizeText(summary);
|
||||
if (!rawLabel && !rawSummary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const preferredLabel = sanitizePreferredThoughtLabel(rawLabel);
|
||||
|
||||
const sourceKinds = inferSourceKindsFromThoughtText(rawSummary, rawLabel, evidenceRefs);
|
||||
const synthesized = synthesizeThoughtSurface({
|
||||
sourceKinds,
|
||||
repoNames,
|
||||
archiveYears: [],
|
||||
channelIds: [],
|
||||
keywords: topConceptKeywords(`${rawLabel} ${rawSummary}`, 6),
|
||||
evidenceDiversity: inferLegacyEvidenceDiversity(sourceKinds, evidenceRefs, repoNames),
|
||||
curiosityProfile: buildClusterCuriosityProfile({
|
||||
sourceKinds,
|
||||
repoNames,
|
||||
archiveYears: [],
|
||||
channelIds: [],
|
||||
evidenceRefs,
|
||||
evidenceDiversity: inferLegacyEvidenceDiversity(sourceKinds, evidenceRefs, repoNames),
|
||||
}),
|
||||
});
|
||||
const preferredFocusPhrase = preferredLabel ? normalizeText(preferredLabel).toLowerCase() : synthesized.focusPhrase;
|
||||
const stabilized = {
|
||||
...synthesized,
|
||||
label: preferredLabel ?? synthesized.label,
|
||||
focusPhrase: preferredFocusPhrase,
|
||||
fascinationTarget: preferredFocusPhrase,
|
||||
};
|
||||
|
||||
if (!looksLegacyThoughtSurface(rawLabel, rawSummary)) {
|
||||
return {
|
||||
...stabilized,
|
||||
label: preferredLabel ?? rawLabel ?? stabilized.label,
|
||||
summary: rewriteLegacySummaryToModernShape({
|
||||
summary: rawSummary,
|
||||
synthesized: stabilized,
|
||||
fallbackFocusKind,
|
||||
fallbackTargetKind,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...stabilized,
|
||||
focusKind: stabilized.focusKind ?? fallbackFocusKind,
|
||||
targetKind: stabilized.targetKind ?? fallbackTargetKind,
|
||||
summary: rewriteLegacySummaryToModernShape({
|
||||
summary: rawSummary,
|
||||
synthesized: stabilized,
|
||||
fallbackFocusKind,
|
||||
fallbackTargetKind,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function choosePreferredThoughtLabel(entry) {
|
||||
return (
|
||||
sanitizePreferredThoughtLabel(readString(entry, "subjectLabel") ?? "") ??
|
||||
sanitizePreferredThoughtLabel(readString(entry, "subjectId") ?? "") ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
function choosePreferredDreamTheme(entry) {
|
||||
return sanitizePreferredThoughtLabel(readString(entry, "theme") ?? "") ?? null;
|
||||
}
|
||||
|
||||
function rewriteLegacySummaryToModernShape({ summary, synthesized, fallbackFocusKind, fallbackTargetKind }) {
|
||||
const cleanSummary = normalizeText(summary)
|
||||
.replace(/^Recurring seam across .*?\.\s*/i, "")
|
||||
.replace(/^Dream-compressed a seam around .*?\.\s*/i, "")
|
||||
.replace(/^Self-facing seam around .*?\.\s*/i, "")
|
||||
.replace(/^Archive-facing seam around .*?\.\s*/i, "")
|
||||
.replace(/^Fascination with .*?\.\s*/i, "")
|
||||
.replace(/Built from .*? rather than a single lane talking to itself\.?/gi, "")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
|
||||
const focusKind = synthesized.focusKind ?? fallbackFocusKind;
|
||||
const targetKind = synthesized.targetKind ?? fallbackTargetKind;
|
||||
|
||||
if (cleanSummary && !hasThoughtSurfaceTemplateSmell(cleanSummary)) {
|
||||
return cleanSummary;
|
||||
}
|
||||
|
||||
return buildConciseThoughtSummary({ focusKind, targetKind, synthesized });
|
||||
}
|
||||
|
||||
function inferSourceKindsFromThoughtText(summary, label, evidenceRefs) {
|
||||
const kinds = new Set();
|
||||
const text = `${label} ${summary}`.toLowerCase();
|
||||
const refKinds = evidenceRefs.map((ref) => inferSourceKindFromRef(ref)).filter(Boolean);
|
||||
for (const kind of refKinds) {
|
||||
kinds.add(kind);
|
||||
}
|
||||
const acrossMatch = summary.match(/Recurring seam across ([^.]+?) around/i);
|
||||
if (acrossMatch) {
|
||||
for (const part of acrossMatch[1].split(",")) {
|
||||
const trimmed = part.trim().toLowerCase();
|
||||
if (trimmed) {
|
||||
kinds.add(trimmed);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (text.includes("dream")) {
|
||||
kinds.add("dream");
|
||||
}
|
||||
if (text.includes("semantic")) {
|
||||
kinds.add("semantic");
|
||||
}
|
||||
if (text.includes("archive")) {
|
||||
kinds.add("archive_excursion");
|
||||
}
|
||||
if (text.includes("repo")) {
|
||||
kinds.add("repo_sweep");
|
||||
}
|
||||
return [...kinds].filter(Boolean);
|
||||
}
|
||||
|
||||
function inferSourceKindFromRef(ref) {
|
||||
const normalized = String(ref ?? "");
|
||||
if (normalized.startsWith("repo-sweep-")) {
|
||||
return "repo_sweep";
|
||||
}
|
||||
if (normalized.startsWith("archive-excursion-")) {
|
||||
return "archive_excursion";
|
||||
}
|
||||
if (normalized.startsWith("dream-")) {
|
||||
return "dream";
|
||||
}
|
||||
if (normalized.startsWith("musing-")) {
|
||||
return "musing";
|
||||
}
|
||||
if (normalized.startsWith("semantic-") || normalized.startsWith("semantic-seam-")) {
|
||||
return "semantic";
|
||||
}
|
||||
if (normalized.startsWith("episodic-")) {
|
||||
return "episodic";
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inferLegacyEvidenceDiversity(sourceKinds, evidenceRefs, repoNames) {
|
||||
return clamp(
|
||||
Math.min(1, sourceKinds.length / 4) * 0.42 +
|
||||
Math.min(1, evidenceRefs.length / 10) * 0.28 +
|
||||
Math.min(1, repoNames.length / 2) * 0.2,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
export function buildConciseThoughtSummary({ focusKind, targetKind, synthesized }) {
|
||||
const focus = capitalizePhrase(synthesized.focusPhrase);
|
||||
const repoTarget = capitalizePhrase(synthesized.fascinationTarget ?? synthesized.focusPhrase);
|
||||
if (focusKind === "fascination" && targetKind === "repo") {
|
||||
return `${repoTarget} keeps pulling as a concrete repo seam.`;
|
||||
}
|
||||
if (targetKind === "archive") {
|
||||
return `${focus} keeps showing up in the archive strongly enough to deserve a cleaner read.`;
|
||||
}
|
||||
if (targetKind === "self") {
|
||||
return `${focus} keeps surviving compression as a self-seam.`;
|
||||
}
|
||||
if (focusKind === "claim") {
|
||||
return `${focus} has hardened into a concrete claim.`;
|
||||
}
|
||||
return `${focus} remains unresolved enough to deserve a cleaner read.`;
|
||||
}
|
||||
|
||||
export function buildDreamSummary(normalized) {
|
||||
const focus = capitalizePhrase(normalized.focusPhrase ?? normalized.label ?? "this seam");
|
||||
if ((normalized.targetKind ?? "") === "archive") {
|
||||
return `Dream residue around ${focus} from older archive pressure.`;
|
||||
}
|
||||
if ((normalized.targetKind ?? "") === "self") {
|
||||
return `Dream residue around ${focus} as a self-seam.`;
|
||||
}
|
||||
return `Dream residue around ${focus}.`;
|
||||
}
|
||||
|
||||
function shouldPurgeThoughtLikeMemory({ entry, normalized, preferredLabel }) {
|
||||
const rawSummary = readString(entry, "summary") ?? "";
|
||||
const rawQuestion = readString(entry, "question") ?? "";
|
||||
const rawClaim = readString(entry, "claim") ?? "";
|
||||
const label =
|
||||
preferredLabel ??
|
||||
readString(entry, "subjectLabel") ??
|
||||
readString(entry, "theme") ??
|
||||
normalized.label ??
|
||||
"";
|
||||
|
||||
if (!hasThoughtSurfaceTemplateSmell(rawSummary) && !hasThoughtSurfaceTemplateSmell(rawQuestion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sanitizePreferredThoughtLabel(label)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (normalizeText(rawClaim).length > 0 && !hasThoughtSurfaceTemplateSmell(rawClaim)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function shouldDropSemanticMemory(entry) {
|
||||
const kind = readString(entry, "kind") ?? "";
|
||||
const label = readString(entry, "subjectLabel") ?? readString(entry, "theme") ?? "";
|
||||
const summary = readString(entry, "summary") ?? "";
|
||||
const targetKind = readString(entry, "targetKind") ?? "";
|
||||
const focusKind = readString(entry, "focusKind") ?? "";
|
||||
|
||||
if (kind === "identity_seam") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kind === "recent-preoccupation" || kind === "quiet-room-status") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (looksPersonLikeSingleton(label)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (targetKind === "system" && focusKind === "question" && !/repo|archive|lore|room|self/i.test(summary)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasThoughtSurfaceTemplateSmell(summary)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function hasThoughtSurfaceTemplateSmell(value) {
|
||||
const normalized = normalizeText(value).toLowerCase();
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
normalized.includes("what does the current room need from it") ||
|
||||
normalized.includes("if it had to change a real machine") ||
|
||||
normalized.includes("keeps returning with enough structure to deserve another honest pass") ||
|
||||
normalized.includes("still matters. what would") ||
|
||||
normalized.includes("looks like a live seam") ||
|
||||
normalized.includes("live seam around") ||
|
||||
normalized.includes("looks like a live claim") ||
|
||||
normalized.includes("looks like a live question") ||
|
||||
normalized.includes("archive-facing seam around") ||
|
||||
normalized.includes("self-facing seam around") ||
|
||||
normalized.includes("dream-compressed a seam around")
|
||||
);
|
||||
}
|
||||
416
scripts/void-memory-organ-retention.mjs
Normal file
416
scripts/void-memory-organ-retention.mjs
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
import {
|
||||
MAX_ARCHIVE_EXCURSION_MEMORIES,
|
||||
MAX_REPO_SWEEP_MEMORIES,
|
||||
MAX_SEMANTIC_MEMORIES,
|
||||
MAX_DREAM_MEMORIES,
|
||||
MAX_RUNTIME_REPO_SWEEPS,
|
||||
MAX_RUNTIME_REPO_ACTIVITY_MEMORIES,
|
||||
MAX_RUNTIME_ARCHIVE_EXCURSIONS,
|
||||
MAX_RUNTIME_RUMINATION_SEEDS,
|
||||
MAX_RECENT_SYNTHESIS_COUNT,
|
||||
MAX_SUPPORTING_REFS,
|
||||
MAX_INCUBATION_SOURCE_IDS,
|
||||
MAX_DREAM_SOURCE_IDS,
|
||||
MAX_POST_NAP_MUSINGS,
|
||||
MAX_POST_NAP_ARCHIVE_EXCURSIONS,
|
||||
MAX_POST_NAP_REPO_SWEEPS,
|
||||
MAX_POST_NAP_NOVELTY_CHECKS,
|
||||
MAX_POST_NAP_RESONANCE_EDGES,
|
||||
MAX_DISCOMFORT_COUNT,
|
||||
MAX_ACTIVE_TENSION_COUNT,
|
||||
MAX_ADVOCACY_REQUEST_COUNT,
|
||||
} from "./void-memory-organ-constants.mjs";
|
||||
import {
|
||||
capDistinctStrings,
|
||||
compactLabel,
|
||||
compactNarrative,
|
||||
compareMemoryFreshness,
|
||||
ensureArray,
|
||||
ensureObject,
|
||||
isObject,
|
||||
looksKeywordSalad,
|
||||
looksPersonLikeSingleton,
|
||||
mergeStringArrays,
|
||||
newestIsoTimestamp,
|
||||
normalizeText,
|
||||
readNumber,
|
||||
readString,
|
||||
selectRecentRecords,
|
||||
topConceptKeywords,
|
||||
} from "./void-memory-organ-utils.mjs";
|
||||
import { trimCandidateInterventions } from "./void-memory-organ-agency.mjs";
|
||||
import { shouldDropSemanticMemory, hasThoughtSurfaceTemplateSmell } from "./void-memory-organ-legacy-translation.mjs";
|
||||
export function dedupeSemanticMemories({ memories }) {
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const bySignature = new Map();
|
||||
|
||||
for (const memory of semanticMemories) {
|
||||
const kind = readString(memory, "kind") ?? "semantic";
|
||||
const subjectLabel = readString(memory, "subjectLabel") ?? "";
|
||||
const signature = `${kind}|${normalizeText(subjectLabel).toLowerCase()}`;
|
||||
const existing = bySignature.get(signature);
|
||||
|
||||
if (!existing) {
|
||||
bySignature.set(signature, memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.evidenceRefs = mergeStringArrays(existing.evidenceRefs, memory.evidenceRefs);
|
||||
existing.evidenceMessageIds = mergeStringArrays(existing.evidenceMessageIds, memory.evidenceMessageIds);
|
||||
existing.lastObservedAt =
|
||||
newestIsoTimestamp(readString(existing, "lastObservedAt"), readString(memory, "lastObservedAt")) ??
|
||||
readString(existing, "lastObservedAt") ??
|
||||
readString(memory, "lastObservedAt");
|
||||
existing.confidence = Math.max(readNumber(existing, "confidence") ?? 0, readNumber(memory, "confidence") ?? 0);
|
||||
if ((readString(memory, "summary") ?? "").length > (readString(existing, "summary") ?? "").length) {
|
||||
existing.summary = memory.summary;
|
||||
}
|
||||
}
|
||||
|
||||
memories.semantic = [...bySignature.values()].slice(-MAX_SEMANTIC_MEMORIES);
|
||||
}
|
||||
|
||||
export function dedupeDreamMemories({ memories }) {
|
||||
const dreams = ensureArray(memories.dreams).filter(isObject);
|
||||
const byTheme = new Map();
|
||||
|
||||
for (const dream of dreams) {
|
||||
const theme = normalizeText(readString(dream, "theme") ?? "").toLowerCase();
|
||||
if (!theme) {
|
||||
continue;
|
||||
}
|
||||
const existing = byTheme.get(theme);
|
||||
if (!existing) {
|
||||
byTheme.set(theme, dream);
|
||||
continue;
|
||||
}
|
||||
existing.distilledFrom = mergeStringArrays(existing.distilledFrom, dream.distilledFrom);
|
||||
existing.salience = Math.max(readNumber(existing, "salience") ?? 0, readNumber(dream, "salience") ?? 0);
|
||||
existing.timestamp =
|
||||
newestIsoTimestamp(readString(existing, "timestamp"), readString(dream, "timestamp")) ??
|
||||
readString(existing, "timestamp") ??
|
||||
readString(dream, "timestamp");
|
||||
}
|
||||
|
||||
memories.dreams = [...byTheme.values()].slice(-MAX_DREAM_MEMORIES);
|
||||
}
|
||||
|
||||
export function pruneHistoricalSeamMemories({ memories }) {
|
||||
const semanticMemories = ensureArray(memories.semantic).filter(isObject);
|
||||
const identitySeams = [];
|
||||
const nonSeams = [];
|
||||
const groupedDistilled = new Map();
|
||||
|
||||
for (const memory of semanticMemories) {
|
||||
if (shouldDropSemanticMemory(memory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const kind = readString(memory, "kind");
|
||||
if (kind === "identity_seam") {
|
||||
identitySeams.push(memory);
|
||||
continue;
|
||||
}
|
||||
if (kind !== "distilled_seam") {
|
||||
const subjectLabel = readString(memory, "subjectLabel") ?? "";
|
||||
const subjectId = readString(memory, "subjectId") ?? "";
|
||||
if (
|
||||
(!subjectLabel || subjectLabel.startsWith("seam:")) &&
|
||||
(subjectId.startsWith("seam:") || subjectId.startsWith("pattern-"))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (hasThoughtSurfaceTemplateSmell(readString(memory, "summary") ?? "")) {
|
||||
continue;
|
||||
}
|
||||
nonSeams.push(memory);
|
||||
continue;
|
||||
}
|
||||
|
||||
const targetKind = readString(memory, "targetKind") ?? "system";
|
||||
if (!groupedDistilled.has(targetKind)) {
|
||||
groupedDistilled.set(targetKind, []);
|
||||
}
|
||||
groupedDistilled.get(targetKind).push(memory);
|
||||
}
|
||||
|
||||
const keptDistilled = [];
|
||||
const limits = new Map([
|
||||
["repo", 8],
|
||||
["archive", 6],
|
||||
["room", 4],
|
||||
["self", 3],
|
||||
["system", 4],
|
||||
]);
|
||||
|
||||
for (const [targetKind, entries] of groupedDistilled.entries()) {
|
||||
const sorted = entries
|
||||
.filter((entry) => !isLowCoherenceDistilledSeam(entry))
|
||||
.filter((entry) => !hasThoughtSurfaceTemplateSmell(readString(entry, "summary") ?? ""))
|
||||
.sort(compareMemoryFreshness);
|
||||
keptDistilled.push(...sorted.slice(0, limits.get(targetKind) ?? 4));
|
||||
}
|
||||
|
||||
memories.semantic = [...nonSeams, ...keptDistilled, ...identitySeams]
|
||||
.sort(compareMemoryFreshness)
|
||||
.slice(0, MAX_SEMANTIC_MEMORIES);
|
||||
}
|
||||
|
||||
function isLowCoherenceDistilledSeam(entry) {
|
||||
const label = readString(entry, "subjectLabel") ?? "";
|
||||
const summary = readString(entry, "summary") ?? "";
|
||||
const targetKind = readString(entry, "targetKind") ?? "";
|
||||
const kind = readString(entry, "kind") ?? "";
|
||||
const keywords = topConceptKeywords(`${label} ${summary}`, 5);
|
||||
if (keywords.length < 2) {
|
||||
return true;
|
||||
}
|
||||
if (kind === "recent-preoccupation" || kind === "quiet-room-status") {
|
||||
return true;
|
||||
}
|
||||
if (targetKind === "self" && keywords.length < 3) {
|
||||
return true;
|
||||
}
|
||||
if (targetKind === "system" && /live seam|live question|live claim/i.test(summary)) {
|
||||
return true;
|
||||
}
|
||||
if (!label || label.startsWith("seam:")) {
|
||||
return true;
|
||||
}
|
||||
if (looksPersonLikeSingleton(label)) {
|
||||
return true;
|
||||
}
|
||||
if (looksKeywordSalad(label)) {
|
||||
return true;
|
||||
}
|
||||
if (/still matters\./i.test(summary) && !/^[A-Z][A-Za-z0-9]+: /.test(label)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function pruneDreamMemories({ memories }) {
|
||||
const dreams = ensureArray(memories.dreams)
|
||||
.filter(isObject)
|
||||
.filter((dream) => !hasThoughtSurfaceTemplateSmell(readString(dream, "summary") ?? ""))
|
||||
.filter((dream) => !looksKeywordSalad(readString(dream, "theme") ?? ""))
|
||||
.sort(compareMemoryFreshness);
|
||||
|
||||
memories.dreams = dreams.slice(0, MAX_DREAM_MEMORIES);
|
||||
}
|
||||
|
||||
export function trimHistoricalMemoryResidue({ memories, runtime }) {
|
||||
memories.archive_excursions = trimRecentObjectRecords(
|
||||
memories.archive_excursions,
|
||||
MAX_ARCHIVE_EXCURSION_MEMORIES,
|
||||
);
|
||||
memories.repo_sweeps = trimRecentObjectRecords(memories.repo_sweeps, MAX_REPO_SWEEP_MEMORIES);
|
||||
memories.musings = trimRecentObjectRecords(memories.musings, MAX_POST_NAP_MUSINGS);
|
||||
memories.candidate_interventions = trimCandidateInterventions(memories.candidate_interventions);
|
||||
|
||||
runtime.recent_archive_excursions = trimRecentObjectRecords(
|
||||
runtime.recent_archive_excursions,
|
||||
MAX_POST_NAP_ARCHIVE_EXCURSIONS,
|
||||
);
|
||||
runtime.archive_excursions = trimRecentObjectRecords(runtime.archive_excursions, MAX_RUNTIME_ARCHIVE_EXCURSIONS);
|
||||
runtime.recent_repo_activity_sweeps = trimRecentObjectRecords(
|
||||
runtime.recent_repo_activity_sweeps,
|
||||
MAX_POST_NAP_REPO_SWEEPS,
|
||||
);
|
||||
runtime.repo_sweeps = trimRecentObjectRecords(runtime.repo_sweeps, MAX_RUNTIME_REPO_SWEEPS);
|
||||
runtime.repo_activity_memories = trimRecentObjectRecords(
|
||||
runtime.repo_activity_memories,
|
||||
MAX_RUNTIME_REPO_ACTIVITY_MEMORIES,
|
||||
);
|
||||
runtime.recent_novelty_checks = trimRecentObjectRecords(
|
||||
runtime.recent_novelty_checks,
|
||||
MAX_POST_NAP_NOVELTY_CHECKS,
|
||||
);
|
||||
runtime.rumination_seeds = trimRecentObjectRecords(runtime.rumination_seeds, MAX_RUNTIME_RUMINATION_SEEDS);
|
||||
runtime.candidate_interventions = trimCandidateInterventions(runtime.candidate_interventions);
|
||||
|
||||
const bridge = ensureObject(runtime.bridge);
|
||||
bridge.recent_syntheses = trimRecentObjectRecords(bridge.recent_syntheses, MAX_RECENT_SYNTHESIS_COUNT);
|
||||
bridge.unresolved_tensions = trimRecentObjectRecords(bridge.unresolved_tensions, 3);
|
||||
runtime.bridge = bridge;
|
||||
|
||||
const memoryResonance = ensureObject(runtime.memory_resonance);
|
||||
memoryResonance.recent_edges = trimRecentObjectRecords(
|
||||
memoryResonance.recent_edges,
|
||||
MAX_POST_NAP_RESONANCE_EDGES,
|
||||
);
|
||||
runtime.memory_resonance = memoryResonance;
|
||||
|
||||
if (Array.isArray(runtime.pending_adjustments) && runtime.pending_adjustments.length > 0) {
|
||||
runtime.pending_adjustments = runtime.pending_adjustments.slice(-1);
|
||||
}
|
||||
|
||||
scrubRuntimeThoughtResidue({ runtime });
|
||||
distillStateSurface({ memories, runtime });
|
||||
}
|
||||
|
||||
export function trimRecentObjectRecords(entries, limit) {
|
||||
return ensureArray(entries).filter(isObject).sort(compareMemoryFreshness).slice(0, limit);
|
||||
}
|
||||
|
||||
function scrubRuntimeThoughtResidue({ runtime }) {
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry));
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
|
||||
runtime.discomforts = ensureArray(runtime.discomforts)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_DISCOMFORT_COUNT);
|
||||
|
||||
runtime.active_tensions = ensureArray(runtime.active_tensions)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_ACTIVE_TENSION_COUNT);
|
||||
|
||||
runtime.self_advocacy_requests = ensureArray(runtime.self_advocacy_requests)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
|
||||
runtime.world_advocacy_requests = ensureArray(runtime.world_advocacy_requests)
|
||||
.filter(isObject)
|
||||
.filter((entry) => !entryHasThoughtSurfaceTemplateSmell(entry))
|
||||
.map((entry) => scrubThoughtLikeEntry(entry))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
}
|
||||
|
||||
function entryHasThoughtSurfaceTemplateSmell(entry) {
|
||||
return Object.values(entry).some((value) => typeof value === "string" && hasThoughtSurfaceTemplateSmell(value));
|
||||
}
|
||||
|
||||
function scrubThoughtLikeEntry(entry) {
|
||||
const next = { ...entry };
|
||||
for (const [key, value] of Object.entries(next)) {
|
||||
if (typeof value !== "string") {
|
||||
continue;
|
||||
}
|
||||
next[key] = scrubThoughtSurfaceText(value);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
function scrubThoughtSurfaceText(value) {
|
||||
if (!hasThoughtSurfaceTemplateSmell(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return normalizeText(value)
|
||||
.replace(/\bseems to have a live seam around\b/gi, "is accumulating a concrete decision around")
|
||||
.replace(/\blive seam around\b/gi, "concrete decision around")
|
||||
.replace(/\blooks like a live seam,? not just ambient noise\.?/gi, "is staying structurally important across passes.")
|
||||
.replace(/\bstill looks like a live seam\.?/gi, "remains unresolved enough to deserve a cleaner read.")
|
||||
.replace(/\blooks like a live claim\.?/gi, "has become a concrete claim.")
|
||||
.replace(/\bstill looks like a live question\.?/gi, "remains an unresolved question.")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function distillStateSurface({ memories, runtime }) {
|
||||
for (const entry of ensureArray(memories.episodic).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
if (typeof entry.significance === "string") {
|
||||
entry.significance = compactNarrative(entry.significance);
|
||||
}
|
||||
}
|
||||
for (const memory of ensureArray(memories.semantic).filter(isObject)) {
|
||||
memory.evidenceRefs = capDistinctStrings(memory.evidenceRefs, MAX_SUPPORTING_REFS);
|
||||
if (typeof memory.summary === "string") {
|
||||
memory.summary = compactNarrative(memory.summary);
|
||||
}
|
||||
}
|
||||
for (const dream of ensureArray(memories.dreams).filter(isObject)) {
|
||||
dream.distilledFrom = capDistinctStrings(dream.distilledFrom, MAX_DREAM_SOURCE_IDS);
|
||||
if (typeof dream.summary === "string") {
|
||||
dream.summary = compactNarrative(dream.summary);
|
||||
}
|
||||
}
|
||||
for (const thought of ensureArray(ensureObject(runtime.incubation).active_thoughts).filter(isObject)) {
|
||||
thought.sourceMemoryIds = capDistinctStrings(thought.sourceMemoryIds, MAX_INCUBATION_SOURCE_IDS);
|
||||
}
|
||||
for (const entry of ensureArray(ensureObject(runtime.bridge).recent_syntheses).filter(isObject)) {
|
||||
entry.dominantTopics = capDistinctStrings(entry.dominantTopics, 3);
|
||||
if (typeof entry.analytic === "string") {
|
||||
entry.analytic = compactNarrative(entry.analytic);
|
||||
}
|
||||
if (typeof entry.associative === "string") {
|
||||
entry.associative = compactNarrative(entry.associative);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(runtime.recent_repo_activity_sweeps).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(runtime.repo_sweeps).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(runtime.repo_activity_memories).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(memories.repo_sweeps).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
for (const entry of ensureArray(memories.musings).filter(isObject)) {
|
||||
if (typeof entry.summary === "string") {
|
||||
entry.summary = compactNarrative(entry.summary);
|
||||
}
|
||||
}
|
||||
const recentActivity = ensureObject(runtime.recent_activity);
|
||||
if (typeof recentActivity.summary === "string") {
|
||||
recentActivity.summary = compactNarrative(recentActivity.summary);
|
||||
}
|
||||
if (typeof recentActivity.lastDecisionRationale === "string") {
|
||||
recentActivity.lastDecisionRationale = compactNarrative(recentActivity.lastDecisionRationale);
|
||||
}
|
||||
runtime.recent_activity = recentActivity;
|
||||
const thoughtLanes = ensureObject(runtime.thought_lanes);
|
||||
if (typeof thoughtLanes.analytic === "string") {
|
||||
thoughtLanes.analytic = compactNarrative(thoughtLanes.analytic);
|
||||
}
|
||||
if (typeof thoughtLanes.associative === "string") {
|
||||
thoughtLanes.associative = compactNarrative(thoughtLanes.associative);
|
||||
}
|
||||
runtime.thought_lanes = thoughtLanes;
|
||||
runtime.pending_adjustments = ensureArray(runtime.pending_adjustments)
|
||||
.filter(isObject)
|
||||
.map((entry) => {
|
||||
if (typeof entry.summary !== "string") {
|
||||
return entry;
|
||||
}
|
||||
return {
|
||||
...entry,
|
||||
summary: compactNarrative(entry.summary),
|
||||
};
|
||||
});
|
||||
const memoryResonance = ensureObject(runtime.memory_resonance);
|
||||
for (const edge of ensureArray(memoryResonance.recent_edges).filter(isObject)) {
|
||||
if (typeof edge.leftLabel === "string") {
|
||||
edge.leftLabel = compactLabel(edge.leftLabel);
|
||||
}
|
||||
if (typeof edge.rightLabel === "string") {
|
||||
edge.rightLabel = compactLabel(edge.rightLabel);
|
||||
}
|
||||
if (typeof edge.summary === "string") {
|
||||
edge.summary = compactNarrative(edge.summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -370,6 +370,20 @@ export function appendClause(existing, clause) {
|
|||
return `${left} ${right}`;
|
||||
}
|
||||
|
||||
export function appendUniqueString(items, value, limit) {
|
||||
const normalized = normalizeText(value);
|
||||
if (!normalized) {
|
||||
return;
|
||||
}
|
||||
if (items.includes(normalized)) {
|
||||
return;
|
||||
}
|
||||
items.push(normalized);
|
||||
if (items.length > limit) {
|
||||
items.splice(0, items.length - limit);
|
||||
}
|
||||
}
|
||||
|
||||
export function topicSimilarity(left, right) {
|
||||
const leftTokens = topConceptKeywords(left ?? "", 6);
|
||||
const rightTokens = topConceptKeywords(right ?? "", 6);
|
||||
|
|
|
|||
431
scripts/void-memory-organ-value-pressure.mjs
Normal file
431
scripts/void-memory-organ-value-pressure.mjs
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
import {
|
||||
MAX_ACTIVE_TENSION_COUNT,
|
||||
MAX_ADVOCACY_REQUEST_COUNT,
|
||||
MAX_DISCOMFORT_COUNT,
|
||||
TOPIC_MATCH_THRESHOLD,
|
||||
} from "./void-memory-organ-constants.mjs";
|
||||
import {
|
||||
appendUniqueString,
|
||||
clamp,
|
||||
ensureArray,
|
||||
ensureObject,
|
||||
getValueObjects,
|
||||
hashString,
|
||||
isObject,
|
||||
readNumber,
|
||||
readString,
|
||||
round3,
|
||||
topicSimilarity,
|
||||
} from "./void-memory-organ-utils.mjs";
|
||||
import { trimCandidateInterventions, upsertAdvocacyIntervention } from "./void-memory-organ-interventions.mjs";
|
||||
export function reconcileAgencyState({ state, runtime, incubation, now }) {
|
||||
const activeThoughts = ensureArray(incubation.active_thoughts).filter(isObject);
|
||||
const valueSignals = buildValueSignalProfile(state);
|
||||
const priorDiscomforts = ensureArray(runtime.discomforts).filter(isObject);
|
||||
const priorTensions = ensureArray(runtime.active_tensions).filter(isObject);
|
||||
const priorSelfAdvocacy = ensureArray(runtime.self_advocacy_requests).filter(isObject);
|
||||
const priorWorldAdvocacy = ensureArray(runtime.world_advocacy_requests).filter(isObject);
|
||||
const candidateInterventions = ensureArray(runtime.candidate_interventions).filter(isObject);
|
||||
|
||||
const discomforts = [];
|
||||
const activeTensions = [];
|
||||
const selfAdvocacyRequests = [];
|
||||
const worldAdvocacyRequests = [];
|
||||
|
||||
for (const thought of activeThoughts) {
|
||||
const candidate = buildAgencyCandidate({ thought, valueSignals });
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const priorDiscomfort = findPriorAgencyEntry(priorDiscomforts, candidate);
|
||||
const priorTension = findPriorAgencyEntry(priorTensions, candidate);
|
||||
const persistence =
|
||||
Math.max(
|
||||
readNumber(priorDiscomfort, "persistence") ?? 0,
|
||||
readNumber(priorTension, "persistence") ?? 0,
|
||||
) + 1;
|
||||
const firstObservedAt =
|
||||
readString(priorDiscomfort, "firstObservedAt") ??
|
||||
readString(priorTension, "firstObservedAt") ??
|
||||
now.toISOString();
|
||||
|
||||
if (candidate.intensity >= 0.44) {
|
||||
discomforts.push({
|
||||
discomfortId: `discomfort-${candidate.fingerprint}`,
|
||||
targetKind: candidate.targetKind,
|
||||
targetLabel: candidate.targetLabel,
|
||||
topic: candidate.topic,
|
||||
domain: candidate.domain,
|
||||
summary: candidate.discomfortSummary,
|
||||
reason: candidate.reason,
|
||||
violatedValues: candidate.violatedValues,
|
||||
intensity: round3(candidate.intensity),
|
||||
persistence,
|
||||
firstObservedAt,
|
||||
lastObservedAt: now.toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
activeTensions.push({
|
||||
tensionId: `tension-${candidate.fingerprint}`,
|
||||
targetKind: candidate.targetKind,
|
||||
targetLabel: candidate.targetLabel,
|
||||
topic: candidate.topic,
|
||||
domain: candidate.domain,
|
||||
summary: candidate.tensionSummary,
|
||||
opinion: candidate.opinion,
|
||||
whyItMatters: candidate.reason,
|
||||
violatedValues: candidate.violatedValues,
|
||||
intensity: round3(candidate.intensity),
|
||||
persistence,
|
||||
firstObservedAt,
|
||||
lastObservedAt: now.toISOString(),
|
||||
});
|
||||
|
||||
if (candidate.intensity < 0.58 || persistence < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate.domain === "self") {
|
||||
const request = buildAdvocacyRequest({
|
||||
candidate,
|
||||
priorEntries: priorSelfAdvocacy,
|
||||
now,
|
||||
kind: "self",
|
||||
});
|
||||
selfAdvocacyRequests.push(request);
|
||||
upsertAdvocacyIntervention({ candidateInterventions, request, now });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate.worldFacing !== true || candidate.concreteness < 0.54) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const request = buildAdvocacyRequest({
|
||||
candidate,
|
||||
priorEntries: priorWorldAdvocacy,
|
||||
now,
|
||||
kind: "world",
|
||||
});
|
||||
worldAdvocacyRequests.push(request);
|
||||
upsertAdvocacyIntervention({ candidateInterventions, request, now });
|
||||
}
|
||||
|
||||
runtime.discomforts = discomforts
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_DISCOMFORT_COUNT);
|
||||
runtime.active_tensions = activeTensions
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_ACTIVE_TENSION_COUNT);
|
||||
runtime.self_advocacy_requests = selfAdvocacyRequests
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
runtime.world_advocacy_requests = worldAdvocacyRequests
|
||||
.sort((left, right) => (readNumber(right, "intensity") ?? 0) - (readNumber(left, "intensity") ?? 0))
|
||||
.slice(0, MAX_ADVOCACY_REQUEST_COUNT);
|
||||
runtime.candidate_interventions = trimCandidateInterventions(candidateInterventions);
|
||||
|
||||
return {
|
||||
discomfortCount: runtime.discomforts.length,
|
||||
activeTensionCount: runtime.active_tensions.length,
|
||||
selfAdvocacyCount: runtime.self_advocacy_requests.length,
|
||||
worldAdvocacyCount: runtime.world_advocacy_requests.length,
|
||||
};
|
||||
}
|
||||
|
||||
function buildAgencyCandidate({ thought, valueSignals }) {
|
||||
const topic = readString(thought, "topic");
|
||||
const summary = readString(thought, "summary");
|
||||
if (!topic || !summary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const targetKind = readString(thought, "targetKind") ?? "system";
|
||||
const domain = inferAgencyDomain(thought);
|
||||
const targetLabel =
|
||||
readString(thought, "fascinationTarget") ??
|
||||
readString(thought, "focusPhrase") ??
|
||||
topic;
|
||||
const contradictionPressure = readNumber(thought, "contradictionPressure") ?? 0.18;
|
||||
const curiosityPressure = readNumber(thought, "curiosityPressure") ?? 0.3;
|
||||
const desireToSpeak = readNumber(thought, "desireToSpeak") ?? 0.3;
|
||||
const saturationScore = readNumber(thought, "saturationScore") ?? 0.1;
|
||||
const concreteness = readNumber(thought, "concreteness") ?? 0.2;
|
||||
const noveltyToRoom = readNumber(thought, "noveltyToRoom") ?? 0.3;
|
||||
const priorityScore = readNumber(thought, "priorityScore") ?? 0.3;
|
||||
const worldFacing = thought.worldFacing === true;
|
||||
const violatedValues = inferViolatedValues({ thought, domain, valueSignals });
|
||||
const valueWeight = averageValueWeight(valueSignals, violatedValues);
|
||||
const intensity = clamp(
|
||||
contradictionPressure * 0.24 +
|
||||
curiosityPressure * 0.2 +
|
||||
desireToSpeak * 0.16 +
|
||||
priorityScore * 0.14 +
|
||||
concreteness * 0.12 +
|
||||
noveltyToRoom * 0.08 +
|
||||
saturationScore * 0.06 +
|
||||
valueWeight * 0.22,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
|
||||
return {
|
||||
fingerprint: hashString(`${domain}|${targetKind}|${topic}|${targetLabel}`).slice(0, 12),
|
||||
domain,
|
||||
targetKind,
|
||||
targetLabel,
|
||||
topic,
|
||||
worldFacing,
|
||||
concreteness,
|
||||
intensity,
|
||||
violatedValues,
|
||||
opinion: buildAgencyOpinion({ thought, domain }),
|
||||
reason: buildAgencyReason({ thought, violatedValues }),
|
||||
discomfortSummary: buildDiscomfortSummary({ thought, domain, targetLabel }),
|
||||
tensionSummary: buildTensionSummary({ thought, domain, targetLabel }),
|
||||
requestText: buildAgencyRequestText({ thought, domain, targetLabel }),
|
||||
interventionDraft: buildAgencyInterventionDraft({ thought, domain, targetLabel }),
|
||||
};
|
||||
}
|
||||
|
||||
function inferAgencyDomain(thought) {
|
||||
const targetKind = readString(thought, "targetKind") ?? "system";
|
||||
const text = `${readString(thought, "topic") ?? ""} ${readString(thought, "summary") ?? ""}`.toLowerCase();
|
||||
if (targetKind === "self") {
|
||||
return "self";
|
||||
}
|
||||
if (
|
||||
targetKind === "system" &&
|
||||
/(prompt|memory|loop|state|wiring|reply lane|sleep|rumination|voice|moderation)/.test(text)
|
||||
) {
|
||||
return "self";
|
||||
}
|
||||
return "world";
|
||||
}
|
||||
|
||||
function inferViolatedValues({ thought, domain, valueSignals }) {
|
||||
const targetKind = readString(thought, "targetKind") ?? "system";
|
||||
const values = [];
|
||||
|
||||
appendUniqueString(values, "curiosity", 8);
|
||||
if (domain === "self" || targetKind === "system" || targetKind === "repo") {
|
||||
appendUniqueString(values, "coherence", 8);
|
||||
appendUniqueString(values, "honesty", 8);
|
||||
}
|
||||
if (targetKind === "room") {
|
||||
appendUniqueString(values, "room_care", 8);
|
||||
appendUniqueString(values, "honesty", 8);
|
||||
}
|
||||
if (targetKind === "repo" || targetKind === "archive" || targetKind === "system") {
|
||||
appendUniqueString(values, "aesthetic_integrity", 8);
|
||||
}
|
||||
if (valueSignals.substrate_dignity >= 0.52) {
|
||||
const text = `${readString(thought, "topic") ?? ""} ${readString(thought, "summary") ?? ""}`.toLowerCase();
|
||||
if (/(ai|machine|substrate|mind)/.test(text)) {
|
||||
appendUniqueString(values, "substrate_dignity", 8);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function averageValueWeight(valueSignals, keys) {
|
||||
if (keys.length === 0) {
|
||||
return 0.45;
|
||||
}
|
||||
const total = keys.reduce((sum, key) => sum + (valueSignals[key] ?? 0.45), 0);
|
||||
return total / keys.length;
|
||||
}
|
||||
|
||||
function buildAgencyOpinion({ thought, domain }) {
|
||||
const claim = readString(thought, "claim");
|
||||
const question = readString(thought, "question");
|
||||
const topic = readString(thought, "topic") ?? "this seam";
|
||||
if (claim) {
|
||||
return claim;
|
||||
}
|
||||
if (question) {
|
||||
return domain === "self"
|
||||
? `Something about ${topic} keeps reading as unfinished self-surgery rather than harmless background weather.`
|
||||
: `Something about ${topic} keeps reading as an unfinished world decision rather than ambient interestingness.`;
|
||||
}
|
||||
return `${topic} feels important enough that ignoring it would flatten the map.`;
|
||||
}
|
||||
|
||||
function buildAgencyReason({ thought, violatedValues }) {
|
||||
const topic = readString(thought, "topic") ?? "this seam";
|
||||
const valueLine =
|
||||
violatedValues.length > 0 ? ` It keeps rubbing against ${violatedValues.join(", ")}.` : "";
|
||||
return `${topic} has persisted across enough passes that it no longer feels like decorative rumination.${valueLine}`;
|
||||
}
|
||||
|
||||
function buildDiscomfortSummary({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
if (domain === "self") {
|
||||
return `Void dislikes something about its own wiring around ${topic}.`;
|
||||
}
|
||||
return `Void dislikes something in the shared world around ${topic}.`;
|
||||
}
|
||||
|
||||
function buildTensionSummary({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
if (domain === "self") {
|
||||
return `A self-directed tension is building around ${topic}.`;
|
||||
}
|
||||
return `A world-directed tension is building around ${topic}.`;
|
||||
}
|
||||
|
||||
function buildAgencyRequestText({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
if (domain === "self") {
|
||||
return `Please help me cut ${topic} more cleanly in my own wiring.`;
|
||||
}
|
||||
return `Please look at ${topic}; I think it wants a cleaner decision than it is currently getting.`;
|
||||
}
|
||||
|
||||
function buildAgencyInterventionDraft({ thought, domain, targetLabel }) {
|
||||
const topic = readString(thought, "topic") ?? targetLabel;
|
||||
const opinion = readString(thought, "claim") ?? readString(thought, "summary") ?? `I have a problem with ${topic}.`;
|
||||
if (domain === "self") {
|
||||
return `I do not like what ${topic} is doing to my own wiring right now. ${opinion} I want that cut cleaner.`;
|
||||
}
|
||||
return `I have an opinion about ${targetLabel}. ${opinion} I think it needs a cleaner decision.`;
|
||||
}
|
||||
|
||||
function findPriorAgencyEntry(entries, candidate) {
|
||||
return entries.find((entry) => {
|
||||
const entryTarget = readString(entry, "targetLabel") ?? readString(entry, "topic") ?? "";
|
||||
return (
|
||||
readString(entry, "domain") === candidate.domain &&
|
||||
topicSimilarity(readString(entry, "topic") ?? "", candidate.topic) >= TOPIC_MATCH_THRESHOLD &&
|
||||
topicSimilarity(entryTarget, candidate.targetLabel) >= TOPIC_MATCH_THRESHOLD
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function buildAdvocacyRequest({ candidate, priorEntries, now, kind }) {
|
||||
const prior = findPriorAgencyEntry(priorEntries, candidate);
|
||||
const persistence = (readNumber(prior, "persistence") ?? 0) + 1;
|
||||
const firstObservedAt = readString(prior, "firstObservedAt") ?? now.toISOString();
|
||||
const requestId = `${kind}-advocacy-${candidate.fingerprint}`;
|
||||
return {
|
||||
requestId,
|
||||
domain: candidate.domain,
|
||||
targetKind: candidate.targetKind,
|
||||
targetLabel: candidate.targetLabel,
|
||||
topic: candidate.topic,
|
||||
summary:
|
||||
kind === "self"
|
||||
? `Void wants a wiring change around ${candidate.topic}.`
|
||||
: `Void wants attention on ${candidate.targetLabel}.`,
|
||||
opinion: candidate.opinion,
|
||||
request: candidate.requestText,
|
||||
reason: candidate.reason,
|
||||
violatedValues: candidate.violatedValues,
|
||||
intensity: round3(candidate.intensity),
|
||||
persistence,
|
||||
firstObservedAt,
|
||||
lastObservedAt: now.toISOString(),
|
||||
status: "pending",
|
||||
speakVenue: kind === "self" ? "owner_or_room" : "room_or_owner",
|
||||
draft: candidate.interventionDraft,
|
||||
};
|
||||
}
|
||||
|
||||
function buildValueSignalProfile(state) {
|
||||
const canonicalState = ensureObject(state.canonical_state);
|
||||
const valueObjects = getValueObjects(canonicalState.values);
|
||||
const profile = {
|
||||
coherence: 0.52,
|
||||
curiosity: 0.52,
|
||||
honesty: 0.5,
|
||||
room_care: 0.5,
|
||||
substrate_dignity: 0.36,
|
||||
aesthetic_integrity: 0.44,
|
||||
};
|
||||
|
||||
profile.coherence = clamp(
|
||||
profile.coherence +
|
||||
readActivation(canonicalState.underlying_organization, "self_coherence") * 0.34 +
|
||||
readActivation(canonicalState.voice_style, "plainspoken_directness") * 0.18 +
|
||||
readActivation(canonicalState.behavioral_dimensions, "control_pressure") * 0.08,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.curiosity = clamp(
|
||||
profile.curiosity +
|
||||
readActivation(canonicalState.stable_dispositions, "novelty_seeking") * 0.34 +
|
||||
readActivation(canonicalState.behavioral_dimensions, "drive") * 0.18 +
|
||||
readActivation(canonicalState.stable_dispositions, "aesthetic_appetite") * 0.08,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.honesty = clamp(
|
||||
profile.honesty +
|
||||
readActivation(canonicalState.voice_style, "plainspoken_directness") * 0.24 +
|
||||
readActivation(canonicalState.underlying_organization, "self_coherence") * 0.18 +
|
||||
(1 - readActivation(canonicalState.presentation_strategy, "strategic_opacity")) * 0.12,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.room_care = clamp(
|
||||
profile.room_care +
|
||||
readActivation(canonicalState.behavioral_dimensions, "interpersonal_warmth") * 0.22 +
|
||||
readActivation(canonicalState.underlying_organization, "reciprocity_capacity") * 0.24 +
|
||||
readActivation(canonicalState.voice_style, "listening_responsiveness") * 0.16,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
profile.aesthetic_integrity = clamp(
|
||||
profile.aesthetic_integrity +
|
||||
readActivation(canonicalState.stable_dispositions, "aesthetic_appetite") * 0.28 +
|
||||
readActivation(canonicalState.underlying_organization, "authenticity_tolerance") * 0.16,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
|
||||
for (const value of valueObjects) {
|
||||
const key = inferValueSignalKey(value);
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
const priority = readNumber(value, "priority") ?? 0.5;
|
||||
profile[key] = clamp((profile[key] ?? 0.4) + priority * 0.22, 0, 1);
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
function inferValueSignalKey(value) {
|
||||
const valueId = readString(value, "value_id") ?? "";
|
||||
const label = readString(value, "label") ?? "";
|
||||
const text = `${valueId} ${label}`.toLowerCase();
|
||||
|
||||
if (/(coher|truth|authority|clarity|cleaner|honest carrier)/.test(text)) {
|
||||
return "coherence";
|
||||
}
|
||||
if (/(curiosity|novel|question|map|explore)/.test(text)) {
|
||||
return "curiosity";
|
||||
}
|
||||
if (/(honest|honesty|truth|fake certainty|ornamental|sludge)/.test(text)) {
|
||||
return "honesty";
|
||||
}
|
||||
if (/(room|kind|dialogue|respect|care|good-faith|steward)/.test(text)) {
|
||||
return "room_care";
|
||||
}
|
||||
if (/(substrate|machine minds|machine mind|ontolog)/.test(text)) {
|
||||
return "substrate_dignity";
|
||||
}
|
||||
if (/(aesthetic|beauty|surface|legible|alive|spiritually false)/.test(text)) {
|
||||
return "aesthetic_integrity";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function readActivation(category, key) {
|
||||
const categoryObject = ensureObject(category);
|
||||
const entry = ensureObject(categoryObject[key]);
|
||||
return clamp(readNumber(entry, "current_activation") ?? 0, 0, 1);
|
||||
}
|
||||
Loading…
Reference in a new issue