feat(tcs): bind history revisit to current persona subject

This commit is contained in:
冰朔 2026-08-12 15:44:33 +08:00
commit ab3c4e05a9
15 changed files with 523 additions and 7 deletions

View file

@ -5,6 +5,10 @@ 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);
@ -48,6 +52,8 @@ export class MotherBrainEngine {
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, {
@ -60,6 +66,8 @@ export class MotherBrainEngine {
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(),
@ -67,6 +75,121 @@ export class MotherBrainEngine {
}
}
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 raw = await this.modelClient.revisit({
...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",
});
const reunderstanding = this.validateReunderstanding(raw, binding);
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" };
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) {