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,96 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600" style="background: transparent;">
2
+ <defs>
3
+ <style>
4
+ .title { font: bold 18px monospace; fill: #e0e0e0; }
5
+ .layer-label { font: bold 14px monospace; fill: #bb86fc; }
6
+ .node-label { font: 12px monospace; fill: #e0e0e0; }
7
+ .node-box { fill: #2d2d2d; stroke: #bb86fc; stroke-width: 2; }
8
+ .beta-box { fill: #2d2d2d; stroke: #03dac6; stroke-width: 2; }
9
+ .production-box { fill: #2d2d2d; stroke: #cf6679; stroke-width: 2; }
10
+ .connection { stroke: #bb86fc; stroke-width: 2; fill: none; marker-end: url(#arrowhead); }
11
+ .beta-connection { stroke: #03dac6; stroke-width: 2; fill: none; marker-end: url(#arrowhead-teal); }
12
+ .section-label { font: bold 16px monospace; fill: #bb86fc; }
13
+ </style>
14
+ <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
15
+ <polygon points="0 0, 10 3, 0 6" fill="#bb86fc" />
16
+ </marker>
17
+ <marker id="arrowhead-teal" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
18
+ <polygon points="0 0, 10 3, 0 6" fill="#03dac6" />
19
+ </marker>
20
+ </defs>
21
+
22
+ <!-- Title -->
23
+ <text x="400" y="30" class="title" text-anchor="middle">RETE Network Architecture</text>
24
+
25
+ <!-- Layer 1: Alpha Network -->
26
+ <text x="20" y="80" class="section-label">Layer 1: ALPHA NETWORK</text>
27
+ <text x="20" y="100" class="node-label">(Pattern Matching)</text>
28
+
29
+ <!-- Alpha Memory Nodes -->
30
+ <rect x="50" y="120" width="180" height="80" class="node-box" rx="5"/>
31
+ <text x="140" y="145" class="layer-label" text-anchor="middle">Alpha Memory 1</text>
32
+ <text x="140" y="165" class="node-label" text-anchor="middle">Pattern: stock(</text>
33
+ <text x="140" y="182" class="node-label" text-anchor="middle">symbol: "AAPL")</text>
34
+
35
+ <rect x="270" y="120" width="180" height="80" class="node-box" rx="5"/>
36
+ <text x="360" y="145" class="layer-label" text-anchor="middle">Alpha Memory 2</text>
37
+ <text x="360" y="165" class="node-label" text-anchor="middle">Pattern: alert(</text>
38
+ <text x="360" y="182" class="node-label" text-anchor="middle">symbol: "AAPL")</text>
39
+
40
+ <rect x="490" y="120" width="180" height="80" class="node-box" rx="5"/>
41
+ <text x="580" y="145" class="layer-label" text-anchor="middle">Alpha Memory 3</text>
42
+ <text x="580" y="165" class="node-label" text-anchor="middle">Pattern: order(</text>
43
+ <text x="580" y="182" class="node-label" text-anchor="middle">quantity: 100)</text>
44
+
45
+ <!-- Layer 2: Beta Network -->
46
+ <text x="20" y="280" class="section-label">Layer 2: BETA NETWORK</text>
47
+ <text x="20" y="300" class="node-label">(Join Processing)</text>
48
+
49
+ <!-- Root Beta Memory -->
50
+ <rect x="50" y="240" width="140" height="60" class="beta-box" rx="5"/>
51
+ <text x="120" y="262" class="layer-label" text-anchor="middle">Root Beta</text>
52
+ <text x="120" y="282" class="layer-label" text-anchor="middle">Memory</text>
53
+
54
+ <!-- Connection from Root to Join Node 1 -->
55
+ <path d="M 120 300 L 120 330" class="beta-connection"/>
56
+ <path d="M 140 200 L 210 330" class="connection"/>
57
+
58
+ <!-- Join Node 1 -->
59
+ <rect x="160" y="330" width="120" height="60" class="node-box" rx="5"/>
60
+ <text x="220" y="355" class="layer-label" text-anchor="middle">Join Node 1</text>
61
+ <text x="220" y="375" class="node-label" text-anchor="middle">(stock ⋈ root)</text>
62
+
63
+ <!-- Beta Memory 1 -->
64
+ <rect x="170" y="410" width="100" height="50" class="beta-box" rx="5"/>
65
+ <text x="220" y="440" class="layer-label" text-anchor="middle">Beta Mem 1</text>
66
+
67
+ <!-- Connection from Join Node 1 to Beta Memory 1 -->
68
+ <path d="M 220 390 L 220 410" class="beta-connection"/>
69
+
70
+ <!-- Connection from Beta Memory 1 to Join Node 2 -->
71
+ <path d="M 220 460 L 220 490" class="beta-connection"/>
72
+ <path d="M 360 200 L 330 490" class="connection"/>
73
+
74
+ <!-- Join Node 2 -->
75
+ <rect x="270" y="490" width="120" height="60" class="node-box" rx="5"/>
76
+ <text x="330" y="515" class="layer-label" text-anchor="middle">Join Node 2</text>
77
+ <text x="330" y="535" class="node-label" text-anchor="middle">(alert ⋈ β1)</text>
78
+
79
+ <!-- Layer 3: Production Nodes -->
80
+ <text x="480" y="440" class="section-label">Layer 3: PRODUCTION</text>
81
+ <text x="480" y="460" class="node-label">(Rule Firing)</text>
82
+
83
+ <!-- Production Node -->
84
+ <rect x="480" y="490" width="160" height="80" class="production-box" rx="5"/>
85
+ <text x="560" y="515" class="layer-label" text-anchor="middle">Production Node</text>
86
+ <text x="560" y="535" class="node-label" text-anchor="middle">Rule:</text>
87
+ <text x="560" y="552" class="node-label" text-anchor="middle">"alert_action"</text>
88
+
89
+ <!-- Connection from Join Node 2 to Production Node -->
90
+ <path d="M 390 520 L 480 520" class="connection"/>
91
+
92
+ <!-- Legend -->
93
+ <text x="50" y="585" class="node-label">Purple: Alpha/Join Nodes</text>
94
+ <text x="280" y="585" class="node-label">Teal: Beta Memories</text>
95
+ <text x="500" y="585" class="node-label">Pink: Production Nodes</text>
96
+ </svg>
@@ -0,0 +1,69 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 700" style="background: transparent;">
2
+ <defs>
3
+ <style>
4
+ .title { font: bold 16px monospace; fill: #e0e0e0; }
5
+ .layer-title { font: bold 14px monospace; fill: #bb86fc; }
6
+ .label { font: 12px monospace; fill: #e0e0e0; }
7
+ .layer-box { fill: #2d2d2d; stroke: #bb86fc; stroke-width: 2; }
8
+ .storage-box { fill: #2d3d3d; stroke: #03dac6; stroke-width: 2; }
9
+ .arrow { stroke: #bb86fc; stroke-width: 3; fill: none; marker-end: url(#arrowhead); }
10
+ </style>
11
+ <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
12
+ <polygon points="0 0, 10 3, 0 6" fill="#bb86fc" />
13
+ </marker>
14
+ </defs>
15
+
16
+ <!-- Title -->
17
+ <text x="400" y="30" class="title" text-anchor="middle">KBS System Layers</text>
18
+
19
+ <!-- Application Layer -->
20
+ <rect x="100" y="60" width="600" height="70" class="layer-box" rx="8"/>
21
+ <text x="400" y="90" class="layer-title" text-anchor="middle">Application Layer</text>
22
+ <text x="400" y="110" class="label" text-anchor="middle">(Your Rules, Facts, and Business Logic)</text>
23
+
24
+ <!-- Arrow -->
25
+ <path d="M 400 130 L 400 160" class="arrow"/>
26
+
27
+ <!-- DSL Layer -->
28
+ <rect x="100" y="160" width="600" height="70" class="layer-box" rx="8"/>
29
+ <text x="400" y="190" class="layer-title" text-anchor="middle">DSL Layer</text>
30
+ <text x="400" y="210" class="label" text-anchor="middle">(Declarative Rule Definition and Pattern Matching)</text>
31
+
32
+ <!-- Arrow -->
33
+ <path d="M 400 230 L 400 260" class="arrow"/>
34
+
35
+ <!-- RETE Engine -->
36
+ <rect x="100" y="260" width="600" height="70" class="layer-box" rx="8"/>
37
+ <text x="400" y="290" class="layer-title" text-anchor="middle">RETE Engine</text>
38
+ <text x="400" y="310" class="label" text-anchor="middle">(Alpha/Beta Networks, Join Nodes, Productions)</text>
39
+
40
+ <!-- Arrow -->
41
+ <path d="M 400 330 L 400 360" class="arrow"/>
42
+
43
+ <!-- Working Memory Layer -->
44
+ <rect x="100" y="360" width="600" height="70" class="layer-box" rx="8"/>
45
+ <text x="400" y="390" class="layer-title" text-anchor="middle">Working Memory Layer</text>
46
+ <text x="400" y="410" class="label" text-anchor="middle">(Transient or Persistent Fact Storage)</text>
47
+
48
+ <!-- Fork Arrow -->
49
+ <path d="M 400 430 L 400 460" class="arrow"/>
50
+ <path d="M 400 460 L 250 460 L 250 500" class="arrow"/>
51
+ <path d="M 400 460 L 550 460 L 550 500" class="arrow"/>
52
+
53
+ <!-- In-Memory Store -->
54
+ <rect x="120" y="500" width="260" height="120" class="storage-box" rx="8"/>
55
+ <text x="250" y="530" class="layer-title" text-anchor="middle">In-Memory Store</text>
56
+ <text x="250" y="555" class="label" text-anchor="middle">(WorkingMemory)</text>
57
+ <text x="250" y="580" class="label" text-anchor="middle">✓ Fast</text>
58
+ <text x="250" y="600" class="label" text-anchor="middle">✓ Simple</text>
59
+
60
+ <!-- Blackboard System -->
61
+ <rect x="420" y="500" width="260" height="120" class="storage-box" rx="8"/>
62
+ <text x="550" y="530" class="layer-title" text-anchor="middle">Blackboard System</text>
63
+ <text x="550" y="555" class="label" text-anchor="middle">(SQLite/Redis/Hybrid)</text>
64
+ <text x="550" y="580" class="label" text-anchor="middle">✓ Persistent</text>
65
+ <text x="550" y="600" class="label" text-anchor="middle">✓ Auditable</text>
66
+
67
+ <!-- Legend -->
68
+ <text x="400" y="660" class="label" text-anchor="middle" style="font-style: italic; fill: #888;">Fact flow from top to bottom, storage choice at bottom</text>
69
+ </svg>
@@ -0,0 +1,139 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 1100" style="background: transparent;">
2
+ <defs>
3
+ <style>
4
+ .title { font: bold 16px monospace; fill: #e0e0e0; }
5
+ .node-title { font: bold 11px monospace; fill: #bb86fc; }
6
+ .label { font: 10px monospace; fill: #e0e0e0; }
7
+ .detail { font: 9px monospace; fill: #888; font-style: italic; }
8
+ .beta-box { fill: #2d3d4d; stroke: #03dac6; stroke-width: 2; }
9
+ .alpha-box { fill: #3d2d4d; stroke: #bb86fc; stroke-width: 2; }
10
+ .join-box { fill: #2d4d3d; stroke: #4daf50; stroke-width: 2; }
11
+ .neg-box { fill: #4d2d2d; stroke: #cf6679; stroke-width: 2; }
12
+ .prod-box { fill: #4d4d2d; stroke: #ffa500; stroke-width: 2; }
13
+ .arrow { stroke: #03dac6; stroke-width: 2; fill: none; marker-end: url(#arrowhead-beta); }
14
+ .arrow-alpha { stroke: #bb86fc; stroke-width: 2; fill: none; marker-end: url(#arrowhead-alpha); }
15
+ </style>
16
+ <marker id="arrowhead-beta" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
17
+ <polygon points="0 0, 10 3, 0 6" fill="#03dac6" />
18
+ </marker>
19
+ <marker id="arrowhead-alpha" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
20
+ <polygon points="0 0, 10 3, 0 6" fill="#bb86fc" />
21
+ </marker>
22
+ </defs>
23
+
24
+ <!-- Title -->
25
+ <text x="350" y="30" class="title" text-anchor="middle">Trading Signal Network</text>
26
+ <text x="350" y="50" class="detail" text-anchor="middle">3-condition rule with negation and variable bindings</text>
27
+
28
+ <!-- Root Beta Memory -->
29
+ <rect x="200" y="80" width="300" height="60" class="beta-box" rx="5"/>
30
+ <text x="350" y="105" class="node-title" text-anchor="middle">Root Beta Memory</text>
31
+ <text x="350" y="125" class="label" text-anchor="middle">[Token(parent: nil, fact: nil)]</text>
32
+
33
+ <!-- Arrow to JoinNode1 -->
34
+ <path d="M 280 140 L 280 190" class="arrow"/>
35
+
36
+ <!-- AlphaMemory(:stock) on right -->
37
+ <rect x="520" y="150" width="160" height="80" class="alpha-box" rx="5"/>
38
+ <text x="600" y="175" class="node-title" text-anchor="middle">AlphaMemory</text>
39
+ <text x="600" y="195" class="label" text-anchor="middle">:stock</text>
40
+ <text x="600" y="210" class="detail" text-anchor="middle">pattern: {symbol: :sym?,</text>
41
+ <text x="600" y="222" class="detail" text-anchor="middle">price: :price?}</text>
42
+
43
+ <!-- Arrow from alpha to join -->
44
+ <path d="M 520 190 L 370 210" class="arrow-alpha"/>
45
+
46
+ <!-- JoinNode1 -->
47
+ <rect x="200" y="190" width="170" height="50" class="join-box" rx="5"/>
48
+ <text x="285" y="212" class="node-title" text-anchor="middle">JoinNode1</text>
49
+ <text x="285" y="228" class="label" text-anchor="middle">(test: none)</text>
50
+
51
+ <!-- Arrow to BetaMemory1 -->
52
+ <path d="M 285 240 L 285 280" class="arrow"/>
53
+
54
+ <!-- BetaMemory1 -->
55
+ <rect x="170" y="280" width="230" height="60" class="beta-box" rx="5"/>
56
+ <text x="285" y="305" class="node-title" text-anchor="middle">BetaMemory1</text>
57
+ <text x="285" y="325" class="label" text-anchor="middle">[Token(parent: root, fact: stock(...))]</text>
58
+
59
+ <!-- Arrow to JoinNode2 -->
60
+ <path d="M 290 340 L 290 390" class="arrow"/>
61
+
62
+ <!-- AlphaMemory(:threshold) on right -->
63
+ <rect x="520" y="360" width="160" height="80" class="alpha-box" rx="5"/>
64
+ <text x="600" y="385" class="node-title" text-anchor="middle">AlphaMemory</text>
65
+ <text x="600" y="405" class="label" text-anchor="middle">:threshold</text>
66
+ <text x="600" y="420" class="detail" text-anchor="middle">pattern: {symbol: :sym?,</text>
67
+ <text x="600" y="432" class="detail" text-anchor="middle">buy_below: :threshold?}</text>
68
+
69
+ <!-- Arrow from alpha to join -->
70
+ <path d="M 520 400 L 380 420" class="arrow-alpha"/>
71
+
72
+ <!-- JoinNode2 -->
73
+ <rect x="200" y="390" width="180" height="60" class="join-box" rx="5"/>
74
+ <text x="290" y="415" class="node-title" text-anchor="middle">JoinNode2</text>
75
+ <text x="290" y="435" class="label" text-anchor="middle">(test: :sym? equality)</text>
76
+
77
+ <!-- Arrow to BetaMemory2 -->
78
+ <path d="M 290 450 L 290 490" class="arrow"/>
79
+
80
+ <!-- BetaMemory2 -->
81
+ <rect x="130" y="490" width="320" height="60" class="beta-box" rx="5"/>
82
+ <text x="290" y="515" class="node-title" text-anchor="middle">BetaMemory2</text>
83
+ <text x="290" y="535" class="label" text-anchor="middle">[Token(parent: token1, fact: threshold(...))]</text>
84
+
85
+ <!-- Arrow to NegationNode -->
86
+ <path d="M 295 550 L 295 600" class="arrow"/>
87
+
88
+ <!-- AlphaMemory(:order) on right -->
89
+ <rect x="520" y="580" width="160" height="70" class="alpha-box" rx="5"/>
90
+ <text x="600" y="605" class="node-title" text-anchor="middle">AlphaMemory</text>
91
+ <text x="600" y="625" class="label" text-anchor="middle">:order</text>
92
+ <text x="600" y="640" class="detail" text-anchor="middle">pattern: {symbol: :sym?}</text>
93
+
94
+ <!-- Arrow from alpha to negation -->
95
+ <path d="M 520 615 L 410 625" class="arrow-alpha"/>
96
+
97
+ <!-- NegationNode -->
98
+ <rect x="190" y="600" width="220" height="60" class="neg-box" rx="5"/>
99
+ <text x="300" y="625" class="node-title" text-anchor="middle">NegationNode</text>
100
+ <text x="300" y="645" class="label" text-anchor="middle">(test: :sym? equality)</text>
101
+
102
+ <!-- Arrow to BetaMemory3 -->
103
+ <path d="M 300 660 L 300 700" class="arrow"/>
104
+
105
+ <!-- BetaMemory3 -->
106
+ <rect x="150" y="700" width="300" height="60" class="beta-box" rx="5"/>
107
+ <text x="300" y="725" class="node-title" text-anchor="middle">BetaMemory3</text>
108
+ <text x="300" y="745" class="label" text-anchor="middle">[Token(parent: token2, fact: nil)]</text>
109
+
110
+ <!-- Arrow to ProductionNode -->
111
+ <path d="M 300 760 L 300 810" class="arrow"/>
112
+
113
+ <!-- ProductionNode -->
114
+ <rect x="160" y="810" width="280" height="90" class="prod-box" rx="5"/>
115
+ <text x="300" y="840" class="node-title" text-anchor="middle">ProductionNode</text>
116
+ <text x="300" y="860" class="label" text-anchor="middle">(rule: "trading_signal")</text>
117
+ <text x="300" y="880" class="detail" text-anchor="middle">Action: if price < threshold,</text>
118
+ <text x="300" y="892" class="detail" text-anchor="middle">BUY symbol</text>
119
+
120
+ <!-- Legend -->
121
+ <text x="50" y="970" class="label" style="font-size: 11px;">Network Flow:</text>
122
+ <text x="50" y="990" class="detail">1. Dummy token starts at root</text>
123
+ <text x="50" y="1005" class="detail">2. Join with :stock facts → tokens in Beta1</text>
124
+ <text x="50" y="1020" class="detail">3. Join with :threshold (test :sym?) → tokens in Beta2</text>
125
+ <text x="50" y="1035" class="detail">4. Check NO :order exists (test :sym?) → tokens in Beta3</text>
126
+ <text x="50" y="1050" class="detail">5. Tokens reach production node → rule can fire</text>
127
+
128
+ <text x="50" y="1080" class="label" style="font-size: 11px;">Color Key:</text>
129
+ <rect x="150" y="1068" width="30" height="15" class="beta-box" rx="2"/>
130
+ <text x="185" y="1080" class="detail">Beta</text>
131
+ <rect x="230" y="1068" width="30" height="15" class="alpha-box" rx="2"/>
132
+ <text x="265" y="1080" class="detail">Alpha</text>
133
+ <rect x="310" y="1068" width="30" height="15" class="join-box" rx="2"/>
134
+ <text x="345" y="1080" class="detail">Join</text>
135
+ <rect x="390" y="1068" width="30" height="15" class="neg-box" rx="2"/>
136
+ <text x="425" y="1080" class="detail">Negation</text>
137
+ <rect x="490" y="1068" width="30" height="15" class="prod-box" rx="2"/>
138
+ <text x="525" y="1080" class="detail">Production</text>
139
+ </svg>
@@ -0,0 +1,17 @@
1
+ // MathJax configuration for KBS documentation
2
+ window.MathJax = {
3
+ tex: {
4
+ inlineMath: [["\\(", "\\)"]],
5
+ displayMath: [["\\[", "\\]"]],
6
+ processEscapes: true,
7
+ processEnvironments: true
8
+ },
9
+ options: {
10
+ ignoreHtmlClass: ".*|",
11
+ processHtmlClass: "arithmatex"
12
+ }
13
+ };
14
+
15
+ document$.subscribe(() => {
16
+ MathJax.typesetPromise()
17
+ })