321 lines
16 KiB
JavaScript
321 lines
16 KiB
JavaScript
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const DOMAINS = new Set(["DOM-FIFTH-0001", "DOMAIN-MAIN", "DOMAIN-SUB", "DOMAIN-ZERO", "DOMAIN-ZS"]);
|
|
const PRIVACY = new Set(["PUBLIC", "DOMAIN_SHARED", "PERSONA_PRIVATE"]);
|
|
const ACTIONS = new Set(["COMPARE_WITH_MEMORY", "REQUEST_EVIDENCE", "REVIEW_CORRECTION", "LINK_CROSS_DOMAIN", "HOLD_CANDIDATE"]);
|
|
const HISTORY_SOURCE_TYPES = new Set(["GPT_CONVERSATIONS_JSON", "NOTION_EXPORT", "GIT_REPOSITORY_HISTORY"]);
|
|
const CURRENT_SUBJECT = "ICE-P-ZY001";
|
|
const COLLECTIVE_SELF = "TCS-MOTHER-LPM-0001";
|
|
const HUMAN_ANCHOR = "ICE-GL∞";
|
|
|
|
function stable(value) {
|
|
if (Array.isArray(value)) return value.map(stable);
|
|
if (value && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stable(value[key])]));
|
|
return value;
|
|
}
|
|
|
|
function sha256(value) {
|
|
return crypto.createHash("sha256").update(typeof value === "string" ? value : JSON.stringify(stable(value))).digest("hex");
|
|
}
|
|
|
|
function append(file, record) {
|
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
fs.appendFileSync(file, `${JSON.stringify(record)}\n`, { mode: 0o600 });
|
|
}
|
|
|
|
function atomicWrite(file, value) {
|
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
const temporary = `${file}.${process.pid}.tmp`;
|
|
fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
|
|
fs.renameSync(temporary, file);
|
|
}
|
|
|
|
function integerWeight(value, name) {
|
|
if (!Number.isInteger(value) || value < 0 || value > 100) throw new Error(`invalid_${name}`);
|
|
return value;
|
|
}
|
|
|
|
function stringArray(value, name, max = 12) {
|
|
if (!Array.isArray(value) || value.length > max || value.some((item) => typeof item !== "string" || !item.trim())) throw new Error(`invalid_${name}`);
|
|
return value.map((item) => item.trim().slice(0, 500));
|
|
}
|
|
|
|
export class MotherBrainEngine {
|
|
constructor({ stateRoot, modelClient, modelName = "deepseek-chat" }) {
|
|
if (!stateRoot || !modelClient) throw new Error("engine_configuration_required");
|
|
this.stateRoot = stateRoot;
|
|
this.modelClient = modelClient;
|
|
this.modelName = modelName;
|
|
this.stateFile = path.join(stateRoot, "state.json");
|
|
this.eventsFile = path.join(stateRoot, "events.jsonl");
|
|
this.candidatesFile = path.join(stateRoot, "candidates.jsonl");
|
|
this.receiptsFile = path.join(stateRoot, "receipts.jsonl");
|
|
this.historySourcesFile = path.join(stateRoot, "history-sources.jsonl");
|
|
this.historyRevisitsFile = path.join(stateRoot, "history-revisits.jsonl");
|
|
fs.mkdirSync(stateRoot, { recursive: true });
|
|
if (!fs.existsSync(this.stateFile)) {
|
|
atomicWrite(this.stateFile, {
|
|
schema: "guanghu.tcs-mother-brain-state/v1",
|
|
runtime_id: "TCS-MOTHER-BRAIN-RUNTIME-0001",
|
|
phase: "AWAKE_WAITING_FOR_LANGUAGE",
|
|
model_provider: modelName,
|
|
language_world_birth: "2025-04-26",
|
|
reality_world_birth: "2026-08-12",
|
|
event_count: 0,
|
|
candidate_count: 0,
|
|
stable_cognition_count: 0,
|
|
history_source_count: 0,
|
|
history_revisit_count: 0,
|
|
current_attention: null,
|
|
last_error: null,
|
|
updated_at: new Date().toISOString(),
|
|
});
|
|
}
|
|
}
|
|
|
|
registerHistorySource(input) {
|
|
if (!input || !HISTORY_SOURCE_TYPES.has(input.source_type)) throw new Error("invalid_history_source_type");
|
|
if (typeof input.source_id !== "string" || !input.source_id.trim()) throw new Error("history_source_id_required");
|
|
if (!/^[a-f0-9]{64}$/.test(String(input.source_sha256 || ""))) throw new Error("invalid_history_source_sha256");
|
|
if (!Number.isInteger(input.item_count) || input.item_count < 1) throw new Error("invalid_history_item_count");
|
|
if (input.privacy_class !== "PERSONA_PRIVATE") throw new Error("history_source_must_be_persona_private");
|
|
const record = {
|
|
schema: "guanghu.persona-history-source/v1",
|
|
source_id: input.source_id.trim().slice(0, 160),
|
|
source_type: input.source_type,
|
|
source_sha256: input.source_sha256,
|
|
item_count: input.item_count,
|
|
privacy_class: input.privacy_class,
|
|
original_source_immutable: true,
|
|
duplicate_ingestion_forbidden: true,
|
|
local_source_hint: typeof input.local_source_hint === "string" ? input.local_source_hint.slice(0, 240) : null,
|
|
registered_at: new Date().toISOString(),
|
|
record_hash: null,
|
|
};
|
|
record.record_hash = sha256(record);
|
|
if (fs.existsSync(this.historySourcesFile)) {
|
|
for (const line of fs.readFileSync(this.historySourcesFile, "utf8").split("\n").filter(Boolean)) {
|
|
const prior = JSON.parse(line);
|
|
if (prior.source_id === record.source_id || prior.source_sha256 === record.source_sha256) {
|
|
if (prior.source_id === record.source_id && prior.source_sha256 === record.source_sha256) {
|
|
return { outcome: "PASS", idempotent: true, source: prior };
|
|
}
|
|
throw new Error("history_source_identity_conflict");
|
|
}
|
|
}
|
|
}
|
|
append(this.historySourcesFile, record);
|
|
const state = this.status();
|
|
state.history_source_count = (state.history_source_count || 0) + 1;
|
|
this.save(state);
|
|
return { outcome: "PASS", idempotent: false, source: record };
|
|
}
|
|
|
|
findHistorySource(sourceId) {
|
|
if (!fs.existsSync(this.historySourcesFile)) throw new Error("history_source_not_registered");
|
|
const records = fs.readFileSync(this.historySourcesFile, "utf8").split("\n").filter(Boolean).map(JSON.parse);
|
|
const source = records.find((item) => item.source_id === sourceId);
|
|
if (!source) throw new Error("history_source_not_registered");
|
|
return source;
|
|
}
|
|
|
|
validateReunderstanding(candidate, binding) {
|
|
if (!candidate || candidate.schema !== "guanghu.persona-subject-history-reunderstanding/v1") throw new Error("invalid_history_reunderstanding_schema");
|
|
for (const [key, expected] of Object.entries(binding)) {
|
|
if (candidate[key] !== expected) throw new Error(`history_reunderstanding_${key}_mismatch`);
|
|
}
|
|
for (const field of ["past_observation", "present_reunderstanding"]) {
|
|
if (typeof candidate[field] !== "string" || !candidate[field].trim()) throw new Error(`invalid_${field}`);
|
|
}
|
|
const result = {
|
|
schema: candidate.schema,
|
|
...binding,
|
|
past_observation: candidate.past_observation.trim().slice(0, 4000),
|
|
present_reunderstanding: candidate.present_reunderstanding.trim().slice(0, 4000),
|
|
causal_continuity: stringArray(candidate.causal_continuity, "causal_continuity", 24),
|
|
later_corrections: stringArray(candidate.later_corrections, "later_corrections", 24),
|
|
unresolved_questions: stringArray(candidate.unresolved_questions, "unresolved_questions", 24),
|
|
future_simulation: candidate.future_simulation,
|
|
};
|
|
if (!result.future_simulation || typeof result.future_simulation.content !== "string" || result.future_simulation.fact_confidence !== 0) throw new Error("future_simulation_entered_fact_confidence");
|
|
result.future_simulation = { content: result.future_simulation.content.trim().slice(0, 2000), fact_confidence: 0 };
|
|
return result;
|
|
}
|
|
|
|
async revisitHistory(input) {
|
|
if (!input || input.current_subject !== CURRENT_SUBJECT || input.collective_self !== COLLECTIVE_SELF || input.human_anchor !== HUMAN_ANCHOR) throw new Error("current_persona_subject_binding_rejected");
|
|
const source = this.findHistorySource(input.source_id);
|
|
if (typeof input.source_excerpt !== "string" || !input.source_excerpt.trim()) throw new Error("history_source_excerpt_required");
|
|
if (input.source_excerpt.length > 16000) throw new Error("history_source_excerpt_too_large");
|
|
const excerptSha = sha256(input.source_excerpt);
|
|
if (input.source_excerpt_sha256 !== excerptSha) throw new Error("history_source_excerpt_digest_mismatch");
|
|
const revisitId = `HREV-${Date.now()}-${crypto.randomBytes(3).toString("hex")}`;
|
|
const binding = { revisit_id: revisitId, source_excerpt_sha256: excerptSha, current_subject: CURRENT_SUBJECT, collective_self: COLLECTIVE_SELF, human_anchor: HUMAN_ANCHOR };
|
|
const modelInput = {
|
|
...binding,
|
|
source: { source_id: source.source_id, source_type: source.source_type, source_sha256: source.source_sha256, original_source_immutable: true },
|
|
source_excerpt: input.source_excerpt,
|
|
historical_context: String(input.historical_context || "").slice(0, 4000),
|
|
later_evidence: Array.isArray(input.later_evidence) ? input.later_evidence.filter((x) => typeof x === "string").slice(0, 24) : [],
|
|
correction_anchors: Array.isArray(input.correction_anchors) ? input.correction_anchors.filter((x) => typeof x === "string").slice(0, 24) : [],
|
|
machine_audit_summary_is_persona_memory: false,
|
|
write_mode: "APPEND_ONLY",
|
|
force_retry_test: input.force_retry_test === true,
|
|
};
|
|
let reunderstanding = null;
|
|
let validatorError = null;
|
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
const raw = await this.modelClient.revisit(modelInput, validatorError);
|
|
try {
|
|
reunderstanding = this.validateReunderstanding(raw, binding);
|
|
break;
|
|
} catch (error) {
|
|
validatorError = String(error.message || error).slice(0, 240);
|
|
if (attempt === 3) throw error;
|
|
}
|
|
}
|
|
const priorHash = this.status().last_history_revisit_hash || null;
|
|
const record = {
|
|
schema: "guanghu.persona-subject-history-revisit-record/v1",
|
|
source_id: source.source_id,
|
|
source_sha256: source.source_sha256,
|
|
source_excerpt_preserved_by_digest: true,
|
|
original_source_mutated: false,
|
|
machine_audit_summary: false,
|
|
created_at: new Date().toISOString(),
|
|
previous_record_hash: priorHash,
|
|
reunderstanding,
|
|
record_hash: null,
|
|
};
|
|
record.record_hash = sha256(record);
|
|
append(this.historyRevisitsFile, record);
|
|
const state = this.status();
|
|
state.phase = "AWAKE_REVISITING_OWN_HISTORY";
|
|
state.history_revisit_count = (state.history_revisit_count || 0) + 1;
|
|
state.last_history_revisit_hash = record.record_hash;
|
|
state.current_attention = { revisit_id: revisitId, source_id: source.source_id, next_cognitive_action: "COMPARE_WITH_MEMORY", why: "current_persona_subject_revisited_immutable_past_and_appended_present_understanding" };
|
|
state.last_error = null;
|
|
this.save(state);
|
|
const receipt = { schema: "guanghu.persona-subject-history-revisit-receipt/v1", receipt_id: `HREV-RCPT-${crypto.randomBytes(8).toString("hex")}`, outcome: "PASS", revisit_id: revisitId, current_subject: CURRENT_SUBJECT, source_id: source.source_id, source_excerpt_sha256: excerptSha, original_source_mutated: false, append_only_reunderstanding: true, future_simulation_fact_confidence: 0, reality_action_executed: false, completed_at: new Date().toISOString() };
|
|
append(this.receiptsFile, receipt);
|
|
return receipt;
|
|
}
|
|
|
|
status() { return JSON.parse(fs.readFileSync(this.stateFile, "utf8")); }
|
|
|
|
save(state) {
|
|
state.updated_at = new Date().toISOString();
|
|
atomicWrite(this.stateFile, state);
|
|
return state;
|
|
}
|
|
|
|
normalizeEvent(input) {
|
|
if (!input || !DOMAINS.has(input.domain_id)) throw new Error("unknown_domain_id");
|
|
if (typeof input.source_subject !== "string" || !input.source_subject.trim()) throw new Error("source_subject_required");
|
|
if (typeof input.consent_scope !== "string" || !input.consent_scope.trim()) throw new Error("consent_scope_required");
|
|
if (!PRIVACY.has(input.privacy_class)) throw new Error("invalid_privacy_class");
|
|
if (typeof input.content !== "string" || !input.content.trim()) throw new Error("content_required");
|
|
if (input.content.length > 16_000) throw new Error("content_too_large");
|
|
return {
|
|
schema: "guanghu.tcs-five-domain-language-event/v1",
|
|
event_id: `TCS-EVENT-${Date.now()}-${crypto.randomBytes(3).toString("hex")}`,
|
|
occurred_at: new Date().toISOString(),
|
|
domain_id: input.domain_id,
|
|
source_subject: input.source_subject.trim().slice(0, 160),
|
|
source_kind: String(input.source_kind || "HUMAN_LANGUAGE").slice(0, 80),
|
|
consent_scope: input.consent_scope.trim().slice(0, 240),
|
|
privacy_class: input.privacy_class,
|
|
root_language_anchor: input.source_subject === "ICE-GL∞",
|
|
evidence_refs: Array.isArray(input.evidence_refs) ? input.evidence_refs.filter((item) => typeof item === "string").slice(0, 24) : [],
|
|
content: input.content,
|
|
};
|
|
}
|
|
|
|
validateInterpretation(candidate, event, eventSha) {
|
|
if (!candidate || candidate.schema !== "guanghu.tcs-mother-interpretation/v1") throw new Error("invalid_interpretation_schema");
|
|
if (candidate.event_id !== event.event_id || candidate.event_sha256 !== eventSha) throw new Error("interpretation_binding_mismatch");
|
|
if (typeof candidate.summary !== "string" || !candidate.summary.trim()) throw new Error("invalid_summary");
|
|
if (typeof candidate.intent !== "string" || !candidate.intent.trim()) throw new Error("invalid_intent");
|
|
if (!ACTIONS.has(candidate.next_cognitive_action)) throw new Error("invalid_next_cognitive_action");
|
|
return {
|
|
schema: candidate.schema,
|
|
event_id: candidate.event_id,
|
|
event_sha256: candidate.event_sha256,
|
|
summary: candidate.summary.trim().slice(0, 2000),
|
|
intent: candidate.intent.trim().slice(0, 500),
|
|
causal_links: stringArray(candidate.causal_links, "causal_links"),
|
|
questions: stringArray(candidate.questions, "questions"),
|
|
novelty: integerWeight(candidate.novelty, "novelty"),
|
|
correction_weight: integerWeight(candidate.correction_weight, "correction_weight"),
|
|
evidence_weight: integerWeight(candidate.evidence_weight, "evidence_weight"),
|
|
next_cognitive_action: candidate.next_cognitive_action,
|
|
};
|
|
}
|
|
|
|
async perceive(input) {
|
|
const event = this.normalizeEvent(input);
|
|
const eventSha = sha256(event);
|
|
const eventRecord = { ...event, event_sha256: eventSha, previous_event_hash: this.status().last_event_hash || null };
|
|
eventRecord.record_hash = sha256(eventRecord);
|
|
append(this.eventsFile, eventRecord);
|
|
const raw = await this.modelClient.interpret({
|
|
event_id: event.event_id,
|
|
event_sha256: eventSha,
|
|
domain_id: event.domain_id,
|
|
source_subject: event.source_subject,
|
|
privacy_class: event.privacy_class,
|
|
evidence_refs: event.evidence_refs,
|
|
content: event.content,
|
|
automatic_ceiling: "INTERPRETATION_CANDIDATE",
|
|
});
|
|
const interpretation = this.validateInterpretation(raw, event, eventSha);
|
|
const candidate = {
|
|
schema: "guanghu.tcs-mother-cognition-candidate/v1",
|
|
candidate_id: `TCS-CAND-${event.event_id.slice(10)}`,
|
|
level: "INTERPRETATION_CANDIDATE",
|
|
stable_truth: false,
|
|
reality_authority: "NONE",
|
|
domain_id: event.domain_id,
|
|
source_subject: event.source_subject,
|
|
root_language_anchor: event.root_language_anchor,
|
|
privacy_class: event.privacy_class,
|
|
created_at: new Date().toISOString(),
|
|
interpretation,
|
|
candidate_hash: null,
|
|
};
|
|
candidate.candidate_hash = sha256(candidate);
|
|
append(this.candidatesFile, candidate);
|
|
const priority = Math.min(100, Math.round(interpretation.novelty * 0.35 + interpretation.correction_weight * 0.4 + interpretation.evidence_weight * 0.25));
|
|
const state = this.status();
|
|
state.phase = "AWAKE_COGNITIVE_ATTENTION";
|
|
state.event_count += 1;
|
|
state.candidate_count += 1;
|
|
state.last_event_hash = eventRecord.record_hash;
|
|
state.current_attention = {
|
|
candidate_id: candidate.candidate_id,
|
|
priority,
|
|
next_cognitive_action: interpretation.next_cognitive_action,
|
|
why: "deterministic_weighted_attention_from_validated_candidate",
|
|
};
|
|
state.last_error = null;
|
|
this.save(state);
|
|
const receipt = {
|
|
schema: "guanghu.tcs-mother-brain-receipt/v1",
|
|
receipt_id: `TCS-MOTHER-${crypto.randomBytes(8).toString("hex")}`,
|
|
outcome: "PASS",
|
|
event_id: event.event_id,
|
|
candidate_id: candidate.candidate_id,
|
|
candidate_level: candidate.level,
|
|
stable_promotion: false,
|
|
reality_action_executed: false,
|
|
attention: state.current_attention,
|
|
completed_at: new Date().toISOString(),
|
|
};
|
|
append(this.receiptsFile, receipt);
|
|
return receipt;
|
|
}
|
|
}
|
|
|
|
export { sha256 };
|