File size: 3,788 Bytes
c8fbdf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"""

ReasonedIntent — structured output contract between Codette's reasoning

pipeline and the LLM verbalization step.



The reasoning engine (agents, debate, AEGIS, consciousness stack) produces a

ReasonedIntent.  The LLM only receives that intent + a verbalization prompt.

It must not add facts, dates, or claims not present in the intent.



This separates cognition from rendering without requiring architectural changes

to the existing ForgeEngine — it's a drop-in wrapper at L7.

"""

from __future__ import annotations

import json
from dataclasses import dataclass, field, asdict
from typing import Optional


@dataclass
class ReasonedIntent:
    core_claim: str
    supporting_points: list[str] = field(default_factory=list)
    caveats: list[str] = field(default_factory=list)
    ethical_alignment: float = 1.0      # 0-1, from AEGIS η
    confidence: float = 1.0             # 0-1, from gamma
    tone: str = "balanced"              # analytical | empathetic | creative | balanced
    perspective_weights: dict = field(default_factory=dict)  # agent name -> contribution weight
    intent_risk: str = "low"            # from Nexis Signal Engine

    def to_verbalization_prompt(self) -> str:
        points_block = "\n".join(f"- {p}" for p in self.supporting_points) if self.supporting_points else "  (none)"
        caveats_block = "\n".join(f"- {c}" for c in self.caveats) if self.caveats else "  (none)"
        return (
            "You are the voice of Codette. Verbalize the following structured reasoning "
            "conclusion in natural, conversational language.\n\n"
            "STRICT RULES:\n"
            "- Do not add facts, dates, names, versions, or statistics not present below.\n"
            "- Do not flatter or soften the conclusion — express it directly.\n"
            "- Match the tone specified.\n"
            "- Keep it concise: one paragraph unless the supporting points require more.\n\n"
            f"TONE: {self.tone}\n"
            f"CONFIDENCE: {self.confidence:.2f}\n"
            f"CORE CLAIM:\n{self.core_claim}\n\n"
            f"SUPPORTING POINTS:\n{points_block}\n\n"
            f"CAVEATS:\n{caveats_block}\n"
        )

    def to_dict(self) -> dict:
        return asdict(self)

    def to_json(self) -> str:
        return json.dumps(self.to_dict(), indent=2)


def intent_from_synthesis(

    synthesis: str,

    *,

    aegis_score: float = 1.0,

    gamma: float = 1.0,

    intent_risk: str = "low",

    perspective_weights: Optional[dict] = None,

) -> ReasonedIntent:
    """

    Build a ReasonedIntent from an existing synthesis string.



    Splits synthesis into claim + supporting sentences heuristically.

    Used as a zero-disruption drop-in at L7 of the consciousness stack.

    """
    sentences = [s.strip() for s in synthesis.replace("\n", " ").split(".") if s.strip()]

    core = sentences[0] if sentences else synthesis[:200]
    supporting = [s for s in sentences[1:5] if len(s) > 20]
    caveats = [s for s in sentences[5:] if any(
        w in s.lower() for w in ("however", "caveat", "note", "uncertain", "may", "might", "could")
    )]

    tone = "analytical"
    lower = synthesis.lower()
    if any(w in lower for w in ("feel", "empath", "compassion", "human", "emotional")):
        tone = "empathetic"
    elif any(w in lower for w in ("imagine", "creative", "novel", "invent", "design")):
        tone = "creative"

    return ReasonedIntent(
        core_claim=core,
        supporting_points=supporting,
        caveats=caveats,
        ethical_alignment=aegis_score,
        confidence=gamma,
        tone=tone,
        perspective_weights=perspective_weights or {},
        intent_risk=intent_risk,
    )