kbs 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/deploy-github-pages.yml +52 -0
  3. data/CHANGELOG.md +68 -2
  4. data/README.md +235 -334
  5. data/docs/DOCUMENTATION_STATUS.md +158 -0
  6. data/docs/advanced/custom-persistence.md +775 -0
  7. data/docs/advanced/debugging.md +726 -0
  8. data/docs/advanced/index.md +8 -0
  9. data/docs/advanced/performance.md +832 -0
  10. data/docs/advanced/testing.md +691 -0
  11. data/docs/api/blackboard.md +1157 -0
  12. data/docs/api/engine.md +978 -0
  13. data/docs/api/facts.md +1212 -0
  14. data/docs/api/index.md +12 -0
  15. data/docs/api/rules.md +1034 -0
  16. data/docs/architecture/blackboard.md +553 -0
  17. data/docs/architecture/index.md +277 -0
  18. data/docs/architecture/network-structure.md +343 -0
  19. data/docs/architecture/rete-algorithm.md +737 -0
  20. data/docs/assets/css/custom.css +83 -0
  21. data/docs/assets/images/blackboard-architecture.svg +136 -0
  22. data/docs/assets/images/compiled-network.svg +101 -0
  23. data/docs/assets/images/fact-assertion-flow.svg +117 -0
  24. data/docs/assets/images/kbs.jpg +0 -0
  25. data/docs/assets/images/pattern-matching-trace.svg +136 -0
  26. data/docs/assets/images/rete-network-layers.svg +96 -0
  27. data/docs/assets/images/system-layers.svg +69 -0
  28. data/docs/assets/images/trading-signal-network.svg +139 -0
  29. data/docs/assets/js/mathjax.js +17 -0
  30. data/docs/examples/expert-systems.md +1031 -0
  31. data/docs/examples/index.md +9 -0
  32. data/docs/examples/multi-agent.md +1335 -0
  33. data/docs/examples/stock-trading.md +488 -0
  34. data/docs/guides/blackboard-memory.md +558 -0
  35. data/docs/guides/dsl.md +1321 -0
  36. data/docs/guides/facts.md +652 -0
  37. data/docs/guides/getting-started.md +383 -0
  38. data/docs/guides/index.md +23 -0
  39. data/docs/guides/negation.md +529 -0
  40. data/docs/guides/pattern-matching.md +561 -0
  41. data/docs/guides/persistence.md +451 -0
  42. data/docs/guides/variable-binding.md +491 -0
  43. data/docs/guides/writing-rules.md +755 -0
  44. data/docs/index.md +157 -0
  45. data/docs/installation.md +156 -0
  46. data/docs/quick-start.md +228 -0
  47. data/examples/README.md +2 -2
  48. data/examples/advanced_example.rb +2 -2
  49. data/examples/advanced_example_dsl.rb +224 -0
  50. data/examples/ai_enhanced_kbs.rb +1 -1
  51. data/examples/ai_enhanced_kbs_dsl.rb +538 -0
  52. data/examples/blackboard_demo_dsl.rb +50 -0
  53. data/examples/car_diagnostic.rb +1 -1
  54. data/examples/car_diagnostic_dsl.rb +54 -0
  55. data/examples/concurrent_inference_demo.rb +5 -5
  56. data/examples/concurrent_inference_demo_dsl.rb +363 -0
  57. data/examples/csv_trading_system.rb +1 -1
  58. data/examples/csv_trading_system_dsl.rb +525 -0
  59. data/examples/knowledge_base.db +0 -0
  60. data/examples/portfolio_rebalancing_system.rb +2 -2
  61. data/examples/portfolio_rebalancing_system_dsl.rb +613 -0
  62. data/examples/redis_trading_demo_dsl.rb +177 -0
  63. data/examples/run_all.rb +50 -0
  64. data/examples/run_all_dsl.rb +49 -0
  65. data/examples/stock_trading_advanced.rb +1 -1
  66. data/examples/stock_trading_advanced_dsl.rb +404 -0
  67. data/examples/temp.txt +7693 -0
  68. data/examples/temp_dsl.txt +8447 -0
  69. data/examples/timestamped_trading.rb +1 -1
  70. data/examples/timestamped_trading_dsl.rb +258 -0
  71. data/examples/trading_demo.rb +1 -1
  72. data/examples/trading_demo_dsl.rb +322 -0
  73. data/examples/working_demo.rb +1 -1
  74. data/examples/working_demo_dsl.rb +160 -0
  75. data/lib/kbs/blackboard/engine.rb +3 -3
  76. data/lib/kbs/blackboard/fact.rb +1 -1
  77. data/lib/kbs/condition.rb +1 -1
  78. data/lib/kbs/dsl/knowledge_base.rb +1 -1
  79. data/lib/kbs/dsl/variable.rb +1 -1
  80. data/lib/kbs/{rete_engine.rb → engine.rb} +1 -1
  81. data/lib/kbs/fact.rb +1 -1
  82. data/lib/kbs/version.rb +1 -1
  83. data/lib/kbs.rb +2 -2
  84. data/mkdocs.yml +181 -0
  85. metadata +66 -6
  86. data/examples/stock_trading_system.rb.bak +0 -563
@@ -0,0 +1,83 @@
1
+ /* Custom CSS for KBS Documentation */
2
+
3
+ /* SVG image styling */
4
+ img[src$=".svg"] {
5
+ max-width: 100%;
6
+ height: auto;
7
+ margin: 2em 0;
8
+ border-radius: 8px;
9
+ background: transparent;
10
+ }
11
+
12
+ /* Code block enhancements */
13
+ .highlight pre {
14
+ border-radius: 8px;
15
+ padding: 1em;
16
+ }
17
+
18
+ /* Improve table styling */
19
+ table {
20
+ border-collapse: collapse;
21
+ width: 100%;
22
+ margin: 1.5em 0;
23
+ }
24
+
25
+ table th {
26
+ background-color: rgba(187, 134, 252, 0.2);
27
+ font-weight: bold;
28
+ }
29
+
30
+ table td, table th {
31
+ padding: 0.75em;
32
+ border: 1px solid rgba(255, 255, 255, 0.1);
33
+ }
34
+
35
+ table tr:hover {
36
+ background-color: rgba(187, 134, 252, 0.1);
37
+ }
38
+
39
+ /* Admonition customization */
40
+ .admonition {
41
+ border-radius: 8px;
42
+ margin: 1.5em 0;
43
+ }
44
+
45
+ /* Implementation reference links */
46
+ strong + a[href*="lib/kbs"] {
47
+ font-family: monospace;
48
+ font-size: 0.9em;
49
+ color: #03dac6;
50
+ }
51
+
52
+ /* Enhance inline code */
53
+ code {
54
+ background-color: rgba(187, 134, 252, 0.15);
55
+ padding: 0.2em 0.4em;
56
+ border-radius: 4px;
57
+ font-size: 0.9em;
58
+ }
59
+
60
+ /* Navigation improvements */
61
+ .md-nav__title {
62
+ font-weight: bold;
63
+ }
64
+
65
+ /* Search result highlighting */
66
+ .md-search-result__article--document {
67
+ border-left: 3px solid #bb86fc;
68
+ }
69
+
70
+ /* Smooth scrolling for anchor links */
71
+ html {
72
+ scroll-behavior: smooth;
73
+ }
74
+
75
+ /* Figure captions for SVG diagrams */
76
+ em {
77
+ display: block;
78
+ text-align: center;
79
+ font-style: italic;
80
+ color: rgba(255, 255, 255, 0.6);
81
+ margin-top: -1.5em;
82
+ margin-bottom: 1.5em;
83
+ }
@@ -0,0 +1,136 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 700" style="background: transparent;">
2
+ <defs>
3
+ <style>
4
+ .title { font: bold 18px monospace; fill: #e0e0e0; }
5
+ .component-title { font: bold 14px monospace; fill: #bb86fc; }
6
+ .label { font: 12px monospace; fill: #e0e0e0; }
7
+ .code { font: 11px monospace; fill: #03dac6; }
8
+ .comment { font: italic 10px monospace; fill: #888; }
9
+ .box { fill: #2d2d2d; stroke: #bb86fc; stroke-width: 2; }
10
+ .core-box { fill: #3d2d4d; stroke: #bb86fc; stroke-width: 3; }
11
+ .storage-box { fill: #2d3d3d; stroke: #03dac6; stroke-width: 2; }
12
+ .agent-box { fill: #4d3d2d; stroke: #cf6679; stroke-width: 2; }
13
+ .arrow { stroke: #bb86fc; stroke-width: 2; fill: none; marker-end: url(#arrowhead); }
14
+ .data-arrow { stroke: #03dac6; stroke-width: 2; fill: none; marker-end: url(#data-arrowhead); stroke-dasharray: 5,3; }
15
+ </style>
16
+ <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
17
+ <polygon points="0 0, 10 3, 0 6" fill="#bb86fc" />
18
+ </marker>
19
+ <marker id="data-arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
20
+ <polygon points="0 0, 10 3, 0 6" fill="#03dac6" />
21
+ </marker>
22
+ </defs>
23
+
24
+ <!-- Title -->
25
+ <text x="500" y="30" class="title" text-anchor="middle">Blackboard Architecture</text>
26
+
27
+ <!-- Central Blackboard Memory -->
28
+ <rect x="350" y="70" width="300" height="200" class="core-box" rx="8"/>
29
+ <text x="500" y="95" class="component-title" text-anchor="middle">Blackboard Memory</text>
30
+ <text x="500" y="115" class="comment" text-anchor="middle">(Central Shared Workspace)</text>
31
+
32
+ <!-- Memory components -->
33
+ <text x="370" y="140" class="label">• Facts (persistent)</text>
34
+ <text x="370" y="160" class="label">• Message Queue</text>
35
+ <text x="370" y="180" class="label">• Audit Log</text>
36
+ <text x="370" y="200" class="label">• Observer notifications</text>
37
+ <text x="370" y="220" class="label">• Transaction support</text>
38
+ <text x="370" y="240" class="code">UUID-based fact tracking</text>
39
+
40
+ <!-- Agents (top) -->
41
+ <text x="500" y="315" class="component-title" text-anchor="middle">Agents / Knowledge Sources</text>
42
+
43
+ <!-- Agent 1 -->
44
+ <rect x="50" y="330" width="200" height="100" class="agent-box" rx="5"/>
45
+ <text x="150" y="355" class="component-title" text-anchor="middle">Trading Agent</text>
46
+ <text x="150" y="380" class="code" text-anchor="middle">Reads: stock prices</text>
47
+ <text x="150" y="397" class="code" text-anchor="middle">Writes: buy/sell orders</text>
48
+ <text x="150" y="414" class="code" text-anchor="middle">Priority: 10</text>
49
+
50
+ <!-- Agent 2 -->
51
+ <rect x="280" y="330" width="200" height="100" class="agent-box" rx="5"/>
52
+ <text x="380" y="355" class="component-title" text-anchor="middle">Risk Agent</text>
53
+ <text x="380" y="380" class="code" text-anchor="middle">Reads: orders, portfolio</text>
54
+ <text x="380" y="397" class="code" text-anchor="middle">Writes: risk alerts</text>
55
+ <text x="380" y="414" class="code" text-anchor="middle">Priority: 20</text>
56
+
57
+ <!-- Agent 3 -->
58
+ <rect x="510" y="330" width="200" height="100" class="agent-box" rx="5"/>
59
+ <text x="610" y="355" class="component-title" text-anchor="middle">Analytics Agent</text>
60
+ <text x="610" y="380" class="code" text-anchor="middle">Reads: all facts</text>
61
+ <text x="610" y="397" class="code" text-anchor="middle">Writes: insights</text>
62
+ <text x="610" y="414" class="code" text-anchor="middle">Priority: 5</text>
63
+
64
+ <!-- Agent 4 -->
65
+ <rect x="750" y="330" width="200" height="100" class="agent-box" rx="5"/>
66
+ <text x="850" y="355" class="component-title" text-anchor="middle">Execution Agent</text>
67
+ <text x="850" y="380" class="code" text-anchor="middle">Reads: approved orders</text>
68
+ <text x="850" y="397" class="code" text-anchor="middle">Writes: executions</text>
69
+ <text x="850" y="414" class="code" text-anchor="middle">Priority: 30</text>
70
+
71
+ <!-- Arrows from agents to blackboard -->
72
+ <path d="M 150 330 L 400 270" class="arrow"/>
73
+ <path d="M 380 330 L 450 270" class="arrow"/>
74
+ <path d="M 610 330 L 550 270" class="arrow"/>
75
+ <path d="M 850 330 L 600 270" class="arrow"/>
76
+
77
+ <!-- RETE Engine -->
78
+ <rect x="100" y="90" width="180" height="80" class="box" rx="5"/>
79
+ <text x="190" y="115" class="component-title" text-anchor="middle">RETE Engine</text>
80
+ <text x="190" y="135" class="code" text-anchor="middle">Pattern matching</text>
81
+ <text x="190" y="152" class="code" text-anchor="middle">Rule execution</text>
82
+
83
+ <!-- Arrow from RETE to Blackboard -->
84
+ <path d="M 280 130 L 350 130" class="arrow"/>
85
+
86
+ <!-- Persistence Layer (bottom) -->
87
+ <text x="500" y="485" class="component-title" text-anchor="middle">Persistence Layer (Pluggable)</text>
88
+
89
+ <!-- SQLite Store -->
90
+ <rect x="100" y="500" width="220" height="150" class="storage-box" rx="5"/>
91
+ <text x="210" y="525" class="component-title" text-anchor="middle">SQLite Store</text>
92
+ <text x="210" y="550" class="label" text-anchor="middle">Tables:</text>
93
+ <text x="210" y="570" class="code" text-anchor="middle">• facts</text>
94
+ <text x="210" y="587" class="code" text-anchor="middle">• messages</text>
95
+ <text x="210" y="604" class="code" text-anchor="middle">• audit_log</text>
96
+ <text x="210" y="625" class="comment" text-anchor="middle">✓ ACID transactions</text>
97
+ <text x="210" y="642" class="comment" text-anchor="middle">✓ Durable</text>
98
+
99
+ <!-- Redis Store -->
100
+ <rect x="350" y="500" width="220" height="150" class="storage-box" rx="5"/>
101
+ <text x="460" y="525" class="component-title" text-anchor="middle">Redis Store</text>
102
+ <text x="460" y="550" class="label" text-anchor="middle">Data Structures:</text>
103
+ <text x="460" y="570" class="code" text-anchor="middle">• fact:{uuid} (hash)</text>
104
+ <text x="460" y="587" class="code" text-anchor="middle">• facts:type:{t} (set)</text>
105
+ <text x="460" y="604" class="code" text-anchor="middle">• messages (zset)</text>
106
+ <text x="460" y="625" class="comment" text-anchor="middle">✓ 100x faster</text>
107
+ <text x="460" y="642" class="comment" text-anchor="middle">✓ Distributed</text>
108
+
109
+ <!-- Hybrid Store -->
110
+ <rect x="600" y="500" width="220" height="150" class="storage-box" rx="5"/>
111
+ <text x="710" y="525" class="component-title" text-anchor="middle">Hybrid Store</text>
112
+ <text x="710" y="550" class="label" text-anchor="middle">Best of Both:</text>
113
+ <text x="710" y="570" class="code" text-anchor="middle">• Redis for facts</text>
114
+ <text x="710" y="587" class="code" text-anchor="middle">• SQLite for audit</text>
115
+ <text x="710" y="604" class="code" text-anchor="middle">• Fast + durable</text>
116
+ <text x="710" y="625" class="comment" text-anchor="middle">✓ </text>
117
+ <text x="710" y="642" class="comment" text-anchor="middle">✓ Full audit trail</text>
118
+
119
+ <!-- Arrows from Blackboard to Storage -->
120
+ <path d="M 400 270 L 210 500" class="data-arrow"/>
121
+ <path d="M 500 270 L 460 500" class="data-arrow"/>
122
+ <path d="M 600 270 L 710 500" class="data-arrow"/>
123
+
124
+ <!-- Message Flow Indicator -->
125
+ <rect x="850" y="90" width="130" height="160" class="box" rx="5" stroke-dasharray="5,3"/>
126
+ <text x="915" y="110" class="component-title" text-anchor="middle">Message Flow</text>
127
+ <text x="915" y="135" class="code" text-anchor="middle">1. Agent writes fact</text>
128
+ <text x="915" y="155" class="code" text-anchor="middle">2. RETE matches</text>
129
+ <text x="915" y="175" class="code" text-anchor="middle">3. Rules fire</text>
130
+ <text x="915" y="195" class="code" text-anchor="middle">4. New facts added</text>
131
+ <text x="915" y="215" class="code" text-anchor="middle">5. Other agents see</text>
132
+ <text x="915" y="235" class="code" text-anchor="middle">6. Cycle continues</text>
133
+
134
+ <!-- Legend -->
135
+ <text x="50" y="690" class="comment">Purple: Control/Logic | Teal: Data Storage | Pink: Agents/Knowledge Sources</text>
136
+ </svg>
@@ -0,0 +1,101 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 700" style="background: transparent;">
2
+ <defs>
3
+ <style>
4
+ .title { font: bold 16px monospace; fill: #e0e0e0; }
5
+ .node-title { font: bold 12px monospace; fill: #bb86fc; }
6
+ .label { font: 11px monospace; fill: #e0e0e0; }
7
+ .beta-box { fill: #2d3d4d; stroke: #03dac6; stroke-width: 2; }
8
+ .alpha-box { fill: #3d2d4d; stroke: #bb86fc; stroke-width: 2; }
9
+ .join-box { fill: #2d4d3d; stroke: #4daf50; stroke-width: 2; }
10
+ .neg-box { fill: #4d2d2d; stroke: #cf6679; stroke-width: 2; }
11
+ .prod-box { fill: #4d4d2d; stroke: #ffa500; stroke-width: 2; }
12
+ .arrow { stroke: #bb86fc; stroke-width: 2; fill: none; marker-end: url(#arrowhead); }
13
+ .arrow-beta { stroke: #03dac6; stroke-width: 2; fill: none; marker-end: url(#arrowhead-beta); }
14
+ </style>
15
+ <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
16
+ <polygon points="0 0, 10 3, 0 6" fill="#bb86fc" />
17
+ </marker>
18
+ <marker id="arrowhead-beta" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
19
+ <polygon points="0 0, 10 3, 0 6" fill="#03dac6" />
20
+ </marker>
21
+ </defs>
22
+
23
+ <!-- Title -->
24
+ <text x="300" y="30" class="title" text-anchor="middle">Compiled RETE Network</text>
25
+ <text x="300" y="50" class="label" text-anchor="middle" style="font-style: italic; fill: #888;">Example rule with negation</text>
26
+
27
+ <!-- Root Beta Memory -->
28
+ <rect x="200" y="80" width="200" height="50" class="beta-box" rx="5"/>
29
+ <text x="300" y="105" class="node-title" text-anchor="middle">Root Beta Memory</text>
30
+ <text x="300" y="120" class="label" text-anchor="middle">(dummy token)</text>
31
+
32
+ <!-- Arrow from root to join -->
33
+ <path d="M 250 130 L 250 180" class="arrow-beta"/>
34
+
35
+ <!-- AlphaMemory(stock) on right -->
36
+ <rect x="420" y="150" width="150" height="60" class="alpha-box" rx="5"/>
37
+ <text x="495" y="175" class="node-title" text-anchor="middle">AlphaMemory</text>
38
+ <text x="495" y="195" class="label" text-anchor="middle">:stock</text>
39
+
40
+ <!-- Arrow from alpha to join -->
41
+ <path d="M 420 180 L 310 200" class="arrow"/>
42
+
43
+ <!-- JoinNode1 -->
44
+ <rect x="200" y="180" width="110" height="50" class="join-box" rx="5"/>
45
+ <text x="255" y="205" class="node-title" text-anchor="middle">JoinNode1</text>
46
+ <text x="255" y="220" class="label" text-anchor="middle">test: ?sym</text>
47
+
48
+ <!-- Arrow from join to beta1 -->
49
+ <path d="M 255 230 L 255 270" class="arrow-beta"/>
50
+
51
+ <!-- BetaMemory1 -->
52
+ <rect x="180" y="270" width="150" height="50" class="beta-box" rx="5"/>
53
+ <text x="255" y="295" class="node-title" text-anchor="middle">BetaMemory1</text>
54
+ <text x="255" y="310" class="label" text-anchor="middle">(stock tokens)</text>
55
+
56
+ <!-- Arrow from beta1 to negation -->
57
+ <path d="M 255 320 L 255 370" class="arrow-beta"/>
58
+
59
+ <!-- AlphaMemory(alert) on right -->
60
+ <rect x="420" y="350" width="150" height="60" class="alpha-box" rx="5"/>
61
+ <text x="495" y="375" class="node-title" text-anchor="middle">AlphaMemory</text>
62
+ <text x="495" y="395" class="label" text-anchor="middle">:alert</text>
63
+
64
+ <!-- Arrow from alpha alert to negation -->
65
+ <path d="M 420 380 L 340 390" class="arrow"/>
66
+
67
+ <!-- NegationNode -->
68
+ <rect x="170" y="370" width="170" height="50" class="neg-box" rx="5"/>
69
+ <text x="255" y="395" class="node-title" text-anchor="middle">NegationNode</text>
70
+ <text x="255" y="410" class="label" text-anchor="middle">NOT :alert, test: ?sym</text>
71
+
72
+ <!-- Arrow from negation to beta2 -->
73
+ <path d="M 255 420 L 255 460" class="arrow-beta"/>
74
+
75
+ <!-- BetaMemory2 (implicit) -->
76
+ <rect x="180" y="460" width="150" height="50" class="beta-box" rx="5"/>
77
+ <text x="255" y="485" class="node-title" text-anchor="middle">BetaMemory2</text>
78
+ <text x="255" y="500" class="label" text-anchor="middle">(matched tokens)</text>
79
+
80
+ <!-- Arrow from beta2 to production -->
81
+ <path d="M 255 510 L 255 560" class="arrow"/>
82
+
83
+ <!-- ProductionNode -->
84
+ <rect x="160" y="560" width="190" height="70" class="prod-box" rx="5"/>
85
+ <text x="255" y="590" class="node-title" text-anchor="middle">ProductionNode</text>
86
+ <text x="255" y="610" class="label" text-anchor="middle">Rule: "example"</text>
87
+ <text x="255" y="625" class="label" text-anchor="middle">Action: print ?sym</text>
88
+
89
+ <!-- Legend -->
90
+ <text x="50" y="670" class="label" style="font-size: 10px;">Legend:</text>
91
+ <rect x="120" y="655" width="40" height="20" class="beta-box" rx="2"/>
92
+ <text x="165" y="670" class="label" style="font-size: 10px;">Beta</text>
93
+ <rect x="210" y="655" width="40" height="20" class="alpha-box" rx="2"/>
94
+ <text x="255" y="670" class="label" style="font-size: 10px;">Alpha</text>
95
+ <rect x="300" y="655" width="40" height="20" class="join-box" rx="2"/>
96
+ <text x="345" y="670" class="label" style="font-size: 10px;">Join</text>
97
+ <rect x="385" y="655" width="40" height="20" class="neg-box" rx="2"/>
98
+ <text x="430" y="670" class="label" style="font-size: 10px;">Negation</text>
99
+ <rect x="480" y="655" width="40" height="20" class="prod-box" rx="2"/>
100
+ <text x="525" y="670" class="label" style="font-size: 10px;">Production</text>
101
+ </svg>
@@ -0,0 +1,117 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 700" style="background: transparent;">
2
+ <defs>
3
+ <style>
4
+ .title { font: bold 18px monospace; fill: #e0e0e0; }
5
+ .step-label { font: bold 14px monospace; fill: #bb86fc; }
6
+ .node-label { font: 12px monospace; fill: #e0e0e0; }
7
+ .code-label { font: 11px monospace; fill: #03dac6; }
8
+ .box { fill: #2d2d2d; stroke: #bb86fc; stroke-width: 2; }
9
+ .highlight-box { fill: #3d2d4d; stroke: #bb86fc; stroke-width: 3; }
10
+ .flow-arrow { stroke: #cf6679; stroke-width: 3; fill: none; marker-end: url(#flow-arrow); }
11
+ .data-arrow { stroke: #03dac6; stroke-width: 2; fill: none; marker-end: url(#data-arrow); stroke-dasharray: 5,5; }
12
+ </style>
13
+ <marker id="flow-arrow" markerWidth="12" markerHeight="12" refX="10" refY="3" orient="auto">
14
+ <polygon points="0 0, 12 3, 0 6" fill="#cf6679" />
15
+ </marker>
16
+ <marker id="data-arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
17
+ <polygon points="0 0, 10 3, 0 6" fill="#03dac6" />
18
+ </marker>
19
+ </defs>
20
+
21
+ <!-- Title -->
22
+ <text x="450" y="30" class="title" text-anchor="middle">Fact Assertion Flow</text>
23
+ <text x="450" y="50" class="code-label" text-anchor="middle">engine.add_fact(:stock, symbol: "AAPL", price: 150)</text>
24
+
25
+ <!-- Step 1: WorkingMemory.add_fact -->
26
+ <rect x="50" y="80" width="280" height="80" class="highlight-box" rx="5"/>
27
+ <text x="190" y="105" class="step-label" text-anchor="middle">1. WorkingMemory.add_fact(fact)</text>
28
+ <text x="190" y="130" class="code-label" text-anchor="middle">@facts &lt;&lt; fact</text>
29
+ <text x="190" y="147" class="code-label" text-anchor="middle">notify_observers(:add, fact)</text>
30
+
31
+ <!-- Arrow to Step 2 -->
32
+ <path d="M 190 160 L 190 200" class="flow-arrow"/>
33
+
34
+ <!-- Step 2: ReteEngine.update -->
35
+ <rect x="50" y="200" width="280" height="80" class="highlight-box" rx="5"/>
36
+ <text x="190" y="225" class="step-label" text-anchor="middle">2. ReteEngine.update(:add, fact)</text>
37
+ <text x="190" y="250" class="code-label" text-anchor="middle">For each alpha_memory:</text>
38
+ <text x="190" y="267" class="code-label" text-anchor="middle">if fact.matches?(pattern)</text>
39
+
40
+ <!-- Arrow to Step 3 -->
41
+ <path d="M 190 280 L 190 320" class="flow-arrow"/>
42
+
43
+ <!-- Step 3: AlphaMemory.activate -->
44
+ <rect x="50" y="320" width="280" height="100" class="highlight-box" rx="5"/>
45
+ <text x="190" y="345" class="step-label" text-anchor="middle">3. AlphaMemory.activate(fact)</text>
46
+ <text x="190" y="370" class="code-label" text-anchor="middle">return unless @linked</text>
47
+ <text x="190" y="387" class="code-label" text-anchor="middle">@items &lt;&lt; fact</text>
48
+ <text x="190" y="404" class="code-label" text-anchor="middle">For each successor join_node:</text>
49
+
50
+ <!-- Arrow to Step 4 -->
51
+ <path d="M 190 420 L 190 460" class="flow-arrow"/>
52
+
53
+ <!-- Step 4: JoinNode.right_activate -->
54
+ <rect x="50" y="460" width="280" height="120" class="highlight-box" rx="5"/>
55
+ <text x="190" y="485" class="step-label" text-anchor="middle">4. JoinNode.right_activate(fact)</text>
56
+ <text x="190" y="510" class="code-label" text-anchor="middle">return unless @left_linked &amp;&amp; @right_linked</text>
57
+ <text x="190" y="527" class="code-label" text-anchor="middle">For each token in beta_memory:</text>
58
+ <text x="190" y="544" class="code-label" text-anchor="middle">if perform_join_tests(token, fact)</text>
59
+ <text x="190" y="561" class="code-label" text-anchor="middle">new_token = Token.new(token, fact, self)</text>
60
+
61
+ <!-- Arrow to Step 5 -->
62
+ <path d="M 190 580 L 190 620" class="flow-arrow"/>
63
+
64
+ <!-- Step 5: Token Propagation -->
65
+ <rect x="50" y="620" width="280" height="60" class="highlight-box" rx="5"/>
66
+ <text x="190" y="645" class="step-label" text-anchor="middle">5. Propagate Token</text>
67
+ <text x="190" y="667" class="code-label" text-anchor="middle">@successors.each { |s| s.activate(new_token) }</text>
68
+
69
+ <!-- Right side: Data structures -->
70
+ <text x="550" y="105" class="step-label">Data Structures Updated:</text>
71
+
72
+ <!-- Working Memory -->
73
+ <rect x="450" y="130" width="400" height="80" class="box" rx="5"/>
74
+ <text x="650" y="155" class="step-label" text-anchor="middle">Working Memory</text>
75
+ <text x="650" y="180" class="node-label" text-anchor="middle">@facts = [</text>
76
+ <text x="650" y="197" class="code-label" text-anchor="middle">stock(symbol: "AAPL", price: 150)</text>
77
+ <text x="650" y="205" class="node-label" text-anchor="middle">]</text>
78
+
79
+ <!-- Data flow arrow from step 1 -->
80
+ <path d="M 330 120 L 450 160" class="data-arrow"/>
81
+
82
+ <!-- Alpha Memory -->
83
+ <rect x="450" y="250" width="400" height="80" class="box" rx="5"/>
84
+ <text x="650" y="275" class="step-label" text-anchor="middle">Alpha Memory (stock pattern)</text>
85
+ <text x="650" y="300" class="node-label" text-anchor="middle">@items = [</text>
86
+ <text x="650" y="317" class="code-label" text-anchor="middle">stock(symbol: "AAPL", price: 150)</text>
87
+ <text x="650" y="325" class="node-label" text-anchor="middle">]</text>
88
+
89
+ <!-- Data flow arrow from step 3 -->
90
+ <path d="M 330 360 L 450 280" class="data-arrow"/>
91
+
92
+ <!-- Beta Memory -->
93
+ <rect x="450" y="370" width="400" height="100" class="box" rx="5"/>
94
+ <text x="650" y="395" class="step-label" text-anchor="middle">Beta Memory (after join)</text>
95
+ <text x="650" y="420" class="node-label" text-anchor="middle">@tokens = [</text>
96
+ <text x="650" y="437" class="code-label" text-anchor="middle">Token(parent: root_token,</text>
97
+ <text x="650" y="454" class="code-label" text-anchor="middle">fact: stock(symbol: "AAPL", price: 150))</text>
98
+ <text x="650" y="462" class="node-label" text-anchor="middle">]</text>
99
+
100
+ <!-- Data flow arrow from step 4 -->
101
+ <path d="M 330 520 L 450 420" class="data-arrow"/>
102
+
103
+ <!-- Production Node -->
104
+ <rect x="450" y="500" width="400" height="100" class="box" rx="5"/>
105
+ <text x="650" y="525" class="step-label" text-anchor="middle">Production Node (if fully matched)</text>
106
+ <text x="650" y="550" class="node-label" text-anchor="middle">@tokens = [</text>
107
+ <text x="650" y="567" class="code-label" text-anchor="middle">Token(...) // ready to fire</text>
108
+ <text x="650" y="584" class="node-label" text-anchor="middle">]</text>
109
+ <text x="650" y="592" class="code-label" text-anchor="middle">Call engine.run() to execute rule actions</text>
110
+
111
+ <!-- Data flow arrow from step 5 -->
112
+ <path d="M 330 650 L 450 550" class="data-arrow"/>
113
+
114
+ <!-- Legend -->
115
+ <text x="50" y="695" class="code-label">Pink arrows: Control flow</text>
116
+ <text x="350" y="695" class="code-label">Teal dashed: Data updates</text>
117
+ </svg>
Binary file
@@ -0,0 +1,136 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 800" style="background: transparent;">
2
+ <defs>
3
+ <style>
4
+ .title { font: bold 18px monospace; fill: #e0e0e0; }
5
+ .phase-title { font: bold 16px monospace; fill: #bb86fc; }
6
+ .step-label { font: bold 13px monospace; fill: #cf6679; }
7
+ .node-label { font: 12px monospace; fill: #e0e0e0; }
8
+ .code-label { font: 11px monospace; fill: #03dac6; }
9
+ .comment { font: italic 11px monospace; fill: #888; }
10
+ .box { fill: #2d2d2d; stroke: #bb86fc; stroke-width: 2; }
11
+ .alpha-box { fill: #3d2d4d; stroke: #bb86fc; stroke-width: 2; }
12
+ .beta-box { fill: #2d3d3d; stroke: #03dac6; stroke-width: 2; }
13
+ .negation-box { fill: #4d2d2d; stroke: #cf6679; stroke-width: 2; }
14
+ .production-box { fill: #2d2d3d; stroke: #ffd700; stroke-width: 2; }
15
+ .flow-arrow { stroke: #cf6679; stroke-width: 2.5; fill: none; marker-end: url(#arrow); }
16
+ .inhibit-arrow { stroke: #ff5555; stroke-width: 2.5; fill: none; marker-end: url(#inhibit); stroke-dasharray: 5,3; }
17
+ </style>
18
+ <marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
19
+ <polygon points="0 0, 10 3, 0 6" fill="#cf6679" />
20
+ </marker>
21
+ <marker id="inhibit" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
22
+ <polygon points="0 0, 10 3, 0 6" fill="#ff5555" />
23
+ </marker>
24
+ </defs>
25
+
26
+ <!-- Title -->
27
+ <text x="500" y="25" class="title" text-anchor="middle">Pattern Matching Trace: Negation Example</text>
28
+ <text x="500" y="45" class="code-label" text-anchor="middle">Rule: Alert when AAPL stock exists but NO alert exists</text>
29
+
30
+ <!-- Network Structure -->
31
+ <text x="30" y="80" class="phase-title">Network Structure:</text>
32
+
33
+ <!-- Root Beta Memory -->
34
+ <rect x="30" y="95" width="140" height="60" class="beta-box" rx="5"/>
35
+ <text x="100" y="120" class="node-label" text-anchor="middle">Root Beta</text>
36
+ <text x="100" y="137" class="code-label" text-anchor="middle">[dummy token]</text>
37
+
38
+ <!-- Alpha 1: stock -->
39
+ <rect x="220" y="95" width="140" height="60" class="alpha-box" rx="5"/>
40
+ <text x="290" y="115" class="node-label" text-anchor="middle">Alpha Memory 1</text>
41
+ <text x="290" y="132" class="code-label" text-anchor="middle">stock(symbol:</text>
42
+ <text x="290" y="147" class="code-label" text-anchor="middle">"AAPL")</text>
43
+
44
+ <!-- Join Node 1 -->
45
+ <rect x="30" y="185" width="140" height="50" class="box" rx="5"/>
46
+ <text x="100" y="215" class="node-label" text-anchor="middle">Join Node 1</text>
47
+
48
+ <!-- Beta Memory 1 -->
49
+ <rect x="30" y="265" width="140" height="60" class="beta-box" rx="5"/>
50
+ <text x="100" y="290" class="node-label" text-anchor="middle">Beta Memory 1</text>
51
+ <text x="100" y="307" class="code-label" text-anchor="middle">[partial matches]</text>
52
+
53
+ <!-- Alpha 2: alert -->
54
+ <rect x="220" y="265" width="140" height="60" class="alpha-box" rx="5"/>
55
+ <text x="290" y="285" class="node-label" text-anchor="middle">Alpha Memory 2</text>
56
+ <text x="290" y="302" class="code-label" text-anchor="middle">alert(symbol:</text>
57
+ <text x="290" y="317" class="code-label" text-anchor="middle">"AAPL")</text>
58
+
59
+ <!-- Negation Node -->
60
+ <rect x="30" y="355" width="140" height="50" class="negation-box" rx="5"/>
61
+ <text x="100" y="385" class="node-label" text-anchor="middle">Negation Node</text>
62
+
63
+ <!-- Production Node -->
64
+ <rect x="30" y="435" width="140" height="50" class="production-box" rx="5"/>
65
+ <text x="100" y="465" class="node-label" text-anchor="middle">Production Node</text>
66
+
67
+ <!-- Network connections -->
68
+ <path d="M 100 155 L 100 185" class="flow-arrow"/>
69
+ <path d="M 290 155 L 150 185" class="flow-arrow"/>
70
+ <path d="M 100 235 L 100 265" class="flow-arrow"/>
71
+ <path d="M 100 325 L 100 355" class="flow-arrow"/>
72
+ <path d="M 290 325 L 150 365" class="flow-arrow"/>
73
+ <path d="M 100 405 L 100 435" class="flow-arrow"/>
74
+
75
+ <!-- Phase 1: Add stock fact -->
76
+ <text x="450" y="80" class="phase-title">Phase 1: Add Stock Fact</text>
77
+ <rect x="450" y="95" width="520" height="140" class="box" rx="5"/>
78
+
79
+ <text x="470" y="115" class="step-label">1. engine.add_fact(:stock, symbol: "AAPL", price: 150)</text>
80
+
81
+ <text x="470" y="138" class="code-label">✓ Matches Alpha Memory 1 → activates</text>
82
+ <text x="470" y="155" class="code-label">✓ Join Node 1: joins stock fact with root token</text>
83
+ <text x="470" y="172" class="code-label">✓ Creates Token(parent: root, fact: stock_fact)</text>
84
+ <text x="470" y="189" class="code-label">✓ Propagates to Beta Memory 1</text>
85
+
86
+ <text x="470" y="210" class="step-label">2. Negation Node.left_activate(token)</text>
87
+ <text x="470" y="227" class="code-label">✓ Checks Alpha Memory 2: NO alert facts found</text>
88
+
89
+ <!-- Success indicator -->
90
+ <rect x="450" y="250" width="520" height="50" class="production-box" rx="5"/>
91
+ <text x="710" y="275" class="step-label" text-anchor="middle">✓ RULE FIRES: "No alert for AAPL!"</text>
92
+ <text x="710" y="292" class="comment" text-anchor="middle">Token propagates to Production Node</text>
93
+
94
+ <!-- Phase 2: Add alert fact -->
95
+ <text x="450" y="330" class="phase-title">Phase 2: Add Alert Fact (Inhibit)</text>
96
+ <rect x="450" y="345" width="520" height="140" class="box" rx="5"/>
97
+
98
+ <text x="470" y="365" class="step-label">3. engine.add_fact(:alert, symbol: "AAPL", level: "warning")</text>
99
+
100
+ <text x="470" y="388" class="code-label">✓ Matches Alpha Memory 2 → activates</text>
101
+ <text x="470" y="405" class="code-label">✓ Negation Node.right_activate(alert_fact)</text>
102
+ <text x="470" y="422" class="code-label">✓ Finds existing token in Beta Memory 1</text>
103
+ <text x="470" y="439" class="code-label">✓ Alert fact now INHIBITS the negation condition</text>
104
+
105
+ <text x="470" y="460" class="step-label">4. Negation Node deactivates token</text>
106
+ <text x="470" y="477" class="code-label">✓ Removes token from Production Node</text>
107
+
108
+ <!-- Blocked indicator -->
109
+ <rect x="450" y="500" width="520" height="50" class="negation-box" rx="5"/>
110
+ <text x="710" y="525" class="step-label" text-anchor="middle">✗ RULE BLOCKED: Alert exists, rule does not fire</text>
111
+ <text x="710" y="542" class="comment" text-anchor="middle">Negation condition no longer satisfied</text>
112
+
113
+ <!-- Phase 3: Remove alert fact -->
114
+ <text x="450" y="580" class="phase-title">Phase 3: Remove Alert Fact (Reactivate)</text>
115
+ <rect x="450" y="595" width="520" height="130" class="box" rx="5"/>
116
+
117
+ <text x="470" y="615" class="step-label">5. engine.remove_fact(alert_fact)</text>
118
+
119
+ <text x="470" y="638" class="code-label">✓ Alpha Memory 2 deactivates alert fact</text>
120
+ <text x="470" y="655" class="code-label">✓ Negation Node.right_deactivate(alert_fact)</text>
121
+ <text x="470" y="672" class="code-label">✓ No more inhibiting facts → condition satisfied again</text>
122
+ <text x="470" y="689" class="code-label">✓ Creates new token and propagates to Production Node</text>
123
+
124
+ <text x="470" y="710" class="step-label">6. engine.run()</text>
125
+
126
+ <!-- Success indicator -->
127
+ <rect x="450" y="740" width="520" height="50" class="production-box" rx="5"/>
128
+ <text x="710" y="765" class="step-label" text-anchor="middle">✓ RULE FIRES AGAIN: "No alert for AAPL!"</text>
129
+ <text x="710" y="782" class="comment" text-anchor="middle">Negation condition satisfied once more</text>
130
+
131
+ <!-- Legend -->
132
+ <text x="30" y="540" class="comment">Purple: Alpha Memories</text>
133
+ <text x="30" y="560" class="comment">Teal: Beta Memories</text>
134
+ <text x="30" y="580" class="comment">Pink: Negation Node</text>
135
+ <text x="30" y="600" class="comment">Gold: Production Node</text>
136
+ </svg>