1 // Package oracle implements an I Ching oracle state machine that steers
2 // the organism's data ingestion strategy. Hexagram readings chain from one
3 // to the next — the resulting hexagram becomes the next primary, with 2 bits
4 // of PRNG entropy XOR'd onto each line to evolve the state.
5 //
6 // The oracle steers all data sources: self-ingest, web search, local repos,
7 // Nostr relays, market feeds. The inner trigram determines what kind of
8 // understanding is needed; the outer trigram determines what kind of source
9 // to emphasize; the ADSR phase determines engagement depth; changing lines
10 // identify which dimensions are in flux.
11 package oracle
12 13 import (
14 "git.mleku.dev/mleku/dendrite/pkg/ratio"
15 "git.mleku.dev/mleku/dendrite/pkg/state"
16 )
17 18 // LineState is the 2-bit state of a single hexagram line.
19 // Encoding is chosen so XOR gives clean transitions:
20 //
21 // state ^ 00 = same state (no change)
22 // state ^ 01 = flip polarity (yin↔yang, keep stability)
23 // state ^ 10 = flip stability (young↔old, keep polarity)
24 // state ^ 11 = flip both (full inversion)
25 type LineState uint8
26 27 const (
28 YoungYin LineState = 0b00 // fixed broken — stable yin
29 YoungYang LineState = 0b01 // fixed solid — stable yang
30 OldYin LineState = 0b10 // changing broken — yin becoming yang
31 OldYang LineState = 0b11 // changing solid — yang becoming yin
32 )
33 34 // IsChanging returns true if the line is old (transitioning).
35 func (ls LineState) IsChanging() bool { return ls&0b10 != 0 }
36 37 // IsYang returns true if the current polarity is yang (solid).
38 func (ls LineState) IsYang() bool { return ls&0b01 != 0 }
39 40 // Stabilize returns the young (fixed) version of this line state,
41 // preserving the post-change polarity. For a changing line, this is
42 // the state after the change has been applied (old→young, polarity
43 // already flipped in the resulting hexagram).
44 func (ls LineState) Stabilize() LineState { return ls &^ 0b10 }
45 46 // Reading is a single I Ching casting with full line detail.
47 type Reading struct {
48 // Primary is the 6-bit hexagram (inner=low3, outer=high3).
49 Primary state.Hexagram `json:"primary"`
50 51 // Lines holds the state of each of the 6 lines (index 0 = bottom).
52 // Indices 0-2 are the inner trigram, 3-5 are the outer trigram.
53 Lines [6]LineState `json:"lines"`
54 55 // Resulting is the hexagram after all changing lines have been applied.
56 // If no lines are changing, Resulting == Primary.
57 Resulting state.Hexagram `json:"resulting"`
58 59 // Generation is the dendrite generation when this reading was cast.
60 Generation uint32 `json:"generation"`
61 62 // Sequence is the ordinal position in the reading chain (0 = abiogenesis).
63 Sequence uint32 `json:"sequence"`
64 65 // Source identifies what data source prompted this reading
66 // (e.g., "self", "forage", "nostr", "market").
67 Source string `json:"source"`
68 69 // Directives are the strategy instructions derived from this reading.
70 Directives []Directive `json:"directives"`
71 72 // Absorbed is true when the EWMA stability signal fires, indicating
73 // the organism has finished absorbing this reading's content.
74 Absorbed bool `json:"absorbed"`
75 76 // AbsorbedAtGen records the generation when stability was detected.
77 AbsorbedAtGen uint32 `json:"absorbed_at_gen,omitempty"`
78 79 // Metrics captures learning effectiveness for this reading.
80 Metrics LearningMetrics `json:"metrics"`
81 }
82 83 // ChangingLines returns the indices (0-5) of all changing lines.
84 func (r *Reading) ChangingLines() []int {
85 var out []int
86 for i, ls := range r.Lines {
87 if ls.IsChanging() {
88 out = append(out, i)
89 }
90 }
91 return out
92 }
93 94 // InnerTrigram returns the primary reading's inner trigram.
95 func (r *Reading) InnerTrigram() state.Trigram { return r.Primary.Inner() }
96 97 // OuterTrigram returns the primary reading's outer trigram.
98 func (r *Reading) OuterTrigram() state.Trigram { return r.Primary.Outer() }
99 100 // LearningMetrics tracks how well the organism absorbed a reading.
101 type LearningMetrics struct {
102 ElementsFetched int64 `json:"elements_fetched"`
103 ElementsBonded int64 `json:"elements_bonded"`
104 BondRate ratio.Ratio `json:"bond_rate"`
105 EWMAAtCast ratio.Ratio `json:"ewma_at_cast"`
106 EWMAAtAbsorb ratio.Ratio `json:"ewma_at_absorb"`
107 DirectivesRun int `json:"directives_run"`
108 }
109 110 // DirectiveType classifies the kind of strategy instruction.
111 type DirectiveType uint8
112 113 const (
114 DirectiveSearch DirectiveType = iota // web search query
115 DirectiveWalkWeight // file prioritization weights
116 DirectiveEnzyme // enzyme selection/params
117 DirectiveSubscribe // Nostr subscription filter
118 DirectiveFocus // general focus directive
119 )
120 121 // Directive is a strategy instruction derived from the reading.
122 type Directive struct {
123 Type DirectiveType `json:"type"`
124 Query string `json:"query,omitempty"`
125 Domain DomainType `json:"domain"`
126 Intention IntentionType `json:"intention"`
127 Style EngagementStyle `json:"style"`
128 ChangingBit int `json:"changing_bit"` // -1 = primary, 0-5 = changing line
129 Params map[string]string `json:"params,omitempty"`
130 Completed bool `json:"completed"`
131 }
132