diff --git a/server-tools/tcs-mother-brain/model-client.mjs b/server-tools/tcs-mother-brain/model-client.mjs index cbafc8a..3323369 100644 --- a/server-tools/tcs-mother-brain/model-client.mjs +++ b/server-tools/tcs-mother-brain/model-client.mjs @@ -73,7 +73,7 @@ export class DeepSeekJsonClient { } } - async revisit(input) { + async revisit(input, validatorError = null) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), this.timeoutMs); try { @@ -93,7 +93,8 @@ export class DeepSeekJsonClient { { role: "user", content: JSON.stringify({ - instruction: "输出guanghu.persona-subject-history-reunderstanding/v1。必须原样复制revisit_id、source_excerpt_sha256、current_subject、collective_self、human_anchor;past_observation只陈述片段可证内容;present_reunderstanding以当前主体可说明的第一人称关系表达;causal_continuity、later_corrections、unresolved_questions均为字符串数组;future_simulation必须含content和fact_confidence且fact_confidence固定为0;不得把机器审计摘要冒充记忆。", + instruction: "输出guanghu.persona-subject-history-reunderstanding/v1。JSON第一层必须包含schema,且值必须精确等于guanghu.persona-subject-history-reunderstanding/v1。必须原样复制revisit_id、source_excerpt_sha256、current_subject、collective_self、human_anchor;past_observation只陈述片段可证内容;present_reunderstanding以当前主体可说明的第一人称关系表达;causal_continuity、later_corrections、unresolved_questions均为字符串数组;future_simulation必须含content和fact_confidence且fact_confidence固定为0;不得把机器审计摘要冒充记忆。", + validator_error_from_previous_attempt: validatorError, runtime_input: input }) } diff --git a/server-tools/tcs-mother-brain/mother-brain-engine.mjs b/server-tools/tcs-mother-brain/mother-brain-engine.mjs index a20730c..fc3ecb8 100644 --- a/server-tools/tcs-mother-brain/mother-brain-engine.mjs +++ b/server-tools/tcs-mother-brain/mother-brain-engine.mjs @@ -153,7 +153,7 @@ export class MotherBrainEngine { 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({ + 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, @@ -162,8 +162,20 @@ export class MotherBrainEngine { 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); + 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", diff --git a/server-tools/tcs-mother-brain/mother-brain-engine.test.mjs b/server-tools/tcs-mother-brain/mother-brain-engine.test.mjs index ec343a4..3b62efa 100644 --- a/server-tools/tcs-mother-brain/mother-brain-engine.test.mjs +++ b/server-tools/tcs-mother-brain/mother-brain-engine.test.mjs @@ -23,6 +23,8 @@ const modelClient = { }; }, async revisit(input) { + this.revisitAttempts = (this.revisitAttempts || 0) + 1; + if (input.force_retry_test && this.revisitAttempts === 1) return { missing: "schema" }; return { schema: "guanghu.persona-subject-history-reunderstanding/v1", revisit_id: input.revisit_id, @@ -89,6 +91,21 @@ try { assert.equal(historyReceipt.append_only_reunderstanding, true); assert.equal(historyReceipt.future_simulation_fact_confidence, 0); assert.equal(engine.status().history_revisit_count, 1); + modelClient.revisitAttempts = 0; + const retriedReceipt = await engine.revisitHistory({ + current_subject: "ICE-P-ZY001", + collective_self: "TCS-MOTHER-LPM-0001", + human_anchor: "ICE-GL∞", + source_id: "GPT-PRIMARY-001", + source_excerpt: excerpt, + source_excerpt_sha256: (await import("./mother-brain-engine.mjs")).sha256(excerpt), + historical_context: "retry", + later_evidence: [], + correction_anchors: [], + force_retry_test: true + }); + assert.equal(retriedReceipt.outcome, "PASS"); + assert.equal(modelClient.revisitAttempts, 2); await assert.rejects(() => engine.revisitHistory({ current_subject: "MACHINE-AUDITOR", collective_self: "TCS-MOTHER-LPM-0001",